diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-04 19:20:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-08 19:02:26 +0000 |
commit | 81ad626541db97eb356e2c1d4a20eb2a26a766ab (patch) | |
tree | 311b6a8987c32b1e1dcbab65c54cfac3fdb56175 /contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp | |
parent | 5fff09660e06a66bed6482da9c70df328e16bbb6 (diff) | |
parent | 145449b1e420787bb99721a429341fa6be3adfb6 (diff) |
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp | 674 |
1 files changed, 450 insertions, 224 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp index 2777fc22600d..56ed59d1e3f1 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp @@ -16,6 +16,7 @@ #include "CGCXXABI.h" #include "CGCall.h" #include "CGDebugInfo.h" +#include "CGHLSLRuntime.h" #include "CGObjCRuntime.h" #include "CGOpenCLRuntime.h" #include "CGOpenMPRuntime.h" @@ -43,6 +44,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" +#include "clang/CodeGen/BackendUtil.h" #include "clang/CodeGen/ConstantInitBuilder.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "llvm/ADT/StringSwitch.h" @@ -68,9 +70,8 @@ using namespace clang; using namespace CodeGen; static llvm::cl::opt<bool> LimitedCoverage( - "limited-coverage-experimental", llvm::cl::ZeroOrMore, llvm::cl::Hidden, - llvm::cl::desc("Emit limited coverage mapping information (experimental)"), - llvm::cl::init(false)); + "limited-coverage-experimental", llvm::cl::Hidden, + llvm::cl::desc("Emit limited coverage mapping information (experimental)")); static const char AnnotationSection[] = "llvm.metadata"; @@ -145,6 +146,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO, createOpenMPRuntime(); if (LangOpts.CUDA) createCUDARuntime(); + if (LangOpts.HLSL) + createHLSLRuntime(); // Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0. if (LangOpts.Sanitize.has(SanitizerKind::Thread) || @@ -261,6 +264,10 @@ void CodeGenModule::createCUDARuntime() { CUDARuntime.reset(CreateNVCUDARuntime(*this)); } +void CodeGenModule::createHLSLRuntime() { + HLSLRuntime.reset(new CGHLSLRuntime(*this)); +} + void CodeGenModule::addReplacement(StringRef Name, llvm::Constant *C) { Replacements[Name] = C; } @@ -506,7 +513,6 @@ void CodeGenModule::Release() { EmitVTablesOpportunistically(); applyGlobalValReplacements(); applyReplacements(); - checkAliases(); emitMultiVersionFunctions(); EmitCXXGlobalInitFunc(); EmitCXXGlobalCleanUpFunc(); @@ -538,6 +544,7 @@ void CodeGenModule::Release() { EmitCtorList(GlobalDtors, "llvm.global_dtors"); EmitGlobalAnnotations(); EmitStaticExternCAliases(); + checkAliases(); EmitDeferredUnusedCoverageMappings(); CodeGenPGO(*this).setValueProfilingFlag(getModule()); if (CoverageMapping) @@ -547,27 +554,57 @@ void CodeGenModule::Release() { CodeGenFunction(*this).EmitCfiCheckStub(); } emitAtAvailableLinkGuard(); - if (Context.getTargetInfo().getTriple().isWasm() && - !Context.getTargetInfo().getTriple().isOSEmscripten()) { + if (Context.getTargetInfo().getTriple().isWasm()) EmitMainVoidAlias(); + + if (getTriple().isAMDGPU()) { + // Emit reference of __amdgpu_device_library_preserve_asan_functions to + // preserve ASAN functions in bitcode libraries. + if (LangOpts.Sanitize.has(SanitizerKind::Address)) { + auto *FT = llvm::FunctionType::get(VoidTy, {}); + auto *F = llvm::Function::Create( + FT, llvm::GlobalValue::ExternalLinkage, + "__amdgpu_device_library_preserve_asan_functions", &getModule()); + auto *Var = new llvm::GlobalVariable( + getModule(), FT->getPointerTo(), + /*isConstant=*/true, llvm::GlobalValue::WeakAnyLinkage, F, + "__amdgpu_device_library_preserve_asan_functions_ptr", nullptr, + llvm::GlobalVariable::NotThreadLocal); + addCompilerUsedGlobal(Var); + } + // 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) { + getModule().addModuleFlag(llvm::Module::Error, + "amdgpu_code_object_version", + getTarget().getTargetOpts().CodeObjectVersion); + } } - // Emit reference of __amdgpu_device_library_preserve_asan_functions to - // preserve ASAN functions in bitcode libraries. - if (LangOpts.Sanitize.has(SanitizerKind::Address) && getTriple().isAMDGPU()) { - auto *FT = llvm::FunctionType::get(VoidTy, {}); - auto *F = llvm::Function::Create( - FT, llvm::GlobalValue::ExternalLinkage, - "__amdgpu_device_library_preserve_asan_functions", &getModule()); - auto *Var = new llvm::GlobalVariable( - getModule(), FT->getPointerTo(), - /*isConstant=*/true, llvm::GlobalValue::WeakAnyLinkage, F, - "__amdgpu_device_library_preserve_asan_functions_ptr", nullptr, - llvm::GlobalVariable::NotThreadLocal); - addCompilerUsedGlobal(Var); - if (!getModule().getModuleFlag("amdgpu_hostcall")) { - getModule().addModuleFlag(llvm::Module::Override, "amdgpu_hostcall", 1); + // Emit a global array containing all external kernels or device variables + // used by host functions and mark it as used for CUDA/HIP. This is necessary + // to get kernels or device variables in archives linked in even if these + // kernels or device variables are only used in host functions. + if (!Context.CUDAExternalDeviceDeclODRUsedByHost.empty()) { + SmallVector<llvm::Constant *, 8> UsedArray; + for (auto D : Context.CUDAExternalDeviceDeclODRUsedByHost) { + GlobalDecl GD; + if (auto *FD = dyn_cast<FunctionDecl>(D)) + GD = GlobalDecl(FD, KernelReferenceKind::Kernel); + else + GD = GlobalDecl(D); + UsedArray.push_back(llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast( + GetAddrOfGlobal(GD), Int8PtrTy)); } + + llvm::ArrayType *ATy = llvm::ArrayType::get(Int8PtrTy, UsedArray.size()); + + auto *GV = new llvm::GlobalVariable( + getModule(), ATy, false, llvm::GlobalValue::InternalLinkage, + llvm::ConstantArray::get(ATy, UsedArray), "__clang_gpu_used_external"); + addCompilerUsedGlobal(GV); } emitLLVMUsed(); @@ -720,13 +757,16 @@ void CodeGenModule::Release() { // attributes, but we use module metadata to emit build attributes. This is // needed for LTO, where the function attributes are inside bitcode // serialised into a global variable by the time build attributes are - // emitted, so we can't access them. + // emitted, so we can't access them. LTO objects could be compiled with + // different flags therefore module flags are set to "Min" behavior to achieve + // the same end result of the normal build where e.g BTI is off if any object + // doesn't support it. if (Context.getTargetInfo().hasFeature("ptrauth") && LangOpts.getSignReturnAddressScope() != LangOptions::SignReturnAddressScopeKind::None) getModule().addModuleFlag(llvm::Module::Override, "sign-return-address-buildattr", 1); - if (LangOpts.Sanitize.has(SanitizerKind::MemTag)) + if (LangOpts.Sanitize.has(SanitizerKind::MemtagStack)) getModule().addModuleFlag(llvm::Module::Override, "tag-stack-memory-buildattr", 1); @@ -734,16 +774,16 @@ void CodeGenModule::Release() { Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb || Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 || Arch == llvm::Triple::aarch64_be) { - getModule().addModuleFlag(llvm::Module::Error, "branch-target-enforcement", + getModule().addModuleFlag(llvm::Module::Min, "branch-target-enforcement", LangOpts.BranchTargetEnforcement); - getModule().addModuleFlag(llvm::Module::Error, "sign-return-address", + getModule().addModuleFlag(llvm::Module::Min, "sign-return-address", LangOpts.hasSignReturnAddress()); - getModule().addModuleFlag(llvm::Module::Error, "sign-return-address-all", + getModule().addModuleFlag(llvm::Module::Min, "sign-return-address-all", LangOpts.isSignReturnAddressScopeAll()); - getModule().addModuleFlag(llvm::Module::Error, + getModule().addModuleFlag(llvm::Module::Min, "sign-return-address-with-bkey", !LangOpts.isSignReturnAddressWithAKey()); } @@ -775,7 +815,7 @@ void CodeGenModule::Release() { LangOpts.OpenMP); // Emit OpenCL specific module metadata: OpenCL/SPIR version. - if (LangOpts.OpenCL) { + if (LangOpts.OpenCL || (LangOpts.CUDAIsDevice && getTriple().isSPIRV())) { EmitOpenCLMetadata(); // Emit SPIR version. if (getTriple().isSPIR()) { @@ -796,6 +836,10 @@ void CodeGenModule::Release() { } } + // HLSL related end of code gen work items. + if (LangOpts.HLSL) + getHLSLRuntime().finishCodeGen(); + if (uint32_t PLevel = Context.getLangOpts().PICLevel) { assert(PLevel < 3 && "Invalid PIC Level"); getModule().setPICLevel(static_cast<llvm::PICLevel::Level>(PLevel)); @@ -820,7 +864,7 @@ void CodeGenModule::Release() { if (CodeGenOpts.NoPLT) getModule().setRtLibUseGOT(); if (CodeGenOpts.UnwindTables) - getModule().setUwtable(); + getModule().setUwtable(llvm::UWTableKind(CodeGenOpts.UnwindTables)); switch (CodeGenOpts.getFramePointer()) { case CodeGenOptions::FramePointerKind::None: @@ -868,6 +912,9 @@ void CodeGenModule::Release() { EmitBackendOptionsMetadata(getCodeGenOpts()); + // If there is device offloading code embed it in the host now. + EmbedObject(&getModule(), CodeGenOpts, getDiags()); + // Set visibility from DLL storage class // We do this at the end of LLVM IR generation; after any operation // that might affect the DLL storage class or the visibility, and @@ -1167,7 +1214,9 @@ void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV, if (D && D->isExternallyVisible()) { if (D->hasAttr<DLLImportAttr>()) GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass); - else if (D->hasAttr<DLLExportAttr>() && !GV->isDeclarationForLinker()) + else if ((D->hasAttr<DLLExportAttr>() || + shouldMapVisibilityToDLLExport(D)) && + !GV->isDeclarationForLinker()) GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass); } } @@ -1364,10 +1413,11 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, } // Make unique name for device side static file-scope variable for HIP. - if (CGM.getContext().shouldExternalizeStaticVar(ND) && + if (CGM.getContext().shouldExternalize(ND) && CGM.getLangOpts().GPURelocatableDeviceCode && - CGM.getLangOpts().CUDAIsDevice && !CGM.getLangOpts().CUID.empty()) + CGM.getLangOpts().CUDAIsDevice) CGM.printPostfixForExternalizedDecl(Out, ND); + return std::string(Out.str()); } @@ -1434,8 +1484,7 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) { // static device variable depends on whether the variable is referenced by // a host or device host function. Therefore the mangled name cannot be // cached. - if (!LangOpts.CUDAIsDevice || - !getContext().mayExternalizeStaticVar(GD.getDecl())) { + if (!LangOpts.CUDAIsDevice || !getContext().mayExternalize(GD.getDecl())) { auto FoundName = MangledDeclNames.find(CanonicalGD); if (FoundName != MangledDeclNames.end()) return FoundName->second; @@ -1455,7 +1504,7 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) { // directly between host- and device-compilations, the host- and // device-mangling in host compilation could help catching certain ones. assert(!isa<FunctionDecl>(ND) || !ND->hasAttr<CUDAGlobalAttr>() || - getContext().shouldExternalizeStaticVar(ND) || getLangOpts().CUDAIsDevice || + getContext().shouldExternalize(ND) || getLangOpts().CUDAIsDevice || (getContext().getAuxTargetInfo() && (getContext().getAuxTargetInfo()->getCXXABI() != getContext().getTargetInfo().getCXXABI())) || @@ -1490,6 +1539,16 @@ StringRef CodeGenModule::getBlockMangledName(GlobalDecl GD, return Result.first->first(); } +const GlobalDecl CodeGenModule::getMangledNameDecl(StringRef Name) { + auto it = MangledDeclNames.begin(); + while (it != MangledDeclNames.end()) { + if (it->second == Name) + return it->first; + it++; + } + return GlobalDecl(); +} + llvm::GlobalValue *CodeGenModule::GetGlobalValue(StringRef Name) { return getModule().getNamedValue(Name); } @@ -1638,7 +1697,7 @@ static unsigned ArgInfoAddressSpace(LangAS AS) { } } -void CodeGenModule::GenOpenCLArgMetadata(llvm::Function *Fn, +void CodeGenModule::GenKernelArgMetadata(llvm::Function *Fn, const FunctionDecl *FD, CodeGenFunction *CGF) { assert(((FD && CGF) || (!FD && !CGF)) && @@ -1670,6 +1729,11 @@ void CodeGenModule::GenOpenCLArgMetadata(llvm::Function *Fn, if (FD && CGF) for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) { const ParmVarDecl *parm = FD->getParamDecl(i); + // Get argument name. + argNames.push_back(llvm::MDString::get(VMContext, parm->getName())); + + if (!getLangOpts().OpenCL) + continue; QualType ty = parm->getType(); std::string typeQuals; @@ -1688,9 +1752,6 @@ void CodeGenModule::GenOpenCLArgMetadata(llvm::Function *Fn, } else accessQuals.push_back(llvm::MDString::get(VMContext, "none")); - // Get argument name. - argNames.push_back(llvm::MDString::get(VMContext, parm->getName())); - auto getTypeSpelling = [&](QualType Ty) { auto typeName = Ty.getUnqualifiedType().getAsString(Policy); @@ -1763,17 +1824,20 @@ void CodeGenModule::GenOpenCLArgMetadata(llvm::Function *Fn, argTypeQuals.push_back(llvm::MDString::get(VMContext, typeQuals)); } - Fn->setMetadata("kernel_arg_addr_space", - llvm::MDNode::get(VMContext, addressQuals)); - Fn->setMetadata("kernel_arg_access_qual", - llvm::MDNode::get(VMContext, accessQuals)); - Fn->setMetadata("kernel_arg_type", - llvm::MDNode::get(VMContext, argTypeNames)); - Fn->setMetadata("kernel_arg_base_type", - llvm::MDNode::get(VMContext, argBaseTypeNames)); - Fn->setMetadata("kernel_arg_type_qual", - llvm::MDNode::get(VMContext, argTypeQuals)); - if (getCodeGenOpts().EmitOpenCLArgMetadata) + if (getLangOpts().OpenCL) { + Fn->setMetadata("kernel_arg_addr_space", + llvm::MDNode::get(VMContext, addressQuals)); + Fn->setMetadata("kernel_arg_access_qual", + llvm::MDNode::get(VMContext, accessQuals)); + Fn->setMetadata("kernel_arg_type", + llvm::MDNode::get(VMContext, argTypeNames)); + Fn->setMetadata("kernel_arg_base_type", + llvm::MDNode::get(VMContext, argBaseTypeNames)); + Fn->setMetadata("kernel_arg_type_qual", + llvm::MDNode::get(VMContext, argTypeQuals)); + } + if (getCodeGenOpts().EmitOpenCLArgMetadata || + getCodeGenOpts().HIPSaveKernelArgName) Fn->setMetadata("kernel_arg_name", llvm::MDNode::get(VMContext, argNames)); } @@ -1826,12 +1890,28 @@ CodeGenModule::getMostBaseClasses(const CXXRecordDecl *RD) { return MostBases.takeVector(); } +llvm::GlobalVariable * +CodeGenModule::GetOrCreateRTTIProxyGlobalVariable(llvm::Constant *Addr) { + auto It = RTTIProxyMap.find(Addr); + if (It != RTTIProxyMap.end()) + return It->second; + + auto *FTRTTIProxy = new llvm::GlobalVariable( + TheModule, Addr->getType(), + /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, Addr, + "__llvm_rtti_proxy"); + FTRTTIProxy->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + + RTTIProxyMap[Addr] = FTRTTIProxy; + return FTRTTIProxy; +} + void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F) { llvm::AttrBuilder B(F->getContext()); if (CodeGenOpts.UnwindTables) - B.addAttribute(llvm::Attribute::UWTable); + B.addUWTableAttr(llvm::UWTableKind(CodeGenOpts.UnwindTables)); if (CodeGenOpts.StackClashProtector) B.addAttribute("probe-stack", "inline-asm"); @@ -2052,6 +2132,13 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD, getTarget().isValidCPUName(ParsedAttr.Tune)) TuneCPU = ParsedAttr.Tune; } + + if (SD) { + // Apply the given CPU name as the 'tune-cpu' so that the optimizer can + // favor this processor. + TuneCPU = getTarget().getCPUSpecificTuneName( + SD->getCPUName(GD.getMultiVersionIndex())->getName()); + } } else { // Otherwise just add the existing target cpu and target features to the // function. @@ -2489,8 +2576,8 @@ void CodeGenModule::EmitDeferred() { // Note we should not clear CUDADeviceVarODRUsedByHost since it is still // needed for further handling. if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) - for (const auto *V : getContext().CUDADeviceVarODRUsedByHost) - DeferredDeclsToEmit.push_back(V); + llvm::append_range(DeferredDeclsToEmit, + getContext().CUDADeviceVarODRUsedByHost); // Stop if we're out of both deferred vtables and deferred declarations. if (DeferredDeclsToEmit.empty()) @@ -2694,21 +2781,14 @@ bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind, llvm::Function *Fn, return false; } -bool CodeGenModule::isInNoSanitizeList(llvm::GlobalVariable *GV, +bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind, + llvm::GlobalVariable *GV, SourceLocation Loc, QualType Ty, StringRef Category) const { - // For now globals can be ignored only in ASan and KASan. - const SanitizerMask EnabledAsanMask = - LangOpts.Sanitize.Mask & - (SanitizerKind::Address | SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress | - SanitizerKind::MemTag); - if (!EnabledAsanMask) - return false; const auto &NoSanitizeL = getContext().getNoSanitizeList(); - if (NoSanitizeL.containsGlobal(EnabledAsanMask, GV->getName(), Category)) + if (NoSanitizeL.containsGlobal(Kind, GV->getName(), Category)) return true; - if (NoSanitizeL.containsLocation(EnabledAsanMask, Loc, Category)) + if (NoSanitizeL.containsLocation(Kind, Loc, Category)) return true; // Check global type. if (!Ty.isNull()) { @@ -2720,7 +2800,7 @@ bool CodeGenModule::isInNoSanitizeList(llvm::GlobalVariable *GV, // Only record types (classes, structs etc.) are ignored. if (Ty->isRecordType()) { std::string TypeStr = Ty.getAsString(getContext().getPrintingPolicy()); - if (NoSanitizeL.containsType(EnabledAsanMask, TypeStr, Category)) + if (NoSanitizeL.containsType(Kind, TypeStr, Category)) return true; } } @@ -2762,12 +2842,12 @@ bool CodeGenModule::isProfileInstrExcluded(llvm::Function *Fn, CodeGenOptions::ProfileInstrKind Kind = getCodeGenOpts().getProfileInstr(); // First, check the function name. Optional<bool> V = ProfileList.isFunctionExcluded(Fn->getName(), Kind); - if (V.hasValue()) + if (V) return *V; // Next, check the source location. if (Loc.isValid()) { Optional<bool> V = ProfileList.isLocationExcluded(Loc, Kind); - if (V.hasValue()) + if (V) return *V; } // If location is unknown, this may be a compiler-generated function. Assume @@ -2775,7 +2855,7 @@ bool CodeGenModule::isProfileInstrExcluded(llvm::Function *Fn, auto &SM = Context.getSourceManager(); if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { Optional<bool> V = ProfileList.isFileExcluded(MainFile->getName(), Kind); - if (V.hasValue()) + if (V) return *V; } return ProfileList.getDefault(); @@ -2886,6 +2966,37 @@ ConstantAddress CodeGenModule::GetAddrOfMSGuidDecl(const MSGuidDecl *GD) { return ConstantAddress(Addr, Ty, Alignment); } +ConstantAddress CodeGenModule::GetAddrOfUnnamedGlobalConstantDecl( + const UnnamedGlobalConstantDecl *GCD) { + CharUnits Alignment = getContext().getTypeAlignInChars(GCD->getType()); + + llvm::GlobalVariable **Entry = nullptr; + Entry = &UnnamedGlobalConstantDeclMap[GCD]; + if (*Entry) + return ConstantAddress(*Entry, (*Entry)->getValueType(), Alignment); + + ConstantEmitter Emitter(*this); + llvm::Constant *Init; + + const APValue &V = GCD->getValue(); + + assert(!V.isAbsent()); + Init = Emitter.emitForInitializer(V, GCD->getType().getAddressSpace(), + GCD->getType()); + + auto *GV = new llvm::GlobalVariable(getModule(), Init->getType(), + /*isConstant=*/true, + llvm::GlobalValue::PrivateLinkage, Init, + ".constant"); + GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + GV->setAlignment(Alignment.getAsAlign()); + + Emitter.finalize(GV); + + *Entry = GV; + return ConstantAddress(GV, GV->getValueType(), Alignment); +} + ConstantAddress CodeGenModule::GetAddrOfTemplateParamObject( const TemplateParamObjectDecl *TPO) { StringRef Name = getMangledName(TPO); @@ -3270,13 +3381,13 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD, auto *Spec = FD->getAttr<CPUSpecificAttr>(); for (unsigned I = 0; I < Spec->cpus_size(); ++I) EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr); - // Requires multiple emits. } else if (FD->isTargetClonesMultiVersion()) { auto *Clone = FD->getAttr<TargetClonesAttr>(); for (unsigned I = 0; I < Clone->featuresStrs_size(); ++I) if (Clone->isFirstOfVersion(I)) EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr); - EmitTargetClonesResolver(GD); + // Ensure that the resolver function is also emitted. + GetOrCreateMultiVersionResolver(GD); } else EmitGlobalFunctionDefinition(GD, GV); } @@ -3358,112 +3469,94 @@ llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM, return llvm::GlobalValue::WeakODRLinkage; } -void CodeGenModule::EmitTargetClonesResolver(GlobalDecl GD) { - const auto *FD = cast<FunctionDecl>(GD.getDecl()); - assert(FD && "Not a FunctionDecl?"); - const auto *TC = FD->getAttr<TargetClonesAttr>(); - assert(TC && "Not a target_clones Function?"); - - QualType CanonTy = Context.getCanonicalType(FD->getType()); - llvm::Type *DeclTy = getTypes().ConvertType(CanonTy); - - if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) { - const CGFunctionInfo &FInfo = getTypes().arrangeCXXMethodDeclaration(CXXFD); - DeclTy = getTypes().GetFunctionType(FInfo); - } - - llvm::Function *ResolverFunc; - if (getTarget().supportsIFunc()) { - auto *IFunc = cast<llvm::GlobalIFunc>( - GetOrCreateMultiVersionResolver(GD, DeclTy, FD)); - ResolverFunc = cast<llvm::Function>(IFunc->getResolver()); - } else - ResolverFunc = - cast<llvm::Function>(GetOrCreateMultiVersionResolver(GD, DeclTy, FD)); - - SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options; - for (unsigned VersionIndex = 0; VersionIndex < TC->featuresStrs_size(); - ++VersionIndex) { - if (!TC->isFirstOfVersion(VersionIndex)) - continue; - StringRef Version = TC->getFeatureStr(VersionIndex); - StringRef MangledName = - getMangledName(GD.getWithMultiVersionIndex(VersionIndex)); - llvm::Constant *Func = GetGlobalValue(MangledName); - assert(Func && - "Should have already been created before calling resolver emit"); - - 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); - - Options.emplace_back(cast<llvm::Function>(Func), Architecture, Feature); - } - - const TargetInfo &TI = getTarget(); - std::stable_sort( - Options.begin(), Options.end(), - [&TI](const CodeGenFunction::MultiVersionResolverOption &LHS, - const CodeGenFunction::MultiVersionResolverOption &RHS) { - return TargetMVPriority(TI, LHS) > TargetMVPriority(TI, RHS); - }); - CodeGenFunction CGF(*this); - CGF.EmitMultiVersionResolver(ResolverFunc, Options); -} - void CodeGenModule::emitMultiVersionFunctions() { std::vector<GlobalDecl> MVFuncsToEmit; MultiVersionFuncs.swap(MVFuncsToEmit); for (GlobalDecl GD : MVFuncsToEmit) { + const auto *FD = cast<FunctionDecl>(GD.getDecl()); + assert(FD && "Expected a FunctionDecl"); + SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options; - const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); - getContext().forEachMultiversionedFunctionVersion( - FD, [this, &GD, &Options](const FunctionDecl *CurFD) { - GlobalDecl CurGD{ - (CurFD->isDefined() ? CurFD->getDefinition() : CurFD)}; - StringRef MangledName = getMangledName(CurGD); - llvm::Constant *Func = GetGlobalValue(MangledName); - if (!Func) { - if (CurFD->isDefined()) { - EmitGlobalFunctionDefinition(CurGD, nullptr); - Func = GetGlobalValue(MangledName); - } else { - const CGFunctionInfo &FI = - getTypes().arrangeGlobalDeclaration(GD); - llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); - Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false, - /*DontDefer=*/false, ForDefinition); + if (FD->isTargetMultiVersion()) { + getContext().forEachMultiversionedFunctionVersion( + FD, [this, &GD, &Options](const FunctionDecl *CurFD) { + GlobalDecl CurGD{ + (CurFD->isDefined() ? CurFD->getDefinition() : CurFD)}; + StringRef MangledName = getMangledName(CurGD); + llvm::Constant *Func = GetGlobalValue(MangledName); + if (!Func) { + if (CurFD->isDefined()) { + EmitGlobalFunctionDefinition(CurGD, nullptr); + Func = GetGlobalValue(MangledName); + } else { + const CGFunctionInfo &FI = + getTypes().arrangeGlobalDeclaration(GD); + llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); + Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false, + /*DontDefer=*/false, ForDefinition); + } + assert(Func && "This should have just been created"); } - assert(Func && "This should have just been created"); - } - const auto *TA = CurFD->getAttr<TargetAttr>(); - llvm::SmallVector<StringRef, 8> Feats; - TA->getAddedFeatures(Feats); + 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 if (FD->isTargetClonesMultiVersion()) { + const auto *TC = FD->getAttr<TargetClonesAttr>(); + for (unsigned VersionIndex = 0; VersionIndex < TC->featuresStrs_size(); + ++VersionIndex) { + if (!TC->isFirstOfVersion(VersionIndex)) + continue; + GlobalDecl CurGD{(FD->isDefined() ? FD->getDefinition() : FD), + VersionIndex}; + StringRef Version = TC->getFeatureStr(VersionIndex); + StringRef MangledName = getMangledName(CurGD); + llvm::Constant *Func = GetGlobalValue(MangledName); + if (!Func) { + if (FD->isDefined()) { + EmitGlobalFunctionDefinition(CurGD, nullptr); + Func = GetGlobalValue(MangledName); + } else { + const CGFunctionInfo &FI = + getTypes().arrangeGlobalDeclaration(CurGD); + llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); + Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false, + /*DontDefer=*/false, ForDefinition); + } + assert(Func && "This should have just been created"); + } - Options.emplace_back(cast<llvm::Function>(Func), - TA->getArchitecture(), Feats); - }); + StringRef Architecture; + llvm::SmallVector<StringRef, 1> Feature; - llvm::Function *ResolverFunc; - const TargetInfo &TI = getTarget(); + if (Version.startswith("arch=")) + Architecture = Version.drop_front(sizeof("arch=") - 1); + else if (Version != "default") + Feature.push_back(Version); - if (TI.supportsIFunc() || FD->isTargetMultiVersion()) { - ResolverFunc = cast<llvm::Function>( - GetGlobalValue((getMangledName(GD) + ".resolver").str())); - ResolverFunc->setLinkage(getMultiversionLinkage(*this, GD)); + Options.emplace_back(cast<llvm::Function>(Func), Architecture, Feature); + } } else { - ResolverFunc = cast<llvm::Function>(GetGlobalValue(getMangledName(GD))); + assert(0 && "Expected a target or target_clones multiversion function"); + continue; } + llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD); + if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) + ResolverConstant = IFunc->getResolver(); + llvm::Function *ResolverFunc = cast<llvm::Function>(ResolverConstant); + + ResolverFunc->setLinkage(getMultiversionLinkage(*this, GD)); + if (supportsCOMDAT()) ResolverFunc->setComdat( getModule().getOrInsertComdat(ResolverFunc->getName())); + const TargetInfo &TI = getTarget(); llvm::stable_sort( Options, [&TI](const CodeGenFunction::MultiVersionResolverOption &LHS, const CodeGenFunction::MultiVersionResolverOption &RHS) { @@ -3491,12 +3584,9 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { assert(FD->isCPUDispatchMultiVersion() && "Not a multiversion function?"); const auto *DD = FD->getAttr<CPUDispatchAttr>(); assert(DD && "Not a cpu_dispatch Function?"); - llvm::Type *DeclTy = getTypes().ConvertType(FD->getType()); - if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) { - const CGFunctionInfo &FInfo = getTypes().arrangeCXXMethodDeclaration(CXXFD); - DeclTy = getTypes().GetFunctionType(FInfo); - } + const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); + llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI); StringRef ResolverName = getMangledName(GD); UpdateMultiVersionNames(GD, FD, ResolverName); @@ -3585,16 +3675,27 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { CGF.EmitMultiVersionResolver(ResolverFunc, Options); if (getTarget().supportsIFunc()) { + llvm::GlobalValue::LinkageTypes Linkage = getMultiversionLinkage(*this, GD); + auto *IFunc = cast<llvm::GlobalValue>(GetOrCreateMultiVersionResolver(GD)); + + // Fix up function declarations that were created for cpu_specific before + // cpu_dispatch was known + if (!isa<llvm::GlobalIFunc>(IFunc)) { + assert(cast<llvm::Function>(IFunc)->isDeclaration()); + auto *GI = llvm::GlobalIFunc::create(DeclTy, 0, Linkage, "", ResolverFunc, + &getModule()); + GI->takeName(IFunc); + IFunc->replaceAllUsesWith(GI); + IFunc->eraseFromParent(); + IFunc = GI; + } + std::string AliasName = getMangledNameImpl( *this, GD, FD, /*OmitMultiVersionMangling=*/true); llvm::Constant *AliasFunc = GetGlobalValue(AliasName); if (!AliasFunc) { - auto *IFunc = cast<llvm::GlobalIFunc>(GetOrCreateLLVMFunction( - AliasName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/true, - /*IsThunk=*/false, llvm::AttributeList(), NotForDefinition)); - auto *GA = llvm::GlobalAlias::create(DeclTy, 0, - getMultiversionLinkage(*this, GD), - AliasName, IFunc, &getModule()); + auto *GA = llvm::GlobalAlias::create(DeclTy, 0, Linkage, AliasName, IFunc, + &getModule()); SetCommonAttributes(GD, GA); } } @@ -3602,8 +3703,10 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { /// If a dispatcher for the specified mangled name is not in the module, create /// and return an llvm Function with the specified type. -llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver( - GlobalDecl GD, llvm::Type *DeclTy, const FunctionDecl *FD) { +llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { + const auto *FD = cast<FunctionDecl>(GD.getDecl()); + assert(FD && "Not a FunctionDecl?"); + std::string MangledName = getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true); @@ -3615,34 +3718,21 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver( else if (FD->isTargetMultiVersion()) ResolverName += ".resolver"; - // If this already exists, just return that one. + // If the resolver has already been created, just return it. if (llvm::GlobalValue *ResolverGV = GetGlobalValue(ResolverName)) return ResolverGV; - // Since this is the first time we've created this IFunc, make sure - // that we put this multiversioned function into the list to be - // replaced later if necessary (target multiversioning only). - if (FD->isTargetMultiVersion()) + const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); + llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI); + + // The resolver needs to be created. For target and target_clones, defer + // creation until the end of the TU. + if (FD->isTargetMultiVersion() || FD->isTargetClonesMultiVersion()) MultiVersionFuncs.push_back(GD); - else if (FD->isTargetClonesMultiVersion()) { - // In target_clones multiversioning, make sure we emit this if used. - auto DDI = - DeferredDecls.find(getMangledName(GD.getWithMultiVersionIndex(0))); - if (DDI != DeferredDecls.end()) { - addDeferredDeclToEmit(GD); - DeferredDecls.erase(DDI); - } else { - // Emit the symbol of the 1st variant, so that the deferred decls know we - // need it, otherwise the only global value will be the resolver/ifunc, - // which end up getting broken if we search for them with GetGlobalValue'. - GetOrCreateLLVMFunction( - getMangledName(GD.getWithMultiVersionIndex(0)), DeclTy, FD, - /*ForVTable=*/false, /*DontDefer=*/true, - /*IsThunk=*/false, llvm::AttributeList(), ForDefinition); - } - } - if (getTarget().supportsIFunc()) { + // For cpu_specific, don't create an ifunc yet because we don't know if the + // 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())), @@ -3700,9 +3790,9 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( } if (FD->isMultiVersion()) { - UpdateMultiVersionNames(GD, FD, MangledName); + UpdateMultiVersionNames(GD, FD, MangledName); if (!IsForDefinition) - return GetOrCreateMultiVersionResolver(GD, Ty, FD); + return GetOrCreateMultiVersionResolver(GD); } } @@ -3716,7 +3806,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( } // Handle dropped DLL attributes. - if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>()) { + if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>() && + !shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D))) { Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); setDSOLocal(Entry); } @@ -4028,7 +4119,8 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty, } // Handle dropped DLL attributes. - if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>()) + if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>() && + !shouldMapVisibilityToDLLExport(D)) Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); if (LangOpts.OpenMP && !LangOpts.OpenMPSimd && D) @@ -4390,7 +4482,7 @@ LangAS CodeGenModule::GetGlobalConstantAddressSpace() const { // casted to Generic pointers which are used to model HIP's "flat" pointers. return LangAS::cuda_device; if (auto AS = getTarget().getConstantAddressSpace()) - return AS.getValue(); + return *AS; return LangAS::Default; } @@ -4550,6 +4642,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, T = D->getType(); if (getLangOpts().CPlusPlus) { + if (InitDecl->hasFlexibleArrayInit(getContext())) + ErrorUnsupported(D, "flexible array initializer"); Init = EmitNullConstant(T); NeedsGlobalCtor = true; } else { @@ -4563,6 +4657,14 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, // also don't need to register a destructor. if (getLangOpts().CPlusPlus && !NeedsGlobalDtor) DelayedCXXInitPosition.erase(D); + +#ifndef NDEBUG + CharUnits VarSize = getContext().getTypeSizeInChars(ASTTy) + + InitDecl->getFlexibleArrayInitChars(getContext()); + CharUnits CstSize = CharUnits::fromQuantity( + getDataLayout().getTypeAllocSize(Init->getType())); + assert(VarSize == CstSize && "Emitted constant has unexpected size"); +#endif } } @@ -4651,7 +4753,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, GV->setConstant(true); } - GV->setAlignment(getContext().getDeclAlign(D).getAsAlign()); + CharUnits AlignVal = getContext().getDeclAlign(D); + // Check for alignment specifed in an 'omp allocate' directive. + if (llvm::Optional<CharUnits> AlignValFromAllocate = + getOMPAllocateAlignment(D)) + AlignVal = *AlignValFromAllocate; + GV->setAlignment(AlignVal.getAsAlign()); // On Darwin, unlike other Itanium C++ ABI platforms, the thread-wrapper // function is only defined alongside the variable, not also alongside @@ -4706,7 +4813,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, if (NeedsGlobalCtor || NeedsGlobalDtor) EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor); - SanitizerMD->reportGlobalToASan(GV, *D, NeedsGlobalCtor); + SanitizerMD->reportGlobal(GV, *D, NeedsGlobalCtor); // Emit global variable debug information. if (CGDebugInfo *DI = getModuleDebugInfo()) @@ -4807,12 +4914,8 @@ llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator( if (Linkage == GVA_Internal) return llvm::Function::InternalLinkage; - if (D->hasAttr<WeakAttr>()) { - if (IsConstantVariable) - return llvm::GlobalVariable::WeakODRLinkage; - else - return llvm::GlobalVariable::WeakAnyLinkage; - } + if (D->hasAttr<WeakAttr>()) + return llvm::GlobalVariable::WeakAnyLinkage; if (const auto *FD = D->getAsFunction()) if (FD->isMultiVersion() && Linkage == GVA_AvailableExternally) @@ -5142,6 +5245,11 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { setTLSMode(GA, *VD); SetCommonAttributes(GD, GA); + + // Emit global alias debug information. + if (isa<VarDecl>(D)) + if (CGDebugInfo *DI = getModuleDebugInfo()) + DI->EmitGlobalAlias(cast<llvm::GlobalValue>(GA->getAliasee()), GD); } void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) { @@ -5343,7 +5451,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { auto Fields = Builder.beginStruct(STy); // Class pointer. - Fields.add(cast<llvm::ConstantExpr>(CFConstantStringClassRef)); + Fields.add(cast<llvm::Constant>(CFConstantStringClassRef)); // Flags. if (IsSwiftABI) { @@ -5422,10 +5530,11 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { switch (Triple.getObjectFormat()) { case llvm::Triple::UnknownObjectFormat: llvm_unreachable("unknown file format"); + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: - llvm_unreachable("GOFF is not yet implemented"); + case llvm::Triple::SPIRV: case llvm::Triple::XCOFF: - llvm_unreachable("XCOFF is not yet implemented"); + llvm_unreachable("unimplemented"); case llvm::Triple::COFF: case llvm::Triple::ELF: case llvm::Triple::Wasm: @@ -5578,11 +5687,15 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S, } auto GV = GenerateStringLiteral(C, LT, *this, GlobalVariableName, Alignment); + + CGDebugInfo *DI = getModuleDebugInfo(); + if (DI && getCodeGenOpts().hasReducedDebugInfo()) + DI->AddStringLiteralDebugInfo(GV, S); + if (Entry) *Entry = GV; - SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "<string literal>", - QualType()); + SanitizerMD->reportGlobal(GV, S->getStrTokenLoc(0), "<string literal>"); return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), GV->getValueType(), Alignment); @@ -5662,9 +5775,11 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( getModule(), Type, false, llvm::GlobalVariable::InternalLinkage, nullptr); } - return ConstantAddress( - InsertResult.first->second, - InsertResult.first->second->getType()->getPointerElementType(), Align); + return ConstantAddress(InsertResult.first->second, + llvm::cast<llvm::GlobalVariable>( + InsertResult.first->second->stripPointerCasts()) + ->getValueType(), + Align); } // FIXME: If an externally-visible declaration extends multiple temporaries, @@ -5733,6 +5848,9 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( /*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); GV->setAlignment(Align.getAsAlign()); if (supportsCOMDAT() && GV->isWeakForLinker()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); @@ -6249,8 +6367,10 @@ void CodeGenModule::EmitMainVoidAlias() { // new-style no-argument main is in used. if (llvm::Function *F = getModule().getFunction("main")) { if (!F->isDeclaration() && F->arg_size() == 0 && !F->isVarArg() && - F->getReturnType()->isIntegerTy(Context.getTargetInfo().getIntWidth())) - addUsedGlobal(llvm::GlobalAlias::create("__main_void", F)); + F->getReturnType()->isIntegerTy(Context.getTargetInfo().getIntWidth())) { + auto *GA = llvm::GlobalAlias::create("__main_void", F); + GA->setVisibility(llvm::GlobalValue::HiddenVisibility); + } } } @@ -6277,6 +6397,72 @@ static void EmitGlobalDeclMetadata(CodeGenModule &CGM, GlobalMetadata->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops)); } +bool CodeGenModule::CheckAndReplaceExternCIFuncs(llvm::GlobalValue *Elem, + llvm::GlobalValue *CppFunc) { + // Store the list of ifuncs we need to replace uses in. + llvm::SmallVector<llvm::GlobalIFunc *> IFuncs; + // List of ConstantExprs that we should be able to delete when we're done + // here. + llvm::SmallVector<llvm::ConstantExpr *> CEs; + + // It isn't valid to replace the extern-C ifuncs if all we find is itself! + if (Elem == CppFunc) + return false; + + // First make sure that all users of this are ifuncs (or ifuncs via a + // bitcast), and collect the list of ifuncs and CEs so we can work on them + // later. + for (llvm::User *User : Elem->users()) { + // Users can either be a bitcast ConstExpr that is used by the ifuncs, OR an + // ifunc directly. In any other case, just give up, as we don't know what we + // could break by changing those. + if (auto *ConstExpr = dyn_cast<llvm::ConstantExpr>(User)) { + if (ConstExpr->getOpcode() != llvm::Instruction::BitCast) + return false; + + for (llvm::User *CEUser : ConstExpr->users()) { + if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(CEUser)) { + IFuncs.push_back(IFunc); + } else { + return false; + } + } + CEs.push_back(ConstExpr); + } else if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(User)) { + IFuncs.push_back(IFunc); + } else { + // This user is one we don't know how to handle, so fail redirection. This + // will result in an ifunc retaining a resolver name that will ultimately + // fail to be resolved to a defined function. + return false; + } + } + + // Now we know this is a valid case where we can do this alias replacement, we + // need to remove all of the references to Elem (and the bitcasts!) so we can + // delete it. + for (llvm::GlobalIFunc *IFunc : IFuncs) + IFunc->setResolver(nullptr); + for (llvm::ConstantExpr *ConstExpr : CEs) + ConstExpr->destroyConstant(); + + // We should now be out of uses for the 'old' version of this function, so we + // can erase it as well. + Elem->eraseFromParent(); + + for (llvm::GlobalIFunc *IFunc : IFuncs) { + // The type of the resolver is always just a function-type that returns the + // type of the IFunc, so create that here. If the type of the actual + // resolver doesn't match, it just gets bitcast to the right thing. + auto *ResolverTy = + llvm::FunctionType::get(IFunc->getType(), /*isVarArg*/ false); + llvm::Constant *Resolver = GetOrCreateLLVMFunction( + CppFunc->getName(), ResolverTy, {}, /*ForVTable*/ false); + IFunc->setResolver(Resolver); + } + return true; +} + /// For each function which is declared within an extern "C" region and marked /// as 'used', but has internal linkage, create an alias from the unmangled /// name to the mangled name if possible. People expect to be able to refer @@ -6288,7 +6474,19 @@ void CodeGenModule::EmitStaticExternCAliases() { for (auto &I : StaticExternCValues) { IdentifierInfo *Name = I.first; llvm::GlobalValue *Val = I.second; - if (Val && !getModule().getNamedValue(Name->getName())) + + // If Val is null, that implies there were multiple declarations that each + // had a claim to the unmangled name. In this case, generation of the alias + // is suppressed. See CodeGenModule::MaybeHandleStaticInExternC. + if (!Val) + break; + + llvm::GlobalValue *ExistingElem = + getModule().getNamedValue(Name->getName()); + + // If there is either not something already by this name, or we were able to + // replace all uses from IFuncs, create the alias. + if (!ExistingElem || CheckAndReplaceExternCIFuncs(ExistingElem, Val)) addCompilerUsedGlobal(llvm::GlobalAlias::create(Name->getName(), Val)); } } @@ -6418,7 +6616,9 @@ void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { !VD->getAnyInitializer()->isConstantInitializer(getContext(), /*ForRef=*/false); - Address Addr(GetAddrOfGlobalVar(VD), getContext().getDeclAlign(VD)); + Address Addr(GetAddrOfGlobalVar(VD), + getTypes().ConvertTypeForMem(VD->getType()), + getContext().getDeclAlign(VD)); if (auto InitFunction = getOpenMPRuntime().emitThreadPrivateVarDefinition( VD, Addr, RefExpr->getBeginLoc(), PerformInit)) CXXGlobalInits.push_back(InitFunction); @@ -6647,12 +6847,38 @@ bool CodeGenModule::stopAutoInit() { void CodeGenModule::printPostfixForExternalizedDecl(llvm::raw_ostream &OS, const Decl *D) const { - StringRef Tag; // ptxas does not allow '.' in symbol names. On the other hand, HIP prefers // postfix beginning with '.' since the symbol name can be demangled. if (LangOpts.HIP) - Tag = (isa<VarDecl>(D) ? ".static." : ".intern."); + OS << (isa<VarDecl>(D) ? ".static." : ".intern."); else - Tag = (isa<VarDecl>(D) ? "__static__" : "__intern__"); - OS << Tag << getContext().getCUIDHash(); + OS << (isa<VarDecl>(D) ? "__static__" : "__intern__"); + + // If the CUID is not specified we try to generate a unique postfix. + if (getLangOpts().CUID.empty()) { + SourceManager &SM = getContext().getSourceManager(); + PresumedLoc PLoc = SM.getPresumedLoc(D->getLocation()); + assert(PLoc.isValid() && "Source location is expected to be valid."); + + // Get the hash of the user defined macros. + llvm::MD5 Hash; + llvm::MD5::MD5Result Result; + for (const auto &Arg : PreprocessorOpts.Macros) + Hash.update(Arg.first); + Hash.final(Result); + + // Get the UniqueID for the file containing the decl. + llvm::sys::fs::UniqueID ID; + if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) { + PLoc = SM.getPresumedLoc(D->getLocation(), /*UseLineDirectives=*/false); + assert(PLoc.isValid() && "Source location is expected to be valid."); + if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) + SM.getDiagnostics().Report(diag::err_cannot_open_file) + << PLoc.getFilename() << EC.message(); + } + OS << llvm::format("%x", ID.getFile()) << llvm::format("%x", ID.getDevice()) + << "_" << llvm::utohexstr(Result.low(), /*LowerCase=*/true, /*Width=*/8); + } else { + OS << getContext().getCUIDHash(); + } } |