brintos

brintos / llvm-project-archived public Read only

0
0
Text · 26.2 KiB · 6600d08 Raw
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 &target;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