diff options
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 508 |
1 files changed, 359 insertions, 149 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 4e8e120d89df..12d602fed693 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -47,6 +47,8 @@ #include "clang/CodeGen/BackendUtil.h" #include "clang/CodeGen/ConstantInitBuilder.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Analysis/TargetLibraryInfo.h" @@ -58,14 +60,16 @@ #include "llvm/IR/Module.h" #include "llvm/IR/ProfileSummary.h" #include "llvm/ProfileData/InstrProfReader.h" +#include "llvm/ProfileData/SampleProf.h" #include "llvm/Support/CRC.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MD5.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/X86TargetParser.h" +#include "llvm/Support/xxhash.h" +#include <optional> using namespace clang; using namespace CodeGen; @@ -120,9 +124,10 @@ CodeGenModule::CodeGenModule(ASTContext &C, BFloatTy = llvm::Type::getBFloatTy(LLVMContext); FloatTy = llvm::Type::getFloatTy(LLVMContext); DoubleTy = llvm::Type::getDoubleTy(LLVMContext); - PointerWidthInBits = C.getTargetInfo().getPointerWidth(0); + PointerWidthInBits = C.getTargetInfo().getPointerWidth(LangAS::Default); PointerAlignInBytes = - C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(0)).getQuantity(); + C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(LangAS::Default)) + .getQuantity(); SizeSizeInBytes = C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth()).getQuantity(); IntAlignInBytes = @@ -137,6 +142,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const llvm::DataLayout &DL = M.getDataLayout(); AllocaInt8PtrTy = Int8Ty->getPointerTo(DL.getAllocaAddrSpace()); GlobalsInt8PtrTy = Int8Ty->getPointerTo(DL.getDefaultGlobalsAddressSpace()); + ConstGlobalsPtrTy = Int8Ty->getPointerTo( + C.getTargetAddressSpace(GetGlobalConstantAddressSpace())); ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace(); // Build C++20 Module initializers. @@ -179,15 +186,11 @@ CodeGenModule::CodeGenModule(ASTContext &C, if (CodeGenOpts.hasProfileClangUse()) { auto ReaderOrErr = llvm::IndexedInstrProfReader::create( CodeGenOpts.ProfileInstrumentUsePath, CodeGenOpts.ProfileRemappingFile); - if (auto E = ReaderOrErr.takeError()) { - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "Could not read profile %0: %1"); - llvm::handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) { - getDiags().Report(DiagID) << CodeGenOpts.ProfileInstrumentUsePath - << EI.message(); - }); - } else - PGOReader = std::move(ReaderOrErr.get()); + // We're checking for profile read errors in CompilerInvocation, so if + // there was an error it should've already been caught. If it hasn't been + // somehow, trip an assertion. + assert(ReaderOrErr); + PGOReader = std::move(ReaderOrErr.get()); } // If coverage mapping generation is enabled, create the @@ -205,22 +208,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, Path = Entry.second + Path.substr(Entry.first.size()); break; } - llvm::MD5 Md5; - Md5.update(Path); - llvm::MD5::MD5Result R; - Md5.final(R); - SmallString<32> Str; - llvm::MD5::stringifyResult(R, Str); - // Convert MD5hash to Decimal. Demangler suffixes can either contain - // numbers or characters but not both. - llvm::APInt IntHash(128, Str.str(), 16); - // Prepend "__uniq" before the hash for tools like profilers to understand - // that this symbol is of internal linkage type. The "__uniq" is the - // pre-determined prefix that is used to tell tools that this symbol was - // created with -funique-internal-linakge-symbols and the tools can strip or - // keep the prefix as needed. - ModuleNameHash = (Twine(".__uniq.") + - Twine(toString(IntHash, /* Radix = */ 10, /* Signed = */false))).str(); + ModuleNameHash = llvm::getUniqueInternalLinkagePostfix(Path); } } @@ -521,7 +509,7 @@ static void setVisibilityFromDLLStorageClass(const clang::LangOptions &LO, void CodeGenModule::Release() { Module *Primary = getContext().getModuleForCodeGen(); - if (CXX20ModuleInits && Primary && !Primary->isModuleMapModule()) + if (CXX20ModuleInits && Primary && !Primary->isHeaderLikeModule()) EmitModuleInitializers(Primary); EmitDeferred(); DeferredDecls.insert(EmittedDeferredDecls.begin(), @@ -531,6 +519,14 @@ void CodeGenModule::Release() { applyGlobalValReplacements(); applyReplacements(); emitMultiVersionFunctions(); + + if (Context.getLangOpts().IncrementalExtensions && + GlobalTopLevelStmtBlockInFlight.first) { + const TopLevelStmtDecl *TLSD = GlobalTopLevelStmtBlockInFlight.second; + GlobalTopLevelStmtBlockInFlight.first->FinishFunction(TLSD->getEndLoc()); + GlobalTopLevelStmtBlockInFlight = {nullptr, nullptr}; + } + if (CXX20ModuleInits && Primary && Primary->isInterfaceOrPartition()) EmitCXXModuleInitFunc(Primary); else @@ -560,6 +556,9 @@ void CodeGenModule::Release() { if (PGOStats.hasDiagnostics()) PGOStats.reportDiagnostics(getDiags(), getCodeGenOpts().MainFileName); } + llvm::stable_sort(GlobalCtors, [](const Structor &L, const Structor &R) { + return L.LexOrder < R.LexOrder; + }); EmitCtorList(GlobalCtors, "llvm.global_ctors"); EmitCtorList(GlobalDtors, "llvm.global_dtors"); EmitGlobalAnnotations(); @@ -573,6 +572,8 @@ void CodeGenModule::Release() { CodeGenFunction(*this).EmitCfiCheckFail(); CodeGenFunction(*this).EmitCfiCheckStub(); } + if (LangOpts.Sanitize.has(SanitizerKind::KCFI)) + finalizeKCFITypes(); emitAtAvailableLinkGuard(); if (Context.getTargetInfo().getTriple().isWasm()) EmitMainVoidAlias(); @@ -594,9 +595,8 @@ void CodeGenModule::Release() { } // Emit amdgpu_code_object_version module flag, which is code object version // times 100. - // ToDo: Enable module flag for all code object version when ROCm device - // library is ready. - if (getTarget().getTargetOpts().CodeObjectVersion == TargetOptions::COV_5) { + if (getTarget().getTargetOpts().CodeObjectVersion != + TargetOptions::COV_None) { getModule().addModuleFlag(llvm::Module::Error, "amdgpu_code_object_version", getTarget().getTargetOpts().CodeObjectVersion); @@ -689,6 +689,10 @@ void CodeGenModule::Release() { // Function ID tables for EH Continuation Guard. getModule().addModuleFlag(llvm::Module::Warning, "ehcontguard", 1); } + if (Context.getLangOpts().Kernel) { + // Note if we are compiling with /kernel. + getModule().addModuleFlag(llvm::Module::Warning, "ms-kernel", 1); + } if (CodeGenOpts.OptimizationLevel > 0 && CodeGenOpts.StrictVTablePointers) { // We don't support LTO with 2 with different StrictVTablePointers // FIXME: we could support it by stripping all the information introduced @@ -755,6 +759,15 @@ void CodeGenModule::Release() { CodeGenOpts.SanitizeCfiCanonicalJumpTables); } + if (LangOpts.Sanitize.has(SanitizerKind::KCFI)) { + getModule().addModuleFlag(llvm::Module::Override, "kcfi", 1); + // KCFI assumes patchable-function-prefix is the same for all indirectly + // called functions. Store the expected offset for code generation. + if (CodeGenOpts.PatchableFunctionEntryOffset) + getModule().addModuleFlag(llvm::Module::Override, "kcfi-offset", + CodeGenOpts.PatchableFunctionEntryOffset); + } + if (CodeGenOpts.CFProtectionReturn && Target.checkCFProtectionReturnSupported(getDiags())) { // Indicate that we want to instrument return control flow protection. @@ -769,12 +782,12 @@ void CodeGenModule::Release() { 1); } - if (CodeGenOpts.IBTSeal) - getModule().addModuleFlag(llvm::Module::Min, "ibt-seal", 1); - if (CodeGenOpts.FunctionReturnThunks) getModule().addModuleFlag(llvm::Module::Override, "function_return_thunk_extern", 1); + if (CodeGenOpts.IndirectBranchCSPrefix) + getModule().addModuleFlag(llvm::Module::Override, "indirect_branch_cs_prefix", 1); + // Add module metadata for return address signing (ignoring // non-leaf/all) and stack tagging. These are actually turned on by function // attributes, but we use module metadata to emit build attributes. This is @@ -965,14 +978,9 @@ void CodeGenModule::EmitOpenCLMetadata() { void CodeGenModule::EmitBackendOptionsMetadata( const CodeGenOptions CodeGenOpts) { - switch (getTriple().getArch()) { - default: - break; - case llvm::Triple::riscv32: - case llvm::Triple::riscv64: + if (getTriple().isRISCV()) { getModule().addModuleFlag(llvm::Module::Error, "SmallDataLimit", CodeGenOpts.SmallDataLimit); - break; } } @@ -1101,8 +1109,6 @@ llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) { void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const { - if (GV->hasDLLImportStorageClass()) - return; // Internal definitions always have default visibility. if (GV->hasLocalLinkage()) { GV->setVisibility(llvm::GlobalValue::DefaultVisibility); @@ -1113,6 +1119,21 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, // Set visibility for definitions, and for declarations if requested globally // or set explicitly. LinkageInfo LV = D->getLinkageAndVisibility(); + if (GV->hasDLLExportStorageClass() || GV->hasDLLImportStorageClass()) { + // Reject incompatible dlllstorage and visibility annotations. + if (!LV.isVisibilityExplicit()) + return; + if (GV->hasDLLExportStorageClass()) { + if (LV.getVisibility() == HiddenVisibility) + getDiags().Report(D->getLocation(), + diag::err_hidden_visibility_dllexport); + } else if (LV.getVisibility() != DefaultVisibility) { + getDiags().Report(D->getLocation(), + diag::err_non_default_visibility_dllimport); + } + return; + } + if (LV.isVisibilityExplicit() || getLangOpts().SetVisibilityForExternDecls || !GV->isDeclarationForLinker()) GV->setVisibility(GetLLVMVisibility(LV.getVisibility())); @@ -1320,6 +1341,20 @@ static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM, Out << ".resolver"; } +static void AppendTargetVersionMangling(const CodeGenModule &CGM, + const TargetVersionAttr *Attr, + raw_ostream &Out) { + if (Attr->isDefaultVersion()) + return; + Out << "._"; + llvm::SmallVector<StringRef, 8> Feats; + Attr->getFeatures(Feats); + for (const auto &Feat : Feats) { + Out << 'M'; + Out << Feat; + } +} + static void AppendTargetMangling(const CodeGenModule &CGM, const TargetAttr *Attr, raw_ostream &Out) { if (Attr->isDefaultVersion()) @@ -1327,21 +1362,21 @@ static void AppendTargetMangling(const CodeGenModule &CGM, Out << '.'; const TargetInfo &Target = CGM.getTarget(); - ParsedTargetAttr Info = - Attr->parse([&Target](StringRef LHS, StringRef RHS) { - // Multiversioning doesn't allow "no-${feature}", so we can - // only have "+" prefixes here. - assert(LHS.startswith("+") && RHS.startswith("+") && - "Features should always have a prefix."); - return Target.multiVersionSortPriority(LHS.substr(1)) > - Target.multiVersionSortPriority(RHS.substr(1)); - }); + ParsedTargetAttr Info = Target.parseTargetAttr(Attr->getFeaturesStr()); + llvm::sort(Info.Features, [&Target](StringRef LHS, StringRef RHS) { + // Multiversioning doesn't allow "no-${feature}", so we can + // only have "+" prefixes here. + assert(LHS.startswith("+") && RHS.startswith("+") && + "Features should always have a prefix."); + return Target.multiVersionSortPriority(LHS.substr(1)) > + Target.multiVersionSortPriority(RHS.substr(1)); + }); bool IsFirst = true; - if (!Info.Architecture.empty()) { + if (!Info.CPU.empty()) { IsFirst = false; - Out << "arch_" << Info.Architecture; + Out << "arch_" << Info.CPU; } for (StringRef Feat : Info.Features) { @@ -1365,14 +1400,27 @@ static void AppendTargetClonesMangling(const CodeGenModule &CGM, const TargetClonesAttr *Attr, unsigned VersionIndex, raw_ostream &Out) { - Out << '.'; - StringRef FeatureStr = Attr->getFeatureStr(VersionIndex); - if (FeatureStr.startswith("arch=")) - Out << "arch_" << FeatureStr.substr(sizeof("arch=") - 1); - else - Out << FeatureStr; + if (CGM.getTarget().getTriple().isAArch64()) { + StringRef FeatureStr = Attr->getFeatureStr(VersionIndex); + if (FeatureStr == "default") + return; + Out << "._"; + SmallVector<StringRef, 8> Features; + FeatureStr.split(Features, "+"); + for (auto &Feat : Features) { + Out << 'M'; + Out << Feat; + } + } else { + Out << '.'; + StringRef FeatureStr = Attr->getFeatureStr(VersionIndex); + if (FeatureStr.startswith("arch=")) + Out << "arch_" << FeatureStr.substr(sizeof("arch=") - 1); + else + Out << FeatureStr; - Out << '.' << Attr->getMangledIndex(VersionIndex); + Out << '.' << Attr->getMangledIndex(VersionIndex); + } } static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, @@ -1428,6 +1476,9 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, case MultiVersionKind::Target: AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out); break; + case MultiVersionKind::TargetVersion: + AppendTargetVersionMangling(CGM, FD->getAttr<TargetVersionAttr>(), Out); + break; case MultiVersionKind::TargetClones: AppendTargetClonesMangling(CGM, FD->getAttr<TargetClonesAttr>(), GD.getMultiVersionIndex(), Out); @@ -1581,9 +1632,10 @@ llvm::GlobalValue *CodeGenModule::GetGlobalValue(StringRef Name) { /// AddGlobalCtor - Add a function to the list that will be called before /// main() runs. void CodeGenModule::AddGlobalCtor(llvm::Function *Ctor, int Priority, + unsigned LexOrder, llvm::Constant *AssociatedData) { // FIXME: Type coercion of void()* types. - GlobalCtors.push_back(Structor(Priority, Ctor, AssociatedData)); + GlobalCtors.push_back(Structor(Priority, LexOrder, Ctor, AssociatedData)); } /// AddGlobalDtor - Add a function to the list that will be called @@ -1597,7 +1649,7 @@ void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, int Priority, } // FIXME: Type coercion of void()* types. - GlobalDtors.push_back(Structor(Priority, Dtor, nullptr)); + GlobalDtors.push_back(Structor(Priority, ~0U, Dtor, nullptr)); } void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) { @@ -1633,7 +1685,7 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) { // The LTO linker doesn't seem to like it when we set an alignment // on appending variables. Take it off as a workaround. - list->setAlignment(llvm::None); + list->setAlignment(std::nullopt); Fns.clear(); } @@ -1666,6 +1718,20 @@ llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) { return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString())); } +llvm::ConstantInt *CodeGenModule::CreateKCFITypeId(QualType T) { + if (auto *FnType = T->getAs<FunctionProtoType>()) + T = getContext().getFunctionType( + FnType->getReturnType(), FnType->getParamTypes(), + FnType->getExtProtoInfo().withExceptionSpec(EST_None)); + + std::string OutName; + llvm::raw_string_ostream Out(OutName); + getCXXABI().getMangleContext().mangleTypeName(T, Out); + + return llvm::ConstantInt::get(Int32Ty, + static_cast<uint32_t>(llvm::xxHash64(OutName))); +} + void CodeGenModule::SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info, llvm::Function *F, bool IsThunk) { @@ -1765,7 +1831,7 @@ void CodeGenModule::GenKernelArgMetadata(llvm::Function *Fn, // Get image and pipe access qualifier: if (ty->isImageType() || ty->isPipeType()) { const Decl *PDecl = parm; - if (auto *TD = dyn_cast<TypedefType>(ty)) + if (const auto *TD = ty->getAs<TypedefType>()) PDecl = TD->getDecl(); const OpenCLAccessAttr *A = PDecl->getAttr<OpenCLAccessAttr>(); if (A && A->isWriteOnly()) @@ -1935,7 +2001,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F) { llvm::AttrBuilder B(F->getContext()); - if (CodeGenOpts.UnwindTables) + if ((!D || !D->hasAttr<NoUwtableAttr>()) && CodeGenOpts.UnwindTables) B.addUWTableAttr(llvm::UWTableKind(CodeGenOpts.UnwindTables)); if (CodeGenOpts.StackClashProtector) @@ -1944,14 +2010,17 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, if (!hasUnwindExceptions(LangOpts)) B.addAttribute(llvm::Attribute::NoUnwind); - if (!D || !D->hasAttr<NoStackProtectorAttr>()) { - if (LangOpts.getStackProtector() == LangOptions::SSPOn) - B.addAttribute(llvm::Attribute::StackProtect); - else if (LangOpts.getStackProtector() == LangOptions::SSPStrong) - B.addAttribute(llvm::Attribute::StackProtectStrong); - else if (LangOpts.getStackProtector() == LangOptions::SSPReq) - B.addAttribute(llvm::Attribute::StackProtectReq); - } + if (D && D->hasAttr<NoStackProtectorAttr>()) + ; // Do nothing. + else if (D && D->hasAttr<StrictGuardStackCheckAttr>() && + LangOpts.getStackProtector() == LangOptions::SSPOn) + B.addAttribute(llvm::Attribute::StackProtectStrong); + else if (LangOpts.getStackProtector() == LangOptions::SSPOn) + B.addAttribute(llvm::Attribute::StackProtect); + else if (LangOpts.getStackProtector() == LangOptions::SSPStrong) + B.addAttribute(llvm::Attribute::StackProtectStrong); + else if (LangOpts.getStackProtector() == LangOptions::SSPReq) + B.addAttribute(llvm::Attribute::StackProtectReq); if (!D) { // If we don't have a declaration to control inlining, the function isn't @@ -2131,10 +2200,12 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD, const auto *FD = dyn_cast_or_null<FunctionDecl>(GD.getDecl()); FD = FD ? FD->getMostRecentDecl() : FD; const auto *TD = FD ? FD->getAttr<TargetAttr>() : nullptr; + const auto *TV = FD ? FD->getAttr<TargetVersionAttr>() : nullptr; + assert((!TD || !TV) && "both target_version and target specified"); const auto *SD = FD ? FD->getAttr<CPUSpecificAttr>() : nullptr; const auto *TC = FD ? FD->getAttr<TargetClonesAttr>() : nullptr; bool AddedAttr = false; - if (TD || SD || TC) { + if (TD || TV || SD || TC) { llvm::StringMap<bool> FeatureMap; getContext().getFunctionFeatureMap(FeatureMap, GD); @@ -2147,10 +2218,11 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD, // get and parse the target attribute so we can get the cpu for // the function. if (TD) { - ParsedTargetAttr ParsedAttr = TD->parse(); - if (!ParsedAttr.Architecture.empty() && - getTarget().isValidCPUName(ParsedAttr.Architecture)) { - TargetCPU = ParsedAttr.Architecture; + ParsedTargetAttr ParsedAttr = + Target.parseTargetAttr(TD->getFeaturesStr()); + if (!ParsedAttr.CPU.empty() && + getTarget().isValidCPUName(ParsedAttr.CPU)) { + TargetCPU = ParsedAttr.CPU; TuneCPU = ""; // Clear the tune CPU. } if (!ParsedAttr.Tune.empty() && @@ -2280,6 +2352,57 @@ void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD, F->addTypeMetadata(0, llvm::ConstantAsMetadata::get(CrossDsoTypeId)); } +void CodeGenModule::setKCFIType(const FunctionDecl *FD, llvm::Function *F) { + if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) + return; + + llvm::LLVMContext &Ctx = F->getContext(); + llvm::MDBuilder MDB(Ctx); + F->setMetadata(llvm::LLVMContext::MD_kcfi_type, + llvm::MDNode::get( + Ctx, MDB.createConstant(CreateKCFITypeId(FD->getType())))); +} + +static bool allowKCFIIdentifier(StringRef Name) { + // KCFI type identifier constants are only necessary for external assembly + // functions, which means it's safe to skip unusual names. Subset of + // MCAsmInfo::isAcceptableChar() and MCAsmInfoXCOFF::isAcceptableChar(). + return llvm::all_of(Name, [](const char &C) { + return llvm::isAlnum(C) || C == '_' || C == '.'; + }); +} + +void CodeGenModule::finalizeKCFITypes() { + llvm::Module &M = getModule(); + for (auto &F : M.functions()) { + // Remove KCFI type metadata from non-address-taken local functions. + bool AddressTaken = F.hasAddressTaken(); + if (!AddressTaken && F.hasLocalLinkage()) + F.eraseMetadata(llvm::LLVMContext::MD_kcfi_type); + + // Generate a constant with the expected KCFI type identifier for all + // address-taken function declarations to support annotating indirectly + // called assembly functions. + if (!AddressTaken || !F.isDeclaration()) + continue; + + const llvm::ConstantInt *Type; + if (const llvm::MDNode *MD = F.getMetadata(llvm::LLVMContext::MD_kcfi_type)) + Type = llvm::mdconst::extract<llvm::ConstantInt>(MD->getOperand(0)); + else + continue; + + StringRef Name = F.getName(); + if (!allowKCFIIdentifier(Name)) + continue; + + std::string Asm = (".weak __kcfi_typeid_" + Name + "\n.set __kcfi_typeid_" + + Name + ", " + Twine(Type->getZExtValue()) + "\n") + .str(); + M.appendModuleInlineAsm(Asm); + } +} + void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, bool IsIncompleteFunction, bool IsThunk) { @@ -2362,9 +2485,15 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, !CodeGenOpts.SanitizeCfiCanonicalJumpTables) CreateFunctionTypeMetadataForIcall(FD, F); + if (LangOpts.Sanitize.has(SanitizerKind::KCFI)) + setKCFIType(FD, F); + if (getLangOpts().OpenMP && FD->hasAttr<OMPDeclareSimdDeclAttr>()) getOpenMPRuntime().emitDeclareSimdFunction(FD, F); + if (CodeGenOpts.InlineMaxStackSize != UINT_MAX) + F->addFnAttr("inline-max-stacksize", llvm::utostr(CodeGenOpts.InlineMaxStackSize)); + if (const auto *CB = FD->getAttr<CallbackAttr>()) { // Annotate the callback behavior as metadata: // - The callback callee (as argument number). @@ -2521,21 +2650,23 @@ void CodeGenModule::EmitModuleInitializers(clang::Module *Primary) { // source, first Global Module Fragments, if present. if (auto GMF = Primary->getGlobalModuleFragment()) { for (Decl *D : getContext().getModuleInitializers(GMF)) { - assert(D->getKind() == Decl::Var && "GMF initializer decl is not a var?"); + if (isa<ImportDecl>(D)) + continue; + assert(isa<VarDecl>(D) && "GMF initializer decl is not a var?"); EmitTopLevelDecl(D); } } // Second any associated with the module, itself. for (Decl *D : getContext().getModuleInitializers(Primary)) { // Skip import decls, the inits for those are called explicitly. - if (D->getKind() == Decl::Import) + if (isa<ImportDecl>(D)) continue; EmitTopLevelDecl(D); } // Third any associated with the Privat eMOdule Fragment, if present. if (auto PMF = Primary->getPrivateModuleFragment()) { for (Decl *D : getContext().getModuleInitializers(PMF)) { - assert(D->getKind() == Decl::Var && "PMF initializer decl is not a var?"); + assert(isa<VarDecl>(D) && "PMF initializer decl is not a var?"); EmitTopLevelDecl(D); } } @@ -2719,9 +2850,10 @@ llvm::Constant *CodeGenModule::EmitAnnotationString(StringRef Str) { // Not found yet, create a new global. llvm::Constant *s = llvm::ConstantDataArray::getString(getLLVMContext(), Str); - auto *gv = - new llvm::GlobalVariable(getModule(), s->getType(), true, - llvm::GlobalValue::PrivateLinkage, s, ".str"); + auto *gv = new llvm::GlobalVariable( + getModule(), s->getType(), true, llvm::GlobalValue::PrivateLinkage, s, + ".str", nullptr, llvm::GlobalValue::NotThreadLocal, + ConstGlobalsPtrTy->getAddressSpace()); gv->setSection(AnnotationSection); gv->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); AStr = gv; @@ -2747,7 +2879,7 @@ llvm::Constant *CodeGenModule::EmitAnnotationLineNo(SourceLocation L) { llvm::Constant *CodeGenModule::EmitAnnotationArgs(const AnnotateAttr *Attr) { ArrayRef<Expr *> Exprs = {Attr->args_begin(), Attr->args_size()}; if (Exprs.empty()) - return llvm::ConstantPointerNull::get(GlobalsInt8PtrTy); + return llvm::ConstantPointerNull::get(ConstGlobalsPtrTy); llvm::FoldingSetNodeID ID; for (Expr *E : Exprs) { @@ -2797,8 +2929,8 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV, // Create the ConstantStruct for the global annotation. llvm::Constant *Fields[] = { llvm::ConstantExpr::getBitCast(GVInGlobalsAS, GlobalsInt8PtrTy), - llvm::ConstantExpr::getBitCast(AnnoGV, GlobalsInt8PtrTy), - llvm::ConstantExpr::getBitCast(UnitGV, GlobalsInt8PtrTy), + llvm::ConstantExpr::getBitCast(AnnoGV, ConstGlobalsPtrTy), + llvm::ConstantExpr::getBitCast(UnitGV, ConstGlobalsPtrTy), LineNoCst, Args, }; @@ -2890,46 +3022,44 @@ bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc, return true; } -bool CodeGenModule::isFunctionBlockedByProfileList(llvm::Function *Fn, - SourceLocation Loc) const { +ProfileList::ExclusionType +CodeGenModule::isFunctionBlockedByProfileList(llvm::Function *Fn, + SourceLocation Loc) const { const auto &ProfileList = getContext().getProfileList(); // If the profile list is empty, then instrument everything. if (ProfileList.isEmpty()) - return false; + return ProfileList::Allow; CodeGenOptions::ProfileInstrKind Kind = getCodeGenOpts().getProfileInstr(); // First, check the function name. - Optional<bool> V = ProfileList.isFunctionExcluded(Fn->getName(), Kind); - if (V) + if (auto V = ProfileList.isFunctionExcluded(Fn->getName(), Kind)) return *V; // Next, check the source location. - if (Loc.isValid()) { - Optional<bool> V = ProfileList.isLocationExcluded(Loc, Kind); - if (V) + if (Loc.isValid()) + if (auto V = ProfileList.isLocationExcluded(Loc, Kind)) return *V; - } // If location is unknown, this may be a compiler-generated function. Assume // it's located in the main file. auto &SM = Context.getSourceManager(); - if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { - Optional<bool> V = ProfileList.isFileExcluded(MainFile->getName(), Kind); - if (V) + if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) + if (auto V = ProfileList.isFileExcluded(MainFile->getName(), Kind)) return *V; - } - return ProfileList.getDefault(); + return ProfileList.getDefault(Kind); } -bool CodeGenModule::isFunctionBlockedFromProfileInstr( - llvm::Function *Fn, SourceLocation Loc) const { - if (isFunctionBlockedByProfileList(Fn, Loc)) - return true; +ProfileList::ExclusionType +CodeGenModule::isFunctionBlockedFromProfileInstr(llvm::Function *Fn, + SourceLocation Loc) const { + auto V = isFunctionBlockedByProfileList(Fn, Loc); + if (V != ProfileList::Allow) + return V; auto NumGroups = getCodeGenOpts().ProfileTotalFunctionGroups; if (NumGroups > 1) { auto Group = llvm::crc32(arrayRefFromStringRef(Fn->getName())) % NumGroups; if (Group != getCodeGenOpts().ProfileSelectedFunctionGroup) - return true; + return ProfileList::Skip; } - return false; + return ProfileList::Allow; } bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) { @@ -2955,7 +3085,7 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) { // we have if the level of the declare target attribute is -1. Note that we // check somewhere else if we should emit this at all. if (LangOpts.OpenMP >= 50 && !LangOpts.OpenMPSimd) { - llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = + std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = OMPDeclareTargetDeclAttr::getActiveAttr(Global); if (!ActiveAttr || (*ActiveAttr)->getLevel() != (unsigned)-1) return false; @@ -3113,7 +3243,7 @@ ConstantAddress CodeGenModule::GetWeakRefReference(const ValueDecl *VD) { // See if there is already something with the target's name in the module. llvm::GlobalValue *Entry = GetGlobalValue(AA->getAliasee()); if (Entry) { - unsigned AS = getContext().getTargetAddressSpace(VD->getType()); + unsigned AS = getTypes().getTargetAddressSpace(VD->getType()); auto Ptr = llvm::ConstantExpr::getBitCast(Entry, DeclTy->getPointerTo(AS)); return ConstantAddress(Ptr, DeclTy, Alignment); } @@ -3219,16 +3349,18 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { !Context.isMSStaticDataMemberInlineDefinition(VD)) { if (LangOpts.OpenMP) { // Emit declaration of the must-be-emitted declare target variable. - if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = + if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { bool UnifiedMemoryEnabled = getOpenMPRuntime().hasRequiresUnifiedSharedMemory(); - if (*Res == OMPDeclareTargetDeclAttr::MT_To && + if ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && !UnifiedMemoryEnabled) { (void)GetAddrOfGlobalVar(VD); } else { assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || - (*Res == OMPDeclareTargetDeclAttr::MT_To && + ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && UnifiedMemoryEnabled)) && "Link clause or to clause with unified memory expected."); (void)getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); @@ -3271,6 +3403,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // The value must be emitted, but cannot be emitted eagerly. assert(!MayBeEmittedEagerly(Global)); addDeferredDeclToEmit(GD); + EmittedDeferredDecls[MangledName] = GD; } else { // Otherwise, remember that we saw a deferred decl with this name. The // first use of the mangled name will cause it to move into @@ -3526,12 +3659,18 @@ static unsigned TargetMVPriority(const TargetInfo &TI, const CodeGenFunction::MultiVersionResolverOption &RO) { unsigned Priority = 0; - for (StringRef Feat : RO.Conditions.Features) + unsigned NumFeatures = 0; + for (StringRef Feat : RO.Conditions.Features) { Priority = std::max(Priority, TI.multiVersionSortPriority(Feat)); + NumFeatures++; + } if (!RO.Conditions.Architecture.empty()) Priority = std::max( Priority, TI.multiVersionSortPriority(RO.Conditions.Architecture)); + + Priority += TI.multiVersionFeatureCost() * NumFeatures; + return Priority; } @@ -3576,13 +3715,19 @@ void CodeGenModule::emitMultiVersionFunctions() { } assert(Func && "This should have just been created"); } - - const auto *TA = CurFD->getAttr<TargetAttr>(); - llvm::SmallVector<StringRef, 8> Feats; - TA->getAddedFeatures(Feats); - - Options.emplace_back(cast<llvm::Function>(Func), - TA->getArchitecture(), Feats); + if (CurFD->getMultiVersionKind() == MultiVersionKind::Target) { + const auto *TA = CurFD->getAttr<TargetAttr>(); + llvm::SmallVector<StringRef, 8> Feats; + TA->getAddedFeatures(Feats); + Options.emplace_back(cast<llvm::Function>(Func), + TA->getArchitecture(), Feats); + } else { + const auto *TVA = CurFD->getAttr<TargetVersionAttr>(); + llvm::SmallVector<StringRef, 8> Feats; + TVA->getFeatures(Feats); + Options.emplace_back(cast<llvm::Function>(Func), + /*Architecture*/ "", Feats); + } }); } else if (FD->isTargetClonesMultiVersion()) { const auto *TC = FD->getAttr<TargetClonesAttr>(); @@ -3612,10 +3757,19 @@ void CodeGenModule::emitMultiVersionFunctions() { StringRef Architecture; llvm::SmallVector<StringRef, 1> Feature; - if (Version.startswith("arch=")) - Architecture = Version.drop_front(sizeof("arch=") - 1); - else if (Version != "default") - Feature.push_back(Version); + if (getTarget().getTriple().isAArch64()) { + if (Version != "default") { + llvm::SmallVector<StringRef, 8> VerFeats; + Version.split(VerFeats, "+"); + for (auto &CurFeat : VerFeats) + Feature.push_back(CurFeat.trim()); + } + } else { + if (Version.startswith("arch=")) + Architecture = Version.drop_front(sizeof("arch=") - 1); + else if (Version != "default") + Feature.push_back(Version); + } Options.emplace_back(cast<llvm::Function>(Func), Architecture, Feature); } @@ -3675,7 +3829,7 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { if (getTarget().supportsIFunc()) { ResolverType = llvm::FunctionType::get( llvm::PointerType::get(DeclTy, - Context.getTargetAddressSpace(FD->getType())), + getTypes().getTargetAddressSpace(FD->getType())), false); } else { @@ -3813,8 +3967,8 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { // cpu_dispatch will be emitted in this translation unit. if (getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion()) { llvm::Type *ResolverType = llvm::FunctionType::get( - llvm::PointerType::get( - DeclTy, getContext().getTargetAddressSpace(FD->getType())), + llvm::PointerType::get(DeclTy, + getTypes().getTargetAddressSpace(FD->getType())), false); llvm::Constant *Resolver = GetOrCreateLLVMFunction( MangledName + ".resolver", ResolverType, GlobalDecl{}, @@ -3917,7 +4071,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( // (If function is requested for a definition, we always need to create a new // function, not just return a bitcast.) if (!IsForDefinition) - return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo()); + return llvm::ConstantExpr::getBitCast( + Entry, Ty->getPointerTo(Entry->getAddressSpace())); } // This function doesn't have a complete type (for example, the return @@ -3958,7 +4113,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( } llvm::Constant *BC = llvm::ConstantExpr::getBitCast( - F, Entry->getValueType()->getPointerTo()); + F, Entry->getValueType()->getPointerTo(Entry->getAddressSpace())); addGlobalValReplacement(Entry, BC); } @@ -3974,7 +4129,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( // All MSVC dtors other than the base dtor are linkonce_odr and delegate to // each other bottoming out with the base dtor. Therefore we emit non-base // dtors on usage, even if there is no dtor definition in the TU. - if (D && isa<CXXDestructorDecl>(D) && + if (isa_and_nonnull<CXXDestructorDecl>(D) && getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D), GD.getDtorType())) addDeferredDeclToEmit(GD); @@ -3988,6 +4143,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we // don't need it anymore). addDeferredDeclToEmit(DDI->second); + EmittedDeferredDecls[DDI->first] = DDI->second; DeferredDecls.erase(DDI); // Otherwise, there are cases we have to worry about where we're @@ -4021,8 +4177,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( return F; } - llvm::Type *PTy = llvm::PointerType::getUnqual(Ty); - return llvm::ConstantExpr::getBitCast(F, PTy); + return llvm::ConstantExpr::getBitCast(F, + Ty->getPointerTo(F->getAddressSpace())); } /// GetAddrOfFunction - Return the address of the given function. If Ty is @@ -4071,8 +4227,9 @@ llvm::Constant *CodeGenModule::GetFunctionStart(const ValueDecl *Decl) { llvm::GlobalValue *F = cast<llvm::GlobalValue>(GetAddrOfFunction(Decl)->stripPointerCasts()); - return llvm::ConstantExpr::getBitCast(llvm::NoCFIValue::get(F), - llvm::Type::getInt8PtrTy(VMContext)); + return llvm::ConstantExpr::getBitCast( + llvm::NoCFIValue::get(F), + llvm::Type::getInt8PtrTy(VMContext, F->getAddressSpace())); } static const FunctionDecl * @@ -4269,6 +4426,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty, // Move the potentially referenced deferred decl to the DeferredDeclsToEmit // list, and remove it from DeferredDecls (since we don't need it anymore). addDeferredDeclToEmit(DDI->second); + EmittedDeferredDecls[DDI->first] = DDI->second; DeferredDecls.erase(DDI); } @@ -4408,7 +4566,7 @@ CodeGenModule::GetAddrOfGlobal(GlobalDecl GD, ForDefinition_t IsForDefinition) { llvm::GlobalVariable *CodeGenModule::CreateOrReplaceCXXRuntimeVariable( StringRef Name, llvm::Type *Ty, llvm::GlobalValue::LinkageTypes Linkage, - unsigned Alignment) { + llvm::Align Alignment) { llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name); llvm::GlobalVariable *OldGV = nullptr; @@ -4444,7 +4602,7 @@ llvm::GlobalVariable *CodeGenModule::CreateOrReplaceCXXRuntimeVariable( !GV->hasAvailableExternallyLinkage()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); - GV->setAlignment(llvm::MaybeAlign(Alignment)); + GV->setAlignment(Alignment); return GV; } @@ -4673,13 +4831,19 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, llvm::TrackingVH<llvm::Constant> Init; bool NeedsGlobalCtor = false; + // Whether the definition of the variable is available externally. + // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable + // since this is the job for its original source. + bool IsDefinitionAvailableExternally = + getContext().GetGVALinkageForVariable(D) == GVA_AvailableExternally; bool NeedsGlobalDtor = + !IsDefinitionAvailableExternally && D->needsDestruction(getContext()) == QualType::DK_cxx_destructor; const VarDecl *InitDecl; const Expr *InitExpr = D->getAnyInitializer(InitDecl); - Optional<ConstantEmitter> emitter; + std::optional<ConstantEmitter> emitter; // CUDA E.2.4.1 "__shared__ variables cannot have an initialization // as part of their declaration." Sema has already checked for @@ -4727,7 +4891,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, if (InitDecl->hasFlexibleArrayInit(getContext())) ErrorUnsupported(D, "flexible array initializer"); Init = EmitNullConstant(T); - NeedsGlobalCtor = true; + + if (!IsDefinitionAvailableExternally) + NeedsGlobalCtor = true; } else { ErrorUnsupported(D, "static initializer"); Init = llvm::UndefValue::get(getTypes().ConvertType(T)); @@ -4837,7 +5003,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, CharUnits AlignVal = getContext().getDeclAlign(D); // Check for alignment specifed in an 'omp allocate' directive. - if (llvm::Optional<CharUnits> AlignValFromAllocate = + if (std::optional<CharUnits> AlignValFromAllocate = getOMPAllocateAlignment(D)) AlignVal = *AlignValFromAllocate; GV->setAlignment(AlignVal.getAsAlign()); @@ -5331,7 +5497,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { // Emit global alias debug information. if (isa<VarDecl>(D)) if (CGDebugInfo *DI = getModuleDebugInfo()) - DI->EmitGlobalAlias(cast<llvm::GlobalValue>(GA->getAliasee()), GD); + DI->EmitGlobalAlias(cast<llvm::GlobalValue>(GA->getAliasee()->stripPointerCasts()), GD); } void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) { @@ -5468,7 +5634,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { switch (CFRuntime) { default: break; - case LangOptions::CoreFoundationABI::Swift: LLVM_FALLTHROUGH; + case LangOptions::CoreFoundationABI::Swift: [[fallthrough]]; case LangOptions::CoreFoundationABI::Swift5_0: CFConstantStringClassName = Triple.isOSDarwin() ? "$s15SwiftFoundation19_NSCFConstantStringCN" @@ -5546,7 +5712,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { // String pointer. llvm::Constant *C = nullptr; if (isUTF16) { - auto Arr = llvm::makeArrayRef( + auto Arr = llvm::ArrayRef( reinterpret_cast<uint16_t *>(const_cast<char *>(Entry.first().data())), Entry.first().size() / 2); C = llvm::ConstantDataArray::get(VMContext, Arr); @@ -5891,7 +6057,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( LangAS AddrSpace = VD ? GetGlobalVarAddressSpace(VD) : MaterializedType.getAddressSpace(); - Optional<ConstantEmitter> emitter; + std::optional<ConstantEmitter> emitter; llvm::Constant *InitialValue = nullptr; bool Constant = false; llvm::Type *Type; @@ -5929,10 +6095,13 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(), /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); if (emitter) emitter->finalize(GV); - setGVProperties(GV, VD); - if (GV->getDLLStorageClass() == llvm::GlobalVariable::DLLExportStorageClass) - // The reference temporary should never be dllexport. - GV->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass); + // Don't assign dllimport or dllexport to local linkage globals. + if (!llvm::GlobalValue::isLocalLinkage(Linkage)) { + setGVProperties(GV, VD); + if (GV->getDLLStorageClass() == llvm::GlobalVariable::DLLExportStorageClass) + // The reference temporary should never be dllexport. + GV->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass); + } GV->setAlignment(Align.getAsAlign()); if (supportsCOMDAT() && GV->isWeakForLinker()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); @@ -6058,6 +6227,39 @@ void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) { EmitDeclContext(LSD); } +void CodeGenModule::EmitTopLevelStmt(const TopLevelStmtDecl *D) { + std::unique_ptr<CodeGenFunction> &CurCGF = + GlobalTopLevelStmtBlockInFlight.first; + + // We emitted a top-level stmt but after it there is initialization. + // Stop squashing the top-level stmts into a single function. + if (CurCGF && CXXGlobalInits.back() != CurCGF->CurFn) { + CurCGF->FinishFunction(D->getEndLoc()); + CurCGF = nullptr; + } + + if (!CurCGF) { + // void __stmts__N(void) + // FIXME: Ask the ABI name mangler to pick a name. + std::string Name = "__stmts__" + llvm::utostr(CXXGlobalInits.size()); + FunctionArgList Args; + QualType RetTy = getContext().VoidTy; + const CGFunctionInfo &FnInfo = + getTypes().arrangeBuiltinFunctionDeclaration(RetTy, Args); + llvm::FunctionType *FnTy = getTypes().GetFunctionType(FnInfo); + llvm::Function *Fn = llvm::Function::Create( + FnTy, llvm::GlobalValue::InternalLinkage, Name, &getModule()); + + CurCGF.reset(new CodeGenFunction(*this)); + GlobalTopLevelStmtBlockInFlight.second = D; + CurCGF->StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args, + D->getBeginLoc(), D->getBeginLoc()); + CXXGlobalInits.push_back(Fn); + } + + CurCGF->EmitStmt(D->getStmt()); +} + void CodeGenModule::EmitDeclContext(const DeclContext *DC) { for (auto *I : DC->decls()) { // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope @@ -6125,7 +6327,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { TSK_ExplicitInstantiationDefinition && Spec->hasDefinition()) DI->completeTemplateDefinition(*Spec); - } LLVM_FALLTHROUGH; + } [[fallthrough]]; case Decl::CXXRecord: { CXXRecordDecl *CRD = cast<CXXRecordDecl>(D); if (CGDebugInfo *DI = getModuleDebugInfo()) { @@ -6267,6 +6469,10 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { break; } + case Decl::TopLevelStmt: + EmitTopLevelStmt(cast<TopLevelStmtDecl>(D)); + break; + case Decl::Import: { auto *Import = cast<ImportDecl>(D); @@ -6363,6 +6569,10 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { DI->EmitAndRetainType(getContext().getEnumType(cast<EnumDecl>(D))); break; + case Decl::HLSLBuffer: + getHLSLRuntime().addBuffer(cast<HLSLBufferDecl>(D)); + break; + default: // Make sure we handled everything we should, every other kind is a // non-top-level decl. FIXME: Would be nice to have an isTopLevelDeclKind |