Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenModule.cpp
213799 views
//===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This is the internal per-translation-unit state used for CIR translation.9//10//===----------------------------------------------------------------------===//1112#include "CIRGenModule.h"13#include "CIRGenCXXABI.h"14#include "CIRGenConstantEmitter.h"15#include "CIRGenFunction.h"1617#include "clang/AST/ASTContext.h"18#include "clang/AST/DeclBase.h"19#include "clang/AST/DeclOpenACC.h"20#include "clang/AST/GlobalDecl.h"21#include "clang/AST/RecordLayout.h"22#include "clang/Basic/SourceManager.h"23#include "clang/CIR/Dialect/IR/CIRDialect.h"24#include "clang/CIR/Interfaces/CIROpInterfaces.h"25#include "clang/CIR/MissingFeatures.h"2627#include "CIRGenFunctionInfo.h"28#include "mlir/IR/BuiltinOps.h"29#include "mlir/IR/Location.h"30#include "mlir/IR/MLIRContext.h"31#include "mlir/IR/Verifier.h"3233using namespace clang;34using namespace clang::CIRGen;3536static CIRGenCXXABI *createCXXABI(CIRGenModule &cgm) {37switch (cgm.getASTContext().getCXXABIKind()) {38case TargetCXXABI::GenericItanium:39case TargetCXXABI::GenericAArch64:40case TargetCXXABI::AppleARM64:41return CreateCIRGenItaniumCXXABI(cgm);4243case TargetCXXABI::Fuchsia:44case TargetCXXABI::GenericARM:45case TargetCXXABI::iOS:46case TargetCXXABI::WatchOS:47case TargetCXXABI::GenericMIPS:48case TargetCXXABI::WebAssembly:49case TargetCXXABI::XL:50case TargetCXXABI::Microsoft:51cgm.errorNYI("C++ ABI kind not yet implemented");52return nullptr;53}5455llvm_unreachable("invalid C++ ABI kind");56}5758CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,59clang::ASTContext &astContext,60const clang::CodeGenOptions &cgo,61DiagnosticsEngine &diags)62: builder(mlirContext, *this), astContext(astContext),63langOpts(astContext.getLangOpts()), codeGenOpts(cgo),64theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},65diags(diags), target(astContext.getTargetInfo()),66abi(createCXXABI(*this)), genTypes(*this) {6768// Initialize cached types69VoidTy = cir::VoidType::get(&getMLIRContext());70VoidPtrTy = cir::PointerType::get(VoidTy);71SInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);72SInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);73SInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);74SInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);75SInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);76UInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);77UInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);78UInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);79UInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);80UInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);81FP16Ty = cir::FP16Type::get(&getMLIRContext());82BFloat16Ty = cir::BF16Type::get(&getMLIRContext());83FloatTy = cir::SingleType::get(&getMLIRContext());84DoubleTy = cir::DoubleType::get(&getMLIRContext());85FP80Ty = cir::FP80Type::get(&getMLIRContext());86FP128Ty = cir::FP128Type::get(&getMLIRContext());8788PointerAlignInBytes =89astContext90.toCharUnitsFromBits(91astContext.getTargetInfo().getPointerAlign(LangAS::Default))92.getQuantity();9394// TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed95const unsigned sizeTypeSize =96astContext.getTypeSize(astContext.getSignedSizeType());97SizeAlignInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();98// In CIRGenTypeCache, UIntPtrTy and SizeType are fields of the same union99UIntPtrTy =100cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/false);101PtrDiffTy =102cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/true);103104theModule->setAttr(cir::CIRDialect::getTripleAttrName(),105builder.getStringAttr(getTriple().str()));106107if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)108theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),109cir::OptInfoAttr::get(&mlirContext,110cgo.OptimizationLevel,111cgo.OptimizeSize));112}113114CIRGenModule::~CIRGenModule() = default;115116/// FIXME: this could likely be a common helper and not necessarily related117/// with codegen.118/// Return the best known alignment for an unknown pointer to a119/// particular class.120CharUnits CIRGenModule::getClassPointerAlignment(const CXXRecordDecl *rd) {121if (!rd->hasDefinition())122return CharUnits::One(); // Hopefully won't be used anywhere.123124auto &layout = astContext.getASTRecordLayout(rd);125126// If the class is final, then we know that the pointer points to an127// object of that type and can use the full alignment.128if (rd->isEffectivelyFinal())129return layout.getAlignment();130131// Otherwise, we have to assume it could be a subclass.132return layout.getNonVirtualAlignment();133}134135CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t,136LValueBaseInfo *baseInfo) {137assert(!cir::MissingFeatures::opTBAA());138139// FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but140// that doesn't return the information we need to compute baseInfo.141142// Honor alignment typedef attributes even on incomplete types.143// We also honor them straight for C++ class types, even as pointees;144// there's an expressivity gap here.145if (const auto *tt = t->getAs<TypedefType>()) {146if (unsigned align = tt->getDecl()->getMaxAlignment()) {147if (baseInfo)148*baseInfo = LValueBaseInfo(AlignmentSource::AttributedType);149return astContext.toCharUnitsFromBits(align);150}151}152153// Analyze the base element type, so we don't get confused by incomplete154// array types.155t = astContext.getBaseElementType(t);156157if (t->isIncompleteType()) {158// We could try to replicate the logic from159// ASTContext::getTypeAlignIfKnown, but nothing uses the alignment if the160// type is incomplete, so it's impossible to test. We could try to reuse161// getTypeAlignIfKnown, but that doesn't return the information we need162// to set baseInfo. So just ignore the possibility that the alignment is163// greater than one.164if (baseInfo)165*baseInfo = LValueBaseInfo(AlignmentSource::Type);166return CharUnits::One();167}168169if (baseInfo)170*baseInfo = LValueBaseInfo(AlignmentSource::Type);171172CharUnits alignment;173if (t.getQualifiers().hasUnaligned()) {174alignment = CharUnits::One();175} else {176assert(!cir::MissingFeatures::alignCXXRecordDecl());177alignment = astContext.getTypeAlignInChars(t);178}179180// Cap to the global maximum type alignment unless the alignment181// was somehow explicit on the type.182if (unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {183if (alignment.getQuantity() > maxAlign &&184!astContext.isAlignmentRequired(t))185alignment = CharUnits::fromQuantity(maxAlign);186}187return alignment;188}189190const TargetCIRGenInfo &CIRGenModule::getTargetCIRGenInfo() {191if (theTargetCIRGenInfo)192return *theTargetCIRGenInfo;193194const llvm::Triple &triple = getTarget().getTriple();195switch (triple.getArch()) {196default:197assert(!cir::MissingFeatures::targetCIRGenInfoArch());198199// Currently we just fall through to x86_64.200[[fallthrough]];201202case llvm::Triple::x86_64: {203switch (triple.getOS()) {204default:205assert(!cir::MissingFeatures::targetCIRGenInfoOS());206207// Currently we just fall through to x86_64.208[[fallthrough]];209210case llvm::Triple::Linux:211theTargetCIRGenInfo = createX8664TargetCIRGenInfo(genTypes);212return *theTargetCIRGenInfo;213}214}215}216}217218mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {219assert(cLoc.isValid() && "expected valid source location");220const SourceManager &sm = astContext.getSourceManager();221PresumedLoc pLoc = sm.getPresumedLoc(cLoc);222StringRef filename = pLoc.getFilename();223return mlir::FileLineColLoc::get(builder.getStringAttr(filename),224pLoc.getLine(), pLoc.getColumn());225}226227mlir::Location CIRGenModule::getLoc(SourceRange cRange) {228assert(cRange.isValid() && "expected a valid source range");229mlir::Location begin = getLoc(cRange.getBegin());230mlir::Location end = getLoc(cRange.getEnd());231mlir::Attribute metadata;232return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());233}234235mlir::Operation *236CIRGenModule::getAddrOfGlobal(GlobalDecl gd, ForDefinition_t isForDefinition) {237const Decl *d = gd.getDecl();238239if (isa<CXXConstructorDecl>(d) || isa<CXXDestructorDecl>(d))240return getAddrOfCXXStructor(gd, /*FnInfo=*/nullptr, /*FnType=*/nullptr,241/*DontDefer=*/false, isForDefinition);242243if (isa<CXXMethodDecl>(d)) {244const CIRGenFunctionInfo &fi =245getTypes().arrangeCXXMethodDeclaration(cast<CXXMethodDecl>(d));246cir::FuncType ty = getTypes().getFunctionType(fi);247return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,248isForDefinition);249}250251if (isa<FunctionDecl>(d)) {252const CIRGenFunctionInfo &fi = getTypes().arrangeGlobalDeclaration(gd);253cir::FuncType ty = getTypes().getFunctionType(fi);254return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,255isForDefinition);256}257258return getAddrOfGlobalVar(cast<VarDecl>(d), /*ty=*/nullptr, isForDefinition)259.getDefiningOp();260}261262void CIRGenModule::emitGlobalDecl(const clang::GlobalDecl &d) {263// We call getAddrOfGlobal with isForDefinition set to ForDefinition in264// order to get a Value with exactly the type we need, not something that265// might have been created for another decl with the same mangled name but266// different type.267mlir::Operation *op = getAddrOfGlobal(d, ForDefinition);268269// In case of different address spaces, we may still get a cast, even with270// IsForDefinition equal to ForDefinition. Query mangled names table to get271// GlobalValue.272if (!op)273op = getGlobalValue(getMangledName(d));274275assert(op && "expected a valid global op");276277// Check to see if we've already emitted this. This is necessary for a278// couple of reasons: first, decls can end up in deferred-decls queue279// multiple times, and second, decls can end up with definitions in unusual280// ways (e.g. by an extern inline function acquiring a strong function281// redefinition). Just ignore those cases.282// TODO: Not sure what to map this to for MLIR283mlir::Operation *globalValueOp = op;284if (auto gv = dyn_cast<cir::GetGlobalOp>(op))285globalValueOp =286mlir::SymbolTable::lookupSymbolIn(getModule(), gv.getNameAttr());287288if (auto cirGlobalValue =289dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))290if (!cirGlobalValue.isDeclaration())291return;292293// If this is OpenMP, check if it is legal to emit this global normally.294assert(!cir::MissingFeatures::openMP());295296// Otherwise, emit the definition and move on to the next one.297emitGlobalDefinition(d, op);298}299300void CIRGenModule::emitDeferred() {301// Emit code for any potentially referenced deferred decls. Since a previously302// unused static decl may become used during the generation of code for a303// static function, iterate until no changes are made.304305assert(!cir::MissingFeatures::openMP());306assert(!cir::MissingFeatures::deferredVtables());307assert(!cir::MissingFeatures::cudaSupport());308309// Stop if we're out of both deferred vtables and deferred declarations.310if (deferredDeclsToEmit.empty())311return;312313// Grab the list of decls to emit. If emitGlobalDefinition schedules more314// work, it will not interfere with this.315std::vector<GlobalDecl> curDeclsToEmit;316curDeclsToEmit.swap(deferredDeclsToEmit);317318for (const GlobalDecl &d : curDeclsToEmit) {319emitGlobalDecl(d);320321// If we found out that we need to emit more decls, do that recursively.322// This has the advantage that the decls are emitted in a DFS and related323// ones are close together, which is convenient for testing.324if (!deferredDeclsToEmit.empty()) {325emitDeferred();326assert(deferredDeclsToEmit.empty());327}328}329}330331void CIRGenModule::emitGlobal(clang::GlobalDecl gd) {332if (const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.getDecl())) {333emitGlobalOpenACCDecl(cd);334return;335}336337const auto *global = cast<ValueDecl>(gd.getDecl());338339if (const auto *fd = dyn_cast<FunctionDecl>(global)) {340// Update deferred annotations with the latest declaration if the function341// was already used or defined.342if (fd->hasAttr<AnnotateAttr>())343errorNYI(fd->getSourceRange(), "deferredAnnotations");344if (!fd->doesThisDeclarationHaveABody()) {345if (!fd->doesDeclarationForceExternallyVisibleDefinition())346return;347348errorNYI(fd->getSourceRange(),349"function declaration that forces code gen");350return;351}352} else {353const auto *vd = cast<VarDecl>(global);354assert(vd->isFileVarDecl() && "Cannot emit local var decl as global.");355if (vd->isThisDeclarationADefinition() != VarDecl::Definition &&356!astContext.isMSStaticDataMemberInlineDefinition(vd)) {357assert(!cir::MissingFeatures::openMP());358// If this declaration may have caused an inline variable definition to359// change linkage, make sure that it's emitted.360if (astContext.getInlineVariableDefinitionKind(vd) ==361ASTContext::InlineVariableDefinitionKind::Strong)362getAddrOfGlobalVar(vd);363// Otherwise, we can ignore this declaration. The variable will be emitted364// on its first use.365return;366}367}368369// Defer code generation to first use when possible, e.g. if this is an inline370// function. If the global must always be emitted, do it eagerly if possible371// to benefit from cache locality. Deferring code generation is necessary to372// avoid adding initializers to external declarations.373if (mustBeEmitted(global) && mayBeEmittedEagerly(global)) {374// Emit the definition if it can't be deferred.375emitGlobalDefinition(gd);376return;377}378379// If we're deferring emission of a C++ variable with an initializer, remember380// the order in which it appeared on the file.381assert(!cir::MissingFeatures::deferredCXXGlobalInit());382383llvm::StringRef mangledName = getMangledName(gd);384if (getGlobalValue(mangledName) != nullptr) {385// The value has already been used and should therefore be emitted.386addDeferredDeclToEmit(gd);387} else if (mustBeEmitted(global)) {388// The value must be emitted, but cannot be emitted eagerly.389assert(!mayBeEmittedEagerly(global));390addDeferredDeclToEmit(gd);391} else {392// Otherwise, remember that we saw a deferred decl with this name. The first393// use of the mangled name will cause it to move into deferredDeclsToEmit.394deferredDecls[mangledName] = gd;395}396}397398void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,399mlir::Operation *op) {400auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());401const CIRGenFunctionInfo &fi = getTypes().arrangeGlobalDeclaration(gd);402cir::FuncType funcType = getTypes().getFunctionType(fi);403cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);404if (!funcOp || funcOp.getFunctionType() != funcType) {405funcOp = getAddrOfFunction(gd, funcType, /*ForVTable=*/false,406/*DontDefer=*/true, ForDefinition);407}408409// Already emitted.410if (!funcOp.isDeclaration())411return;412413setFunctionLinkage(gd, funcOp);414setGVProperties(funcOp, funcDecl);415assert(!cir::MissingFeatures::opFuncMaybeHandleStaticInExternC());416maybeSetTrivialComdat(*funcDecl, funcOp);417assert(!cir::MissingFeatures::setLLVMFunctionFEnvAttributes());418419CIRGenFunction cgf(*this, builder);420curCGF = &cgf;421{422mlir::OpBuilder::InsertionGuard guard(builder);423cgf.generateCode(gd, funcOp, funcType);424}425curCGF = nullptr;426427setNonAliasAttributes(gd, funcOp);428assert(!cir::MissingFeatures::opFuncAttributesForDefinition());429430if (funcDecl->getAttr<ConstructorAttr>())431errorNYI(funcDecl->getSourceRange(), "constructor attribute");432if (funcDecl->getAttr<DestructorAttr>())433errorNYI(funcDecl->getSourceRange(), "destructor attribute");434435if (funcDecl->getAttr<AnnotateAttr>())436errorNYI(funcDecl->getSourceRange(), "deferredAnnotations");437}438439mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {440return mlir::SymbolTable::lookupSymbolIn(theModule, name);441}442443cir::GlobalOp CIRGenModule::createGlobalOp(CIRGenModule &cgm,444mlir::Location loc, StringRef name,445mlir::Type t,446mlir::Operation *insertPoint) {447cir::GlobalOp g;448CIRGenBuilderTy &builder = cgm.getBuilder();449450{451mlir::OpBuilder::InsertionGuard guard(builder);452453// If an insertion point is provided, we're replacing an existing global,454// otherwise, create the new global immediately after the last gloabl we455// emitted.456if (insertPoint) {457builder.setInsertionPoint(insertPoint);458} else {459// Group global operations together at the top of the module.460if (cgm.lastGlobalOp)461builder.setInsertionPointAfter(cgm.lastGlobalOp);462else463builder.setInsertionPointToStart(cgm.getModule().getBody());464}465466g = builder.create<cir::GlobalOp>(loc, name, t);467if (!insertPoint)468cgm.lastGlobalOp = g;469470// Default to private until we can judge based on the initializer,471// since MLIR doesn't allow public declarations.472mlir::SymbolTable::setSymbolVisibility(473g, mlir::SymbolTable::Visibility::Private);474}475return g;476}477478void CIRGenModule::setCommonAttributes(GlobalDecl gd, mlir::Operation *gv) {479const Decl *d = gd.getDecl();480if (isa_and_nonnull<NamedDecl>(d))481setGVProperties(gv, dyn_cast<NamedDecl>(d));482assert(!cir::MissingFeatures::defaultVisibility());483assert(!cir::MissingFeatures::opGlobalUsedOrCompilerUsed());484}485486void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {487setCommonAttributes(gd, op);488489assert(!cir::MissingFeatures::opGlobalUsedOrCompilerUsed());490assert(!cir::MissingFeatures::opGlobalSection());491assert(!cir::MissingFeatures::opFuncCPUAndFeaturesAttributes());492assert(!cir::MissingFeatures::opFuncSection());493494assert(!cir::MissingFeatures::setTargetAttributes());495}496497static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd) {498// Set linkage and visibility in case we never see a definition.499LinkageInfo lv = nd->getLinkageAndVisibility();500// Don't set internal linkage on declarations.501// "extern_weak" is overloaded in LLVM; we probably should have502// separate linkage types for this.503if (isExternallyVisible(lv.getLinkage()) &&504(nd->hasAttr<WeakAttr>() || nd->isWeakImported()))505gv.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);506}507508/// If the specified mangled name is not in the module,509/// create and return an mlir GlobalOp with the specified type (TODO(cir):510/// address space).511///512/// TODO(cir):513/// 1. If there is something in the module with the specified name, return514/// it potentially bitcasted to the right type.515///516/// 2. If \p d is non-null, it specifies a decl that correspond to this. This517/// is used to set the attributes on the global when it is first created.518///519/// 3. If \p isForDefinition is true, it is guaranteed that an actual global520/// with type \p ty will be returned, not conversion of a variable with the same521/// mangled name but some other type.522cir::GlobalOp523CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,524LangAS langAS, const VarDecl *d,525ForDefinition_t isForDefinition) {526// Lookup the entry, lazily creating it if necessary.527cir::GlobalOp entry;528if (mlir::Operation *v = getGlobalValue(mangledName)) {529if (!isa<cir::GlobalOp>(v))530errorNYI(d->getSourceRange(), "global with non-GlobalOp type");531entry = cast<cir::GlobalOp>(v);532}533534if (entry) {535assert(!cir::MissingFeatures::addressSpace());536assert(!cir::MissingFeatures::opGlobalWeakRef());537538assert(!cir::MissingFeatures::setDLLStorageClass());539assert(!cir::MissingFeatures::openMP());540541if (entry.getSymType() == ty)542return entry;543544// If there are two attempts to define the same mangled name, issue an545// error.546//547// TODO(cir): look at mlir::GlobalValue::isDeclaration for all aspects of548// recognizing the global as a declaration, for now only check if549// initializer is present.550if (isForDefinition && !entry.isDeclaration()) {551errorNYI(d->getSourceRange(), "global with conflicting type");552}553554// Address space check removed because it is unnecessary because CIR records555// address space info in types.556557// (If global is requested for a definition, we always need to create a new558// global, not just return a bitcast.)559if (!isForDefinition)560return entry;561}562563mlir::Location loc = getLoc(d->getSourceRange());564565// mlir::SymbolTable::Visibility::Public is the default, no need to explicitly566// mark it as such.567cir::GlobalOp gv =568CIRGenModule::createGlobalOp(*this, loc, mangledName, ty,569/*insertPoint=*/entry.getOperation());570571// This is the first use or definition of a mangled name. If there is a572// deferred decl with this name, remember that we need to emit it at the end573// of the file.574auto ddi = deferredDecls.find(mangledName);575if (ddi != deferredDecls.end()) {576// Move the potentially referenced deferred decl to the DeferredDeclsToEmit577// list, and remove it from DeferredDecls (since we don't need it anymore).578addDeferredDeclToEmit(ddi->second);579deferredDecls.erase(ddi);580}581582// Handle things which are present even on external declarations.583if (d) {584if (langOpts.OpenMP && !langOpts.OpenMPSimd)585errorNYI(d->getSourceRange(), "OpenMP target global variable");586587gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));588assert(!cir::MissingFeatures::opGlobalConstant());589590setLinkageForGV(gv, d);591592if (d->getTLSKind())593errorNYI(d->getSourceRange(), "thread local global variable");594595setGVProperties(gv, d);596597// If required by the ABI, treat declarations of static data members with598// inline initializers as definitions.599if (astContext.isMSStaticDataMemberInlineDefinition(d))600errorNYI(d->getSourceRange(), "MS static data member inline definition");601602assert(!cir::MissingFeatures::opGlobalSection());603gv.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(d));604605// Handle XCore specific ABI requirements.606if (getTriple().getArch() == llvm::Triple::xcore)607errorNYI(d->getSourceRange(), "XCore specific ABI requirements");608609// Check if we a have a const declaration with an initializer, we may be610// able to emit it as available_externally to expose it's value to the611// optimizer.612if (getLangOpts().CPlusPlus && gv.isPublic() &&613d->getType().isConstQualified() && gv.isDeclaration() &&614!d->hasDefinition() && d->hasInit() && !d->hasAttr<DLLImportAttr>())615errorNYI(d->getSourceRange(),616"external const declaration with initializer");617}618619return gv;620}621622cir::GlobalOp623CIRGenModule::getOrCreateCIRGlobal(const VarDecl *d, mlir::Type ty,624ForDefinition_t isForDefinition) {625assert(d->hasGlobalStorage() && "Not a global variable");626QualType astTy = d->getType();627if (!ty)628ty = getTypes().convertTypeForMem(astTy);629630StringRef mangledName = getMangledName(d);631return getOrCreateCIRGlobal(mangledName, ty, astTy.getAddressSpace(), d,632isForDefinition);633}634635/// Return the mlir::Value for the address of the given global variable. If636/// \p ty is non-null and if the global doesn't exist, then it will be created637/// with the specified type instead of whatever the normal requested type would638/// be. If \p isForDefinition is true, it is guaranteed that an actual global639/// with type \p ty will be returned, not conversion of a variable with the same640/// mangled name but some other type.641mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,642ForDefinition_t isForDefinition) {643assert(d->hasGlobalStorage() && "Not a global variable");644QualType astTy = d->getType();645if (!ty)646ty = getTypes().convertTypeForMem(astTy);647648assert(!cir::MissingFeatures::opGlobalThreadLocal());649650cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);651mlir::Type ptrTy = builder.getPointerTo(g.getSymType());652return builder.create<cir::GetGlobalOp>(getLoc(d->getSourceRange()), ptrTy,653g.getSymName());654}655656void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,657bool isTentative) {658const QualType astTy = vd->getType();659660if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {661errorNYI(vd->getSourceRange(), "emit OpenCL/OpenMP global variable");662return;663}664665// Whether the definition of the variable is available externally.666// If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable667// since this is the job for its original source.668bool isDefinitionAvailableExternally =669astContext.GetGVALinkageForVariable(vd) == GVA_AvailableExternally;670assert(!cir::MissingFeatures::needsGlobalCtorDtor());671672// It is useless to emit the definition for an available_externally variable673// which can't be marked as const.674if (isDefinitionAvailableExternally &&675(!vd->hasConstantInitialization() ||676// TODO: Update this when we have interface to check constexpr677// destructor.678vd->needsDestruction(astContext) ||679!vd->getType().isConstantStorage(astContext, true, true)))680return;681682mlir::Attribute init;683const VarDecl *initDecl;684const Expr *initExpr = vd->getAnyInitializer(initDecl);685686std::optional<ConstantEmitter> emitter;687688assert(!cir::MissingFeatures::cudaSupport());689690if (vd->hasAttr<LoaderUninitializedAttr>()) {691errorNYI(vd->getSourceRange(), "loader uninitialized attribute");692return;693} else if (!initExpr) {694// This is a tentative definition; tentative definitions are695// implicitly initialized with { 0 }.696//697// Note that tentative definitions are only emitted at the end of698// a translation unit, so they should never have incomplete699// type. In addition, EmitTentativeDefinition makes sure that we700// never attempt to emit a tentative definition if a real one701// exists. A use may still exists, however, so we still may need702// to do a RAUW.703assert(!astTy->isIncompleteType() && "Unexpected incomplete type");704init = builder.getZeroInitAttr(convertType(vd->getType()));705} else {706emitter.emplace(*this);707mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);708if (!initializer) {709QualType qt = initExpr->getType();710if (vd->getType()->isReferenceType())711qt = vd->getType();712713if (getLangOpts().CPlusPlus) {714if (initDecl->hasFlexibleArrayInit(astContext))715errorNYI(vd->getSourceRange(), "flexible array initializer");716init = builder.getZeroInitAttr(convertType(qt));717if (astContext.GetGVALinkageForVariable(vd) != GVA_AvailableExternally)718errorNYI(vd->getSourceRange(), "global constructor");719} else {720errorNYI(vd->getSourceRange(), "static initializer");721}722} else {723init = initializer;724// We don't need an initializer, so remove the entry for the delayed725// initializer position (just in case this entry was delayed) if we726// also don't need to register a destructor.727if (vd->needsDestruction(astContext) == QualType::DK_cxx_destructor)728errorNYI(vd->getSourceRange(), "delayed destructor");729}730}731732mlir::Type initType;733if (mlir::isa<mlir::SymbolRefAttr>(init)) {734errorNYI(vd->getSourceRange(), "global initializer is a symbol reference");735return;736} else {737assert(mlir::isa<mlir::TypedAttr>(init) && "This should have a type");738auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);739initType = typedInitAttr.getType();740}741assert(!mlir::isa<mlir::NoneType>(initType) && "Should have a type by now");742743cir::GlobalOp gv =744getOrCreateCIRGlobal(vd, initType, ForDefinition_t(!isTentative));745// TODO(cir): Strip off pointer casts from Entry if we get them?746747if (!gv || gv.getSymType() != initType) {748errorNYI(vd->getSourceRange(), "global initializer with type mismatch");749return;750}751752assert(!cir::MissingFeatures::maybeHandleStaticInExternC());753754if (vd->hasAttr<AnnotateAttr>()) {755errorNYI(vd->getSourceRange(), "annotate global variable");756}757758if (langOpts.CUDA) {759errorNYI(vd->getSourceRange(), "CUDA global variable");760}761762// Set initializer and finalize emission763CIRGenModule::setInitializer(gv, init);764if (emitter)765emitter->finalize(gv);766767// Set CIR's linkage type as appropriate.768cir::GlobalLinkageKind linkage =769getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);770771// Set CIR linkage and DLL storage class.772gv.setLinkage(linkage);773// FIXME(cir): setLinkage should likely set MLIR's visibility automatically.774gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));775assert(!cir::MissingFeatures::opGlobalDLLImportExport());776if (linkage == cir::GlobalLinkageKind::CommonLinkage)777errorNYI(initExpr->getSourceRange(), "common linkage");778779setNonAliasAttributes(vd, gv);780781assert(!cir::MissingFeatures::opGlobalThreadLocal());782783maybeSetTrivialComdat(*vd, gv);784}785786void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd,787mlir::Operation *op) {788const auto *decl = cast<ValueDecl>(gd.getDecl());789if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {790// TODO(CIR): Skip generation of CIR for functions with available_externally791// linkage at -O0.792793if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {794// Make sure to emit the definition(s) before we emit the thunks. This is795// necessary for the generation of certain thunks.796if (isa<CXXConstructorDecl>(method) || isa<CXXDestructorDecl>(method))797abi->emitCXXStructor(gd);798else if (fd->isMultiVersion())799errorNYI(method->getSourceRange(), "multiversion functions");800else801emitGlobalFunctionDefinition(gd, op);802803if (method->isVirtual())804errorNYI(method->getSourceRange(), "virtual member function");805806return;807}808809if (fd->isMultiVersion())810errorNYI(fd->getSourceRange(), "multiversion functions");811emitGlobalFunctionDefinition(gd, op);812return;813}814815if (const auto *vd = dyn_cast<VarDecl>(decl))816return emitGlobalVarDefinition(vd, !vd->hasDefinition());817818llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");819}820821mlir::Attribute822CIRGenModule::getConstantArrayFromStringLiteral(const StringLiteral *e) {823assert(!e->getType()->isPointerType() && "Strings are always arrays");824825// Don't emit it as the address of the string, emit the string data itself826// as an inline array.827if (e->getCharByteWidth() == 1) {828SmallString<64> str(e->getString());829830// Resize the string to the right size, which is indicated by its type.831const ConstantArrayType *cat =832astContext.getAsConstantArrayType(e->getType());833uint64_t finalSize = cat->getZExtSize();834str.resize(finalSize);835836mlir::Type eltTy = convertType(cat->getElementType());837return builder.getString(str, eltTy, finalSize);838}839840errorNYI(e->getSourceRange(),841"getConstantArrayFromStringLiteral: wide characters");842return mlir::Attribute();843}844845bool CIRGenModule::supportsCOMDAT() const {846return getTriple().supportsCOMDAT();847}848849static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {850if (!cgm.supportsCOMDAT())851return false;852853if (d.hasAttr<SelectAnyAttr>())854return true;855856GVALinkage linkage;857if (auto *vd = dyn_cast<VarDecl>(&d))858linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);859else860linkage =861cgm.getASTContext().GetGVALinkageForFunction(cast<FunctionDecl>(&d));862863switch (linkage) {864case clang::GVA_Internal:865case clang::GVA_AvailableExternally:866case clang::GVA_StrongExternal:867return false;868case clang::GVA_DiscardableODR:869case clang::GVA_StrongODR:870return true;871}872llvm_unreachable("No such linkage");873}874875void CIRGenModule::maybeSetTrivialComdat(const Decl &d, mlir::Operation *op) {876if (!shouldBeInCOMDAT(*this, d))877return;878if (auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {879globalOp.setComdat(true);880} else {881auto funcOp = cast<cir::FuncOp>(op);882funcOp.setComdat(true);883}884}885886void CIRGenModule::updateCompletedType(const TagDecl *td) {887// Make sure that this type is translated.888genTypes.updateCompletedType(td);889}890891void CIRGenModule::addReplacement(StringRef name, mlir::Operation *op) {892replacements[name] = op;893}894895void CIRGenModule::replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF) {896std::optional<mlir::SymbolTable::UseRange> optionalUseRange =897oldF.getSymbolUses(theModule);898if (!optionalUseRange)899return;900901for (const mlir::SymbolTable::SymbolUse &u : *optionalUseRange) {902// CallTryOp only shows up after FlattenCFG.903auto call = mlir::dyn_cast<cir::CallOp>(u.getUser());904if (!call)905continue;906907for (const auto [argOp, fnArgType] :908llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {909if (argOp.getType() == fnArgType)910continue;911912// The purpose of this entire function is to insert bitcasts in the case913// where these types don't match, but I haven't seen a case where that914// happens.915errorNYI(call.getLoc(), "replace call with mismatched types");916}917}918}919920void CIRGenModule::applyReplacements() {921for (auto &i : replacements) {922StringRef mangledName = i.first();923mlir::Operation *replacement = i.second;924mlir::Operation *entry = getGlobalValue(mangledName);925if (!entry)926continue;927assert(isa<cir::FuncOp>(entry) && "expected function");928auto oldF = cast<cir::FuncOp>(entry);929auto newF = dyn_cast<cir::FuncOp>(replacement);930if (!newF) {931// In classic codegen, this can be a global alias, a bitcast, or a GEP.932errorNYI(replacement->getLoc(), "replacement is not a function");933continue;934}935936// LLVM has opaque pointer but CIR not. So we may have to handle these937// different pointer types when performing replacement.938replacePointerTypeArgs(oldF, newF);939940// Replace old with new, but keep the old order.941if (oldF.replaceAllSymbolUses(newF.getSymNameAttr(), theModule).failed())942llvm_unreachable("internal error, cannot RAUW symbol");943if (newF) {944newF->moveBefore(oldF);945oldF->erase();946}947}948}949950// TODO(CIR): this could be a common method between LLVM codegen.951static bool isVarDeclStrongDefinition(const ASTContext &astContext,952CIRGenModule &cgm, const VarDecl *vd,953bool noCommon) {954// Don't give variables common linkage if -fno-common was specified unless it955// was overridden by a NoCommon attribute.956if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())957return true;958959// C11 6.9.2/2:960// A declaration of an identifier for an object that has file scope without961// an initializer, and without a storage-class specifier or with the962// storage-class specifier static, constitutes a tentative definition.963if (vd->getInit() || vd->hasExternalStorage())964return true;965966// A variable cannot be both common and exist in a section.967if (vd->hasAttr<SectionAttr>())968return true;969970// A variable cannot be both common and exist in a section.971// We don't try to determine which is the right section in the front-end.972// If no specialized section name is applicable, it will resort to default.973if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||974vd->hasAttr<PragmaClangDataSectionAttr>() ||975vd->hasAttr<PragmaClangRelroSectionAttr>() ||976vd->hasAttr<PragmaClangRodataSectionAttr>())977return true;978979// Thread local vars aren't considered common linkage.980if (vd->getTLSKind())981return true;982983// Tentative definitions marked with WeakImportAttr are true definitions.984if (vd->hasAttr<WeakImportAttr>())985return true;986987// A variable cannot be both common and exist in a comdat.988if (shouldBeInCOMDAT(cgm, *vd))989return true;990991// Declarations with a required alignment do not have common linkage in MSVC992// mode.993if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {994if (vd->hasAttr<AlignedAttr>())995return true;996QualType varType = vd->getType();997if (astContext.isAlignmentRequired(varType))998return true;9991000if (const auto *rt = varType->getAs<RecordType>()) {1001const RecordDecl *rd = rt->getDecl();1002for (const FieldDecl *fd : rd->fields()) {1003if (fd->isBitField())1004continue;1005if (fd->hasAttr<AlignedAttr>())1006return true;1007if (astContext.isAlignmentRequired(fd->getType()))1008return true;1009}1010}1011}10121013// Microsoft's link.exe doesn't support alignments greater than 32 bytes for1014// common symbols, so symbols with greater alignment requirements cannot be1015// common.1016// Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two1017// alignments for common symbols via the aligncomm directive, so this1018// restriction only applies to MSVC environments.1019if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&1020astContext.getTypeAlignIfKnown(vd->getType()) >1021astContext.toBits(CharUnits::fromQuantity(32)))1022return true;10231024return false;1025}10261027cir::GlobalLinkageKind CIRGenModule::getCIRLinkageForDeclarator(1028const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable) {1029if (linkage == GVA_Internal)1030return cir::GlobalLinkageKind::InternalLinkage;10311032if (dd->hasAttr<WeakAttr>()) {1033if (isConstantVariable)1034return cir::GlobalLinkageKind::WeakODRLinkage;1035return cir::GlobalLinkageKind::WeakAnyLinkage;1036}10371038if (const auto *fd = dd->getAsFunction())1039if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)1040return cir::GlobalLinkageKind::LinkOnceAnyLinkage;10411042// We are guaranteed to have a strong definition somewhere else,1043// so we can use available_externally linkage.1044if (linkage == GVA_AvailableExternally)1045return cir::GlobalLinkageKind::AvailableExternallyLinkage;10461047// Note that Apple's kernel linker doesn't support symbol1048// coalescing, so we need to avoid linkonce and weak linkages there.1049// Normally, this means we just map to internal, but for explicit1050// instantiations we'll map to external.10511052// In C++, the compiler has to emit a definition in every translation unit1053// that references the function. We should use linkonce_odr because1054// a) if all references in this translation unit are optimized away, we1055// don't need to codegen it. b) if the function persists, it needs to be1056// merged with other definitions. c) C++ has the ODR, so we know the1057// definition is dependable.1058if (linkage == GVA_DiscardableODR)1059return !astContext.getLangOpts().AppleKext1060? cir::GlobalLinkageKind::LinkOnceODRLinkage1061: cir::GlobalLinkageKind::InternalLinkage;10621063// An explicit instantiation of a template has weak linkage, since1064// explicit instantiations can occur in multiple translation units1065// and must all be equivalent. However, we are not allowed to1066// throw away these explicit instantiations.1067//1068// CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,1069// so say that CUDA templates are either external (for kernels) or internal.1070// This lets llvm perform aggressive inter-procedural optimizations. For1071// -fgpu-rdc case, device function calls across multiple TU's are allowed,1072// therefore we need to follow the normal linkage paradigm.1073if (linkage == GVA_StrongODR) {1074if (getLangOpts().AppleKext)1075return cir::GlobalLinkageKind::ExternalLinkage;1076if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&1077!getLangOpts().GPURelocatableDeviceCode)1078return dd->hasAttr<CUDAGlobalAttr>()1079? cir::GlobalLinkageKind::ExternalLinkage1080: cir::GlobalLinkageKind::InternalLinkage;1081return cir::GlobalLinkageKind::WeakODRLinkage;1082}10831084// C++ doesn't have tentative definitions and thus cannot have common1085// linkage.1086if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&1087!isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),1088getCodeGenOpts().NoCommon)) {1089errorNYI(dd->getBeginLoc(), "common linkage", dd->getDeclKindName());1090return cir::GlobalLinkageKind::CommonLinkage;1091}10921093// selectany symbols are externally visible, so use weak instead of1094// linkonce. MSVC optimizes away references to const selectany globals, so1095// all definitions should be the same and ODR linkage should be used.1096// http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx1097if (dd->hasAttr<SelectAnyAttr>())1098return cir::GlobalLinkageKind::WeakODRLinkage;10991100// Otherwise, we have strong external linkage.1101assert(linkage == GVA_StrongExternal);1102return cir::GlobalLinkageKind::ExternalLinkage;1103}11041105cir::GlobalLinkageKind1106CIRGenModule::getCIRLinkageVarDefinition(const VarDecl *vd, bool isConstant) {1107assert(!isConstant && "constant variables NYI");1108GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);1109return getCIRLinkageForDeclarator(vd, linkage, isConstant);1110}11111112cir::GlobalLinkageKind CIRGenModule::getFunctionLinkage(GlobalDecl gd) {1113const auto *d = cast<FunctionDecl>(gd.getDecl());11141115GVALinkage linkage = astContext.GetGVALinkageForFunction(d);11161117if (const auto *dtor = dyn_cast<CXXDestructorDecl>(d))1118return getCXXABI().getCXXDestructorLinkage(linkage, dtor, gd.getDtorType());11191120return getCIRLinkageForDeclarator(d, linkage, /*isConstantVariable=*/false);1121}11221123static cir::GlobalOp1124generateStringLiteral(mlir::Location loc, mlir::TypedAttr c,1125cir::GlobalLinkageKind lt, CIRGenModule &cgm,1126StringRef globalName, CharUnits alignment) {1127assert(!cir::MissingFeatures::addressSpace());11281129// Create a global variable for this string1130// FIXME(cir): check for insertion point in module level.1131cir::GlobalOp gv =1132CIRGenModule::createGlobalOp(cgm, loc, globalName, c.getType());11331134// Set up extra information and add to the module1135gv.setAlignmentAttr(cgm.getSize(alignment));1136gv.setLinkageAttr(1137cir::GlobalLinkageKindAttr::get(cgm.getBuilder().getContext(), lt));1138assert(!cir::MissingFeatures::opGlobalThreadLocal());1139assert(!cir::MissingFeatures::opGlobalUnnamedAddr());1140CIRGenModule::setInitializer(gv, c);1141if (gv.isWeakForLinker()) {1142assert(cgm.supportsCOMDAT() && "Only COFF uses weak string literals");1143gv.setComdat(true);1144}1145cgm.setDSOLocal(static_cast<mlir::Operation *>(gv));1146return gv;1147}11481149// LLVM IR automatically uniques names when new llvm::GlobalVariables are1150// created. This is handy, for example, when creating globals for string1151// literals. Since we don't do that when creating cir::GlobalOp's, we need1152// a mechanism to generate a unique name in advance.1153//1154// For now, this mechanism is only used in cases where we know that the1155// name is compiler-generated, so we don't use the MLIR symbol table for1156// the lookup.1157std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {1158// If this is the first time we've generated a name for this basename, use1159// it as is and start a counter for this base name.1160auto it = cgGlobalNames.find(baseName);1161if (it == cgGlobalNames.end()) {1162cgGlobalNames[baseName] = 1;1163return baseName;1164}11651166std::string result =1167baseName + "." + std::to_string(cgGlobalNames[baseName]++);1168// There should not be any symbol with this name in the module.1169assert(!mlir::SymbolTable::lookupSymbolIn(theModule, result));1170return result;1171}11721173/// Return a pointer to a constant array for the given string literal.1174cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,1175StringRef name) {1176CharUnits alignment =1177astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);11781179mlir::Attribute c = getConstantArrayFromStringLiteral(s);11801181if (getLangOpts().WritableStrings) {1182errorNYI(s->getSourceRange(),1183"getGlobalForStringLiteral: Writable strings");1184}11851186// Mangle the string literal if that's how the ABI merges duplicate strings.1187// Don't do it if they are writable, since we don't want writes in one TU to1188// affect strings in another.1189if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&1190!getLangOpts().WritableStrings) {1191errorNYI(s->getSourceRange(),1192"getGlobalForStringLiteral: mangle string literals");1193}11941195// Unlike LLVM IR, CIR doesn't automatically unique names for globals, so1196// we need to do that explicitly.1197std::string uniqueName = getUniqueGlobalName(name.str());1198mlir::Location loc = getLoc(s->getSourceRange());1199auto typedC = llvm::cast<mlir::TypedAttr>(c);1200cir::GlobalOp gv =1201generateStringLiteral(loc, typedC, cir::GlobalLinkageKind::PrivateLinkage,1202*this, uniqueName, alignment);1203setDSOLocal(static_cast<mlir::Operation *>(gv));12041205assert(!cir::MissingFeatures::sanitizers());12061207return gv;1208}12091210void CIRGenModule::emitDeclContext(const DeclContext *dc) {1211for (Decl *decl : dc->decls()) {1212// Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope1213// are themselves considered "top-level", so EmitTopLevelDecl on an1214// ObjCImplDecl does not recursively visit them. We need to do that in1215// case they're nested inside another construct (LinkageSpecDecl /1216// ExportDecl) that does stop them from being considered "top-level".1217if (auto *oid = dyn_cast<ObjCImplDecl>(decl))1218errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");12191220emitTopLevelDecl(decl);1221}1222}12231224// Emit code for a single top level declaration.1225void CIRGenModule::emitTopLevelDecl(Decl *decl) {12261227// Ignore dependent declarations.1228if (decl->isTemplated())1229return;12301231switch (decl->getKind()) {1232default:1233errorNYI(decl->getBeginLoc(), "declaration of kind",1234decl->getDeclKindName());1235break;12361237case Decl::CXXMethod:1238case Decl::Function: {1239auto *fd = cast<FunctionDecl>(decl);1240// Consteval functions shouldn't be emitted.1241if (!fd->isConsteval())1242emitGlobal(fd);1243break;1244}12451246case Decl::Var: {1247auto *vd = cast<VarDecl>(decl);1248emitGlobal(vd);1249break;1250}1251case Decl::OpenACCRoutine:1252emitGlobalOpenACCDecl(cast<OpenACCRoutineDecl>(decl));1253break;1254case Decl::OpenACCDeclare:1255emitGlobalOpenACCDecl(cast<OpenACCDeclareDecl>(decl));1256break;1257case Decl::Enum:1258case Decl::Using: // using X; [C++]1259case Decl::UsingDirective: // using namespace X; [C++]1260case Decl::UsingEnum: // using enum X; [C++]1261case Decl::NamespaceAlias:1262case Decl::Typedef:1263case Decl::TypeAlias: // using foo = bar; [C++11]1264case Decl::Record:1265assert(!cir::MissingFeatures::generateDebugInfo());1266break;12671268// No code generation needed.1269case Decl::UsingShadow:1270case Decl::Empty:1271break;12721273case Decl::CXXConstructor:1274getCXXABI().emitCXXConstructors(cast<CXXConstructorDecl>(decl));1275break;1276case Decl::CXXDestructor:1277getCXXABI().emitCXXDestructors(cast<CXXDestructorDecl>(decl));1278break;12791280// C++ Decls1281case Decl::LinkageSpec:1282case Decl::Namespace:1283emitDeclContext(Decl::castToDeclContext(decl));1284break;12851286case Decl::ClassTemplateSpecialization:1287case Decl::CXXRecord:1288assert(!cir::MissingFeatures::generateDebugInfo());1289assert(!cir::MissingFeatures::cxxRecordStaticMembers());1290break;1291}1292}12931294void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {1295// Recompute visibility when updating initializer.1296op.setInitialValueAttr(value);1297assert(!cir::MissingFeatures::opGlobalVisibility());1298}12991300std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(1301GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,1302bool dontDefer, ForDefinition_t isForDefinition) {1303auto *md = cast<CXXMethodDecl>(gd.getDecl());13041305if (isa<CXXDestructorDecl>(md)) {1306// Always alias equivalent complete destructors to base destructors in the1307// MS ABI.1308if (getTarget().getCXXABI().isMicrosoft() &&1309gd.getDtorType() == Dtor_Complete &&1310md->getParent()->getNumVBases() == 0)1311errorNYI(md->getSourceRange(),1312"getAddrAndTypeOfCXXStructor: MS ABI complete destructor");1313}13141315if (!fnType) {1316if (!fnInfo)1317fnInfo = &getTypes().arrangeCXXStructorDeclaration(gd);1318fnType = getTypes().getFunctionType(*fnInfo);1319}13201321auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,1322/*ForVtable=*/false, dontDefer,1323/*IsThunk=*/false, isForDefinition);13241325return {fnType, fn};1326}13271328cir::FuncOp CIRGenModule::getAddrOfFunction(clang::GlobalDecl gd,1329mlir::Type funcType, bool forVTable,1330bool dontDefer,1331ForDefinition_t isForDefinition) {1332assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&1333"consteval function should never be emitted");13341335if (!funcType) {1336const auto *fd = cast<FunctionDecl>(gd.getDecl());1337funcType = convertType(fd->getType());1338}13391340// Devirtualized destructor calls may come through here instead of via1341// getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead1342// of the complete destructor when necessary.1343if (const auto *dd = dyn_cast<CXXDestructorDecl>(gd.getDecl())) {1344if (getTarget().getCXXABI().isMicrosoft() &&1345gd.getDtorType() == Dtor_Complete &&1346dd->getParent()->getNumVBases() == 0)1347errorNYI(dd->getSourceRange(),1348"getAddrOfFunction: MS ABI complete destructor");1349}13501351StringRef mangledName = getMangledName(gd);1352cir::FuncOp func =1353getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,1354/*isThunk=*/false, isForDefinition);1355return func;1356}13571358static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,1359const NamedDecl *nd) {1360SmallString<256> buffer;13611362llvm::raw_svector_ostream out(buffer);1363MangleContext &mc = cgm.getCXXABI().getMangleContext();13641365assert(!cir::MissingFeatures::moduleNameHash());13661367if (mc.shouldMangleDeclName(nd)) {1368mc.mangleName(gd.getWithDecl(nd), out);1369} else {1370IdentifierInfo *ii = nd->getIdentifier();1371assert(ii && "Attempt to mangle unnamed decl.");13721373const auto *fd = dyn_cast<FunctionDecl>(nd);1374if (fd &&1375fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {1376cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");1377} else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&1378gd.getKernelReferenceKind() == KernelReferenceKind::Stub) {1379cgm.errorNYI(nd->getSourceRange(), "getMangledName: CUDA device stub");1380}1381out << ii->getName();1382}13831384// Check if the module name hash should be appended for internal linkage1385// symbols. This should come before multi-version target suffixes are1386// appendded. This is to keep the name and module hash suffix of the internal1387// linkage function together. The unique suffix should only be added when name1388// mangling is done to make sure that the final name can be properly1389// demangled. For example, for C functions without prototypes, name mangling1390// is not done and the unique suffix should not be appended then.1391assert(!cir::MissingFeatures::moduleNameHash());13921393if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {1394if (fd->isMultiVersion()) {1395cgm.errorNYI(nd->getSourceRange(),1396"getMangledName: multi-version functions");1397}1398}1399if (cgm.getLangOpts().GPURelocatableDeviceCode) {1400cgm.errorNYI(nd->getSourceRange(),1401"getMangledName: GPU relocatable device code");1402}14031404return std::string(out.str());1405}14061407StringRef CIRGenModule::getMangledName(GlobalDecl gd) {1408GlobalDecl canonicalGd = gd.getCanonicalDecl();14091410// Some ABIs don't have constructor variants. Make sure that base and complete1411// constructors get mangled the same.1412if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {1413if (!getTarget().getCXXABI().hasConstructorVariants()) {1414errorNYI(cd->getSourceRange(),1415"getMangledName: C++ constructor without variants");1416return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();1417}1418}14191420// Keep the first result in the case of a mangling collision.1421const auto *nd = cast<NamedDecl>(gd.getDecl());1422std::string mangledName = getMangledNameImpl(*this, gd, nd);14231424auto result = manglings.insert(std::make_pair(mangledName, gd));1425return mangledDeclNames[canonicalGd] = result.first->first();1426}14271428void CIRGenModule::emitTentativeDefinition(const VarDecl *d) {1429assert(!d->getInit() && "Cannot emit definite definitions here!");14301431StringRef mangledName = getMangledName(d);1432mlir::Operation *gv = getGlobalValue(mangledName);14331434// If we already have a definition, not declaration, with the same mangled1435// name, emitting of declaration is not required (and would actually overwrite1436// the emitted definition).1437if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())1438return;14391440// If we have not seen a reference to this variable yet, place it into the1441// deferred declarations table to be emitted if needed later.1442if (!mustBeEmitted(d) && !gv) {1443deferredDecls[mangledName] = d;1444return;1445}14461447// The tentative definition is the only definition.1448emitGlobalVarDefinition(d);1449}14501451bool CIRGenModule::mustBeEmitted(const ValueDecl *global) {1452// Never defer when EmitAllDecls is specified.1453if (langOpts.EmitAllDecls)1454return true;14551456const auto *vd = dyn_cast<VarDecl>(global);1457if (vd &&1458((codeGenOpts.KeepPersistentStorageVariables &&1459(vd->getStorageDuration() == SD_Static ||1460vd->getStorageDuration() == SD_Thread)) ||1461(codeGenOpts.KeepStaticConsts && vd->getStorageDuration() == SD_Static &&1462vd->getType().isConstQualified())))1463return true;14641465return getASTContext().DeclMustBeEmitted(global);1466}14671468bool CIRGenModule::mayBeEmittedEagerly(const ValueDecl *global) {1469// In OpenMP 5.0 variables and function may be marked as1470// device_type(host/nohost) and we should not emit them eagerly unless we sure1471// that they must be emitted on the host/device. To be sure we need to have1472// seen a declare target with an explicit mentioning of the function, we know1473// we have if the level of the declare target attribute is -1. Note that we1474// check somewhere else if we should emit this at all.1475if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {1476std::optional<OMPDeclareTargetDeclAttr *> activeAttr =1477OMPDeclareTargetDeclAttr::getActiveAttr(global);1478if (!activeAttr || (*activeAttr)->getLevel() != (unsigned)-1)1479return false;1480}14811482const auto *fd = dyn_cast<FunctionDecl>(global);1483if (fd) {1484// Implicit template instantiations may change linkage if they are later1485// explicitly instantiated, so they should not be emitted eagerly.1486if (fd->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)1487return false;1488// Defer until all versions have been semantically checked.1489if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())1490return false;1491if (langOpts.SYCLIsDevice) {1492errorNYI(fd->getSourceRange(), "mayBeEmittedEagerly: SYCL");1493return false;1494}1495}1496const auto *vd = dyn_cast<VarDecl>(global);1497if (vd)1498if (astContext.getInlineVariableDefinitionKind(vd) ==1499ASTContext::InlineVariableDefinitionKind::WeakUnknown)1500// A definition of an inline constexpr static data member may change1501// linkage later if it's redeclared outside the class.1502return false;15031504// If OpenMP is enabled and threadprivates must be generated like TLS, delay1505// codegen for global variables, because they may be marked as threadprivate.1506if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&1507astContext.getTargetInfo().isTLSSupported() && isa<VarDecl>(global) &&1508!global->getType().isConstantStorage(astContext, false, false) &&1509!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))1510return false;15111512assert((fd || vd) &&1513"Only FunctionDecl and VarDecl should hit this path so far.");1514return true;1515}15161517static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,1518cir::CIRGlobalValueInterface gv) {1519if (gv.hasLocalLinkage())1520return true;15211522if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())1523return true;15241525// DLLImport explicitly marks the GV as external.1526// so it shouldn't be dso_local1527// But we don't have the info set now1528assert(!cir::MissingFeatures::opGlobalDLLImportExport());15291530const llvm::Triple &tt = cgm.getTriple();1531const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();1532if (tt.isWindowsGNUEnvironment()) {1533// In MinGW, variables without DLLImport can still be automatically1534// imported from a DLL by the linker; don't mark variables that1535// potentially could come from another DLL as DSO local.15361537// With EmulatedTLS, TLS variables can be autoimported from other DLLs1538// (and this actually happens in the public interface of libstdc++), so1539// such variables can't be marked as DSO local. (Native TLS variables1540// can't be dllimported at all, though.)1541cgm.errorNYI("shouldAssumeDSOLocal: MinGW");1542}15431544// On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols1545// remain unresolved in the link, they can be resolved to zero, which is1546// outside the current DSO.1547if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())1548return false;15491550// Every other GV is local on COFF.1551// Make an exception for windows OS in the triple: Some firmware builds use1552// *-win32-macho triples. This (accidentally?) produced windows relocations1553// without GOT tables in older clang versions; Keep this behaviour.1554// FIXME: even thread local variables?1555if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))1556return true;15571558// Only handle COFF and ELF for now.1559if (!tt.isOSBinFormatELF())1560return false;15611562llvm::Reloc::Model rm = cgOpts.RelocationModel;1563const LangOptions &lOpts = cgm.getLangOpts();1564if (rm != llvm::Reloc::Static && !lOpts.PIE) {1565// On ELF, if -fno-semantic-interposition is specified and the target1566// supports local aliases, there will be neither CC11567// -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set1568// dso_local on the function if using a local alias is preferable (can avoid1569// PLT indirection).1570if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))1571return false;1572return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);1573}15741575// A definition cannot be preempted from an executable.1576if (!gv.isDeclarationForLinker())1577return true;15781579// Most PIC code sequences that assume that a symbol is local cannot produce a1580// 0 if it turns out the symbol is undefined. While this is ABI and relocation1581// depended, it seems worth it to handle it here.1582if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())1583return false;15841585// PowerPC64 prefers TOC indirection to avoid copy relocations.1586if (tt.isPPC64())1587return false;15881589if (cgOpts.DirectAccessExternalData) {1590// If -fdirect-access-external-data (default for -fno-pic), set dso_local1591// for non-thread-local variables. If the symbol is not defined in the1592// executable, a copy relocation will be needed at link time. dso_local is1593// excluded for thread-local variables because they generally don't support1594// copy relocations.1595if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {1596// Assume variables are not thread-local until that support is added.1597assert(!cir::MissingFeatures::opGlobalThreadLocal());1598return true;1599}16001601// -fno-pic sets dso_local on a function declaration to allow direct1602// accesses when taking its address (similar to a data symbol). If the1603// function is not defined in the executable, a canonical PLT entry will be1604// needed at link time. -fno-direct-access-external-data can avoid the1605// canonical PLT entry. We don't generalize this condition to -fpie/-fpic as1606// it could just cause trouble without providing perceptible benefits.1607if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)1608return true;1609}16101611// If we can use copy relocations we can assume it is local.16121613// Otherwise don't assume it is local.16141615return false;1616}16171618void CIRGenModule::setGlobalVisibility(mlir::Operation *gv,1619const NamedDecl *d) const {1620assert(!cir::MissingFeatures::opGlobalVisibility());1621}16221623void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {1624gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));1625}16261627void CIRGenModule::setDSOLocal(mlir::Operation *op) const {1628if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))1629setDSOLocal(globalValue);1630}16311632void CIRGenModule::setGVProperties(mlir::Operation *op,1633const NamedDecl *d) const {1634assert(!cir::MissingFeatures::opGlobalDLLImportExport());1635setGVPropertiesAux(op, d);1636}16371638void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,1639const NamedDecl *d) const {1640setGlobalVisibility(op, d);1641setDSOLocal(op);1642assert(!cir::MissingFeatures::opGlobalPartition());1643}16441645void CIRGenModule::setFunctionAttributes(GlobalDecl globalDecl,1646cir::FuncOp func,1647bool isIncompleteFunction,1648bool isThunk) {1649// NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we1650// represent them in dedicated ops. The correct attributes are ensured during1651// translation to LLVM. Thus, we don't need to check for them here.16521653assert(!cir::MissingFeatures::setFunctionAttributes());1654assert(!cir::MissingFeatures::setTargetAttributes());16551656// TODO(cir): This needs a lot of work to better match CodeGen. That1657// ultimately ends up in setGlobalVisibility, which already has the linkage of1658// the LLVM GV (corresponding to our FuncOp) computed, so it doesn't have to1659// recompute it here. This is a minimal fix for now.1660if (!isLocalLinkage(getFunctionLinkage(globalDecl))) {1661const Decl *decl = globalDecl.getDecl();1662func.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(decl));1663}1664}16651666cir::FuncOp CIRGenModule::getOrCreateCIRFunction(1667StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,1668bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,1669mlir::ArrayAttr extraAttrs) {1670const Decl *d = gd.getDecl();16711672if (isThunk)1673errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: thunk");16741675// In what follows, we continue past 'errorNYI' as if nothing happened because1676// the rest of the implementation is better than doing nothing.16771678if (const auto *fd = cast_or_null<FunctionDecl>(d)) {1679// For the device mark the function as one that should be emitted.1680if (getLangOpts().OpenMPIsTargetDevice && fd->isDefined() && !dontDefer &&1681!isForDefinition)1682errorNYI(fd->getSourceRange(),1683"getOrCreateCIRFunction: OpenMP target function");16841685// Any attempts to use a MultiVersion function should result in retrieving1686// the iFunc instead. Name mangling will handle the rest of the changes.1687if (fd->isMultiVersion())1688errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");1689}16901691// Lookup the entry, lazily creating it if necessary.1692mlir::Operation *entry = getGlobalValue(mangledName);1693if (entry) {1694if (!isa<cir::FuncOp>(entry))1695errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: non-FuncOp");16961697assert(!cir::MissingFeatures::weakRefReference());16981699// Handle dropped DLL attributes.1700if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {1701assert(!cir::MissingFeatures::setDLLStorageClass());1702setDSOLocal(entry);1703}17041705// If there are two attempts to define the same mangled name, issue an1706// error.1707auto fn = cast<cir::FuncOp>(entry);1708if (isForDefinition && fn && !fn.isDeclaration()) {1709errorNYI(d->getSourceRange(), "Duplicate function definition");1710}1711if (fn && fn.getFunctionType() == funcType) {1712return fn;1713}17141715if (!isForDefinition) {1716return fn;1717}17181719// TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.1720// How will we support this?1721}17221723auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());1724bool invalidLoc = !funcDecl ||1725funcDecl->getSourceRange().getBegin().isInvalid() ||1726funcDecl->getSourceRange().getEnd().isInvalid();1727cir::FuncOp funcOp = createCIRFunction(1728invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),1729mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);17301731if (d)1732setFunctionAttributes(gd, funcOp, /*isIncompleteFunction=*/false, isThunk);17331734// 'dontDefer' actually means don't move this to the deferredDeclsToEmit list.1735if (dontDefer) {1736// TODO(cir): This assertion will need an additional condition when we1737// support incomplete functions.1738assert(funcOp.getFunctionType() == funcType);1739return funcOp;1740}17411742// All MSVC dtors other than the base dtor are linkonce_odr and delegate to1743// each other bottoming out wiht the base dtor. Therefore we emit non-base1744// dtors on usage, even if there is no dtor definition in the TU.1745if (isa_and_nonnull<CXXDestructorDecl>(d) &&1746getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),1747gd.getDtorType()))1748errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");17491750// This is the first use or definition of a mangled name. If there is a1751// deferred decl with this name, remember that we need to emit it at the end1752// of the file.1753auto ddi = deferredDecls.find(mangledName);1754if (ddi != deferredDecls.end()) {1755// Move the potentially referenced deferred decl to the1756// DeferredDeclsToEmit list, and remove it from DeferredDecls (since we1757// don't need it anymore).1758addDeferredDeclToEmit(ddi->second);1759deferredDecls.erase(ddi);17601761// Otherwise, there are cases we have to worry about where we're using a1762// declaration for which we must emit a definition but where we might not1763// find a top-level definition.1764// - member functions defined inline in their classes1765// - friend functions defined inline in some class1766// - special member functions with implicit definitions1767// If we ever change our AST traversal to walk into class methods, this1768// will be unnecessary.1769//1770// We also don't emit a definition for a function if it's going to be an1771// entry in a vtable, unless it's already marked as used.1772} else if (getLangOpts().CPlusPlus && d) {1773// Look for a declaration that's lexically in a record.1774for (const auto *fd = cast<FunctionDecl>(d)->getMostRecentDecl(); fd;1775fd = fd->getPreviousDecl()) {1776if (isa<CXXRecordDecl>(fd->getLexicalDeclContext())) {1777if (fd->doesThisDeclarationHaveABody()) {1778addDeferredDeclToEmit(gd.getWithDecl(fd));1779break;1780}1781}1782}1783}17841785return funcOp;1786}17871788cir::FuncOp1789CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,1790cir::FuncType funcType,1791const clang::FunctionDecl *funcDecl) {1792cir::FuncOp func;1793{1794mlir::OpBuilder::InsertionGuard guard(builder);17951796// Some global emissions are triggered while emitting a function, e.g.1797// void s() { x.method() }1798//1799// Be sure to insert a new function before a current one.1800CIRGenFunction *cgf = this->curCGF;1801if (cgf)1802builder.setInsertionPoint(cgf->curFn);18031804func = builder.create<cir::FuncOp>(loc, name, funcType);18051806assert(!cir::MissingFeatures::opFuncAstDeclAttr());1807assert(!cir::MissingFeatures::opFuncNoProto());18081809assert(func.isDeclaration() && "expected empty body");18101811// A declaration gets private visibility by default, but external linkage1812// as the default linkage.1813func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(1814&getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));1815mlir::SymbolTable::setSymbolVisibility(1816func, mlir::SymbolTable::Visibility::Private);18171818assert(!cir::MissingFeatures::opFuncExtraAttrs());18191820if (!cgf)1821theModule.push_back(func);1822}1823return func;1824}18251826mlir::SymbolTable::Visibility1827CIRGenModule::getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind glk) {1828switch (glk) {1829case cir::GlobalLinkageKind::InternalLinkage:1830case cir::GlobalLinkageKind::PrivateLinkage:1831return mlir::SymbolTable::Visibility::Private;1832case cir::GlobalLinkageKind::ExternalLinkage:1833case cir::GlobalLinkageKind::ExternalWeakLinkage:1834case cir::GlobalLinkageKind::LinkOnceODRLinkage:1835case cir::GlobalLinkageKind::AvailableExternallyLinkage:1836case cir::GlobalLinkageKind::CommonLinkage:1837case cir::GlobalLinkageKind::WeakAnyLinkage:1838case cir::GlobalLinkageKind::WeakODRLinkage:1839return mlir::SymbolTable::Visibility::Public;1840default: {1841llvm::errs() << "visibility not implemented for '"1842<< stringifyGlobalLinkageKind(glk) << "'\n";1843assert(0 && "not implemented");1844}1845}1846llvm_unreachable("linkage should be handled above!");1847}18481849cir::VisibilityKind CIRGenModule::getGlobalVisibilityKindFromClangVisibility(1850clang::VisibilityAttr::VisibilityType visibility) {1851switch (visibility) {1852case clang::VisibilityAttr::VisibilityType::Default:1853return cir::VisibilityKind::Default;1854case clang::VisibilityAttr::VisibilityType::Hidden:1855return cir::VisibilityKind::Hidden;1856case clang::VisibilityAttr::VisibilityType::Protected:1857return cir::VisibilityKind::Protected;1858}1859llvm_unreachable("unexpected visibility value");1860}18611862cir::VisibilityAttr1863CIRGenModule::getGlobalVisibilityAttrFromDecl(const Decl *decl) {1864const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();1865cir::VisibilityAttr cirVisibility =1866cir::VisibilityAttr::get(&getMLIRContext());1867if (va) {1868cirVisibility = cir::VisibilityAttr::get(1869&getMLIRContext(),1870getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));1871}1872return cirVisibility;1873}18741875void CIRGenModule::release() {1876emitDeferred();1877applyReplacements();18781879// There's a lot of code that is not implemented yet.1880assert(!cir::MissingFeatures::cgmRelease());1881}18821883void CIRGenModule::emitAliasForGlobal(StringRef mangledName,1884mlir::Operation *op, GlobalDecl aliasGD,1885cir::FuncOp aliasee,1886cir::GlobalLinkageKind linkage) {18871888auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());1889assert(aliasFD && "expected FunctionDecl");18901891// The aliasee function type is different from the alias one, this difference1892// is specific to CIR because in LLVM the ptr types are already erased at this1893// point.1894const CIRGenFunctionInfo &fnInfo =1895getTypes().arrangeCXXStructorDeclaration(aliasGD);1896cir::FuncType fnType = getTypes().getFunctionType(fnInfo);18971898cir::FuncOp alias =1899createCIRFunction(getLoc(aliasGD.getDecl()->getSourceRange()),1900mangledName, fnType, aliasFD);1901alias.setAliasee(aliasee.getName());1902alias.setLinkage(linkage);1903// Declarations cannot have public MLIR visibility, just mark them private1904// but this really should have no meaning since CIR should not be using1905// this information to derive linkage information.1906mlir::SymbolTable::setSymbolVisibility(1907alias, mlir::SymbolTable::Visibility::Private);19081909// Alias constructors and destructors are always unnamed_addr.1910assert(!cir::MissingFeatures::opGlobalUnnamedAddr());19111912// Switch any previous uses to the alias.1913if (op) {1914errorNYI(aliasFD->getSourceRange(), "emitAliasForGlobal: previous uses");1915} else {1916// Name already set by createCIRFunction1917}19181919// Finally, set up the alias with its proper name and attributes.1920setCommonAttributes(aliasGD, alias);1921}19221923mlir::Type CIRGenModule::convertType(QualType type) {1924return genTypes.convertType(type);1925}19261927bool CIRGenModule::verifyModule() const {1928// Verify the module after we have finished constructing it, this will1929// check the structural properties of the IR and invoke any specific1930// verifiers we have on the CIR operations.1931return mlir::verify(theModule).succeeded();1932}19331934// TODO(cir): this can be shared with LLVM codegen.1935CharUnits CIRGenModule::computeNonVirtualBaseClassOffset(1936const CXXRecordDecl *derivedClass,1937llvm::iterator_range<CastExpr::path_const_iterator> path) {1938CharUnits offset = CharUnits::Zero();19391940const ASTContext &astContext = getASTContext();1941const CXXRecordDecl *rd = derivedClass;19421943for (const CXXBaseSpecifier *base : path) {1944assert(!base->isVirtual() && "Should not see virtual bases here!");19451946// Get the layout.1947const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);19481949const auto *baseDecl = cast<CXXRecordDecl>(1950base->getType()->castAs<clang::RecordType>()->getDecl());19511952// Add the offset.1953offset += layout.getBaseClassOffset(baseDecl);19541955rd = baseDecl;1956}19571958return offset;1959}19601961DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,1962llvm::StringRef feature) {1963unsigned diagID = diags.getCustomDiagID(1964DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");1965return diags.Report(loc, diagID) << feature;1966}19671968DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,1969llvm::StringRef feature) {1970return errorNYI(loc.getBegin(), feature) << loc;1971}197219731974