brintos

brintos / llvm-project-archived public Read only

0
0
Text · 94.7 KiB · 809c24f Raw
2499 lines · cpp
1//===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//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#include "CIRGenModule.h"14#include "CIRGenCXXABI.h"15#include "CIRGenConstantEmitter.h"16#include "CIRGenFunction.h"17 18#include "clang/AST/ASTContext.h"19#include "clang/AST/DeclBase.h"20#include "clang/AST/DeclOpenACC.h"21#include "clang/AST/GlobalDecl.h"22#include "clang/AST/RecordLayout.h"23#include "clang/Basic/SourceManager.h"24#include "clang/CIR/Dialect/IR/CIRDialect.h"25#include "clang/CIR/Interfaces/CIROpInterfaces.h"26#include "clang/CIR/MissingFeatures.h"27 28#include "CIRGenFunctionInfo.h"29#include "mlir/IR/BuiltinOps.h"30#include "mlir/IR/Location.h"31#include "mlir/IR/MLIRContext.h"32#include "mlir/IR/Verifier.h"33 34using namespace clang;35using namespace clang::CIRGen;36 37static CIRGenCXXABI *createCXXABI(CIRGenModule &cgm) {38  switch (cgm.getASTContext().getCXXABIKind()) {39  case TargetCXXABI::GenericItanium:40  case TargetCXXABI::GenericAArch64:41  case TargetCXXABI::AppleARM64:42    return CreateCIRGenItaniumCXXABI(cgm);43 44  case TargetCXXABI::Fuchsia:45  case TargetCXXABI::GenericARM:46  case TargetCXXABI::iOS:47  case TargetCXXABI::WatchOS:48  case TargetCXXABI::GenericMIPS:49  case TargetCXXABI::WebAssembly:50  case TargetCXXABI::XL:51  case TargetCXXABI::Microsoft:52    cgm.errorNYI("C++ ABI kind not yet implemented");53    return nullptr;54  }55 56  llvm_unreachable("invalid C++ ABI kind");57}58 59CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,60                           clang::ASTContext &astContext,61                           const clang::CodeGenOptions &cgo,62                           DiagnosticsEngine &diags)63    : builder(mlirContext, *this), astContext(astContext),64      langOpts(astContext.getLangOpts()), codeGenOpts(cgo),65      theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},66      diags(diags), target(astContext.getTargetInfo()),67      abi(createCXXABI(*this)), genTypes(*this), vtables(*this) {68 69  // Initialize cached types70  voidTy = cir::VoidType::get(&getMLIRContext());71  voidPtrTy = cir::PointerType::get(voidTy);72  sInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);73  sInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);74  sInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);75  sInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);76  sInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);77  uInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);78  uInt8PtrTy = cir::PointerType::get(uInt8Ty);79  cirAllocaAddressSpace = getTargetCIRGenInfo().getCIRAllocaAddressSpace();80  uInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);81  uInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);82  uInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);83  uInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);84  fP16Ty = cir::FP16Type::get(&getMLIRContext());85  bFloat16Ty = cir::BF16Type::get(&getMLIRContext());86  floatTy = cir::SingleType::get(&getMLIRContext());87  doubleTy = cir::DoubleType::get(&getMLIRContext());88  fP80Ty = cir::FP80Type::get(&getMLIRContext());89  fP128Ty = cir::FP128Type::get(&getMLIRContext());90 91  allocaInt8PtrTy = cir::PointerType::get(uInt8Ty, cirAllocaAddressSpace);92 93  PointerAlignInBytes =94      astContext95          .toCharUnitsFromBits(96              astContext.getTargetInfo().getPointerAlign(LangAS::Default))97          .getQuantity();98 99  const unsigned charSize = astContext.getTargetInfo().getCharWidth();100  uCharTy = cir::IntType::get(&getMLIRContext(), charSize, /*isSigned=*/false);101 102  // TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed103  const unsigned sizeTypeSize =104      astContext.getTypeSize(astContext.getSignedSizeType());105  SizeSizeInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();106  // In CIRGenTypeCache, UIntPtrTy and SizeType are fields of the same union107  uIntPtrTy =108      cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/false);109  ptrDiffTy =110      cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/true);111 112  std::optional<cir::SourceLanguage> sourceLanguage = getCIRSourceLanguage();113  if (sourceLanguage)114    theModule->setAttr(115        cir::CIRDialect::getSourceLanguageAttrName(),116        cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage));117  theModule->setAttr(cir::CIRDialect::getTripleAttrName(),118                     builder.getStringAttr(getTriple().str()));119 120  if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)121    theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),122                       cir::OptInfoAttr::get(&mlirContext,123                                             cgo.OptimizationLevel,124                                             cgo.OptimizeSize));125  // Set the module name to be the name of the main file. TranslationUnitDecl126  // often contains invalid source locations and isn't a reliable source for the127  // module location.128  FileID mainFileId = astContext.getSourceManager().getMainFileID();129  const FileEntry &mainFile =130      *astContext.getSourceManager().getFileEntryForID(mainFileId);131  StringRef path = mainFile.tryGetRealPathName();132  if (!path.empty()) {133    theModule.setSymName(path);134    theModule->setLoc(mlir::FileLineColLoc::get(&mlirContext, path,135                                                /*line=*/0,136                                                /*column=*/0));137  }138}139 140CIRGenModule::~CIRGenModule() = default;141 142/// FIXME: this could likely be a common helper and not necessarily related143/// with codegen.144/// Return the best known alignment for an unknown pointer to a145/// particular class.146CharUnits CIRGenModule::getClassPointerAlignment(const CXXRecordDecl *rd) {147  if (!rd->hasDefinition())148    return CharUnits::One(); // Hopefully won't be used anywhere.149 150  auto &layout = astContext.getASTRecordLayout(rd);151 152  // If the class is final, then we know that the pointer points to an153  // object of that type and can use the full alignment.154  if (rd->isEffectivelyFinal())155    return layout.getAlignment();156 157  // Otherwise, we have to assume it could be a subclass.158  return layout.getNonVirtualAlignment();159}160 161CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t,162                                                LValueBaseInfo *baseInfo) {163  assert(!cir::MissingFeatures::opTBAA());164 165  // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but166  // that doesn't return the information we need to compute baseInfo.167 168  // Honor alignment typedef attributes even on incomplete types.169  // We also honor them straight for C++ class types, even as pointees;170  // there's an expressivity gap here.171  if (const auto *tt = t->getAs<TypedefType>()) {172    if (unsigned align = tt->getDecl()->getMaxAlignment()) {173      if (baseInfo)174        *baseInfo = LValueBaseInfo(AlignmentSource::AttributedType);175      return astContext.toCharUnitsFromBits(align);176    }177  }178 179  // Analyze the base element type, so we don't get confused by incomplete180  // array types.181  t = astContext.getBaseElementType(t);182 183  if (t->isIncompleteType()) {184    // We could try to replicate the logic from185    // ASTContext::getTypeAlignIfKnown, but nothing uses the alignment if the186    // type is incomplete, so it's impossible to test. We could try to reuse187    // getTypeAlignIfKnown, but that doesn't return the information we need188    // to set baseInfo.  So just ignore the possibility that the alignment is189    // greater than one.190    if (baseInfo)191      *baseInfo = LValueBaseInfo(AlignmentSource::Type);192    return CharUnits::One();193  }194 195  if (baseInfo)196    *baseInfo = LValueBaseInfo(AlignmentSource::Type);197 198  CharUnits alignment;199  if (t.getQualifiers().hasUnaligned()) {200    alignment = CharUnits::One();201  } else {202    assert(!cir::MissingFeatures::alignCXXRecordDecl());203    alignment = astContext.getTypeAlignInChars(t);204  }205 206  // Cap to the global maximum type alignment unless the alignment207  // was somehow explicit on the type.208  if (unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {209    if (alignment.getQuantity() > maxAlign &&210        !astContext.isAlignmentRequired(t))211      alignment = CharUnits::fromQuantity(maxAlign);212  }213  return alignment;214}215 216const TargetCIRGenInfo &CIRGenModule::getTargetCIRGenInfo() {217  if (theTargetCIRGenInfo)218    return *theTargetCIRGenInfo;219 220  const llvm::Triple &triple = getTarget().getTriple();221  switch (triple.getArch()) {222  default:223    assert(!cir::MissingFeatures::targetCIRGenInfoArch());224 225    // Currently we just fall through to x86_64.226    [[fallthrough]];227 228  case llvm::Triple::x86_64: {229    switch (triple.getOS()) {230    default:231      assert(!cir::MissingFeatures::targetCIRGenInfoOS());232 233      // Currently we just fall through to x86_64.234      [[fallthrough]];235 236    case llvm::Triple::Linux:237      theTargetCIRGenInfo = createX8664TargetCIRGenInfo(genTypes);238      return *theTargetCIRGenInfo;239    }240  }241  }242}243 244mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {245  assert(cLoc.isValid() && "expected valid source location");246  const SourceManager &sm = astContext.getSourceManager();247  PresumedLoc pLoc = sm.getPresumedLoc(cLoc);248  StringRef filename = pLoc.getFilename();249  return mlir::FileLineColLoc::get(builder.getStringAttr(filename),250                                   pLoc.getLine(), pLoc.getColumn());251}252 253mlir::Location CIRGenModule::getLoc(SourceRange cRange) {254  assert(cRange.isValid() && "expected a valid source range");255  mlir::Location begin = getLoc(cRange.getBegin());256  mlir::Location end = getLoc(cRange.getEnd());257  mlir::Attribute metadata;258  return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());259}260 261mlir::Operation *262CIRGenModule::getAddrOfGlobal(GlobalDecl gd, ForDefinition_t isForDefinition) {263  const Decl *d = gd.getDecl();264 265  if (isa<CXXConstructorDecl>(d) || isa<CXXDestructorDecl>(d))266    return getAddrOfCXXStructor(gd, /*FnInfo=*/nullptr, /*FnType=*/nullptr,267                                /*DontDefer=*/false, isForDefinition);268 269  if (isa<CXXMethodDecl>(d)) {270    const CIRGenFunctionInfo &fi =271        getTypes().arrangeCXXMethodDeclaration(cast<CXXMethodDecl>(d));272    cir::FuncType ty = getTypes().getFunctionType(fi);273    return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,274                             isForDefinition);275  }276 277  if (isa<FunctionDecl>(d)) {278    const CIRGenFunctionInfo &fi = getTypes().arrangeGlobalDeclaration(gd);279    cir::FuncType ty = getTypes().getFunctionType(fi);280    return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,281                             isForDefinition);282  }283 284  return getAddrOfGlobalVar(cast<VarDecl>(d), /*ty=*/nullptr, isForDefinition)285      .getDefiningOp();286}287 288void CIRGenModule::emitGlobalDecl(const clang::GlobalDecl &d) {289  // We call getAddrOfGlobal with isForDefinition set to ForDefinition in290  // order to get a Value with exactly the type we need, not something that291  // might have been created for another decl with the same mangled name but292  // different type.293  mlir::Operation *op = getAddrOfGlobal(d, ForDefinition);294 295  // In case of different address spaces, we may still get a cast, even with296  // IsForDefinition equal to ForDefinition. Query mangled names table to get297  // GlobalValue.298  if (!op)299    op = getGlobalValue(getMangledName(d));300 301  assert(op && "expected a valid global op");302 303  // Check to see if we've already emitted this. This is necessary for a304  // couple of reasons: first, decls can end up in deferred-decls queue305  // multiple times, and second, decls can end up with definitions in unusual306  // ways (e.g. by an extern inline function acquiring a strong function307  // redefinition). Just ignore those cases.308  // TODO: Not sure what to map this to for MLIR309  mlir::Operation *globalValueOp = op;310  if (auto gv = dyn_cast<cir::GetGlobalOp>(op))311    globalValueOp =312        mlir::SymbolTable::lookupSymbolIn(getModule(), gv.getNameAttr());313 314  if (auto cirGlobalValue =315          dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))316    if (!cirGlobalValue.isDeclaration())317      return;318 319  // If this is OpenMP, check if it is legal to emit this global normally.320  assert(!cir::MissingFeatures::openMP());321 322  // Otherwise, emit the definition and move on to the next one.323  emitGlobalDefinition(d, op);324}325 326void CIRGenModule::emitDeferred() {327  // Emit code for any potentially referenced deferred decls. Since a previously328  // unused static decl may become used during the generation of code for a329  // static function, iterate until no changes are made.330 331  assert(!cir::MissingFeatures::openMP());332  assert(!cir::MissingFeatures::deferredVtables());333  assert(!cir::MissingFeatures::cudaSupport());334 335  // Stop if we're out of both deferred vtables and deferred declarations.336  if (deferredDeclsToEmit.empty())337    return;338 339  // Grab the list of decls to emit. If emitGlobalDefinition schedules more340  // work, it will not interfere with this.341  std::vector<GlobalDecl> curDeclsToEmit;342  curDeclsToEmit.swap(deferredDeclsToEmit);343 344  for (const GlobalDecl &d : curDeclsToEmit) {345    emitGlobalDecl(d);346 347    // If we found out that we need to emit more decls, do that recursively.348    // This has the advantage that the decls are emitted in a DFS and related349    // ones are close together, which is convenient for testing.350    if (!deferredDeclsToEmit.empty()) {351      emitDeferred();352      assert(deferredDeclsToEmit.empty());353    }354  }355}356 357void CIRGenModule::emitGlobal(clang::GlobalDecl gd) {358  if (const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.getDecl())) {359    emitGlobalOpenACCDecl(cd);360    return;361  }362 363  const auto *global = cast<ValueDecl>(gd.getDecl());364 365  if (const auto *fd = dyn_cast<FunctionDecl>(global)) {366    // Update deferred annotations with the latest declaration if the function367    // was already used or defined.368    if (fd->hasAttr<AnnotateAttr>())369      errorNYI(fd->getSourceRange(), "deferredAnnotations");370    if (!fd->doesThisDeclarationHaveABody()) {371      if (!fd->doesDeclarationForceExternallyVisibleDefinition())372        return;373 374      errorNYI(fd->getSourceRange(),375               "function declaration that forces code gen");376      return;377    }378  } else {379    const auto *vd = cast<VarDecl>(global);380    assert(vd->isFileVarDecl() && "Cannot emit local var decl as global.");381    if (vd->isThisDeclarationADefinition() != VarDecl::Definition &&382        !astContext.isMSStaticDataMemberInlineDefinition(vd)) {383      assert(!cir::MissingFeatures::openMP());384      // If this declaration may have caused an inline variable definition to385      // change linkage, make sure that it's emitted.386      if (astContext.getInlineVariableDefinitionKind(vd) ==387          ASTContext::InlineVariableDefinitionKind::Strong)388        getAddrOfGlobalVar(vd);389      // Otherwise, we can ignore this declaration. The variable will be emitted390      // on its first use.391      return;392    }393  }394 395  // Defer code generation to first use when possible, e.g. if this is an inline396  // function. If the global must always be emitted, do it eagerly if possible397  // to benefit from cache locality. Deferring code generation is necessary to398  // avoid adding initializers to external declarations.399  if (mustBeEmitted(global) && mayBeEmittedEagerly(global)) {400    // Emit the definition if it can't be deferred.401    emitGlobalDefinition(gd);402    return;403  }404 405  // If we're deferring emission of a C++ variable with an initializer, remember406  // the order in which it appeared on the file.407  assert(!cir::MissingFeatures::deferredCXXGlobalInit());408 409  llvm::StringRef mangledName = getMangledName(gd);410  if (getGlobalValue(mangledName) != nullptr) {411    // The value has already been used and should therefore be emitted.412    addDeferredDeclToEmit(gd);413  } else if (mustBeEmitted(global)) {414    // The value must be emitted, but cannot be emitted eagerly.415    assert(!mayBeEmittedEagerly(global));416    addDeferredDeclToEmit(gd);417  } else {418    // Otherwise, remember that we saw a deferred decl with this name. The first419    // use of the mangled name will cause it to move into deferredDeclsToEmit.420    deferredDecls[mangledName] = gd;421  }422}423 424void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,425                                                mlir::Operation *op) {426  auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());427  const CIRGenFunctionInfo &fi = getTypes().arrangeGlobalDeclaration(gd);428  cir::FuncType funcType = getTypes().getFunctionType(fi);429  cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);430  if (!funcOp || funcOp.getFunctionType() != funcType) {431    funcOp = getAddrOfFunction(gd, funcType, /*ForVTable=*/false,432                               /*DontDefer=*/true, ForDefinition);433  }434 435  // Already emitted.436  if (!funcOp.isDeclaration())437    return;438 439  setFunctionLinkage(gd, funcOp);440  setGVProperties(funcOp, funcDecl);441  assert(!cir::MissingFeatures::opFuncMaybeHandleStaticInExternC());442  maybeSetTrivialComdat(*funcDecl, funcOp);443  assert(!cir::MissingFeatures::setLLVMFunctionFEnvAttributes());444 445  CIRGenFunction cgf(*this, builder);446  curCGF = &cgf;447  {448    mlir::OpBuilder::InsertionGuard guard(builder);449    cgf.generateCode(gd, funcOp, funcType);450  }451  curCGF = nullptr;452 453  setNonAliasAttributes(gd, funcOp);454  setCIRFunctionAttributesForDefinition(funcDecl, funcOp);455 456  auto getPriority = [this](const auto *attr) -> int {457    Expr *e = attr->getPriority();458    if (e)459      return e->EvaluateKnownConstInt(this->getASTContext()).getExtValue();460    return attr->DefaultPriority;461  };462 463  if (const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>())464    addGlobalCtor(funcOp, getPriority(ca));465  if (const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>())466    addGlobalDtor(funcOp, getPriority(da));467 468  if (funcDecl->getAttr<AnnotateAttr>())469    errorNYI(funcDecl->getSourceRange(), "deferredAnnotations");470}471 472/// Track functions to be called before main() runs.473void CIRGenModule::addGlobalCtor(cir::FuncOp ctor,474                                 std::optional<int> priority) {475  assert(!cir::MissingFeatures::globalCtorLexOrder());476  assert(!cir::MissingFeatures::globalCtorAssociatedData());477 478  // Traditional LLVM codegen directly adds the function to the list of global479  // ctors. In CIR we just add a global_ctor attribute to the function. The480  // global list is created in LoweringPrepare.481  //482  // FIXME(from traditional LLVM): Type coercion of void()* types.483  ctor.setGlobalCtorPriority(priority);484}485 486/// Add a function to the list that will be called when the module is unloaded.487void CIRGenModule::addGlobalDtor(cir::FuncOp dtor,488                                 std::optional<int> priority) {489  if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&490      (!getASTContext().getTargetInfo().getTriple().isOSAIX()))491    errorNYI(dtor.getLoc(), "registerGlobalDtorsWithAtExit");492 493  // FIXME(from traditional LLVM): Type coercion of void()* types.494  dtor.setGlobalDtorPriority(priority);495}496 497void CIRGenModule::handleCXXStaticMemberVarInstantiation(VarDecl *vd) {498  VarDecl::DefinitionKind dk = vd->isThisDeclarationADefinition();499  if (dk == VarDecl::Definition && vd->hasAttr<DLLImportAttr>())500    return;501 502  TemplateSpecializationKind tsk = vd->getTemplateSpecializationKind();503  // If we have a definition, this might be a deferred decl. If the504  // instantiation is explicit, make sure we emit it at the end.505  if (vd->getDefinition() && tsk == TSK_ExplicitInstantiationDefinition)506    getAddrOfGlobalVar(vd);507 508  emitTopLevelDecl(vd);509}510 511mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {512  return mlir::SymbolTable::lookupSymbolIn(theModule, name);513}514 515cir::GlobalOp CIRGenModule::createGlobalOp(CIRGenModule &cgm,516                                           mlir::Location loc, StringRef name,517                                           mlir::Type t, bool isConstant,518                                           mlir::Operation *insertPoint) {519  cir::GlobalOp g;520  CIRGenBuilderTy &builder = cgm.getBuilder();521 522  {523    mlir::OpBuilder::InsertionGuard guard(builder);524 525    // If an insertion point is provided, we're replacing an existing global,526    // otherwise, create the new global immediately after the last gloabl we527    // emitted.528    if (insertPoint) {529      builder.setInsertionPoint(insertPoint);530    } else {531      // Group global operations together at the top of the module.532      if (cgm.lastGlobalOp)533        builder.setInsertionPointAfter(cgm.lastGlobalOp);534      else535        builder.setInsertionPointToStart(cgm.getModule().getBody());536    }537 538    g = cir::GlobalOp::create(builder, loc, name, t, isConstant);539    if (!insertPoint)540      cgm.lastGlobalOp = g;541 542    // Default to private until we can judge based on the initializer,543    // since MLIR doesn't allow public declarations.544    mlir::SymbolTable::setSymbolVisibility(545        g, mlir::SymbolTable::Visibility::Private);546  }547  return g;548}549 550void CIRGenModule::setCommonAttributes(GlobalDecl gd, mlir::Operation *gv) {551  const Decl *d = gd.getDecl();552  if (isa_and_nonnull<NamedDecl>(d))553    setGVProperties(gv, dyn_cast<NamedDecl>(d));554  assert(!cir::MissingFeatures::defaultVisibility());555  assert(!cir::MissingFeatures::opGlobalUsedOrCompilerUsed());556}557 558void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {559  setCommonAttributes(gd, op);560 561  assert(!cir::MissingFeatures::opGlobalUsedOrCompilerUsed());562  assert(!cir::MissingFeatures::opGlobalSection());563  assert(!cir::MissingFeatures::opFuncCPUAndFeaturesAttributes());564  assert(!cir::MissingFeatures::opFuncSection());565 566  assert(!cir::MissingFeatures::setTargetAttributes());567}568 569std::optional<cir::SourceLanguage> CIRGenModule::getCIRSourceLanguage() const {570  using ClangStd = clang::LangStandard;571  using CIRLang = cir::SourceLanguage;572  auto opts = getLangOpts();573 574  if (opts.CPlusPlus)575    return CIRLang::CXX;576  if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||577      opts.LangStd == ClangStd::lang_c89 ||578      opts.LangStd == ClangStd::lang_gnu89)579    return CIRLang::C;580 581  // TODO(cir): support remaining source languages.582  assert(!cir::MissingFeatures::sourceLanguageCases());583  errorNYI("CIR does not yet support the given source language");584  return std::nullopt;585}586 587static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd) {588  // Set linkage and visibility in case we never see a definition.589  LinkageInfo lv = nd->getLinkageAndVisibility();590  // Don't set internal linkage on declarations.591  // "extern_weak" is overloaded in LLVM; we probably should have592  // separate linkage types for this.593  if (isExternallyVisible(lv.getLinkage()) &&594      (nd->hasAttr<WeakAttr>() || nd->isWeakImported()))595    gv.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);596}597 598/// If the specified mangled name is not in the module,599/// create and return an mlir GlobalOp with the specified type (TODO(cir):600/// address space).601///602/// TODO(cir):603/// 1. If there is something in the module with the specified name, return604/// it potentially bitcasted to the right type.605///606/// 2. If \p d is non-null, it specifies a decl that correspond to this.  This607/// is used to set the attributes on the global when it is first created.608///609/// 3. If \p isForDefinition is true, it is guaranteed that an actual global610/// with type \p ty will be returned, not conversion of a variable with the same611/// mangled name but some other type.612cir::GlobalOp613CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,614                                   LangAS langAS, const VarDecl *d,615                                   ForDefinition_t isForDefinition) {616  // Lookup the entry, lazily creating it if necessary.617  cir::GlobalOp entry;618  if (mlir::Operation *v = getGlobalValue(mangledName)) {619    if (!isa<cir::GlobalOp>(v))620      errorNYI(d->getSourceRange(), "global with non-GlobalOp type");621    entry = cast<cir::GlobalOp>(v);622  }623 624  if (entry) {625    assert(!cir::MissingFeatures::addressSpace());626    assert(!cir::MissingFeatures::opGlobalWeakRef());627 628    assert(!cir::MissingFeatures::setDLLStorageClass());629    assert(!cir::MissingFeatures::openMP());630 631    if (entry.getSymType() == ty)632      return entry;633 634    // If there are two attempts to define the same mangled name, issue an635    // error.636    //637    // TODO(cir): look at mlir::GlobalValue::isDeclaration for all aspects of638    // recognizing the global as a declaration, for now only check if639    // initializer is present.640    if (isForDefinition && !entry.isDeclaration()) {641      errorNYI(d->getSourceRange(), "global with conflicting type");642    }643 644    // Address space check removed because it is unnecessary because CIR records645    // address space info in types.646 647    // (If global is requested for a definition, we always need to create a new648    // global, not just return a bitcast.)649    if (!isForDefinition)650      return entry;651  }652 653  mlir::Location loc = getLoc(d->getSourceRange());654 655  // mlir::SymbolTable::Visibility::Public is the default, no need to explicitly656  // mark it as such.657  cir::GlobalOp gv =658      CIRGenModule::createGlobalOp(*this, loc, mangledName, ty, false,659                                   /*insertPoint=*/entry.getOperation());660 661  // This is the first use or definition of a mangled name.  If there is a662  // deferred decl with this name, remember that we need to emit it at the end663  // of the file.664  auto ddi = deferredDecls.find(mangledName);665  if (ddi != deferredDecls.end()) {666    // Move the potentially referenced deferred decl to the DeferredDeclsToEmit667    // list, and remove it from DeferredDecls (since we don't need it anymore).668    addDeferredDeclToEmit(ddi->second);669    deferredDecls.erase(ddi);670  }671 672  // Handle things which are present even on external declarations.673  if (d) {674    if (langOpts.OpenMP && !langOpts.OpenMPSimd)675      errorNYI(d->getSourceRange(), "OpenMP target global variable");676 677    gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));678    // FIXME: This code is overly simple and should be merged with other global679    // handling.680    gv.setConstant(d->getType().isConstantStorage(681        astContext, /*ExcludeCtor=*/false, /*ExcludeDtor=*/false));682 683    setLinkageForGV(gv, d);684 685    if (d->getTLSKind())686      errorNYI(d->getSourceRange(), "thread local global variable");687 688    setGVProperties(gv, d);689 690    // If required by the ABI, treat declarations of static data members with691    // inline initializers as definitions.692    if (astContext.isMSStaticDataMemberInlineDefinition(d))693      errorNYI(d->getSourceRange(), "MS static data member inline definition");694 695    assert(!cir::MissingFeatures::opGlobalSection());696    gv.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(d));697 698    // Handle XCore specific ABI requirements.699    if (getTriple().getArch() == llvm::Triple::xcore)700      errorNYI(d->getSourceRange(), "XCore specific ABI requirements");701 702    // Check if we a have a const declaration with an initializer, we may be703    // able to emit it as available_externally to expose it's value to the704    // optimizer.705    if (getLangOpts().CPlusPlus && gv.isPublic() &&706        d->getType().isConstQualified() && gv.isDeclaration() &&707        !d->hasDefinition() && d->hasInit() && !d->hasAttr<DLLImportAttr>())708      errorNYI(d->getSourceRange(),709               "external const declaration with initializer");710  }711 712  return gv;713}714 715cir::GlobalOp716CIRGenModule::getOrCreateCIRGlobal(const VarDecl *d, mlir::Type ty,717                                   ForDefinition_t isForDefinition) {718  assert(d->hasGlobalStorage() && "Not a global variable");719  QualType astTy = d->getType();720  if (!ty)721    ty = getTypes().convertTypeForMem(astTy);722 723  StringRef mangledName = getMangledName(d);724  return getOrCreateCIRGlobal(mangledName, ty, astTy.getAddressSpace(), d,725                              isForDefinition);726}727 728/// Return the mlir::Value for the address of the given global variable. If729/// \p ty is non-null and if the global doesn't exist, then it will be created730/// with the specified type instead of whatever the normal requested type would731/// be. If \p isForDefinition is true, it is guaranteed that an actual global732/// with type \p ty will be returned, not conversion of a variable with the same733/// mangled name but some other type.734mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,735                                             ForDefinition_t isForDefinition) {736  assert(d->hasGlobalStorage() && "Not a global variable");737  QualType astTy = d->getType();738  if (!ty)739    ty = getTypes().convertTypeForMem(astTy);740 741  assert(!cir::MissingFeatures::opGlobalThreadLocal());742 743  cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);744  mlir::Type ptrTy = builder.getPointerTo(g.getSymType());745  return cir::GetGlobalOp::create(builder, getLoc(d->getSourceRange()), ptrTy,746                                  g.getSymName());747}748 749cir::GlobalViewAttr CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *d) {750  assert(d->hasGlobalStorage() && "Not a global variable");751  mlir::Type ty = getTypes().convertTypeForMem(d->getType());752 753  cir::GlobalOp globalOp = getOrCreateCIRGlobal(d, ty, NotForDefinition);754  assert(!cir::MissingFeatures::addressSpace());755  cir::PointerType ptrTy = builder.getPointerTo(globalOp.getSymType());756  return builder.getGlobalViewAttr(ptrTy, globalOp);757}758 759void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,760                                           bool isTentative) {761  if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {762    errorNYI(vd->getSourceRange(), "emit OpenCL/OpenMP global variable");763    return;764  }765 766  // Whether the definition of the variable is available externally.767  // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable768  // since this is the job for its original source.769  bool isDefinitionAvailableExternally =770      astContext.GetGVALinkageForVariable(vd) == GVA_AvailableExternally;771 772  // It is useless to emit the definition for an available_externally variable773  // which can't be marked as const.774  if (isDefinitionAvailableExternally &&775      (!vd->hasConstantInitialization() ||776       // TODO: Update this when we have interface to check constexpr777       // destructor.778       vd->needsDestruction(astContext) ||779       !vd->getType().isConstantStorage(astContext, true, true)))780    return;781 782  mlir::Attribute init;783  bool needsGlobalCtor = false;784  bool needsGlobalDtor =785      !isDefinitionAvailableExternally &&786      vd->needsDestruction(astContext) == QualType::DK_cxx_destructor;787  const VarDecl *initDecl;788  const Expr *initExpr = vd->getAnyInitializer(initDecl);789 790  std::optional<ConstantEmitter> emitter;791 792  assert(!cir::MissingFeatures::cudaSupport());793 794  if (vd->hasAttr<LoaderUninitializedAttr>()) {795    errorNYI(vd->getSourceRange(), "loader uninitialized attribute");796    return;797  } else if (!initExpr) {798    // This is a tentative definition; tentative definitions are799    // implicitly initialized with { 0 }.800    //801    // Note that tentative definitions are only emitted at the end of802    // a translation unit, so they should never have incomplete803    // type. In addition, EmitTentativeDefinition makes sure that we804    // never attempt to emit a tentative definition if a real one805    // exists. A use may still exists, however, so we still may need806    // to do a RAUW.807    assert(!vd->getType()->isIncompleteType() && "Unexpected incomplete type");808    init = builder.getZeroInitAttr(convertType(vd->getType()));809  } else {810    emitter.emplace(*this);811    mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);812    if (!initializer) {813      QualType qt = initExpr->getType();814      if (vd->getType()->isReferenceType())815        qt = vd->getType();816 817      if (getLangOpts().CPlusPlus) {818        if (initDecl->hasFlexibleArrayInit(astContext))819          errorNYI(vd->getSourceRange(), "flexible array initializer");820        init = builder.getZeroInitAttr(convertType(qt));821        if (!isDefinitionAvailableExternally)822          needsGlobalCtor = true;823      } else {824        errorNYI(vd->getSourceRange(), "static initializer");825      }826    } else {827      init = initializer;828      // We don't need an initializer, so remove the entry for the delayed829      // initializer position (just in case this entry was delayed) if we830      // also don't need to register a destructor.831      assert(!cir::MissingFeatures::deferredCXXGlobalInit());832    }833  }834 835  mlir::Type initType;836  if (mlir::isa<mlir::SymbolRefAttr>(init)) {837    errorNYI(vd->getSourceRange(), "global initializer is a symbol reference");838    return;839  } else {840    assert(mlir::isa<mlir::TypedAttr>(init) && "This should have a type");841    auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);842    initType = typedInitAttr.getType();843  }844  assert(!mlir::isa<mlir::NoneType>(initType) && "Should have a type by now");845 846  cir::GlobalOp gv =847      getOrCreateCIRGlobal(vd, initType, ForDefinition_t(!isTentative));848  // TODO(cir): Strip off pointer casts from Entry if we get them?849 850  if (!gv || gv.getSymType() != initType) {851    errorNYI(vd->getSourceRange(), "global initializer with type mismatch");852    return;853  }854 855  assert(!cir::MissingFeatures::maybeHandleStaticInExternC());856 857  if (vd->hasAttr<AnnotateAttr>()) {858    errorNYI(vd->getSourceRange(), "annotate global variable");859  }860 861  if (langOpts.CUDA) {862    errorNYI(vd->getSourceRange(), "CUDA global variable");863  }864 865  // Set initializer and finalize emission866  CIRGenModule::setInitializer(gv, init);867  if (emitter)868    emitter->finalize(gv);869 870  // If it is safe to mark the global 'constant', do so now.871  gv.setConstant((vd->hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||872                 (!needsGlobalCtor && !needsGlobalDtor &&873                  vd->getType().isConstantStorage(874                      astContext, /*ExcludeCtor=*/true, /*ExcludeDtor=*/true)));875  assert(!cir::MissingFeatures::opGlobalSection());876 877  // Set CIR's linkage type as appropriate.878  cir::GlobalLinkageKind linkage =879      getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);880 881  // Set CIR linkage and DLL storage class.882  gv.setLinkage(linkage);883  // FIXME(cir): setLinkage should likely set MLIR's visibility automatically.884  gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));885  assert(!cir::MissingFeatures::opGlobalDLLImportExport());886  if (linkage == cir::GlobalLinkageKind::CommonLinkage) {887    // common vars aren't constant even if declared const.888    gv.setConstant(false);889    // Tentative definition of global variables may be initialized with890    // non-zero null pointers. In this case they should have weak linkage891    // since common linkage must have zero initializer and must not have892    // explicit section therefore cannot have non-zero initial value.893    std::optional<mlir::Attribute> initializer = gv.getInitialValue();894    if (initializer && !getBuilder().isNullValue(*initializer))895      gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);896  }897 898  setNonAliasAttributes(vd, gv);899 900  assert(!cir::MissingFeatures::opGlobalThreadLocal());901 902  maybeSetTrivialComdat(*vd, gv);903 904  // Emit the initializer function if necessary.905  if (needsGlobalCtor || needsGlobalDtor)906    emitCXXGlobalVarDeclInitFunc(vd, gv, needsGlobalCtor);907}908 909void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd,910                                        mlir::Operation *op) {911  const auto *decl = cast<ValueDecl>(gd.getDecl());912  if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {913    // TODO(CIR): Skip generation of CIR for functions with available_externally914    // linkage at -O0.915 916    if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {917      // Make sure to emit the definition(s) before we emit the thunks. This is918      // necessary for the generation of certain thunks.919      if (isa<CXXConstructorDecl>(method) || isa<CXXDestructorDecl>(method))920        abi->emitCXXStructor(gd);921      else if (fd->isMultiVersion())922        errorNYI(method->getSourceRange(), "multiversion functions");923      else924        emitGlobalFunctionDefinition(gd, op);925 926      if (method->isVirtual())927        getVTables().emitThunks(gd);928 929      return;930    }931 932    if (fd->isMultiVersion())933      errorNYI(fd->getSourceRange(), "multiversion functions");934    emitGlobalFunctionDefinition(gd, op);935    return;936  }937 938  if (const auto *vd = dyn_cast<VarDecl>(decl))939    return emitGlobalVarDefinition(vd, !vd->hasDefinition());940 941  llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");942}943 944mlir::Attribute945CIRGenModule::getConstantArrayFromStringLiteral(const StringLiteral *e) {946  assert(!e->getType()->isPointerType() && "Strings are always arrays");947 948  // Don't emit it as the address of the string, emit the string data itself949  // as an inline array.950  if (e->getCharByteWidth() == 1) {951    SmallString<64> str(e->getString());952 953    // Resize the string to the right size, which is indicated by its type.954    const ConstantArrayType *cat =955        astContext.getAsConstantArrayType(e->getType());956    uint64_t finalSize = cat->getZExtSize();957    str.resize(finalSize);958 959    mlir::Type eltTy = convertType(cat->getElementType());960    return builder.getString(str, eltTy, finalSize);961  }962 963  errorNYI(e->getSourceRange(),964           "getConstantArrayFromStringLiteral: wide characters");965  return mlir::Attribute();966}967 968bool CIRGenModule::supportsCOMDAT() const {969  return getTriple().supportsCOMDAT();970}971 972static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {973  if (!cgm.supportsCOMDAT())974    return false;975 976  if (d.hasAttr<SelectAnyAttr>())977    return true;978 979  GVALinkage linkage;980  if (auto *vd = dyn_cast<VarDecl>(&d))981    linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);982  else983    linkage =984        cgm.getASTContext().GetGVALinkageForFunction(cast<FunctionDecl>(&d));985 986  switch (linkage) {987  case clang::GVA_Internal:988  case clang::GVA_AvailableExternally:989  case clang::GVA_StrongExternal:990    return false;991  case clang::GVA_DiscardableODR:992  case clang::GVA_StrongODR:993    return true;994  }995  llvm_unreachable("No such linkage");996}997 998void CIRGenModule::maybeSetTrivialComdat(const Decl &d, mlir::Operation *op) {999  if (!shouldBeInCOMDAT(*this, d))1000    return;1001  if (auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {1002    globalOp.setComdat(true);1003  } else {1004    auto funcOp = cast<cir::FuncOp>(op);1005    funcOp.setComdat(true);1006  }1007}1008 1009void CIRGenModule::updateCompletedType(const TagDecl *td) {1010  // Make sure that this type is translated.1011  genTypes.updateCompletedType(td);1012}1013 1014void CIRGenModule::addReplacement(StringRef name, mlir::Operation *op) {1015  replacements[name] = op;1016}1017 1018void CIRGenModule::replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF) {1019  std::optional<mlir::SymbolTable::UseRange> optionalUseRange =1020      oldF.getSymbolUses(theModule);1021  if (!optionalUseRange)1022    return;1023 1024  for (const mlir::SymbolTable::SymbolUse &u : *optionalUseRange) {1025    // CallTryOp only shows up after FlattenCFG.1026    auto call = mlir::dyn_cast<cir::CallOp>(u.getUser());1027    if (!call)1028      continue;1029 1030    for (const auto [argOp, fnArgType] :1031         llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {1032      if (argOp.getType() == fnArgType)1033        continue;1034 1035      // The purpose of this entire function is to insert bitcasts in the case1036      // where these types don't match, but I haven't seen a case where that1037      // happens.1038      errorNYI(call.getLoc(), "replace call with mismatched types");1039    }1040  }1041}1042 1043void CIRGenModule::applyReplacements() {1044  for (auto &i : replacements) {1045    StringRef mangledName = i.first();1046    mlir::Operation *replacement = i.second;1047    mlir::Operation *entry = getGlobalValue(mangledName);1048    if (!entry)1049      continue;1050    assert(isa<cir::FuncOp>(entry) && "expected function");1051    auto oldF = cast<cir::FuncOp>(entry);1052    auto newF = dyn_cast<cir::FuncOp>(replacement);1053    if (!newF) {1054      // In classic codegen, this can be a global alias, a bitcast, or a GEP.1055      errorNYI(replacement->getLoc(), "replacement is not a function");1056      continue;1057    }1058 1059    // LLVM has opaque pointer but CIR not. So we may have to handle these1060    // different pointer types when performing replacement.1061    replacePointerTypeArgs(oldF, newF);1062 1063    // Replace old with new, but keep the old order.1064    if (oldF.replaceAllSymbolUses(newF.getSymNameAttr(), theModule).failed())1065      llvm_unreachable("internal error, cannot RAUW symbol");1066    if (newF) {1067      newF->moveBefore(oldF);1068      oldF->erase();1069    }1070  }1071}1072 1073cir::GlobalOp CIRGenModule::createOrReplaceCXXRuntimeVariable(1074    mlir::Location loc, StringRef name, mlir::Type ty,1075    cir::GlobalLinkageKind linkage, clang::CharUnits alignment) {1076  auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(1077      mlir::SymbolTable::lookupSymbolIn(theModule, name));1078 1079  if (gv) {1080    // Check if the variable has the right type.1081    if (gv.getSymType() == ty)1082      return gv;1083 1084    // Because of C++ name mangling, the only way we can end up with an already1085    // existing global with the same name is if it has been declared extern1086    // "C".1087    assert(gv.isDeclaration() && "Declaration has wrong type!");1088 1089    errorNYI(loc, "createOrReplaceCXXRuntimeVariable: declaration exists with "1090                  "wrong type");1091    return gv;1092  }1093 1094  // Create a new variable.1095  gv = createGlobalOp(*this, loc, name, ty);1096 1097  // Set up extra information and add to the module1098  gv.setLinkageAttr(1099      cir::GlobalLinkageKindAttr::get(&getMLIRContext(), linkage));1100  mlir::SymbolTable::setSymbolVisibility(gv,1101                                         CIRGenModule::getMLIRVisibility(gv));1102 1103  if (supportsCOMDAT() && cir::isWeakForLinker(linkage) &&1104      !gv.hasAvailableExternallyLinkage()) {1105    gv.setComdat(true);1106  }1107 1108  gv.setAlignmentAttr(getSize(alignment));1109  setDSOLocal(static_cast<mlir::Operation *>(gv));1110  return gv;1111}1112 1113// TODO(CIR): this could be a common method between LLVM codegen.1114static bool isVarDeclStrongDefinition(const ASTContext &astContext,1115                                      CIRGenModule &cgm, const VarDecl *vd,1116                                      bool noCommon) {1117  // Don't give variables common linkage if -fno-common was specified unless it1118  // was overridden by a NoCommon attribute.1119  if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())1120    return true;1121 1122  // C11 6.9.2/2:1123  //   A declaration of an identifier for an object that has file scope without1124  //   an initializer, and without a storage-class specifier or with the1125  //   storage-class specifier static, constitutes a tentative definition.1126  if (vd->getInit() || vd->hasExternalStorage())1127    return true;1128 1129  // A variable cannot be both common and exist in a section.1130  if (vd->hasAttr<SectionAttr>())1131    return true;1132 1133  // A variable cannot be both common and exist in a section.1134  // We don't try to determine which is the right section in the front-end.1135  // If no specialized section name is applicable, it will resort to default.1136  if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||1137      vd->hasAttr<PragmaClangDataSectionAttr>() ||1138      vd->hasAttr<PragmaClangRelroSectionAttr>() ||1139      vd->hasAttr<PragmaClangRodataSectionAttr>())1140    return true;1141 1142  // Thread local vars aren't considered common linkage.1143  if (vd->getTLSKind())1144    return true;1145 1146  // Tentative definitions marked with WeakImportAttr are true definitions.1147  if (vd->hasAttr<WeakImportAttr>())1148    return true;1149 1150  // A variable cannot be both common and exist in a comdat.1151  if (shouldBeInCOMDAT(cgm, *vd))1152    return true;1153 1154  // Declarations with a required alignment do not have common linkage in MSVC1155  // mode.1156  if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {1157    if (vd->hasAttr<AlignedAttr>())1158      return true;1159    QualType varType = vd->getType();1160    if (astContext.isAlignmentRequired(varType))1161      return true;1162 1163    if (const auto *rd = varType->getAsRecordDecl()) {1164      for (const FieldDecl *fd : rd->fields()) {1165        if (fd->isBitField())1166          continue;1167        if (fd->hasAttr<AlignedAttr>())1168          return true;1169        if (astContext.isAlignmentRequired(fd->getType()))1170          return true;1171      }1172    }1173  }1174 1175  // Microsoft's link.exe doesn't support alignments greater than 32 bytes for1176  // common symbols, so symbols with greater alignment requirements cannot be1177  // common.1178  // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two1179  // alignments for common symbols via the aligncomm directive, so this1180  // restriction only applies to MSVC environments.1181  if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&1182      astContext.getTypeAlignIfKnown(vd->getType()) >1183          astContext.toBits(CharUnits::fromQuantity(32)))1184    return true;1185 1186  return false;1187}1188 1189cir::GlobalLinkageKind CIRGenModule::getCIRLinkageForDeclarator(1190    const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable) {1191  if (linkage == GVA_Internal)1192    return cir::GlobalLinkageKind::InternalLinkage;1193 1194  if (dd->hasAttr<WeakAttr>()) {1195    if (isConstantVariable)1196      return cir::GlobalLinkageKind::WeakODRLinkage;1197    return cir::GlobalLinkageKind::WeakAnyLinkage;1198  }1199 1200  if (const auto *fd = dd->getAsFunction())1201    if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)1202      return cir::GlobalLinkageKind::LinkOnceAnyLinkage;1203 1204  // We are guaranteed to have a strong definition somewhere else,1205  // so we can use available_externally linkage.1206  if (linkage == GVA_AvailableExternally)1207    return cir::GlobalLinkageKind::AvailableExternallyLinkage;1208 1209  // Note that Apple's kernel linker doesn't support symbol1210  // coalescing, so we need to avoid linkonce and weak linkages there.1211  // Normally, this means we just map to internal, but for explicit1212  // instantiations we'll map to external.1213 1214  // In C++, the compiler has to emit a definition in every translation unit1215  // that references the function.  We should use linkonce_odr because1216  // a) if all references in this translation unit are optimized away, we1217  // don't need to codegen it.  b) if the function persists, it needs to be1218  // merged with other definitions. c) C++ has the ODR, so we know the1219  // definition is dependable.1220  if (linkage == GVA_DiscardableODR)1221    return !astContext.getLangOpts().AppleKext1222               ? cir::GlobalLinkageKind::LinkOnceODRLinkage1223               : cir::GlobalLinkageKind::InternalLinkage;1224 1225  // An explicit instantiation of a template has weak linkage, since1226  // explicit instantiations can occur in multiple translation units1227  // and must all be equivalent. However, we are not allowed to1228  // throw away these explicit instantiations.1229  //1230  // CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,1231  // so say that CUDA templates are either external (for kernels) or internal.1232  // This lets llvm perform aggressive inter-procedural optimizations. For1233  // -fgpu-rdc case, device function calls across multiple TU's are allowed,1234  // therefore we need to follow the normal linkage paradigm.1235  if (linkage == GVA_StrongODR) {1236    if (getLangOpts().AppleKext)1237      return cir::GlobalLinkageKind::ExternalLinkage;1238    if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&1239        !getLangOpts().GPURelocatableDeviceCode)1240      return dd->hasAttr<CUDAGlobalAttr>()1241                 ? cir::GlobalLinkageKind::ExternalLinkage1242                 : cir::GlobalLinkageKind::InternalLinkage;1243    return cir::GlobalLinkageKind::WeakODRLinkage;1244  }1245 1246  // C++ doesn't have tentative definitions and thus cannot have common1247  // linkage.1248  if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&1249      !isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),1250                                 getCodeGenOpts().NoCommon))1251    return cir::GlobalLinkageKind::CommonLinkage;1252 1253  // selectany symbols are externally visible, so use weak instead of1254  // linkonce.  MSVC optimizes away references to const selectany globals, so1255  // all definitions should be the same and ODR linkage should be used.1256  // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx1257  if (dd->hasAttr<SelectAnyAttr>())1258    return cir::GlobalLinkageKind::WeakODRLinkage;1259 1260  // Otherwise, we have strong external linkage.1261  assert(linkage == GVA_StrongExternal);1262  return cir::GlobalLinkageKind::ExternalLinkage;1263}1264 1265/// This function is called when we implement a function with no prototype, e.g.1266/// "int foo() {}". If there are existing call uses of the old function in the1267/// module, this adjusts them to call the new function directly.1268///1269/// This is not just a cleanup: the always_inline pass requires direct calls to1270/// functions to be able to inline them.  If there is a bitcast in the way, it1271/// won't inline them. Instcombine normally deletes these calls, but it isn't1272/// run at -O0.1273void CIRGenModule::replaceUsesOfNonProtoTypeWithRealFunction(1274    mlir::Operation *old, cir::FuncOp newFn) {1275  // If we're redefining a global as a function, don't transform it.1276  auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);1277  if (!oldFn)1278    return;1279 1280  // TODO(cir): this RAUW ignores the features below.1281  assert(!cir::MissingFeatures::opFuncExceptions());1282  assert(!cir::MissingFeatures::opFuncParameterAttributes());1283  assert(!cir::MissingFeatures::opFuncOperandBundles());1284  if (oldFn->getAttrs().size() <= 1)1285    errorNYI(old->getLoc(),1286             "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");1287 1288  // Mark new function as originated from a no-proto declaration.1289  newFn.setNoProto(oldFn.getNoProto());1290 1291  // Iterate through all calls of the no-proto function.1292  std::optional<mlir::SymbolTable::UseRange> symUses =1293      oldFn.getSymbolUses(oldFn->getParentOp());1294  for (const mlir::SymbolTable::SymbolUse &use : symUses.value()) {1295    mlir::OpBuilder::InsertionGuard guard(builder);1296 1297    if (auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {1298      builder.setInsertionPoint(noProtoCallOp);1299 1300      // Patch call type with the real function type.1301      cir::CallOp realCallOp = builder.createCallOp(1302          noProtoCallOp.getLoc(), newFn, noProtoCallOp.getOperands());1303 1304      // Replace old no proto call with fixed call.1305      noProtoCallOp.replaceAllUsesWith(realCallOp);1306      noProtoCallOp.erase();1307    } else if (auto getGlobalOp =1308                   mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {1309      // Replace type1310      getGlobalOp.getAddr().setType(1311          cir::PointerType::get(newFn.getFunctionType()));1312    } else {1313      errorNYI(use.getUser()->getLoc(),1314               "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use");1315    }1316  }1317}1318 1319cir::GlobalLinkageKind1320CIRGenModule::getCIRLinkageVarDefinition(const VarDecl *vd, bool isConstant) {1321  assert(!isConstant && "constant variables NYI");1322  GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);1323  return getCIRLinkageForDeclarator(vd, linkage, isConstant);1324}1325 1326cir::GlobalLinkageKind CIRGenModule::getFunctionLinkage(GlobalDecl gd) {1327  const auto *d = cast<FunctionDecl>(gd.getDecl());1328 1329  GVALinkage linkage = astContext.GetGVALinkageForFunction(d);1330 1331  if (const auto *dtor = dyn_cast<CXXDestructorDecl>(d))1332    return getCXXABI().getCXXDestructorLinkage(linkage, dtor, gd.getDtorType());1333 1334  return getCIRLinkageForDeclarator(d, linkage, /*isConstantVariable=*/false);1335}1336 1337static cir::GlobalOp1338generateStringLiteral(mlir::Location loc, mlir::TypedAttr c,1339                      cir::GlobalLinkageKind lt, CIRGenModule &cgm,1340                      StringRef globalName, CharUnits alignment) {1341  assert(!cir::MissingFeatures::addressSpace());1342 1343  // Create a global variable for this string1344  // FIXME(cir): check for insertion point in module level.1345  cir::GlobalOp gv = CIRGenModule::createGlobalOp(1346      cgm, loc, globalName, c.getType(), !cgm.getLangOpts().WritableStrings);1347 1348  // Set up extra information and add to the module1349  gv.setAlignmentAttr(cgm.getSize(alignment));1350  gv.setLinkageAttr(1351      cir::GlobalLinkageKindAttr::get(cgm.getBuilder().getContext(), lt));1352  assert(!cir::MissingFeatures::opGlobalThreadLocal());1353  assert(!cir::MissingFeatures::opGlobalUnnamedAddr());1354  CIRGenModule::setInitializer(gv, c);1355  if (gv.isWeakForLinker()) {1356    assert(cgm.supportsCOMDAT() && "Only COFF uses weak string literals");1357    gv.setComdat(true);1358  }1359  cgm.setDSOLocal(static_cast<mlir::Operation *>(gv));1360  return gv;1361}1362 1363// LLVM IR automatically uniques names when new llvm::GlobalVariables are1364// created. This is handy, for example, when creating globals for string1365// literals. Since we don't do that when creating cir::GlobalOp's, we need1366// a mechanism to generate a unique name in advance.1367//1368// For now, this mechanism is only used in cases where we know that the1369// name is compiler-generated, so we don't use the MLIR symbol table for1370// the lookup.1371std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {1372  // If this is the first time we've generated a name for this basename, use1373  // it as is and start a counter for this base name.1374  auto it = cgGlobalNames.find(baseName);1375  if (it == cgGlobalNames.end()) {1376    cgGlobalNames[baseName] = 1;1377    return baseName;1378  }1379 1380  std::string result =1381      baseName + "." + std::to_string(cgGlobalNames[baseName]++);1382  // There should not be any symbol with this name in the module.1383  assert(!mlir::SymbolTable::lookupSymbolIn(theModule, result));1384  return result;1385}1386 1387/// Return a pointer to a constant array for the given string literal.1388cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,1389                                                      StringRef name) {1390  CharUnits alignment =1391      astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);1392 1393  mlir::Attribute c = getConstantArrayFromStringLiteral(s);1394 1395  cir::GlobalOp gv;1396  if (!getLangOpts().WritableStrings && constantStringMap.count(c)) {1397    gv = constantStringMap[c];1398    // The bigger alignment always wins.1399    if (!gv.getAlignment() ||1400        uint64_t(alignment.getQuantity()) > *gv.getAlignment())1401      gv.setAlignmentAttr(getSize(alignment));1402  } else {1403    // Mangle the string literal if that's how the ABI merges duplicate strings.1404    // Don't do it if they are writable, since we don't want writes in one TU to1405    // affect strings in another.1406    if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&1407        !getLangOpts().WritableStrings) {1408      errorNYI(s->getSourceRange(),1409               "getGlobalForStringLiteral: mangle string literals");1410    }1411 1412    // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so1413    // we need to do that explicitly.1414    std::string uniqueName = getUniqueGlobalName(name.str());1415    mlir::Location loc = getLoc(s->getSourceRange());1416    auto typedC = llvm::cast<mlir::TypedAttr>(c);1417    gv = generateStringLiteral(loc, typedC,1418                               cir::GlobalLinkageKind::PrivateLinkage, *this,1419                               uniqueName, alignment);1420    setDSOLocal(static_cast<mlir::Operation *>(gv));1421    constantStringMap[c] = gv;1422 1423    assert(!cir::MissingFeatures::sanitizers());1424  }1425  return gv;1426}1427 1428/// Return a pointer to a constant array for the given string literal.1429cir::GlobalViewAttr1430CIRGenModule::getAddrOfConstantStringFromLiteral(const StringLiteral *s,1431                                                 StringRef name) {1432  cir::GlobalOp gv = getGlobalForStringLiteral(s, name);1433  auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());1434  assert(arrayTy && "String literal must be array");1435  assert(!cir::MissingFeatures::addressSpace());1436  cir::PointerType ptrTy = getBuilder().getPointerTo(arrayTy.getElementType());1437 1438  return builder.getGlobalViewAttr(ptrTy, gv);1439}1440 1441// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.1442LangAS CIRGenModule::getLangTempAllocaAddressSpace() const {1443  if (getLangOpts().OpenCL)1444    return LangAS::opencl_private;1445 1446  // For temporaries inside functions, CUDA treats them as normal variables.1447  // LangAS::cuda_device, on the other hand, is reserved for those variables1448  // explicitly marked with __device__.1449  if (getLangOpts().CUDAIsDevice)1450    return LangAS::Default;1451 1452  if (getLangOpts().SYCLIsDevice ||1453      (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice))1454    errorNYI("SYCL or OpenMP temp address space");1455  return LangAS::Default;1456}1457 1458void CIRGenModule::emitExplicitCastExprType(const ExplicitCastExpr *e,1459                                            CIRGenFunction *cgf) {1460  if (cgf && e->getType()->isVariablyModifiedType())1461    cgf->emitVariablyModifiedType(e->getType());1462 1463  assert(!cir::MissingFeatures::generateDebugInfo() &&1464         "emitExplicitCastExprType");1465}1466 1467void CIRGenModule::emitDeclContext(const DeclContext *dc) {1468  for (Decl *decl : dc->decls()) {1469    // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope1470    // are themselves considered "top-level", so EmitTopLevelDecl on an1471    // ObjCImplDecl does not recursively visit them. We need to do that in1472    // case they're nested inside another construct (LinkageSpecDecl /1473    // ExportDecl) that does stop them from being considered "top-level".1474    if (auto *oid = dyn_cast<ObjCImplDecl>(decl))1475      errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");1476 1477    emitTopLevelDecl(decl);1478  }1479}1480 1481// Emit code for a single top level declaration.1482void CIRGenModule::emitTopLevelDecl(Decl *decl) {1483 1484  // Ignore dependent declarations.1485  if (decl->isTemplated())1486    return;1487 1488  switch (decl->getKind()) {1489  default:1490    errorNYI(decl->getBeginLoc(), "declaration of kind",1491             decl->getDeclKindName());1492    break;1493 1494  case Decl::CXXConversion:1495  case Decl::CXXMethod:1496  case Decl::Function: {1497    auto *fd = cast<FunctionDecl>(decl);1498    // Consteval functions shouldn't be emitted.1499    if (!fd->isConsteval())1500      emitGlobal(fd);1501    break;1502  }1503 1504  case Decl::Var:1505  case Decl::Decomposition:1506  case Decl::VarTemplateSpecialization: {1507    auto *vd = cast<VarDecl>(decl);1508    if (isa<DecompositionDecl>(decl)) {1509      errorNYI(decl->getSourceRange(), "global variable decompositions");1510      break;1511    }1512    emitGlobal(vd);1513    break;1514  }1515  case Decl::OpenACCRoutine:1516    emitGlobalOpenACCRoutineDecl(cast<OpenACCRoutineDecl>(decl));1517    break;1518  case Decl::OpenACCDeclare:1519    emitGlobalOpenACCDeclareDecl(cast<OpenACCDeclareDecl>(decl));1520    break;1521  case Decl::Enum:1522  case Decl::Using:          // using X; [C++]1523  case Decl::UsingDirective: // using namespace X; [C++]1524  case Decl::UsingEnum:      // using enum X; [C++]1525  case Decl::NamespaceAlias:1526  case Decl::Typedef:1527  case Decl::TypeAlias: // using foo = bar; [C++11]1528  case Decl::Record:1529    assert(!cir::MissingFeatures::generateDebugInfo());1530    break;1531 1532  // No code generation needed.1533  case Decl::ClassTemplate:1534  case Decl::Concept:1535  case Decl::CXXDeductionGuide:1536  case Decl::Empty:1537  case Decl::FunctionTemplate:1538  case Decl::StaticAssert:1539  case Decl::TypeAliasTemplate:1540  case Decl::UsingShadow:1541  case Decl::VarTemplate:1542  case Decl::VarTemplatePartialSpecialization:1543    break;1544 1545  case Decl::CXXConstructor:1546    getCXXABI().emitCXXConstructors(cast<CXXConstructorDecl>(decl));1547    break;1548  case Decl::CXXDestructor:1549    getCXXABI().emitCXXDestructors(cast<CXXDestructorDecl>(decl));1550    break;1551 1552  // C++ Decls1553  case Decl::LinkageSpec:1554  case Decl::Namespace:1555    emitDeclContext(Decl::castToDeclContext(decl));1556    break;1557 1558  case Decl::ClassTemplateSpecialization:1559  case Decl::CXXRecord: {1560    CXXRecordDecl *crd = cast<CXXRecordDecl>(decl);1561    assert(!cir::MissingFeatures::generateDebugInfo());1562    for (auto *childDecl : crd->decls())1563      if (isa<VarDecl, CXXRecordDecl, EnumDecl, OpenACCDeclareDecl>(childDecl))1564        emitTopLevelDecl(childDecl);1565    break;1566  }1567 1568  case Decl::FileScopeAsm:1569    // File-scope asm is ignored during device-side CUDA compilation.1570    if (langOpts.CUDA && langOpts.CUDAIsDevice)1571      break;1572    // File-scope asm is ignored during device-side OpenMP compilation.1573    if (langOpts.OpenMPIsTargetDevice)1574      break;1575    // File-scope asm is ignored during device-side SYCL compilation.1576    if (langOpts.SYCLIsDevice)1577      break;1578    auto *file_asm = cast<FileScopeAsmDecl>(decl);1579    std::string line = file_asm->getAsmString();1580    globalScopeAsm.push_back(builder.getStringAttr(line));1581    break;1582  }1583}1584 1585void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {1586  // Recompute visibility when updating initializer.1587  op.setInitialValueAttr(value);1588  assert(!cir::MissingFeatures::opGlobalVisibility());1589}1590 1591std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(1592    GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,1593    bool dontDefer, ForDefinition_t isForDefinition) {1594  auto *md = cast<CXXMethodDecl>(gd.getDecl());1595 1596  if (isa<CXXDestructorDecl>(md)) {1597    // Always alias equivalent complete destructors to base destructors in the1598    // MS ABI.1599    if (getTarget().getCXXABI().isMicrosoft() &&1600        gd.getDtorType() == Dtor_Complete &&1601        md->getParent()->getNumVBases() == 0)1602      errorNYI(md->getSourceRange(),1603               "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");1604  }1605 1606  if (!fnType) {1607    if (!fnInfo)1608      fnInfo = &getTypes().arrangeCXXStructorDeclaration(gd);1609    fnType = getTypes().getFunctionType(*fnInfo);1610  }1611 1612  auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,1613                                   /*ForVtable=*/false, dontDefer,1614                                   /*IsThunk=*/false, isForDefinition);1615 1616  return {fnType, fn};1617}1618 1619cir::FuncOp CIRGenModule::getAddrOfFunction(clang::GlobalDecl gd,1620                                            mlir::Type funcType, bool forVTable,1621                                            bool dontDefer,1622                                            ForDefinition_t isForDefinition) {1623  assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&1624         "consteval function should never be emitted");1625 1626  if (!funcType) {1627    const auto *fd = cast<FunctionDecl>(gd.getDecl());1628    funcType = convertType(fd->getType());1629  }1630 1631  // Devirtualized destructor calls may come through here instead of via1632  // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead1633  // of the complete destructor when necessary.1634  if (const auto *dd = dyn_cast<CXXDestructorDecl>(gd.getDecl())) {1635    if (getTarget().getCXXABI().isMicrosoft() &&1636        gd.getDtorType() == Dtor_Complete &&1637        dd->getParent()->getNumVBases() == 0)1638      errorNYI(dd->getSourceRange(),1639               "getAddrOfFunction: MS ABI complete destructor");1640  }1641 1642  StringRef mangledName = getMangledName(gd);1643  cir::FuncOp func =1644      getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,1645                             /*isThunk=*/false, isForDefinition);1646  return func;1647}1648 1649static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,1650                                      const NamedDecl *nd) {1651  SmallString<256> buffer;1652 1653  llvm::raw_svector_ostream out(buffer);1654  MangleContext &mc = cgm.getCXXABI().getMangleContext();1655 1656  assert(!cir::MissingFeatures::moduleNameHash());1657 1658  if (mc.shouldMangleDeclName(nd)) {1659    mc.mangleName(gd.getWithDecl(nd), out);1660  } else {1661    IdentifierInfo *ii = nd->getIdentifier();1662    assert(ii && "Attempt to mangle unnamed decl.");1663 1664    const auto *fd = dyn_cast<FunctionDecl>(nd);1665    if (fd &&1666        fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {1667      cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");1668    } else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&1669               gd.getKernelReferenceKind() == KernelReferenceKind::Stub) {1670      cgm.errorNYI(nd->getSourceRange(), "getMangledName: CUDA device stub");1671    }1672    out << ii->getName();1673  }1674 1675  // Check if the module name hash should be appended for internal linkage1676  // symbols. This should come before multi-version target suffixes are1677  // appendded. This is to keep the name and module hash suffix of the internal1678  // linkage function together. The unique suffix should only be added when name1679  // mangling is done to make sure that the final name can be properly1680  // demangled. For example, for C functions without prototypes, name mangling1681  // is not done and the unique suffix should not be appended then.1682  assert(!cir::MissingFeatures::moduleNameHash());1683 1684  if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {1685    if (fd->isMultiVersion()) {1686      cgm.errorNYI(nd->getSourceRange(),1687                   "getMangledName: multi-version functions");1688    }1689  }1690  if (cgm.getLangOpts().GPURelocatableDeviceCode) {1691    cgm.errorNYI(nd->getSourceRange(),1692                 "getMangledName: GPU relocatable device code");1693  }1694 1695  return std::string(out.str());1696}1697 1698StringRef CIRGenModule::getMangledName(GlobalDecl gd) {1699  GlobalDecl canonicalGd = gd.getCanonicalDecl();1700 1701  // Some ABIs don't have constructor variants. Make sure that base and complete1702  // constructors get mangled the same.1703  if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {1704    if (!getTarget().getCXXABI().hasConstructorVariants()) {1705      errorNYI(cd->getSourceRange(),1706               "getMangledName: C++ constructor without variants");1707      return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();1708    }1709  }1710 1711  // Keep the first result in the case of a mangling collision.1712  const auto *nd = cast<NamedDecl>(gd.getDecl());1713  std::string mangledName = getMangledNameImpl(*this, gd, nd);1714 1715  auto result = manglings.insert(std::make_pair(mangledName, gd));1716  return mangledDeclNames[canonicalGd] = result.first->first();1717}1718 1719void CIRGenModule::emitTentativeDefinition(const VarDecl *d) {1720  assert(!d->getInit() && "Cannot emit definite definitions here!");1721 1722  StringRef mangledName = getMangledName(d);1723  mlir::Operation *gv = getGlobalValue(mangledName);1724 1725  // If we already have a definition, not declaration, with the same mangled1726  // name, emitting of declaration is not required (and would actually overwrite1727  // the emitted definition).1728  if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())1729    return;1730 1731  // If we have not seen a reference to this variable yet, place it into the1732  // deferred declarations table to be emitted if needed later.1733  if (!mustBeEmitted(d) && !gv) {1734    deferredDecls[mangledName] = d;1735    return;1736  }1737 1738  // The tentative definition is the only definition.1739  emitGlobalVarDefinition(d);1740}1741 1742bool CIRGenModule::mustBeEmitted(const ValueDecl *global) {1743  // Never defer when EmitAllDecls is specified.1744  if (langOpts.EmitAllDecls)1745    return true;1746 1747  const auto *vd = dyn_cast<VarDecl>(global);1748  if (vd &&1749      ((codeGenOpts.KeepPersistentStorageVariables &&1750        (vd->getStorageDuration() == SD_Static ||1751         vd->getStorageDuration() == SD_Thread)) ||1752       (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() == SD_Static &&1753        vd->getType().isConstQualified())))1754    return true;1755 1756  return getASTContext().DeclMustBeEmitted(global);1757}1758 1759bool CIRGenModule::mayBeEmittedEagerly(const ValueDecl *global) {1760  // In OpenMP 5.0 variables and function may be marked as1761  // device_type(host/nohost) and we should not emit them eagerly unless we sure1762  // that they must be emitted on the host/device. To be sure we need to have1763  // seen a declare target with an explicit mentioning of the function, we know1764  // we have if the level of the declare target attribute is -1. Note that we1765  // check somewhere else if we should emit this at all.1766  if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {1767    std::optional<OMPDeclareTargetDeclAttr *> activeAttr =1768        OMPDeclareTargetDeclAttr::getActiveAttr(global);1769    if (!activeAttr || (*activeAttr)->getLevel() != (unsigned)-1)1770      return false;1771  }1772 1773  const auto *fd = dyn_cast<FunctionDecl>(global);1774  if (fd) {1775    // Implicit template instantiations may change linkage if they are later1776    // explicitly instantiated, so they should not be emitted eagerly.1777    if (fd->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)1778      return false;1779    // Defer until all versions have been semantically checked.1780    if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())1781      return false;1782    if (langOpts.SYCLIsDevice) {1783      errorNYI(fd->getSourceRange(), "mayBeEmittedEagerly: SYCL");1784      return false;1785    }1786  }1787  const auto *vd = dyn_cast<VarDecl>(global);1788  if (vd)1789    if (astContext.getInlineVariableDefinitionKind(vd) ==1790        ASTContext::InlineVariableDefinitionKind::WeakUnknown)1791      // A definition of an inline constexpr static data member may change1792      // linkage later if it's redeclared outside the class.1793      return false;1794 1795  // If OpenMP is enabled and threadprivates must be generated like TLS, delay1796  // codegen for global variables, because they may be marked as threadprivate.1797  if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&1798      astContext.getTargetInfo().isTLSSupported() && isa<VarDecl>(global) &&1799      !global->getType().isConstantStorage(astContext, false, false) &&1800      !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))1801    return false;1802 1803  assert((fd || vd) &&1804         "Only FunctionDecl and VarDecl should hit this path so far.");1805  return true;1806}1807 1808static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,1809                                 cir::CIRGlobalValueInterface gv) {1810  if (gv.hasLocalLinkage())1811    return true;1812 1813  if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())1814    return true;1815 1816  // DLLImport explicitly marks the GV as external.1817  // so it shouldn't be dso_local1818  // But we don't have the info set now1819  assert(!cir::MissingFeatures::opGlobalDLLImportExport());1820 1821  const llvm::Triple &tt = cgm.getTriple();1822  const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();1823  if (tt.isOSCygMing()) {1824    // In MinGW and Cygwin, variables without DLLImport can still be1825    // automatically imported from a DLL by the linker; don't mark variables1826    // that potentially could come from another DLL as DSO local.1827 1828    // With EmulatedTLS, TLS variables can be autoimported from other DLLs1829    // (and this actually happens in the public interface of libstdc++), so1830    // such variables can't be marked as DSO local. (Native TLS variables1831    // can't be dllimported at all, though.)1832    cgm.errorNYI("shouldAssumeDSOLocal: MinGW");1833  }1834 1835  // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols1836  // remain unresolved in the link, they can be resolved to zero, which is1837  // outside the current DSO.1838  if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())1839    return false;1840 1841  // Every other GV is local on COFF.1842  // Make an exception for windows OS in the triple: Some firmware builds use1843  // *-win32-macho triples. This (accidentally?) produced windows relocations1844  // without GOT tables in older clang versions; Keep this behaviour.1845  // FIXME: even thread local variables?1846  if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))1847    return true;1848 1849  // Only handle COFF and ELF for now.1850  if (!tt.isOSBinFormatELF())1851    return false;1852 1853  llvm::Reloc::Model rm = cgOpts.RelocationModel;1854  const LangOptions &lOpts = cgm.getLangOpts();1855  if (rm != llvm::Reloc::Static && !lOpts.PIE) {1856    // On ELF, if -fno-semantic-interposition is specified and the target1857    // supports local aliases, there will be neither CC11858    // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set1859    // dso_local on the function if using a local alias is preferable (can avoid1860    // PLT indirection).1861    if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))1862      return false;1863    return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);1864  }1865 1866  // A definition cannot be preempted from an executable.1867  if (!gv.isDeclarationForLinker())1868    return true;1869 1870  // Most PIC code sequences that assume that a symbol is local cannot produce a1871  // 0 if it turns out the symbol is undefined. While this is ABI and relocation1872  // depended, it seems worth it to handle it here.1873  if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())1874    return false;1875 1876  // PowerPC64 prefers TOC indirection to avoid copy relocations.1877  if (tt.isPPC64())1878    return false;1879 1880  if (cgOpts.DirectAccessExternalData) {1881    // If -fdirect-access-external-data (default for -fno-pic), set dso_local1882    // for non-thread-local variables. If the symbol is not defined in the1883    // executable, a copy relocation will be needed at link time. dso_local is1884    // excluded for thread-local variables because they generally don't support1885    // copy relocations.1886    if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {1887      // Assume variables are not thread-local until that support is added.1888      assert(!cir::MissingFeatures::opGlobalThreadLocal());1889      return true;1890    }1891 1892    // -fno-pic sets dso_local on a function declaration to allow direct1893    // accesses when taking its address (similar to a data symbol). If the1894    // function is not defined in the executable, a canonical PLT entry will be1895    // needed at link time. -fno-direct-access-external-data can avoid the1896    // canonical PLT entry. We don't generalize this condition to -fpie/-fpic as1897    // it could just cause trouble without providing perceptible benefits.1898    if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)1899      return true;1900  }1901 1902  // If we can use copy relocations we can assume it is local.1903 1904  // Otherwise don't assume it is local.1905 1906  return false;1907}1908 1909void CIRGenModule::setGlobalVisibility(mlir::Operation *gv,1910                                       const NamedDecl *d) const {1911  assert(!cir::MissingFeatures::opGlobalVisibility());1912}1913 1914void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {1915  gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));1916}1917 1918void CIRGenModule::setDSOLocal(mlir::Operation *op) const {1919  if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))1920    setDSOLocal(globalValue);1921}1922 1923void CIRGenModule::setGVProperties(mlir::Operation *op,1924                                   const NamedDecl *d) const {1925  assert(!cir::MissingFeatures::opGlobalDLLImportExport());1926  setGVPropertiesAux(op, d);1927}1928 1929void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,1930                                      const NamedDecl *d) const {1931  setGlobalVisibility(op, d);1932  setDSOLocal(op);1933  assert(!cir::MissingFeatures::opGlobalPartition());1934}1935 1936void CIRGenModule::setFunctionAttributes(GlobalDecl globalDecl,1937                                         cir::FuncOp func,1938                                         bool isIncompleteFunction,1939                                         bool isThunk) {1940  // NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we1941  // represent them in dedicated ops. The correct attributes are ensured during1942  // translation to LLVM. Thus, we don't need to check for them here.1943 1944  assert(!cir::MissingFeatures::setFunctionAttributes());1945  assert(!cir::MissingFeatures::setTargetAttributes());1946 1947  // TODO(cir): This needs a lot of work to better match CodeGen. That1948  // ultimately ends up in setGlobalVisibility, which already has the linkage of1949  // the LLVM GV (corresponding to our FuncOp) computed, so it doesn't have to1950  // recompute it here. This is a minimal fix for now.1951  if (!isLocalLinkage(getFunctionLinkage(globalDecl))) {1952    const Decl *decl = globalDecl.getDecl();1953    func.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(decl));1954  }1955 1956  // If we plan on emitting this inline builtin, we can't treat it as a builtin.1957  const auto *fd = cast<FunctionDecl>(globalDecl.getDecl());1958  if (fd->isInlineBuiltinDeclaration()) {1959    const FunctionDecl *fdBody;1960    bool hasBody = fd->hasBody(fdBody);1961    (void)hasBody;1962    assert(hasBody && "Inline builtin declarations should always have an "1963                      "available body!");1964    assert(!cir::MissingFeatures::attributeNoBuiltin());1965  }1966}1967 1968void CIRGenModule::setCIRFunctionAttributesForDefinition(1969    const clang::FunctionDecl *decl, cir::FuncOp f) {1970  assert(!cir::MissingFeatures::opFuncUnwindTablesAttr());1971  assert(!cir::MissingFeatures::stackProtector());1972 1973  std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();1974  bool isNoInline =1975      existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;1976  bool isAlwaysInline = existingInlineKind &&1977                        *existingInlineKind == cir::InlineKind::AlwaysInline;1978 1979  if (!decl) {1980    assert(!cir::MissingFeatures::hlsl());1981 1982    if (!isAlwaysInline &&1983        codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {1984      // If inlining is disabled and we don't have a declaration to control1985      // inlining, mark the function as 'noinline' unless it is explicitly1986      // marked as 'alwaysinline'.1987      f.setInlineKindAttr(1988          cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));1989    }1990 1991    return;1992  }1993 1994  assert(!cir::MissingFeatures::opFuncArmStreamingAttr());1995  assert(!cir::MissingFeatures::opFuncArmNewAttr());1996  assert(!cir::MissingFeatures::opFuncOptNoneAttr());1997  assert(!cir::MissingFeatures::opFuncMinSizeAttr());1998  assert(!cir::MissingFeatures::opFuncNakedAttr());1999  assert(!cir::MissingFeatures::opFuncNoDuplicateAttr());2000  assert(!cir::MissingFeatures::hlsl());2001 2002  // Handle inline attributes2003  if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {2004    // Add noinline if the function isn't always_inline.2005    f.setInlineKindAttr(2006        cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));2007  } else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {2008    // Don't override AlwaysInline with NoInline, or vice versa, since we can't2009    // specify both in IR.2010    f.setInlineKindAttr(2011        cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::AlwaysInline));2012  } else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {2013    // If inlining is disabled, force everything that isn't always_inline2014    // to carry an explicit noinline attribute.2015    if (!isAlwaysInline) {2016      f.setInlineKindAttr(2017          cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));2018    }2019  } else {2020    // Otherwise, propagate the inline hint attribute and potentially use its2021    // absence to mark things as noinline.2022    // Search function and template pattern redeclarations for inline.2023    if (auto *fd = dyn_cast<FunctionDecl>(decl)) {2024      // TODO: Share this checkForInline implementation with classic codegen.2025      // This logic is likely to change over time, so sharing would help ensure2026      // consistency.2027      auto checkForInline = [](const FunctionDecl *decl) {2028        auto checkRedeclForInline = [](const FunctionDecl *redecl) {2029          return redecl->isInlineSpecified();2030        };2031        if (any_of(decl->redecls(), checkRedeclForInline))2032          return true;2033        const FunctionDecl *pattern = decl->getTemplateInstantiationPattern();2034        if (!pattern)2035          return false;2036        return any_of(pattern->redecls(), checkRedeclForInline);2037      };2038      if (checkForInline(fd)) {2039        f.setInlineKindAttr(cir::InlineAttr::get(&getMLIRContext(),2040                                                 cir::InlineKind::InlineHint));2041      } else if (codeGenOpts.getInlining() ==2042                     CodeGenOptions::OnlyHintInlining &&2043                 !fd->isInlined() && !isAlwaysInline) {2044        f.setInlineKindAttr(2045            cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));2046      }2047    }2048  }2049 2050  assert(!cir::MissingFeatures::opFuncColdHotAttr());2051}2052 2053cir::FuncOp CIRGenModule::getOrCreateCIRFunction(2054    StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,2055    bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,2056    mlir::ArrayAttr extraAttrs) {2057  const Decl *d = gd.getDecl();2058 2059  if (isThunk)2060    errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: thunk");2061 2062  // In what follows, we continue past 'errorNYI' as if nothing happened because2063  // the rest of the implementation is better than doing nothing.2064 2065  if (const auto *fd = cast_or_null<FunctionDecl>(d)) {2066    // For the device mark the function as one that should be emitted.2067    if (getLangOpts().OpenMPIsTargetDevice && fd->isDefined() && !dontDefer &&2068        !isForDefinition)2069      errorNYI(fd->getSourceRange(),2070               "getOrCreateCIRFunction: OpenMP target function");2071 2072    // Any attempts to use a MultiVersion function should result in retrieving2073    // the iFunc instead. Name mangling will handle the rest of the changes.2074    if (fd->isMultiVersion())2075      errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");2076  }2077 2078  // Lookup the entry, lazily creating it if necessary.2079  mlir::Operation *entry = getGlobalValue(mangledName);2080  if (entry) {2081    assert(mlir::isa<cir::FuncOp>(entry));2082 2083    assert(!cir::MissingFeatures::weakRefReference());2084 2085    // Handle dropped DLL attributes.2086    if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {2087      assert(!cir::MissingFeatures::setDLLStorageClass());2088      setDSOLocal(entry);2089    }2090 2091    // If there are two attempts to define the same mangled name, issue an2092    // error.2093    auto fn = cast<cir::FuncOp>(entry);2094    if (isForDefinition && fn && !fn.isDeclaration()) {2095      errorNYI(d->getSourceRange(), "Duplicate function definition");2096    }2097    if (fn && fn.getFunctionType() == funcType) {2098      return fn;2099    }2100 2101    if (!isForDefinition) {2102      return fn;2103    }2104 2105    // TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.2106    // How will we support this?2107  }2108 2109  auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());2110  bool invalidLoc = !funcDecl ||2111                    funcDecl->getSourceRange().getBegin().isInvalid() ||2112                    funcDecl->getSourceRange().getEnd().isInvalid();2113  cir::FuncOp funcOp = createCIRFunction(2114      invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),2115      mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);2116 2117  // If we already created a function with the same mangled name (but different2118  // type) before, take its name and add it to the list of functions to be2119  // replaced with F at the end of CodeGen.2120  //2121  // This happens if there is a prototype for a function (e.g. "int f()") and2122  // then a definition of a different type (e.g. "int f(int x)").2123  if (entry) {2124 2125    // Fetch a generic symbol-defining operation and its uses.2126    auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);2127 2128    // This might be an implementation of a function without a prototype, in2129    // which case, try to do special replacement of calls which match the new2130    // prototype. The really key thing here is that we also potentially drop2131    // arguments from the call site so as to make a direct call, which makes the2132    // inliner happier and suppresses a number of optimizer warnings (!) about2133    // dropping arguments.2134    if (symbolOp.getSymbolUses(symbolOp->getParentOp()))2135      replaceUsesOfNonProtoTypeWithRealFunction(entry, funcOp);2136 2137    // Obliterate no-proto declaration.2138    entry->erase();2139  }2140 2141  if (d)2142    setFunctionAttributes(gd, funcOp, /*isIncompleteFunction=*/false, isThunk);2143 2144  // 'dontDefer' actually means don't move this to the deferredDeclsToEmit list.2145  if (dontDefer) {2146    // TODO(cir): This assertion will need an additional condition when we2147    // support incomplete functions.2148    assert(funcOp.getFunctionType() == funcType);2149    return funcOp;2150  }2151 2152  // All MSVC dtors other than the base dtor are linkonce_odr and delegate to2153  // each other bottoming out wiht the base dtor. Therefore we emit non-base2154  // dtors on usage, even if there is no dtor definition in the TU.2155  if (isa_and_nonnull<CXXDestructorDecl>(d) &&2156      getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),2157                                         gd.getDtorType()))2158    errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");2159 2160  // This is the first use or definition of a mangled name. If there is a2161  // deferred decl with this name, remember that we need to emit it at the end2162  // of the file.2163  auto ddi = deferredDecls.find(mangledName);2164  if (ddi != deferredDecls.end()) {2165    // Move the potentially referenced deferred decl to the2166    // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we2167    // don't need it anymore).2168    addDeferredDeclToEmit(ddi->second);2169    deferredDecls.erase(ddi);2170 2171    // Otherwise, there are cases we have to worry about where we're using a2172    // declaration for which we must emit a definition but where we might not2173    // find a top-level definition.2174    //   - member functions defined inline in their classes2175    //   - friend functions defined inline in some class2176    //   - special member functions with implicit definitions2177    // If we ever change our AST traversal to walk into class methods, this2178    // will be unnecessary.2179    //2180    // We also don't emit a definition for a function if it's going to be an2181    // entry in a vtable, unless it's already marked as used.2182  } else if (getLangOpts().CPlusPlus && d) {2183    // Look for a declaration that's lexically in a record.2184    for (const auto *fd = cast<FunctionDecl>(d)->getMostRecentDecl(); fd;2185         fd = fd->getPreviousDecl()) {2186      if (isa<CXXRecordDecl>(fd->getLexicalDeclContext())) {2187        if (fd->doesThisDeclarationHaveABody()) {2188          addDeferredDeclToEmit(gd.getWithDecl(fd));2189          break;2190        }2191      }2192    }2193  }2194 2195  return funcOp;2196}2197 2198cir::FuncOp2199CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,2200                                cir::FuncType funcType,2201                                const clang::FunctionDecl *funcDecl) {2202  cir::FuncOp func;2203  {2204    mlir::OpBuilder::InsertionGuard guard(builder);2205 2206    // Some global emissions are triggered while emitting a function, e.g.2207    // void s() { x.method() }2208    //2209    // Be sure to insert a new function before a current one.2210    CIRGenFunction *cgf = this->curCGF;2211    if (cgf)2212      builder.setInsertionPoint(cgf->curFn);2213 2214    func = cir::FuncOp::create(builder, loc, name, funcType);2215 2216    assert(!cir::MissingFeatures::opFuncAstDeclAttr());2217 2218    if (funcDecl && !funcDecl->hasPrototype())2219      func.setNoProto(true);2220 2221    assert(func.isDeclaration() && "expected empty body");2222 2223    // A declaration gets private visibility by default, but external linkage2224    // as the default linkage.2225    func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(2226        &getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));2227    mlir::SymbolTable::setSymbolVisibility(2228        func, mlir::SymbolTable::Visibility::Private);2229 2230    assert(!cir::MissingFeatures::opFuncExtraAttrs());2231 2232    // Mark C++ special member functions (Constructor, Destructor etc.)2233    setCXXSpecialMemberAttr(func, funcDecl);2234 2235    if (!cgf)2236      theModule.push_back(func);2237  }2238  return func;2239}2240 2241cir::FuncOp2242CIRGenModule::createCIRBuiltinFunction(mlir::Location loc, StringRef name,2243                                       cir::FuncType ty,2244                                       const clang::FunctionDecl *fd) {2245  cir::FuncOp fnOp = createCIRFunction(loc, name, ty, fd);2246  fnOp.setBuiltin(true);2247  return fnOp;2248}2249 2250static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor) {2251  if (ctor->isDefaultConstructor())2252    return cir::CtorKind::Default;2253  if (ctor->isCopyConstructor())2254    return cir::CtorKind::Copy;2255  if (ctor->isMoveConstructor())2256    return cir::CtorKind::Move;2257  return cir::CtorKind::Custom;2258}2259 2260static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method) {2261  if (method->isCopyAssignmentOperator())2262    return cir::AssignKind::Copy;2263  if (method->isMoveAssignmentOperator())2264    return cir::AssignKind::Move;2265  llvm_unreachable("not a copy or move assignment operator");2266}2267 2268void CIRGenModule::setCXXSpecialMemberAttr(2269    cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl) {2270  if (!funcDecl)2271    return;2272 2273  if (const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {2274    auto cxxDtor = cir::CXXDtorAttr::get(2275        convertType(getASTContext().getCanonicalTagType(dtor->getParent())),2276        dtor->isTrivial());2277    funcOp.setCxxSpecialMemberAttr(cxxDtor);2278    return;2279  }2280 2281  if (const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {2282    cir::CtorKind kind = getCtorKindFromDecl(ctor);2283    auto cxxCtor = cir::CXXCtorAttr::get(2284        convertType(getASTContext().getCanonicalTagType(ctor->getParent())),2285        kind, ctor->isTrivial());2286    funcOp.setCxxSpecialMemberAttr(cxxCtor);2287    return;2288  }2289 2290  const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);2291  if (method && (method->isCopyAssignmentOperator() ||2292                 method->isMoveAssignmentOperator())) {2293    cir::AssignKind assignKind = getAssignKindFromDecl(method);2294    auto cxxAssign = cir::CXXAssignAttr::get(2295        convertType(getASTContext().getCanonicalTagType(method->getParent())),2296        assignKind, method->isTrivial());2297    funcOp.setCxxSpecialMemberAttr(cxxAssign);2298    return;2299  }2300}2301 2302cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,2303                                                StringRef name, mlir::ArrayAttr,2304                                                [[maybe_unused]] bool isLocal,2305                                                bool assumeConvergent) {2306  if (assumeConvergent)2307    errorNYI("createRuntimeFunction: assumeConvergent");2308  if (isLocal)2309    errorNYI("createRuntimeFunction: local");2310 2311  cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),2312                                             /*forVtable=*/false);2313 2314  if (entry) {2315    // TODO(cir): set the attributes of the function.2316    assert(!cir::MissingFeatures::setLLVMFunctionFEnvAttributes());2317    assert(!cir::MissingFeatures::opFuncCallingConv());2318    assert(!cir::MissingFeatures::opGlobalDLLImportExport());2319    entry.setDSOLocal(true);2320  }2321 2322  return entry;2323}2324 2325mlir::SymbolTable::Visibility2326CIRGenModule::getMLIRVisibility(cir::GlobalOp op) {2327  // MLIR doesn't accept public symbols declarations (only2328  // definitions).2329  if (op.isDeclaration())2330    return mlir::SymbolTable::Visibility::Private;2331  return getMLIRVisibilityFromCIRLinkage(op.getLinkage());2332}2333 2334mlir::SymbolTable::Visibility2335CIRGenModule::getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind glk) {2336  switch (glk) {2337  case cir::GlobalLinkageKind::InternalLinkage:2338  case cir::GlobalLinkageKind::PrivateLinkage:2339    return mlir::SymbolTable::Visibility::Private;2340  case cir::GlobalLinkageKind::ExternalLinkage:2341  case cir::GlobalLinkageKind::ExternalWeakLinkage:2342  case cir::GlobalLinkageKind::LinkOnceODRLinkage:2343  case cir::GlobalLinkageKind::AvailableExternallyLinkage:2344  case cir::GlobalLinkageKind::CommonLinkage:2345  case cir::GlobalLinkageKind::WeakAnyLinkage:2346  case cir::GlobalLinkageKind::WeakODRLinkage:2347    return mlir::SymbolTable::Visibility::Public;2348  default: {2349    llvm::errs() << "visibility not implemented for '"2350                 << stringifyGlobalLinkageKind(glk) << "'\n";2351    assert(0 && "not implemented");2352  }2353  }2354  llvm_unreachable("linkage should be handled above!");2355}2356 2357cir::VisibilityKind CIRGenModule::getGlobalVisibilityKindFromClangVisibility(2358    clang::VisibilityAttr::VisibilityType visibility) {2359  switch (visibility) {2360  case clang::VisibilityAttr::VisibilityType::Default:2361    return cir::VisibilityKind::Default;2362  case clang::VisibilityAttr::VisibilityType::Hidden:2363    return cir::VisibilityKind::Hidden;2364  case clang::VisibilityAttr::VisibilityType::Protected:2365    return cir::VisibilityKind::Protected;2366  }2367  llvm_unreachable("unexpected visibility value");2368}2369 2370cir::VisibilityAttr2371CIRGenModule::getGlobalVisibilityAttrFromDecl(const Decl *decl) {2372  const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();2373  cir::VisibilityAttr cirVisibility =2374      cir::VisibilityAttr::get(&getMLIRContext());2375  if (va) {2376    cirVisibility = cir::VisibilityAttr::get(2377        &getMLIRContext(),2378        getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));2379  }2380  return cirVisibility;2381}2382 2383void CIRGenModule::release() {2384  emitDeferred();2385  applyReplacements();2386 2387  theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),2388                     builder.getArrayAttr(globalScopeAsm));2389 2390  // There's a lot of code that is not implemented yet.2391  assert(!cir::MissingFeatures::cgmRelease());2392}2393 2394void CIRGenModule::emitAliasForGlobal(StringRef mangledName,2395                                      mlir::Operation *op, GlobalDecl aliasGD,2396                                      cir::FuncOp aliasee,2397                                      cir::GlobalLinkageKind linkage) {2398 2399  auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());2400  assert(aliasFD && "expected FunctionDecl");2401 2402  // The aliasee function type is different from the alias one, this difference2403  // is specific to CIR because in LLVM the ptr types are already erased at this2404  // point.2405  const CIRGenFunctionInfo &fnInfo =2406      getTypes().arrangeCXXStructorDeclaration(aliasGD);2407  cir::FuncType fnType = getTypes().getFunctionType(fnInfo);2408 2409  cir::FuncOp alias =2410      createCIRFunction(getLoc(aliasGD.getDecl()->getSourceRange()),2411                        mangledName, fnType, aliasFD);2412  alias.setAliasee(aliasee.getName());2413  alias.setLinkage(linkage);2414  // Declarations cannot have public MLIR visibility, just mark them private2415  // but this really should have no meaning since CIR should not be using2416  // this information to derive linkage information.2417  mlir::SymbolTable::setSymbolVisibility(2418      alias, mlir::SymbolTable::Visibility::Private);2419 2420  // Alias constructors and destructors are always unnamed_addr.2421  assert(!cir::MissingFeatures::opGlobalUnnamedAddr());2422 2423  // Switch any previous uses to the alias.2424  if (op) {2425    errorNYI(aliasFD->getSourceRange(), "emitAliasForGlobal: previous uses");2426  } else {2427    // Name already set by createCIRFunction2428  }2429 2430  // Finally, set up the alias with its proper name and attributes.2431  setCommonAttributes(aliasGD, alias);2432}2433 2434mlir::Type CIRGenModule::convertType(QualType type) {2435  return genTypes.convertType(type);2436}2437 2438bool CIRGenModule::verifyModule() const {2439  // Verify the module after we have finished constructing it, this will2440  // check the structural properties of the IR and invoke any specific2441  // verifiers we have on the CIR operations.2442  return mlir::verify(theModule).succeeded();2443}2444 2445mlir::Attribute CIRGenModule::getAddrOfRTTIDescriptor(mlir::Location loc,2446                                                      QualType ty, bool forEh) {2447  // Return a bogus pointer if RTTI is disabled, unless it's for EH.2448  // FIXME: should we even be calling this method if RTTI is disabled2449  // and it's not for EH?2450  if (!shouldEmitRTTI(forEh))2451    return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());2452 2453  if (forEh && ty->isObjCObjectPointerType() &&2454      langOpts.ObjCRuntime.isGNUFamily()) {2455    errorNYI(loc, "getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");2456    return {};2457  }2458 2459  return getCXXABI().getAddrOfRTTIDescriptor(loc, ty);2460}2461 2462// TODO(cir): this can be shared with LLVM codegen.2463CharUnits CIRGenModule::computeNonVirtualBaseClassOffset(2464    const CXXRecordDecl *derivedClass,2465    llvm::iterator_range<CastExpr::path_const_iterator> path) {2466  CharUnits offset = CharUnits::Zero();2467 2468  const ASTContext &astContext = getASTContext();2469  const CXXRecordDecl *rd = derivedClass;2470 2471  for (const CXXBaseSpecifier *base : path) {2472    assert(!base->isVirtual() && "Should not see virtual bases here!");2473 2474    // Get the layout.2475    const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);2476 2477    const auto *baseDecl = base->getType()->castAsCXXRecordDecl();2478 2479    // Add the offset.2480    offset += layout.getBaseClassOffset(baseDecl);2481 2482    rd = baseDecl;2483  }2484 2485  return offset;2486}2487 2488DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,2489                                         llvm::StringRef feature) {2490  unsigned diagID = diags.getCustomDiagID(2491      DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");2492  return diags.Report(loc, diagID) << feature;2493}2494 2495DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,2496                                         llvm::StringRef feature) {2497  return errorNYI(loc.getBegin(), feature) << loc;2498}2499