Mercurial > hg > CbC > CbC_llvm
diff clang/lib/CodeGen/CGDeclCXX.cpp @ 236:c4bab56944e8 llvm-original
LLVM 16
author | kono |
---|---|
date | Wed, 09 Nov 2022 17:45:10 +0900 |
parents | 70dce7da266c |
children | 1f2b6ac9f198 |
line wrap: on
line diff
--- a/clang/lib/CodeGen/CGDeclCXX.cpp Wed Jul 21 10:27:27 2021 +0900 +++ b/clang/lib/CodeGen/CGDeclCXX.cpp Wed Nov 09 17:45:10 2022 +0900 @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "CGCXXABI.h" +#include "CGHLSLRuntime.h" #include "CGObjCRuntime.h" #include "CGOpenMPRuntime.h" #include "CodeGenFunction.h" @@ -136,6 +137,7 @@ } // Otherwise, the standard logic requires a helper function. } else { + Addr = Addr.getElementBitCast(CGF.ConvertTypeForMem(Type)); Func = CodeGenFunction(CGM) .generateDestroyHelper(Addr, Type, CGF.getDestroyer(DtorKind), CGF.needsEHCleanup(DtorKind), &D); @@ -172,7 +174,7 @@ } void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, - llvm::Constant *DeclPtr, + llvm::GlobalVariable *GV, bool PerformInit) { const Expr *Init = D.getInit(); @@ -194,14 +196,16 @@ // "shared" address space qualifier, but the constructor of StructWithCtor // expects "this" in the "generic" address space. unsigned ExpectedAddrSpace = getContext().getTargetAddressSpace(T); - unsigned ActualAddrSpace = DeclPtr->getType()->getPointerAddressSpace(); + unsigned ActualAddrSpace = GV->getAddressSpace(); + llvm::Constant *DeclPtr = GV; if (ActualAddrSpace != ExpectedAddrSpace) { - llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(T); - llvm::PointerType *PTy = llvm::PointerType::get(LTy, ExpectedAddrSpace); + llvm::PointerType *PTy = llvm::PointerType::getWithSamePointeeType( + GV->getType(), ExpectedAddrSpace); DeclPtr = llvm::ConstantExpr::getAddrSpaceCast(DeclPtr, PTy); } - ConstantAddress DeclAddr(DeclPtr, getContext().getDeclAlign(&D)); + ConstantAddress DeclAddr( + DeclPtr, GV->getValueType(), getContext().getDeclAlign(&D)); if (!T->isReferenceType()) { if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && @@ -422,9 +426,8 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction( llvm::FunctionType *FTy, const Twine &Name, const CGFunctionInfo &FI, - SourceLocation Loc, bool TLS) { - llvm::Function *Fn = llvm::Function::Create( - FTy, llvm::GlobalValue::InternalLinkage, Name, &getModule()); + SourceLocation Loc, bool TLS, llvm::GlobalVariable::LinkageTypes Linkage) { + llvm::Function *Fn = llvm::Function::Create(FTy, Linkage, Name, &getModule()); if (!getLangOpts().AppleKext && !TLS) { // Set the section if needed. @@ -432,7 +435,8 @@ Fn->setSection(Section); } - SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); + if (Linkage == llvm::GlobalVariable::InternalLinkage) + SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); Fn->setCallingConv(getRuntimeCC()); @@ -455,8 +459,8 @@ !isInNoSanitizeList(SanitizerKind::KernelHWAddress, Fn, Loc)) Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress); - if (getLangOpts().Sanitize.has(SanitizerKind::MemTag) && - !isInNoSanitizeList(SanitizerKind::MemTag, Fn, Loc)) + if (getLangOpts().Sanitize.has(SanitizerKind::MemtagStack) && + !isInNoSanitizeList(SanitizerKind::MemtagStack, Fn, Loc)) Fn->addFnAttr(llvm::Attribute::SanitizeMemTag); if (getLangOpts().Sanitize.has(SanitizerKind::Thread) && @@ -549,13 +553,25 @@ CXXThreadLocalInits.push_back(Fn); CXXThreadLocalInitVars.push_back(D); } else if (PerformInit && ISA) { - EmitPointerToInitFunc(D, Addr, Fn, ISA); + // Contract with backend that "init_seg(compiler)" corresponds to priority + // 200 and "init_seg(lib)" corresponds to priority 400. + int Priority = -1; + if (ISA->getSection() == ".CRT$XCC") + Priority = 200; + else if (ISA->getSection() == ".CRT$XCL") + Priority = 400; + + if (Priority != -1) + AddGlobalCtor(Fn, Priority, ~0U, COMDATKey); + else + EmitPointerToInitFunc(D, Addr, Fn, ISA); } else if (auto *IPA = D->getAttr<InitPriorityAttr>()) { OrderGlobalInitsOrStermFinalizers Key(IPA->getPriority(), PrioritizedCXXGlobalInits.size()); PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn)); } else if (isTemplateInstantiation(D->getTemplateSpecializationKind()) || - getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR) { + getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR || + D->hasAttr<SelectAnyAttr>()) { // C++ [basic.start.init]p2: // Definitions of explicitly specialized class template static data // members have ordered initialization. Other class template static data @@ -568,17 +584,36 @@ // group with the global being initialized. On most platforms, this is a // minor startup time optimization. In the MS C++ ABI, there are no guard // variables, so this COMDAT key is required for correctness. - AddGlobalCtor(Fn, 65535, COMDATKey); - if (getTarget().getCXXABI().isMicrosoft() && COMDATKey) { - // In The MS C++, MS add template static data member in the linker - // drective. - addUsedGlobal(COMDATKey); - } - } else if (D->hasAttr<SelectAnyAttr>()) { + // // SelectAny globals will be comdat-folded. Put the initializer into a // COMDAT group associated with the global, so the initializers get folded // too. - AddGlobalCtor(Fn, 65535, COMDATKey); + I = DelayedCXXInitPosition.find(D); + // CXXGlobalInits.size() is the lex order number for the next deferred + // VarDecl. Use it when the current VarDecl is non-deferred. Although this + // lex order number is shared between current VarDecl and some following + // VarDecls, their order of insertion into `llvm.global_ctors` is the same + // as the lexing order and the following stable sort would preserve such + // order. + unsigned LexOrder = + I == DelayedCXXInitPosition.end() ? CXXGlobalInits.size() : I->second; + AddGlobalCtor(Fn, 65535, LexOrder, COMDATKey); + if (COMDATKey && (getTriple().isOSBinFormatELF() || + getTarget().getCXXABI().isMicrosoft())) { + // When COMDAT is used on ELF or in the MS C++ ABI, the key must be in + // llvm.used to prevent linker GC. + addUsedGlobal(COMDATKey); + } + + // If we used a COMDAT key for the global ctor, the init function can be + // discarded if the global ctor entry is discarded. + // FIXME: Do we need to restrict this to ELF and Wasm? + llvm::Comdat *C = Addr->getComdat(); + if (COMDATKey && C && + (getTarget().getTriple().isOSBinFormatELF() || + getTarget().getTriple().isOSBinFormatWasm())) { + Fn->setComdat(C); + } } else { I = DelayedCXXInitPosition.find(D); // Re-do lookup in case of re-hash. if (I == DelayedCXXInitPosition.end()) { @@ -603,6 +638,130 @@ CXXThreadLocals.clear(); } +/* Build the initializer for a C++20 module: + This is arranged to be run only once regardless of how many times the module + might be included transitively. This arranged by using a control variable. + + First we call any initializers for imported modules. + We then call initializers for the Global Module Fragment (if present) + We then call initializers for the current module. + We then call initializers for the Private Module Fragment (if present) +*/ + +void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) { + while (!CXXGlobalInits.empty() && !CXXGlobalInits.back()) + CXXGlobalInits.pop_back(); + + // We create the function, even if it is empty, since an importer of this + // module will refer to it unconditionally (for the current implementation + // there is no way for the importer to know that an importee does not need + // an initializer to be run). + + // Module initializers for imported modules are emitted first. + // Collect the modules that we import + SmallVector<Module *> AllImports; + // Ones that we export + for (auto I : Primary->Exports) + AllImports.push_back(I.getPointer()); + // Ones that we only import. + for (Module *M : Primary->Imports) + AllImports.push_back(M); + + SmallVector<llvm::Function *, 8> ModuleInits; + for (Module *M : AllImports) { + // No Itanium initializer in header like modules. + if (M->isHeaderLikeModule()) + continue; // TODO: warn of mixed use of module map modules and C++20? + llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); + SmallString<256> FnName; + { + llvm::raw_svector_ostream Out(FnName); + cast<ItaniumMangleContext>(getCXXABI().getMangleContext()) + .mangleModuleInitializer(M, Out); + } + assert(!GetGlobalValue(FnName.str()) && + "We should only have one use of the initializer call"); + llvm::Function *Fn = llvm::Function::Create( + FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule()); + ModuleInits.push_back(Fn); + } + AllImports.clear(); + + // Add any initializers with specified priority; this uses the same approach + // as EmitCXXGlobalInitFunc(). + if (!PrioritizedCXXGlobalInits.empty()) { + SmallVector<llvm::Function *, 8> LocalCXXGlobalInits; + llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(), + PrioritizedCXXGlobalInits.end()); + for (SmallVectorImpl<GlobalInitData>::iterator + I = PrioritizedCXXGlobalInits.begin(), + E = PrioritizedCXXGlobalInits.end(); + I != E;) { + SmallVectorImpl<GlobalInitData>::iterator PrioE = + std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp()); + + for (; I < PrioE; ++I) + ModuleInits.push_back(I->second); + } + PrioritizedCXXGlobalInits.clear(); + } + + // Now append the ones without specified priority. + for (auto *F : CXXGlobalInits) + ModuleInits.push_back(F); + CXXGlobalInits.clear(); + + llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); + const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction(); + + // We now build the initializer for this module, which has a mangled name + // as per the Itanium ABI . The action of the initializer is guarded so that + // each init is run just once (even though a module might be imported + // multiple times via nested use). + llvm::Function *Fn; + llvm::GlobalVariable *Guard = nullptr; + { + SmallString<256> InitFnName; + llvm::raw_svector_ostream Out(InitFnName); + cast<ItaniumMangleContext>(getCXXABI().getMangleContext()) + .mangleModuleInitializer(Primary, Out); + Fn = CreateGlobalInitOrCleanUpFunction( + FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false, + llvm::GlobalVariable::ExternalLinkage); + + Guard = new llvm::GlobalVariable(getModule(), Int8Ty, /*isConstant=*/false, + llvm::GlobalVariable::InternalLinkage, + llvm::ConstantInt::get(Int8Ty, 0), + InitFnName.str() + "__in_chrg"); + } + CharUnits GuardAlign = CharUnits::One(); + Guard->setAlignment(GuardAlign.getAsAlign()); + + CodeGenFunction(*this).GenerateCXXGlobalInitFunc( + Fn, ModuleInits, ConstantAddress(Guard, Int8Ty, GuardAlign)); + // We allow for the case that a module object is added to a linked binary + // without a specific call to the the initializer. This also ensure that + // implementation partition initializers are called when the partition + // is not imported as an interface. + AddGlobalCtor(Fn); + + // See the comment in EmitCXXGlobalInitFunc about OpenCL global init + // functions. + if (getLangOpts().OpenCL) { + GenKernelArgMetadata(Fn); + Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL); + } + + assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice || + getLangOpts().GPUAllowDeviceInit); + if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) { + Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); + Fn->addFnAttr("device-init"); + } + + ModuleInits.clear(); +} + static SmallString<128> getTransformedFileName(llvm::Module &M) { SmallString<128> FileName = llvm::sys::path::filename(M.getName()); @@ -635,7 +794,29 @@ while (!CXXGlobalInits.empty() && !CXXGlobalInits.back()) CXXGlobalInits.pop_back(); - if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty()) + // When we import C++20 modules, we must run their initializers first. + SmallVector<llvm::Function *, 8> ModuleInits; + if (CXX20ModuleInits) + for (Module *M : ImportedModules) { + // No Itanium initializer in header like modules. + if (M->isHeaderLikeModule()) + continue; + llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); + SmallString<256> FnName; + { + llvm::raw_svector_ostream Out(FnName); + cast<ItaniumMangleContext>(getCXXABI().getMangleContext()) + .mangleModuleInitializer(M, Out); + } + assert(!GetGlobalValue(FnName.str()) && + "We should only have one use of the initializer call"); + llvm::Function *Fn = llvm::Function::Create( + FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule()); + ModuleInits.push_back(Fn); + } + + if (ModuleInits.empty() && CXXGlobalInits.empty() && + PrioritizedCXXGlobalInits.empty()) return; llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); @@ -661,6 +842,13 @@ llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction( FTy, "_GLOBAL__I_" + getPrioritySuffix(Priority), FI); + // Prepend the module inits to the highest priority set. + if (!ModuleInits.empty()) { + for (auto *F : ModuleInits) + LocalCXXGlobalInits.push_back(F); + ModuleInits.clear(); + } + for (; I < PrioE; ++I) LocalCXXGlobalInits.push_back(I->second); @@ -670,17 +858,33 @@ PrioritizedCXXGlobalInits.clear(); } - if (getCXXABI().useSinitAndSterm() && CXXGlobalInits.empty()) + if (getCXXABI().useSinitAndSterm() && ModuleInits.empty() && + CXXGlobalInits.empty()) return; + for (auto *F : CXXGlobalInits) + ModuleInits.push_back(F); + CXXGlobalInits.clear(); + // Include the filename in the symbol name. Including "sub_" matches gcc // and makes sure these symbols appear lexicographically behind the symbols // with priority emitted above. - llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction( - FTy, llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())), - FI); + llvm::Function *Fn; + if (CXX20ModuleInits && getContext().getModuleForCodeGen()) { + SmallString<256> InitFnName; + llvm::raw_svector_ostream Out(InitFnName); + cast<ItaniumMangleContext>(getCXXABI().getMangleContext()) + .mangleModuleInitializer(getContext().getModuleForCodeGen(), Out); + Fn = CreateGlobalInitOrCleanUpFunction( + FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false, + llvm::GlobalVariable::ExternalLinkage); + } else + Fn = CreateGlobalInitOrCleanUpFunction( + FTy, + llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())), + FI); - CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits); + CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits); AddGlobalCtor(Fn); // In OpenCL global init functions must be converted to kernels in order to @@ -692,7 +896,7 @@ // dynamic resource allocation on the device and program scope variables are // destroyed by the runtime when program is released. if (getLangOpts().OpenCL) { - GenOpenCLArgMetadata(Fn); + GenKernelArgMetadata(Fn); Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL); } @@ -703,7 +907,7 @@ Fn->addFnAttr("device-init"); } - CXXGlobalInits.clear(); + ModuleInits.clear(); } void CodeGenModule::EmitCXXGlobalCleanUpFunc() { @@ -793,6 +997,9 @@ EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit); } + if (getLangOpts().HLSL) + CGM.getHLSLRuntime().annotateHLSLResource(D, Addr); + FinishFunction(); }