631 lines · c
1//===--- CIRGenModule.h - Per-Module state for CIR gen ----------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This is the internal per-translation-unit state used for CIR translation.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H14#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H15 16#include "CIRGenBuilder.h"17#include "CIRGenCall.h"18#include "CIRGenTypeCache.h"19#include "CIRGenTypes.h"20#include "CIRGenVTables.h"21#include "CIRGenValue.h"22 23#include "clang/AST/CharUnits.h"24#include "clang/CIR/Dialect/IR/CIRDataLayout.h"25#include "clang/CIR/Dialect/IR/CIRDialect.h"26 27#include "TargetInfo.h"28#include "mlir/IR/Builders.h"29#include "mlir/IR/BuiltinOps.h"30#include "mlir/IR/MLIRContext.h"31#include "clang/AST/Decl.h"32#include "clang/Basic/SourceManager.h"33#include "clang/Basic/TargetInfo.h"34#include "clang/CIR/Dialect/IR/CIROpsEnums.h"35#include "llvm/ADT/StringRef.h"36#include "llvm/TargetParser/Triple.h"37 38namespace clang {39class ASTContext;40class CodeGenOptions;41class Decl;42class GlobalDecl;43class LangOptions;44class TargetInfo;45class VarDecl;46 47namespace CIRGen {48 49class CIRGenFunction;50class CIRGenCXXABI;51 52enum ForDefinition_t : bool { NotForDefinition = false, ForDefinition = true };53 54/// This class organizes the cross-function state that is used while generating55/// CIR code.56class CIRGenModule : public CIRGenTypeCache {57 CIRGenModule(CIRGenModule &) = delete;58 CIRGenModule &operator=(CIRGenModule &) = delete;59 60public:61 CIRGenModule(mlir::MLIRContext &mlirContext, clang::ASTContext &astContext,62 const clang::CodeGenOptions &cgo,63 clang::DiagnosticsEngine &diags);64 65 ~CIRGenModule();66 67private:68 mutable std::unique_ptr<TargetCIRGenInfo> theTargetCIRGenInfo;69 70 CIRGenBuilderTy builder;71 72 /// Hold Clang AST information.73 clang::ASTContext &astContext;74 75 const clang::LangOptions &langOpts;76 77 const clang::CodeGenOptions &codeGenOpts;78 79 /// A "module" matches a c/cpp source file: containing a list of functions.80 mlir::ModuleOp theModule;81 82 clang::DiagnosticsEngine &diags;83 84 const clang::TargetInfo ⌖85 86 std::unique_ptr<CIRGenCXXABI> abi;87 88 CIRGenTypes genTypes;89 90 /// Holds information about C++ vtables.91 CIRGenVTables vtables;92 93 /// Per-function codegen information. Updated everytime emitCIR is called94 /// for FunctionDecls's.95 CIRGenFunction *curCGF = nullptr;96 97 llvm::SmallVector<mlir::Attribute> globalScopeAsm;98 99public:100 mlir::ModuleOp getModule() const { return theModule; }101 CIRGenBuilderTy &getBuilder() { return builder; }102 clang::ASTContext &getASTContext() const { return astContext; }103 const clang::TargetInfo &getTarget() const { return target; }104 const clang::CodeGenOptions &getCodeGenOpts() const { return codeGenOpts; }105 clang::DiagnosticsEngine &getDiags() const { return diags; }106 CIRGenTypes &getTypes() { return genTypes; }107 const clang::LangOptions &getLangOpts() const { return langOpts; }108 109 CIRGenCXXABI &getCXXABI() const { return *abi; }110 mlir::MLIRContext &getMLIRContext() { return *builder.getContext(); }111 112 const cir::CIRDataLayout getDataLayout() const {113 // FIXME(cir): instead of creating a CIRDataLayout every time, set it as an114 // attribute for the CIRModule class.115 return cir::CIRDataLayout(theModule);116 }117 118 /// -------119 /// Handling globals120 /// -------121 122 mlir::Operation *lastGlobalOp = nullptr;123 124 /// Keep a map between lambda fields and names, this needs to be per module125 /// since lambdas might get generated later as part of defered work, and since126 /// the pointers are supposed to be uniqued, should be fine. Revisit this if127 /// it ends up taking too much memory.128 llvm::DenseMap<const clang::FieldDecl *, llvm::StringRef> lambdaFieldToName;129 130 /// Tell the consumer that this variable has been instantiated.131 void handleCXXStaticMemberVarInstantiation(VarDecl *vd);132 133 llvm::DenseMap<const Decl *, cir::GlobalOp> staticLocalDeclMap;134 135 mlir::Operation *getGlobalValue(llvm::StringRef ref);136 137 cir::GlobalOp getStaticLocalDeclAddress(const VarDecl *d) {138 return staticLocalDeclMap[d];139 }140 141 void setStaticLocalDeclAddress(const VarDecl *d, cir::GlobalOp c) {142 staticLocalDeclMap[d] = c;143 }144 145 cir::GlobalOp getOrCreateStaticVarDecl(const VarDecl &d,146 cir::GlobalLinkageKind linkage);147 148 /// If the specified mangled name is not in the module, create and return an149 /// mlir::GlobalOp value150 cir::GlobalOp getOrCreateCIRGlobal(llvm::StringRef mangledName, mlir::Type ty,151 LangAS langAS, const VarDecl *d,152 ForDefinition_t isForDefinition);153 154 cir::GlobalOp getOrCreateCIRGlobal(const VarDecl *d, mlir::Type ty,155 ForDefinition_t isForDefinition);156 157 static cir::GlobalOp createGlobalOp(CIRGenModule &cgm, mlir::Location loc,158 llvm::StringRef name, mlir::Type t,159 bool isConstant = false,160 mlir::Operation *insertPoint = nullptr);161 162 /// Add a global constructor or destructor to the module.163 /// The priority is optional, if not specified, the default priority is used.164 void addGlobalCtor(cir::FuncOp ctor,165 std::optional<int> priority = std::nullopt);166 void addGlobalDtor(cir::FuncOp dtor,167 std::optional<int> priority = std::nullopt);168 169 bool shouldZeroInitPadding() const {170 // In C23 (N3096) $6.7.10:171 // """172 // If any object is initialized with an empty initializer, then it is173 // subject to default initialization:174 // - if it is an aggregate, every member is initialized (recursively)175 // according to these rules, and any padding is initialized to zero bits;176 // - if it is a union, the first named member is initialized (recursively)177 // according to these rules, and any padding is initialized to zero bits.178 //179 // If the aggregate or union contains elements or members that are180 // aggregates or unions, these rules apply recursively to the subaggregates181 // or contained unions.182 //183 // If there are fewer initializers in a brace-enclosed list than there are184 // elements or members of an aggregate, or fewer characters in a string185 // literal used to initialize an array of known size than there are elements186 // in the array, the remainder of the aggregate is subject to default187 // initialization.188 // """189 //190 // The standard seems ambiguous in the following two areas:191 // 1. For a union type with empty initializer, if the first named member is192 // not the largest member, then the bytes comes after the first named member193 // but before padding are left unspecified. An example is:194 // union U { int a; long long b;};195 // union U u = {}; // The first 4 bytes are 0, but 4-8 bytes are left196 // unspecified.197 //198 // 2. It only mentions padding for empty initializer, but doesn't mention199 // padding for a non empty initialization list. And if the aggregation or200 // union contains elements or members that are aggregates or unions, and201 // some are non empty initializers, while others are empty initializers,202 // the padding initialization is unclear. An example is:203 // struct S1 { int a; long long b; };204 // struct S2 { char c; struct S1 s1; };205 // // The values for paddings between s2.c and s2.s1.a, between s2.s1.a206 // and s2.s1.b are unclear.207 // struct S2 s2 = { 'c' };208 //209 // Here we choose to zero initiailize left bytes of a union type because210 // projects like the Linux kernel are relying on this behavior. If we don't211 // explicitly zero initialize them, the undef values can be optimized to212 // return garbage data. We also choose to zero initialize paddings for213 // aggregates and unions, no matter they are initialized by empty214 // initializers or non empty initializers. This can provide a consistent215 // behavior. So projects like the Linux kernel can rely on it.216 return !getLangOpts().CPlusPlus;217 }218 219 llvm::StringMap<unsigned> cgGlobalNames;220 std::string getUniqueGlobalName(const std::string &baseName);221 222 /// Return the mlir::Value for the address of the given global variable.223 /// If Ty is non-null and if the global doesn't exist, then it will be created224 /// with the specified type instead of whatever the normal requested type225 /// would be. If IsForDefinition is true, it is guaranteed that an actual226 /// global with type Ty will be returned, not conversion of a variable with227 /// the same mangled name but some other type.228 mlir::Value229 getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty = {},230 ForDefinition_t isForDefinition = NotForDefinition);231 232 /// Return the mlir::GlobalViewAttr for the address of the given global.233 cir::GlobalViewAttr getAddrOfGlobalVarAttr(const VarDecl *d);234 235 CharUnits computeNonVirtualBaseClassOffset(236 const CXXRecordDecl *derivedClass,237 llvm::iterator_range<CastExpr::path_const_iterator> path);238 239 /// Get the CIR attributes and calling convention to use for a particular240 /// function type.241 ///242 /// \param calleeInfo - The callee information these attributes are being243 /// constructed for. If valid, the attributes applied to this decl may244 /// contribute to the function attributes and calling convention.245 void constructAttributeList(CIRGenCalleeInfo calleeInfo,246 mlir::NamedAttrList &attrs);247 248 /// Will return a global variable of the given type. If a variable with a249 /// different type already exists then a new variable with the right type250 /// will be created and all uses of the old variable will be replaced with a251 /// bitcast to the new variable.252 cir::GlobalOp createOrReplaceCXXRuntimeVariable(253 mlir::Location loc, llvm::StringRef name, mlir::Type ty,254 cir::GlobalLinkageKind linkage, clang::CharUnits alignment);255 256 void emitVTable(const CXXRecordDecl *rd);257 258 /// Return the appropriate linkage for the vtable, VTT, and type information259 /// of the given class.260 cir::GlobalLinkageKind getVTableLinkage(const CXXRecordDecl *rd);261 262 /// Get the address of the RTTI descriptor for the given type.263 mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty,264 bool forEH = false);265 266 static mlir::SymbolTable::Visibility getMLIRVisibility(Visibility v) {267 switch (v) {268 case DefaultVisibility:269 return mlir::SymbolTable::Visibility::Public;270 case HiddenVisibility:271 return mlir::SymbolTable::Visibility::Private;272 case ProtectedVisibility:273 // The distinction between ProtectedVisibility and DefaultVisibility is274 // that symbols with ProtectedVisibility, while visible to the dynamic275 // linker like DefaultVisibility, are guaranteed to always dynamically276 // resolve to a symbol in the current shared object. There is currently no277 // equivalent MLIR visibility, so we fall back on the fact that the symbol278 // is visible.279 return mlir::SymbolTable::Visibility::Public;280 }281 llvm_unreachable("unknown visibility!");282 }283 284 llvm::DenseMap<mlir::Attribute, cir::GlobalOp> constantStringMap;285 286 /// Return a constant array for the given string.287 mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e);288 289 /// Return a global symbol reference to a constant array for the given string290 /// literal.291 cir::GlobalOp getGlobalForStringLiteral(const StringLiteral *s,292 llvm::StringRef name = ".str");293 294 /// Return a global symbol reference to a constant array for the given string295 /// literal.296 cir::GlobalViewAttr297 getAddrOfConstantStringFromLiteral(const StringLiteral *s,298 llvm::StringRef name = ".str");299 300 /// Returns the address space for temporary allocations in the language. This301 /// ensures that the allocated variable's address space matches the302 /// expectations of the AST, rather than using the target's allocation address303 /// space, which may lead to type mismatches in other parts of the IR.304 LangAS getLangTempAllocaAddressSpace() const;305 306 /// Set attributes which are common to any form of a global definition (alias,307 /// Objective-C method, function, global variable).308 ///309 /// NOTE: This should only be called for definitions.310 void setCommonAttributes(GlobalDecl gd, mlir::Operation *op);311 312 const TargetCIRGenInfo &getTargetCIRGenInfo();313 314 /// Helpers to convert the presumed location of Clang's SourceLocation to an315 /// MLIR Location.316 mlir::Location getLoc(clang::SourceLocation cLoc);317 mlir::Location getLoc(clang::SourceRange cRange);318 319 /// Return the best known alignment for an unknown pointer to a320 /// particular class.321 clang::CharUnits getClassPointerAlignment(const clang::CXXRecordDecl *rd);322 323 /// FIXME: this could likely be a common helper and not necessarily related324 /// with codegen.325 clang::CharUnits getNaturalTypeAlignment(clang::QualType t,326 LValueBaseInfo *baseInfo);327 328 /// TODO: Add TBAAAccessInfo329 CharUnits getDynamicOffsetAlignment(CharUnits actualBaseAlign,330 const CXXRecordDecl *baseDecl,331 CharUnits expectedTargetAlign);332 333 /// Returns the assumed alignment of a virtual base of a class.334 CharUnits getVBaseAlignment(CharUnits derivedAlign,335 const CXXRecordDecl *derived,336 const CXXRecordDecl *vbase);337 338 cir::FuncOp339 getAddrOfCXXStructor(clang::GlobalDecl gd,340 const CIRGenFunctionInfo *fnInfo = nullptr,341 cir::FuncType fnType = nullptr, bool dontDefer = false,342 ForDefinition_t isForDefinition = NotForDefinition) {343 return getAddrAndTypeOfCXXStructor(gd, fnInfo, fnType, dontDefer,344 isForDefinition)345 .second;346 }347 348 std::pair<cir::FuncType, cir::FuncOp> getAddrAndTypeOfCXXStructor(349 clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo = nullptr,350 cir::FuncType fnType = nullptr, bool dontDefer = false,351 ForDefinition_t isForDefinition = NotForDefinition);352 353 mlir::Type getVTableComponentType();354 CIRGenVTables &getVTables() { return vtables; }355 356 ItaniumVTableContext &getItaniumVTableContext() {357 return vtables.getItaniumVTableContext();358 }359 const ItaniumVTableContext &getItaniumVTableContext() const {360 return vtables.getItaniumVTableContext();361 }362 363 /// This contains all the decls which have definitions but which are deferred364 /// for emission and therefore should only be output if they are actually365 /// used. If a decl is in this, then it is known to have not been referenced366 /// yet.367 std::map<llvm::StringRef, clang::GlobalDecl> deferredDecls;368 369 // This is a list of deferred decls which we have seen that *are* actually370 // referenced. These get code generated when the module is done.371 std::vector<clang::GlobalDecl> deferredDeclsToEmit;372 void addDeferredDeclToEmit(clang::GlobalDecl GD) {373 deferredDeclsToEmit.emplace_back(GD);374 }375 376 void emitTopLevelDecl(clang::Decl *decl);377 378 /// Determine whether the definition must be emitted; if this returns \c379 /// false, the definition can be emitted lazily if it's used.380 bool mustBeEmitted(const clang::ValueDecl *d);381 382 /// Determine whether the definition can be emitted eagerly, or should be383 /// delayed until the end of the translation unit. This is relevant for384 /// definitions whose linkage can change, e.g. implicit function385 /// instantiations which may later be explicitly instantiated.386 bool mayBeEmittedEagerly(const clang::ValueDecl *d);387 388 bool verifyModule() const;389 390 /// Return the address of the given function. If funcType is non-null, then391 /// this function will use the specified type if it has to create it.392 // TODO: this is a bit weird as `GetAddr` given we give back a FuncOp?393 cir::FuncOp394 getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType = nullptr,395 bool forVTable = false, bool dontDefer = false,396 ForDefinition_t isForDefinition = NotForDefinition);397 398 mlir::Operation *399 getAddrOfGlobal(clang::GlobalDecl gd,400 ForDefinition_t isForDefinition = NotForDefinition);401 402 // Return whether RTTI information should be emitted for this target.403 bool shouldEmitRTTI(bool forEH = false) {404 return (forEH || getLangOpts().RTTI) && !getLangOpts().CUDAIsDevice &&405 !(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&406 getTriple().isNVPTX());407 }408 409 /// Emit type info if type of an expression is a variably modified410 /// type. Also emit proper debug info for cast types.411 void emitExplicitCastExprType(const ExplicitCastExpr *e,412 CIRGenFunction *cgf = nullptr);413 414 /// Emit code for a single global function or variable declaration. Forward415 /// declarations are emitted lazily.416 void emitGlobal(clang::GlobalDecl gd);417 418 void emitAliasForGlobal(llvm::StringRef mangledName, mlir::Operation *op,419 GlobalDecl aliasGD, cir::FuncOp aliasee,420 cir::GlobalLinkageKind linkage);421 422 mlir::Type convertType(clang::QualType type);423 424 /// Set the visibility for the given global.425 void setGlobalVisibility(mlir::Operation *op, const NamedDecl *d) const;426 void setDSOLocal(mlir::Operation *op) const;427 void setDSOLocal(cir::CIRGlobalValueInterface gv) const;428 429 /// Set visibility, dllimport/dllexport and dso_local.430 /// This must be called after dllimport/dllexport is set.431 void setGVProperties(mlir::Operation *op, const NamedDecl *d) const;432 void setGVPropertiesAux(mlir::Operation *op, const NamedDecl *d) const;433 434 /// Set function attributes for a function declaration.435 void setFunctionAttributes(GlobalDecl gd, cir::FuncOp f,436 bool isIncompleteFunction, bool isThunk);437 438 /// Set extra attributes (inline, etc.) for a function.439 void setCIRFunctionAttributesForDefinition(const clang::FunctionDecl *fd,440 cir::FuncOp f);441 442 void emitGlobalDefinition(clang::GlobalDecl gd,443 mlir::Operation *op = nullptr);444 void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op);445 void emitGlobalVarDefinition(const clang::VarDecl *vd,446 bool isTentative = false);447 448 /// Emit the function that initializes the specified global449 void emitCXXGlobalVarDeclInit(const VarDecl *varDecl, cir::GlobalOp addr,450 bool performInit);451 452 void emitCXXGlobalVarDeclInitFunc(const VarDecl *vd, cir::GlobalOp addr,453 bool performInit);454 455 void emitGlobalOpenACCDecl(const clang::OpenACCConstructDecl *cd);456 void emitGlobalOpenACCRoutineDecl(const clang::OpenACCRoutineDecl *cd);457 void emitGlobalOpenACCDeclareDecl(const clang::OpenACCDeclareDecl *cd);458 template <typename BeforeOpTy, typename DataClauseTy>459 void emitGlobalOpenACCDeclareDataOperands(const Expr *varOperand,460 DataClauseTy dataClause,461 OpenACCModifierKind modifiers,462 bool structured, bool implicit,463 bool requiresDtor);464 465 // C++ related functions.466 void emitDeclContext(const DeclContext *dc);467 468 /// Return the result of value-initializing the given type, i.e. a null469 /// expression of the given type.470 mlir::Value emitNullConstant(QualType t, mlir::Location loc);471 472 mlir::TypedAttr emitNullConstantAttr(QualType t);473 474 /// Return a null constant appropriate for zero-initializing a base class with475 /// the given type. This is usually, but not always, an LLVM null constant.476 mlir::TypedAttr emitNullConstantForBase(const CXXRecordDecl *record);477 478 llvm::StringRef getMangledName(clang::GlobalDecl gd);479 480 void emitTentativeDefinition(const VarDecl *d);481 482 // Make sure that this type is translated.483 void updateCompletedType(const clang::TagDecl *td);484 485 // Produce code for this constructor/destructor. This method doesn't try to486 // apply any ABI rules about which other constructors/destructors are needed487 // or if they are alias to each other.488 cir::FuncOp codegenCXXStructor(clang::GlobalDecl gd);489 490 bool supportsCOMDAT() const;491 void maybeSetTrivialComdat(const clang::Decl &d, mlir::Operation *op);492 493 static void setInitializer(cir::GlobalOp &op, mlir::Attribute value);494 495 void replaceUsesOfNonProtoTypeWithRealFunction(mlir::Operation *old,496 cir::FuncOp newFn);497 498 cir::FuncOp499 getOrCreateCIRFunction(llvm::StringRef mangledName, mlir::Type funcType,500 clang::GlobalDecl gd, bool forVTable,501 bool dontDefer = false, bool isThunk = false,502 ForDefinition_t isForDefinition = NotForDefinition,503 mlir::ArrayAttr extraAttrs = {});504 505 cir::FuncOp createCIRFunction(mlir::Location loc, llvm::StringRef name,506 cir::FuncType funcType,507 const clang::FunctionDecl *funcDecl);508 509 /// Create a CIR function with builtin attribute set.510 cir::FuncOp createCIRBuiltinFunction(mlir::Location loc, llvm::StringRef name,511 cir::FuncType ty,512 const clang::FunctionDecl *fd);513 514 /// Mark the function as a special member (e.g. constructor, destructor)515 void setCXXSpecialMemberAttr(cir::FuncOp funcOp,516 const clang::FunctionDecl *funcDecl);517 518 cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name,519 mlir::ArrayAttr = {}, bool isLocal = false,520 bool assumeConvergent = false);521 522 static constexpr const char *builtinCoroId = "__builtin_coro_id";523 static constexpr const char *builtinCoroAlloc = "__builtin_coro_alloc";524 static constexpr const char *builtinCoroBegin = "__builtin_coro_begin";525 526 /// Given a builtin id for a function like "__builtin_fabsf", return a527 /// Function* for "fabsf".528 cir::FuncOp getBuiltinLibFunction(const FunctionDecl *fd, unsigned builtinID);529 530 mlir::IntegerAttr getSize(CharUnits size) {531 return builder.getSizeFromCharUnits(size);532 }533 534 /// Emit any needed decls for which code generation was deferred.535 void emitDeferred();536 537 /// Helper for `emitDeferred` to apply actual codegen.538 void emitGlobalDecl(const clang::GlobalDecl &d);539 540 const llvm::Triple &getTriple() const { return target.getTriple(); }541 542 // Finalize CIR code generation.543 void release();544 545 /// -------546 /// Visibility and Linkage547 /// -------548 549 static mlir::SymbolTable::Visibility550 getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind GLK);551 static cir::VisibilityKind getGlobalVisibilityKindFromClangVisibility(552 clang::VisibilityAttr::VisibilityType visibility);553 cir::VisibilityAttr getGlobalVisibilityAttrFromDecl(const Decl *decl);554 cir::GlobalLinkageKind getFunctionLinkage(GlobalDecl gd);555 static mlir::SymbolTable::Visibility getMLIRVisibility(cir::GlobalOp op);556 cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd,557 GVALinkage linkage,558 bool isConstantVariable);559 void setFunctionLinkage(GlobalDecl gd, cir::FuncOp f) {560 cir::GlobalLinkageKind l = getFunctionLinkage(gd);561 f.setLinkageAttr(cir::GlobalLinkageKindAttr::get(&getMLIRContext(), l));562 mlir::SymbolTable::setSymbolVisibility(f,563 getMLIRVisibilityFromCIRLinkage(l));564 }565 566 cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd,567 bool isConstant);568 569 void addReplacement(llvm::StringRef name, mlir::Operation *op);570 571 /// Helpers to emit "not yet implemented" error diagnostics572 DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef);573 574 template <typename T>575 DiagnosticBuilder errorNYI(SourceLocation loc, llvm::StringRef feature,576 const T &name) {577 unsigned diagID =578 diags.getCustomDiagID(DiagnosticsEngine::Error,579 "ClangIR code gen Not Yet Implemented: %0: %1");580 return diags.Report(loc, diagID) << feature << name;581 }582 583 DiagnosticBuilder errorNYI(mlir::Location loc, llvm::StringRef feature) {584 // TODO: Convert the location to a SourceLocation585 unsigned diagID = diags.getCustomDiagID(586 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");587 return diags.Report(diagID) << feature;588 }589 590 DiagnosticBuilder errorNYI(llvm::StringRef feature) const {591 // TODO: Make a default location? currSrcLoc?592 unsigned diagID = diags.getCustomDiagID(593 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");594 return diags.Report(diagID) << feature;595 }596 597 DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef);598 599 template <typename T>600 DiagnosticBuilder errorNYI(SourceRange loc, llvm::StringRef feature,601 const T &name) {602 return errorNYI(loc.getBegin(), feature, name) << loc;603 }604 605private:606 // An ordered map of canonical GlobalDecls to their mangled names.607 llvm::MapVector<clang::GlobalDecl, llvm::StringRef> mangledDeclNames;608 llvm::StringMap<clang::GlobalDecl, llvm::BumpPtrAllocator> manglings;609 610 // FIXME: should we use llvm::TrackingVH<mlir::Operation> here?611 typedef llvm::StringMap<mlir::Operation *> ReplacementsTy;612 ReplacementsTy replacements;613 /// Call replaceAllUsesWith on all pairs in replacements.614 void applyReplacements();615 616 /// A helper function to replace all uses of OldF to NewF that replace617 /// the type of pointer arguments. This is not needed to tradtional618 /// pipeline since LLVM has opaque pointers but CIR not.619 void replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF);620 621 void setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op);622 623 /// Map source language used to a CIR attribute.624 std::optional<cir::SourceLanguage> getCIRSourceLanguage() const;625};626} // namespace CIRGen627 628} // namespace clang629 630#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H631