diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
commit | 486754660bb926339aefcf012a3f848592babb8b (patch) | |
tree | ecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/CodeGen/CodeGenModule.cpp | |
parent | 55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff) |
Notes
Diffstat (limited to 'lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 1020 |
1 files changed, 786 insertions, 234 deletions
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 5bdf81aaf66ed..ecdf78d4b3472 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -123,7 +123,6 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO, ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace(); RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC(); - BuiltinCC = getTargetCodeGenInfo().getABIInfo().getBuiltinCC(); if (LangOpts.ObjC1) createObjCRuntime(); @@ -208,7 +207,10 @@ void CodeGenModule::createOpenMPRuntime() { OpenMPRuntime.reset(new CGOpenMPRuntimeNVPTX(*this)); break; default: - OpenMPRuntime.reset(new CGOpenMPRuntime(*this)); + if (LangOpts.OpenMPSimd) + OpenMPRuntime.reset(new CGOpenMPSIMDRuntime(*this)); + else + OpenMPRuntime.reset(new CGOpenMPRuntime(*this)); break; } } @@ -392,26 +394,29 @@ void CodeGenModule::Release() { applyGlobalValReplacements(); applyReplacements(); checkAliases(); + emitMultiVersionFunctions(); EmitCXXGlobalInitFunc(); EmitCXXGlobalDtorFunc(); + registerGlobalDtorsWithAtExit(); EmitCXXThreadLocalInitFunc(); if (ObjCRuntime) if (llvm::Function *ObjCInitFunction = ObjCRuntime->ModuleInitFunction()) AddGlobalCtor(ObjCInitFunction); if (Context.getLangOpts().CUDA && !Context.getLangOpts().CUDAIsDevice && CUDARuntime) { - if (llvm::Function *CudaCtorFunction = CUDARuntime->makeModuleCtorFunction()) + if (llvm::Function *CudaCtorFunction = + CUDARuntime->makeModuleCtorFunction()) AddGlobalCtor(CudaCtorFunction); - if (llvm::Function *CudaDtorFunction = CUDARuntime->makeModuleDtorFunction()) - AddGlobalDtor(CudaDtorFunction); } - if (OpenMPRuntime) + if (OpenMPRuntime) { if (llvm::Function *OpenMPRegistrationFunction = OpenMPRuntime->emitRegistrationFunction()) { auto ComdatKey = OpenMPRegistrationFunction->hasComdat() ? OpenMPRegistrationFunction : nullptr; AddGlobalCtor(OpenMPRegistrationFunction, 0, ComdatKey); } + OpenMPRuntime->clear(); + } if (PGOReader) { getModule().setProfileSummary(PGOReader->getSummary().getMD(VMContext)); if (PGOStats.hasDiagnostics()) @@ -453,6 +458,10 @@ void CodeGenModule::Release() { // Indicate that we want CodeView in the metadata. getModule().addModuleFlag(llvm::Module::Warning, "CodeView", 1); } + if (CodeGenOpts.ControlFlowGuard) { + // We want function ID tables for Control Flow Guard. + getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 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 @@ -498,12 +507,26 @@ void CodeGenModule::Release() { getModule().addModuleFlag(llvm::Module::Override, "Cross-DSO CFI", 1); } + if (CodeGenOpts.CFProtectionReturn && + Target.checkCFProtectionReturnSupported(getDiags())) { + // Indicate that we want to instrument return control flow protection. + getModule().addModuleFlag(llvm::Module::Override, "cf-protection-return", + 1); + } + + if (CodeGenOpts.CFProtectionBranch && + Target.checkCFProtectionBranchSupported(getDiags())) { + // Indicate that we want to instrument branch control flow protection. + getModule().addModuleFlag(llvm::Module::Override, "cf-protection-branch", + 1); + } + if (LangOpts.CUDAIsDevice && getTriple().isNVPTX()) { // Indicate whether __nvvm_reflect should be configured to flush denormal // floating point values to 0. (This corresponds to its "__CUDA_FTZ" // property.) getModule().addModuleFlag(llvm::Module::Override, "nvvm-reflect-ftz", - LangOpts.CUDADeviceFlushDenormalsToZero ? 1 : 0); + CodeGenOpts.FlushDenorm ? 1 : 0); } // Emit OpenCL specific module metadata: OpenCL/SPIR version. @@ -533,6 +556,9 @@ void CodeGenModule::Release() { getModule().setPIELevel(static_cast<llvm::PIELevel::Level>(PLevel)); } + if (CodeGenOpts.NoPLT) + getModule().setRtLibUseGOT(); + SimplifyPersonality(); if (getCodeGenOpts().EmitDeclMetadata) @@ -544,7 +570,8 @@ void CodeGenModule::Release() { if (DebugInfo) DebugInfo->finalize(); - EmitVersionIdentMetadata(); + if (getCodeGenOpts().EmitVersionIdentMetadata) + EmitVersionIdentMetadata(); EmitTargetMetadata(); } @@ -580,13 +607,9 @@ llvm::MDNode *CodeGenModule::getTBAATypeInfo(QualType QTy) { } TBAAAccessInfo CodeGenModule::getTBAAAccessInfo(QualType AccessType) { - // Pointee values may have incomplete types, but they shall never be - // dereferenced. - if (AccessType->isIncompleteType()) - return TBAAAccessInfo::getIncompleteInfo(); - - uint64_t Size = Context.getTypeSizeInChars(AccessType).getQuantity(); - return TBAAAccessInfo(getTBAATypeInfo(AccessType), Size); + if (!TBAA) + return TBAAAccessInfo(); + return TBAA->getAccessInfo(AccessType); } TBAAAccessInfo @@ -629,6 +652,14 @@ CodeGenModule::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA, return TBAA->mergeTBAAInfoForConditionalOperator(InfoA, InfoB); } +TBAAAccessInfo +CodeGenModule::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, + TBAAAccessInfo SrcInfo) { + if (!TBAA) + return TBAAAccessInfo(); + return TBAA->mergeTBAAInfoForConditionalOperator(DestInfo, SrcInfo); +} + void CodeGenModule::DecorateInstructionWithTBAA(llvm::Instruction *Inst, TBAAAccessInfo TBAAInfo) { if (llvm::MDNode *Tag = getTBAAAccessTagInfo(TBAAInfo)) @@ -670,21 +701,129 @@ llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) { } void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, - const NamedDecl *D, - ForDefinition_t IsForDefinition) const { + const NamedDecl *D) const { + if (GV->hasDLLImportStorageClass()) + return; // Internal definitions always have default visibility. if (GV->hasLocalLinkage()) { GV->setVisibility(llvm::GlobalValue::DefaultVisibility); return; } - + if (!D) + return; // Set visibility for definitions. LinkageInfo LV = D->getLinkageAndVisibility(); - if (LV.isVisibilityExplicit() || - (IsForDefinition && !GV->hasAvailableExternallyLinkage())) + if (LV.isVisibilityExplicit() || !GV->isDeclarationForLinker()) GV->setVisibility(GetLLVMVisibility(LV.getVisibility())); } +static bool shouldAssumeDSOLocal(const CodeGenModule &CGM, + llvm::GlobalValue *GV) { + if (GV->hasLocalLinkage()) + return true; + + if (!GV->hasDefaultVisibility() && !GV->hasExternalWeakLinkage()) + return true; + + // DLLImport explicitly marks the GV as external. + if (GV->hasDLLImportStorageClass()) + return false; + + const llvm::Triple &TT = CGM.getTriple(); + // Every other GV is local on COFF. + // Make an exception for windows OS in the triple: Some firmware builds use + // *-win32-macho triples. This (accidentally?) produced windows relocations + // without GOT tables in older clang versions; Keep this behaviour. + // FIXME: even thread local variables? + if (TT.isOSBinFormatCOFF() || (TT.isOSWindows() && TT.isOSBinFormatMachO())) + return true; + + // Only handle COFF and ELF for now. + if (!TT.isOSBinFormatELF()) + return false; + + // If this is not an executable, don't assume anything is local. + const auto &CGOpts = CGM.getCodeGenOpts(); + llvm::Reloc::Model RM = CGOpts.RelocationModel; + const auto &LOpts = CGM.getLangOpts(); + if (RM != llvm::Reloc::Static && !LOpts.PIE) + return false; + + // A definition cannot be preempted from an executable. + if (!GV->isDeclarationForLinker()) + return true; + + // Most PIC code sequences that assume that a symbol is local cannot produce a + // 0 if it turns out the symbol is undefined. While this is ABI and relocation + // depended, it seems worth it to handle it here. + if (RM == llvm::Reloc::PIC_ && GV->hasExternalWeakLinkage()) + return false; + + // PPC has no copy relocations and cannot use a plt entry as a symbol address. + llvm::Triple::ArchType Arch = TT.getArch(); + if (Arch == llvm::Triple::ppc || Arch == llvm::Triple::ppc64 || + Arch == llvm::Triple::ppc64le) + return false; + + // If we can use copy relocations we can assume it is local. + if (auto *Var = dyn_cast<llvm::GlobalVariable>(GV)) + if (!Var->isThreadLocal() && + (RM == llvm::Reloc::Static || CGOpts.PIECopyRelocations)) + return true; + + // If we can use a plt entry as the symbol address we can assume it + // is local. + // FIXME: This should work for PIE, but the gold linker doesn't support it. + if (isa<llvm::Function>(GV) && !CGOpts.NoPLT && RM == llvm::Reloc::Static) + return true; + + // Otherwise don't assue it is local. + return false; +} + +void CodeGenModule::setDSOLocal(llvm::GlobalValue *GV) const { + GV->setDSOLocal(shouldAssumeDSOLocal(*this, GV)); +} + +void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV, + GlobalDecl GD) const { + const auto *D = dyn_cast<NamedDecl>(GD.getDecl()); + // C++ destructors have a few C++ ABI specific special cases. + if (const auto *Dtor = dyn_cast_or_null<CXXDestructorDecl>(D)) { + getCXXABI().setCXXDestructorDLLStorage(GV, Dtor, GD.getDtorType()); + return; + } + setDLLImportDLLExport(GV, D); +} + +void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV, + const NamedDecl *D) const { + if (D && D->isExternallyVisible()) { + if (D->hasAttr<DLLImportAttr>()) + GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass); + else if (D->hasAttr<DLLExportAttr>() && !GV->isDeclarationForLinker()) + GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass); + } +} + +void CodeGenModule::setGVProperties(llvm::GlobalValue *GV, + GlobalDecl GD) const { + setDLLImportDLLExport(GV, GD); + setGlobalVisibilityAndLocal(GV, dyn_cast<NamedDecl>(GD.getDecl())); +} + +void CodeGenModule::setGVProperties(llvm::GlobalValue *GV, + const NamedDecl *D) const { + setDLLImportDLLExport(GV, D); + setGlobalVisibilityAndLocal(GV, D); +} + +void CodeGenModule::setGlobalVisibilityAndLocal(llvm::GlobalValue *GV, + const NamedDecl *D) const { + setGlobalVisibility(GV, D); + setDSOLocal(GV); +} + static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(StringRef S) { return llvm::StringSwitch<llvm::GlobalVariable::ThreadLocalMode>(S) .Case("global-dynamic", llvm::GlobalVariable::GeneralDynamicTLSModel) @@ -722,36 +861,68 @@ void CodeGenModule::setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const { GV->setThreadLocalMode(TLM); } -StringRef CodeGenModule::getMangledName(GlobalDecl GD) { - GlobalDecl CanonicalGD = GD.getCanonicalDecl(); +static std::string getCPUSpecificMangling(const CodeGenModule &CGM, + StringRef Name) { + const TargetInfo &Target = CGM.getTarget(); + return (Twine('.') + Twine(Target.CPUSpecificManglingCharacter(Name))).str(); +} - // Some ABIs don't have constructor variants. Make sure that base and - // complete constructors get mangled the same. - if (const auto *CD = dyn_cast<CXXConstructorDecl>(CanonicalGD.getDecl())) { - if (!getTarget().getCXXABI().hasConstructorVariants()) { - CXXCtorType OrigCtorType = GD.getCtorType(); - assert(OrigCtorType == Ctor_Base || OrigCtorType == Ctor_Complete); - if (OrigCtorType == Ctor_Base) - CanonicalGD = GlobalDecl(CD, Ctor_Complete); - } +static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM, + const CPUSpecificAttr *Attr, + raw_ostream &Out) { + // cpu_specific gets the current name, dispatch gets the resolver. + if (Attr) + Out << getCPUSpecificMangling(CGM, Attr->getCurCPUName()->getName()); + else + Out << ".resolver"; +} + +static void AppendTargetMangling(const CodeGenModule &CGM, + const TargetAttr *Attr, raw_ostream &Out) { + if (Attr->isDefaultVersion()) + return; + + Out << '.'; + const TargetInfo &Target = CGM.getTarget(); + TargetAttr::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)); + }); + + bool IsFirst = true; + + if (!Info.Architecture.empty()) { + IsFirst = false; + Out << "arch_" << Info.Architecture; } - auto FoundName = MangledDeclNames.find(CanonicalGD); - if (FoundName != MangledDeclNames.end()) - return FoundName->second; + for (StringRef Feat : Info.Features) { + if (!IsFirst) + Out << '_'; + IsFirst = false; + Out << Feat.substr(1); + } +} - const auto *ND = cast<NamedDecl>(GD.getDecl()); +static std::string getMangledNameImpl(const CodeGenModule &CGM, GlobalDecl GD, + const NamedDecl *ND, + bool OmitMultiVersionMangling = false) { SmallString<256> Buffer; - StringRef Str; - if (getCXXABI().getMangleContext().shouldMangleDeclName(ND)) { + llvm::raw_svector_ostream Out(Buffer); + MangleContext &MC = CGM.getCXXABI().getMangleContext(); + if (MC.shouldMangleDeclName(ND)) { llvm::raw_svector_ostream Out(Buffer); if (const auto *D = dyn_cast<CXXConstructorDecl>(ND)) - getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Out); + MC.mangleCXXCtor(D, GD.getCtorType(), Out); else if (const auto *D = dyn_cast<CXXDestructorDecl>(ND)) - getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Out); + MC.mangleCXXDtor(D, GD.getDtorType(), Out); else - getCXXABI().getMangleContext().mangleName(ND, Out); - Str = Out.str(); + MC.mangleName(ND, Out); } else { IdentifierInfo *II = ND->getIdentifier(); assert(II && "Attempt to mangle unnamed decl."); @@ -761,14 +932,103 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) { FD->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) { llvm::raw_svector_ostream Out(Buffer); Out << "__regcall3__" << II->getName(); - Str = Out.str(); } else { - Str = II->getName(); + Out << II->getName(); + } + } + + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) + if (FD->isMultiVersion() && !OmitMultiVersionMangling) { + if (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion()) + AppendCPUSpecificCPUDispatchMangling( + CGM, FD->getAttr<CPUSpecificAttr>(), Out); + else + AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out); + } + + return Out.str(); +} + +void CodeGenModule::UpdateMultiVersionNames(GlobalDecl GD, + const FunctionDecl *FD) { + if (!FD->isMultiVersion()) + return; + + // Get the name of what this would be without the 'target' attribute. This + // allows us to lookup the version that was emitted when this wasn't a + // multiversion function. + std::string NonTargetName = + getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true); + GlobalDecl OtherGD; + if (lookupRepresentativeDecl(NonTargetName, OtherGD)) { + assert(OtherGD.getCanonicalDecl() + .getDecl() + ->getAsFunction() + ->isMultiVersion() && + "Other GD should now be a multiversioned function"); + // OtherFD is the version of this function that was mangled BEFORE + // becoming a MultiVersion function. It potentially needs to be updated. + const FunctionDecl *OtherFD = + OtherGD.getCanonicalDecl().getDecl()->getAsFunction(); + std::string OtherName = getMangledNameImpl(*this, OtherGD, OtherFD); + // This is so that if the initial version was already the 'default' + // version, we don't try to update it. + if (OtherName != NonTargetName) { + // Remove instead of erase, since others may have stored the StringRef + // to this. + const auto ExistingRecord = Manglings.find(NonTargetName); + if (ExistingRecord != std::end(Manglings)) + Manglings.remove(&(*ExistingRecord)); + auto Result = Manglings.insert(std::make_pair(OtherName, OtherGD)); + MangledDeclNames[OtherGD.getCanonicalDecl()] = Result.first->first(); + if (llvm::GlobalValue *Entry = GetGlobalValue(NonTargetName)) + Entry->setName(OtherName); + } + } +} + +StringRef CodeGenModule::getMangledName(GlobalDecl GD) { + GlobalDecl CanonicalGD = GD.getCanonicalDecl(); + + // Some ABIs don't have constructor variants. Make sure that base and + // complete constructors get mangled the same. + if (const auto *CD = dyn_cast<CXXConstructorDecl>(CanonicalGD.getDecl())) { + if (!getTarget().getCXXABI().hasConstructorVariants()) { + CXXCtorType OrigCtorType = GD.getCtorType(); + assert(OrigCtorType == Ctor_Base || OrigCtorType == Ctor_Complete); + if (OrigCtorType == Ctor_Base) + CanonicalGD = GlobalDecl(CD, Ctor_Complete); } } + const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl()); + // Since CPUSpecific can require multiple emits per decl, store the manglings + // separately. + if (FD && + (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion())) { + const auto *SD = FD->getAttr<CPUSpecificAttr>(); + + std::pair<GlobalDecl, unsigned> SpecCanonicalGD{ + CanonicalGD, + SD ? SD->ActiveArgIndex : std::numeric_limits<unsigned>::max()}; + + auto FoundName = CPUSpecificMangledDeclNames.find(SpecCanonicalGD); + if (FoundName != CPUSpecificMangledDeclNames.end()) + return FoundName->second; + + auto Result = CPUSpecificManglings.insert( + std::make_pair(getMangledNameImpl(*this, GD, FD), SpecCanonicalGD)); + return CPUSpecificMangledDeclNames[SpecCanonicalGD] = Result.first->first(); + } + + auto FoundName = MangledDeclNames.find(CanonicalGD); + if (FoundName != MangledDeclNames.end()) + return FoundName->second; + // Keep the first result in the case of a mangling collision. - auto Result = Manglings.insert(std::make_pair(Str, GD)); + const auto *ND = cast<NamedDecl>(GD.getDecl()); + auto Result = + Manglings.insert(std::make_pair(getMangledNameImpl(*this, GD, ND), GD)); return MangledDeclNames[CanonicalGD] = Result.first->first(); } @@ -808,6 +1068,11 @@ void CodeGenModule::AddGlobalCtor(llvm::Function *Ctor, int Priority, /// AddGlobalDtor - Add a function to the list that will be called /// when the module is unloaded. void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, int Priority) { + if (CodeGenOpts.RegisterGlobalDtorsWithAtExit) { + DtorsUsingAtExit[Priority].push_back(Dtor); + return; + } + // FIXME: Type coercion of void()* types. GlobalDtors.push_back(Structor(Priority, Dtor, nullptr)); } @@ -855,14 +1120,8 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) { GVALinkage Linkage = getContext().GetGVALinkageForFunction(D); - if (isa<CXXDestructorDecl>(D) && - getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D), - GD.getDtorType())) { - // Destructor variants in the Microsoft C++ ABI are always internal or - // linkonce_odr thunks emitted on an as-needed basis. - return Linkage == GVA_Internal ? llvm::GlobalValue::InternalLinkage - : llvm::GlobalValue::LinkOnceODRLinkage; - } + if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(D)) + return getCXXABI().getCXXDestructorLinkage(Linkage, Dtor, GD.getDtorType()); if (isa<CXXConstructorDecl>(D) && cast<CXXConstructorDecl>(D)->isInheritingConstructor() && @@ -876,25 +1135,6 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) { return getLLVMLinkageForDeclarator(D, Linkage, /*isConstantVariable=*/false); } -void CodeGenModule::setFunctionDLLStorageClass(GlobalDecl GD, llvm::Function *F) { - const auto *FD = cast<FunctionDecl>(GD.getDecl()); - - if (const auto *Dtor = dyn_cast_or_null<CXXDestructorDecl>(FD)) { - if (getCXXABI().useThunkForDtorVariant(Dtor, GD.getDtorType())) { - // Don't dllexport/import destructor thunks. - F->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); - return; - } - } - - if (FD->hasAttr<DLLImportAttr>()) - F->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass); - else if (FD->hasAttr<DLLExportAttr>()) - F->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass); - else - F->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass); -} - llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) { llvm::MDString *MDS = dyn_cast<llvm::MDString>(MD); if (!MDS) return nullptr; @@ -902,11 +1142,6 @@ llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) { return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString())); } -void CodeGenModule::setFunctionDefinitionAttributes(const FunctionDecl *D, - llvm::Function *F) { - setNonAliasAttributes(D, F); -} - void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D, const CGFunctionInfo &Info, llvm::Function *F) { @@ -937,6 +1172,34 @@ static bool hasUnwindExceptions(const LangOptions &LangOpts) { return true; } +static bool requiresMemberFunctionPointerTypeMetadata(CodeGenModule &CGM, + const CXXMethodDecl *MD) { + // Check that the type metadata can ever actually be used by a call. + if (!CGM.getCodeGenOpts().LTOUnit || + !CGM.HasHiddenLTOVisibility(MD->getParent())) + return false; + + // Only functions whose address can be taken with a member function pointer + // need this sort of type metadata. + return !MD->isStatic() && !MD->isVirtual() && !isa<CXXConstructorDecl>(MD) && + !isa<CXXDestructorDecl>(MD); +} + +std::vector<const CXXRecordDecl *> +CodeGenModule::getMostBaseClasses(const CXXRecordDecl *RD) { + llvm::SetVector<const CXXRecordDecl *> MostBases; + + std::function<void (const CXXRecordDecl *)> CollectMostBases; + CollectMostBases = [&](const CXXRecordDecl *RD) { + if (RD->getNumBases() == 0) + MostBases.insert(RD); + for (const CXXBaseSpecifier &B : RD->bases()) + CollectMostBases(B.getType()->getAsCXXRecordDecl()); + }; + CollectMostBases(RD); + return MostBases.takeVector(); +} + void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F) { llvm::AttrBuilder B; @@ -947,12 +1210,14 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, if (!hasUnwindExceptions(LangOpts)) B.addAttribute(llvm::Attribute::NoUnwind); - 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>()) { + 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 @@ -1044,6 +1309,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, if (alignment) F->setAlignment(alignment); + if (!D->hasAttr<AlignedAttr>()) + if (LangOpts.FunctionAlignment) + F->setAlignment(1 << LangOpts.FunctionAlignment); + // Some C++ ABIs require 2-byte alignment for member functions, in order to // reserve a bit for differentiating between virtual and non-virtual member // functions. If the current target's C++ ABI requires this and this is a @@ -1056,13 +1325,26 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, // In the cross-dso CFI mode, we want !type attributes on definitions only. if (CodeGenOpts.SanitizeCfiCrossDso) if (auto *FD = dyn_cast<FunctionDecl>(D)) - CreateFunctionTypeMetadata(FD, F); + CreateFunctionTypeMetadataForIcall(FD, F); + + // Emit type metadata on member functions for member function pointer checks. + // These are only ever necessary on definitions; we're guaranteed that the + // definition will be present in the LTO unit as a result of LTO visibility. + auto *MD = dyn_cast<CXXMethodDecl>(D); + if (MD && requiresMemberFunctionPointerTypeMetadata(*this, MD)) { + for (const CXXRecordDecl *Base : getMostBaseClasses(MD->getParent())) { + llvm::Metadata *Id = + CreateMetadataIdentifierForType(Context.getMemberPointerType( + MD->getType(), Context.getRecordType(Base).getTypePtr())); + F->addTypeMetadata(0, Id); + } + } } -void CodeGenModule::SetCommonAttributes(const Decl *D, - llvm::GlobalValue *GV) { - if (const auto *ND = dyn_cast_or_null<NamedDecl>(D)) - setGlobalVisibility(GV, ND, ForDefinition); +void CodeGenModule::SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV) { + const Decl *D = GD.getDecl(); + if (dyn_cast_or_null<NamedDecl>(D)) + setGVProperties(GV, GD); else GV->setVisibility(llvm::GlobalValue::DefaultVisibility); @@ -1070,19 +1352,59 @@ void CodeGenModule::SetCommonAttributes(const Decl *D, addUsedGlobal(GV); } -void CodeGenModule::setAliasAttributes(const Decl *D, - llvm::GlobalValue *GV) { - SetCommonAttributes(D, GV); +bool CodeGenModule::GetCPUAndFeaturesAttributes(const Decl *D, + llvm::AttrBuilder &Attrs) { + // Add target-cpu and target-features attributes to functions. If + // we have a decl for the function and it has a target attribute then + // parse that and add it to the feature set. + StringRef TargetCPU = getTarget().getTargetOpts().CPU; + std::vector<std::string> Features; + const auto *FD = dyn_cast_or_null<FunctionDecl>(D); + FD = FD ? FD->getMostRecentDecl() : FD; + const auto *TD = FD ? FD->getAttr<TargetAttr>() : nullptr; + const auto *SD = FD ? FD->getAttr<CPUSpecificAttr>() : nullptr; + bool AddedAttr = false; + if (TD || SD) { + llvm::StringMap<bool> FeatureMap; + getFunctionFeatureMap(FeatureMap, FD); + + // Produce the canonical string for this set of features. + for (const llvm::StringMap<bool>::value_type &Entry : FeatureMap) + Features.push_back((Entry.getValue() ? "+" : "-") + Entry.getKey().str()); + + // Now add the target-cpu and target-features to the function. + // While we populated the feature map above, we still need to + // get and parse the target attribute so we can get the cpu for + // the function. + if (TD) { + TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); + if (ParsedAttr.Architecture != "" && + getTarget().isValidCPUName(ParsedAttr.Architecture)) + TargetCPU = ParsedAttr.Architecture; + } + } else { + // Otherwise just add the existing target cpu and target features to the + // function. + Features = getTarget().getTargetOpts().Features; + } + + if (TargetCPU != "") { + Attrs.addAttribute("target-cpu", TargetCPU); + AddedAttr = true; + } + if (!Features.empty()) { + llvm::sort(Features.begin(), Features.end()); + Attrs.addAttribute("target-features", llvm::join(Features, ",")); + AddedAttr = true; + } - // Process the dllexport attribute based on whether the original definition - // (not necessarily the aliasee) was exported. - if (D->hasAttr<DLLExportAttr>()) - GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); + return AddedAttr; } -void CodeGenModule::setNonAliasAttributes(const Decl *D, +void CodeGenModule::setNonAliasAttributes(GlobalDecl GD, llvm::GlobalObject *GO) { - SetCommonAttributes(D, GO); + const Decl *D = GD.getDecl(); + SetCommonAttributes(GD, GO); if (D) { if (auto *GV = dyn_cast<llvm::GlobalVariable>(GO)) { @@ -1096,55 +1418,60 @@ void CodeGenModule::setNonAliasAttributes(const Decl *D, if (auto *F = dyn_cast<llvm::Function>(GO)) { if (auto *SA = D->getAttr<PragmaClangTextSectionAttr>()) - if (!D->getAttr<SectionAttr>()) - F->addFnAttr("implicit-section-name", SA->getName()); + if (!D->getAttr<SectionAttr>()) + F->addFnAttr("implicit-section-name", SA->getName()); + + llvm::AttrBuilder Attrs; + if (GetCPUAndFeaturesAttributes(D, Attrs)) { + // We know that GetCPUAndFeaturesAttributes will always have the + // newest set, since it has the newest possible FunctionDecl, so the + // new ones should replace the old. + F->removeFnAttr("target-cpu"); + F->removeFnAttr("target-features"); + F->addAttributes(llvm::AttributeList::FunctionIndex, Attrs); + } } - - if (const SectionAttr *SA = D->getAttr<SectionAttr>()) + + if (const auto *CSA = D->getAttr<CodeSegAttr>()) + GO->setSection(CSA->getName()); + else if (const auto *SA = D->getAttr<SectionAttr>()) GO->setSection(SA->getName()); } - getTargetCodeGenInfo().setTargetAttributes(D, GO, *this, ForDefinition); + getTargetCodeGenInfo().setTargetAttributes(D, GO, *this); } -void CodeGenModule::SetInternalFunctionAttributes(const Decl *D, +void CodeGenModule::SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI) { + const Decl *D = GD.getDecl(); SetLLVMFunctionAttributes(D, FI, F); SetLLVMFunctionAttributesForDefinition(D, F); F->setLinkage(llvm::Function::InternalLinkage); - setNonAliasAttributes(D, F); + setNonAliasAttributes(GD, F); } -static void setLinkageForGV(llvm::GlobalValue *GV, - const NamedDecl *ND) { +static void setLinkageForGV(llvm::GlobalValue *GV, const NamedDecl *ND) { // Set linkage and visibility in case we never see a definition. LinkageInfo LV = ND->getLinkageAndVisibility(); - if (!isExternallyVisible(LV.getLinkage())) { - // Don't set internal linkage on declarations. - } else { - if (ND->hasAttr<DLLImportAttr>()) { - GV->setLinkage(llvm::GlobalValue::ExternalLinkage); - GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); - } else if (ND->hasAttr<DLLExportAttr>()) { - GV->setLinkage(llvm::GlobalValue::ExternalLinkage); - } else if (ND->hasAttr<WeakAttr>() || ND->isWeakImported()) { - // "extern_weak" is overloaded in LLVM; we probably should have - // separate linkage types for this. - GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); - } - } + // Don't set internal linkage on declarations. + // "extern_weak" is overloaded in LLVM; we probably should have + // separate linkage types for this. + if (isExternallyVisible(LV.getLinkage()) && + (ND->hasAttr<WeakAttr>() || ND->isWeakImported())) + GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); } -void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD, - llvm::Function *F) { +void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD, + llvm::Function *F) { // Only if we are checking indirect calls. if (!LangOpts.Sanitize.has(SanitizerKind::CFIICall)) return; - // Non-static class methods are handled via vtable pointer checks elsewhere. + // Non-static class methods are handled via vtable or member function pointer + // checks elsewhere. if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) return; @@ -1168,8 +1495,7 @@ void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD, void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, bool IsIncompleteFunction, - bool IsThunk, - ForDefinition_t IsForDefinition) { + bool IsThunk) { if (llvm::Intrinsic::ID IID = F->getIntrinsicID()) { // If this is an intrinsic function, set the function's attributes @@ -1183,9 +1509,8 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, if (!IsIncompleteFunction) { SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F); // Setup target-specific attributes. - if (!IsForDefinition) - getTargetCodeGenInfo().setTargetAttributes(FD, F, *this, - NotForDefinition); + if (F->isDeclaration()) + getTargetCodeGenInfo().setTargetAttributes(FD, F, *this); } // Add the Returned attribute for "this", except for iOS 5 and earlier @@ -1204,14 +1529,12 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, // overridden by a definition. setLinkageForGV(F, FD); - setGlobalVisibility(F, FD, NotForDefinition); - - if (FD->getAttr<PragmaClangTextSectionAttr>()) { - F->addFnAttr("implicit-section-name"); - } + setGVProperties(F, FD); - if (const SectionAttr *SA = FD->getAttr<SectionAttr>()) - F->setSection(SA->getName()); + if (const auto *CSA = FD->getAttr<CodeSegAttr>()) + F->setSection(CSA->getName()); + else if (const auto *SA = FD->getAttr<SectionAttr>()) + F->setSection(SA->getName()); if (FD->isReplaceableGlobalAllocationFunction()) { // A replaceable global allocation function does not act like a builtin by @@ -1238,7 +1561,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, // Don't emit entries for function declarations in the cross-DSO mode. This // is handled with better precision by the receiving DSO. if (!CodeGenOpts.SanitizeCfiCrossDso) - CreateFunctionTypeMetadata(FD, F); + CreateFunctionTypeMetadataForIcall(FD, F); if (getLangOpts().OpenMP && FD->hasAttr<OMPDeclareSimdDeclAttr>()) getOpenMPRuntime().emitDeclareSimdFunction(FD, F); @@ -1299,6 +1622,12 @@ void CodeGenModule::AddDetectMismatch(StringRef Name, StringRef Value) { LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts)); } +void CodeGenModule::AddELFLibDirective(StringRef Lib) { + auto &C = getLLVMContext(); + LinkerOptionsMetadata.push_back(llvm::MDNode::get( + C, {llvm::MDString::get(C, "lib"), llvm::MDString::get(C, Lib)})); +} + void CodeGenModule::AddDependentLib(StringRef Lib) { llvm::SmallString<24> Opt; getTargetCodeGenInfo().getDependentLibraryOption(Lib, Opt); @@ -1306,7 +1635,7 @@ void CodeGenModule::AddDependentLib(StringRef Lib) { LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts)); } -/// \brief Add link options implied by the given module, including modules +/// Add link options implied by the given module, including modules /// it depends on, using a postorder walk. static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod, SmallVectorImpl<llvm::MDNode *> &Metadata, @@ -1325,6 +1654,12 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod, // Add linker options to link against the libraries/frameworks // described by this module. llvm::LLVMContext &Context = CGM.getLLVMContext(); + + // For modules that use export_as for linking, use that module + // name instead. + if (Mod->UseExportAsModuleLinkName) + return; + for (unsigned I = Mod->LinkLibraries.size(); I > 0; --I) { // Link against a framework. Frameworks are currently Darwin only, so we // don't to ask TargetCodeGenInfo for the spelling of the linker option. @@ -1586,7 +1921,8 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV, StringRef Category) const { // For now globals can be blacklisted only in ASan and KASan. const SanitizerMask EnabledAsanMask = LangOpts.Sanitize.Mask & - (SanitizerKind::Address | SanitizerKind::KernelAddress | SanitizerKind::HWAddress); + (SanitizerKind::Address | SanitizerKind::KernelAddress | + SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress); if (!EnabledAsanMask) return false; const auto &SanitizerBL = getContext().getSanitizerBlacklist(); @@ -1615,9 +1951,10 @@ bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc, StringRef Category) const { if (!LangOpts.XRayInstrument) return false; + const auto &XRayFilter = getContext().getXRayFilter(); using ImbueAttr = XRayFunctionFilter::ImbueAttribute; - auto Attr = XRayFunctionFilter::ImbueAttribute::NONE; + auto Attr = ImbueAttr::NONE; if (Loc.isValid()) Attr = XRayFilter.shouldImbueLocation(Loc, Category); if (Attr == ImbueAttr::NONE) @@ -1662,7 +1999,8 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) { // If OpenMP is enabled and threadprivates must be generated like TLS, delay // codegen for global variables, because they may be marked as threadprivate. if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS && - getContext().getTargetInfo().isTLSSupported() && isa<VarDecl>(Global)) + getContext().getTargetInfo().isTLSSupported() && isa<VarDecl>(Global) && + !isTypeConstant(Global->getType(), false)) return false; return true; @@ -1691,6 +2029,7 @@ ConstantAddress CodeGenModule::GetAddrOfUuidDescriptor( /*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name); if (supportsCOMDAT()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); + setDSOLocal(GV); return ConstantAddress(GV, Alignment); } @@ -1742,6 +2081,10 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { if (Global->hasAttr<IFuncAttr>()) return emitIFuncDefinition(GD); + // If this is a cpu_dispatch multiversion function, emit the resolver. + if (Global->hasAttr<CPUDispatchAttr>()) + return emitCPUDispatchDefinition(GD); + // If this is CUDA, be selective about which declarations we emit. if (LangOpts.CUDA) { if (LangOpts.CUDAIsDevice) { @@ -2058,6 +2401,124 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) { static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, llvm::Function *NewFn); +void CodeGenModule::emitMultiVersionFunctions() { + for (GlobalDecl GD : MultiVersionFuncs) { + SmallVector<CodeGenFunction::TargetMultiVersionResolverOption, 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); + } + assert(Func && "This should have just been created"); + } + Options.emplace_back(getTarget(), cast<llvm::Function>(Func), + CurFD->getAttr<TargetAttr>()->parse()); + }); + + llvm::Function *ResolverFunc = cast<llvm::Function>( + GetGlobalValue((getMangledName(GD) + ".resolver").str())); + if (supportsCOMDAT()) + ResolverFunc->setComdat( + getModule().getOrInsertComdat(ResolverFunc->getName())); + std::stable_sort( + Options.begin(), Options.end(), + std::greater<CodeGenFunction::TargetMultiVersionResolverOption>()); + CodeGenFunction CGF(*this); + CGF.EmitTargetMultiVersionResolver(ResolverFunc, Options); + } +} + +void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { + const auto *FD = cast<FunctionDecl>(GD.getDecl()); + assert(FD && "Not a FunctionDecl?"); + const auto *DD = FD->getAttr<CPUDispatchAttr>(); + assert(DD && "Not a cpu_dispatch Function?"); + llvm::Type *DeclTy = getTypes().ConvertTypeForMem(FD->getType()); + + StringRef ResolverName = getMangledName(GD); + llvm::Type *ResolverType = llvm::FunctionType::get( + llvm::PointerType::get(DeclTy, + Context.getTargetAddressSpace(FD->getType())), + false); + auto *ResolverFunc = cast<llvm::Function>( + GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{}, + /*ForVTable=*/false)); + + SmallVector<CodeGenFunction::CPUDispatchMultiVersionResolverOption, 10> + Options; + const TargetInfo &Target = getTarget(); + for (const IdentifierInfo *II : DD->cpus()) { + // Get the name of the target function so we can look it up/create it. + std::string MangledName = getMangledNameImpl(*this, GD, FD, true) + + getCPUSpecificMangling(*this, II->getName()); + llvm::Constant *Func = GetOrCreateLLVMFunction( + MangledName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/false, + /*IsThunk=*/false, llvm::AttributeList(), ForDefinition); + llvm::SmallVector<StringRef, 32> Features; + Target.getCPUSpecificCPUDispatchFeatures(II->getName(), Features); + llvm::transform(Features, Features.begin(), + [](StringRef Str) { return Str.substr(1); }); + Features.erase(std::remove_if( + Features.begin(), Features.end(), [&Target](StringRef Feat) { + return !Target.validateCpuSupports(Feat); + }), Features.end()); + Options.emplace_back(cast<llvm::Function>(Func), + CodeGenFunction::GetX86CpuSupportsMask(Features)); + } + + llvm::sort( + Options.begin(), Options.end(), + std::greater<CodeGenFunction::CPUDispatchMultiVersionResolverOption>()); + CodeGenFunction CGF(*this); + CGF.EmitCPUDispatchMultiVersionResolver(ResolverFunc, Options); +} + +/// If an ifunc for the specified mangled name is not in the module, create and +/// return an llvm IFunc Function with the specified type. +llvm::Constant * +CodeGenModule::GetOrCreateMultiVersionIFunc(GlobalDecl GD, llvm::Type *DeclTy, + const FunctionDecl *FD) { + std::string MangledName = + getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true); + std::string IFuncName = MangledName + ".ifunc"; + if (llvm::GlobalValue *IFuncGV = GetGlobalValue(IFuncName)) + return IFuncGV; + + // 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->isCPUDispatchMultiVersion() && !FD->isCPUSpecificMultiVersion()) + MultiVersionFuncs.push_back(GD); + + std::string ResolverName = MangledName + ".resolver"; + llvm::Type *ResolverType = llvm::FunctionType::get( + llvm::PointerType::get(DeclTy, + Context.getTargetAddressSpace(FD->getType())), + false); + llvm::Constant *Resolver = + GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{}, + /*ForVTable=*/false); + llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create( + DeclTy, 0, llvm::Function::ExternalLinkage, "", Resolver, &getModule()); + GIF->setName(IFuncName); + SetCommonAttributes(FD, GIF); + + return GIF; +} + /// GetOrCreateLLVMFunction - If the specified mangled name is not in the /// module, create and return an llvm Function with the specified type. If there /// is something in the module with the specified name, return it potentially @@ -2071,6 +2532,33 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( ForDefinition_t IsForDefinition) { const Decl *D = GD.getDecl(); + // Any attempts to use a MultiVersion function should result in retrieving + // the iFunc instead. Name Mangling will handle the rest of the changes. + if (const FunctionDecl *FD = cast_or_null<FunctionDecl>(D)) { + // For the device mark the function as one that should be emitted. + if (getLangOpts().OpenMPIsDevice && OpenMPRuntime && + !OpenMPRuntime->markAsGlobalTarget(GD) && FD->isDefined() && + !DontDefer && !IsForDefinition) { + const FunctionDecl *FDDef = FD->getDefinition(); + GlobalDecl GDDef; + if (const auto *CD = dyn_cast<CXXConstructorDecl>(FDDef)) + GDDef = GlobalDecl(CD, GD.getCtorType()); + else if (const auto *DD = dyn_cast<CXXDestructorDecl>(FDDef)) + GDDef = GlobalDecl(DD, GD.getDtorType()); + else + GDDef = GlobalDecl(FDDef); + addDeferredDeclToEmit(GDDef); + } + + if (FD->isMultiVersion()) { + const auto *TA = FD->getAttr<TargetAttr>(); + if (TA && TA->isDefaultVersion()) + UpdateMultiVersionNames(GD, FD); + if (!IsForDefinition) + return GetOrCreateMultiVersionIFunc(GD, Ty, FD); + } + } + // Lookup the entry, lazily creating it if necessary. llvm::GlobalValue *Entry = GetGlobalValue(MangledName); if (Entry) { @@ -2081,8 +2569,10 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( } // Handle dropped DLL attributes. - if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>()) + if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>()) { Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); + setDSOLocal(Entry); + } // If there are two attempts to define the same mangled name, issue an // error. @@ -2094,8 +2584,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( (GD.getCanonicalDecl().getDecl() != OtherGD.getCanonicalDecl().getDecl()) && DiagnosedConflictingDefinitions.insert(GD).second) { - getDiags().Report(D->getLocation(), - diag::err_duplicate_mangled_name); + getDiags().Report(D->getLocation(), diag::err_duplicate_mangled_name) + << MangledName; getDiags().Report(OtherGD.getDecl()->getLocation(), diag::note_previous_definition); } @@ -2157,8 +2647,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( assert(F->getName() == MangledName && "name was uniqued!"); if (D) - SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk, - IsForDefinition); + SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk); if (ExtraAttrs.hasAttributes(llvm::AttributeList::FunctionIndex)) { llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeList::FunctionIndex); F->addAttributes(llvm::AttributeList::FunctionIndex, B); @@ -2234,6 +2723,16 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD, Ty = getTypes().ConvertFunctionType(CanonTy, FD); } + // Devirtualized destructor calls may come through here instead of via + // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead + // of the complete destructor when necessary. + if (const auto *DD = dyn_cast<CXXDestructorDecl>(GD.getDecl())) { + if (getTarget().getCXXABI().isMicrosoft() && + GD.getDtorType() == Dtor_Complete && + DD->getParent()->getNumVBases() == 0) + GD = GlobalDecl(DD, Dtor_Base); + } + StringRef MangledName = getMangledName(GD); return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer, /*IsThunk=*/false, llvm::AttributeList(), @@ -2255,7 +2754,7 @@ GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) { // Demangle the premangled name from getTerminateFn() IdentifierInfo &CXXII = - (Name == "_ZSt9terminatev" || Name == "\01?terminate@@YAXXZ") + (Name == "_ZSt9terminatev" || Name == "?terminate@@YAXXZ") ? C.Idents.get("terminate") : C.Idents.get(Name); @@ -2302,6 +2801,7 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, F->setLinkage(llvm::GlobalValue::ExternalLinkage); } } + setDSOLocal(F); } } @@ -2313,13 +2813,7 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, llvm::Constant * CodeGenModule::CreateBuiltinFunction(llvm::FunctionType *FTy, StringRef Name, llvm::AttributeList ExtraAttrs) { - llvm::Constant *C = - GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false, - /*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs); - if (auto *F = dyn_cast<llvm::Function>(C)) - if (F->empty()) - F->setCallingConv(getBuiltinCC()); - return C; + return CreateRuntimeFunction(FTy, Name, ExtraAttrs, true); } /// isTypeConstant - Determine whether an object of this type can be emitted @@ -2350,7 +2844,7 @@ bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) { /// If D is non-null, it specifies a decl that correspond to this. This is used /// to set the attributes on the global when it is first created. /// -/// If IsForDefinition is true, it is guranteed that an actual global with +/// If IsForDefinition is true, it is guaranteed that an actual global with /// type Ty will be returned, not conversion of a variable with the same /// mangled name but some other type. llvm::Constant * @@ -2370,6 +2864,9 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>()) Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); + if (LangOpts.OpenMP && !LangOpts.OpenMPSimd && D) + getOpenMPRuntime().registerTargetGlobalVariable(D, Entry); + if (Entry->getType() == Ty) return Entry; @@ -2386,8 +2883,8 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, (OtherD = dyn_cast<VarDecl>(OtherGD.getDecl())) && OtherD->hasInit() && DiagnosedConflictingDefinitions.insert(D).second) { - getDiags().Report(D->getLocation(), - diag::err_duplicate_mangled_name); + getDiags().Report(D->getLocation(), diag::err_duplicate_mangled_name) + << MangledName; getDiags().Report(OtherGD.getDecl()->getLocation(), diag::note_previous_definition); } @@ -2438,6 +2935,9 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, // Handle things which are present even on external declarations. if (D) { + if (LangOpts.OpenMP && !LangOpts.OpenMPSimd) + getOpenMPRuntime().registerTargetGlobalVariable(D, GV); + // FIXME: This code is overly simple and should be merged with other global // handling. GV->setConstant(isTypeConstant(D->getType(), false)); @@ -2445,7 +2945,6 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, GV->setAlignment(getContext().getDeclAlign(D).getQuantity()); setLinkageForGV(GV, D); - setGlobalVisibility(GV, D, NotForDefinition); if (D->getTLSKind()) { if (D->getTLSKind() == VarDecl::TLS_Dynamic) @@ -2453,6 +2952,8 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, setTLSMode(GV, *D); } + setGVProperties(GV, D); + // If required by the ABI, treat declarations of static data members with // inline initializers as definitions. if (getContext().isMSStaticDataMemberInlineDefinition(D)) { @@ -2501,7 +3002,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, GetAddrOfGlobalVar(D, InitType, IsForDefinition)); // Erase the old global, since it is no longer used. - cast<llvm::GlobalValue>(GV)->eraseFromParent(); + GV->eraseFromParent(); GV = NewGV; } else { GV->setInitializer(Init); @@ -2602,7 +3103,7 @@ CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name, /// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the /// given global variable. If Ty is non-null and if the global doesn't exist, /// then it will be created with the specified type instead of whatever the -/// normal requested type would be. If IsForDefinition is true, it is guranteed +/// normal requested type would be. If IsForDefinition is true, it is guaranteed /// that an actual global with type Ty will be returned, not conversion of a /// variable with the same mangled name but some other type. llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, @@ -2625,7 +3126,10 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, llvm::Constant * CodeGenModule::CreateRuntimeVariable(llvm::Type *Ty, StringRef Name) { - return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), nullptr); + auto *Ret = + GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), nullptr); + setDSOLocal(cast<llvm::GlobalValue>(Ret->stripPointerCasts())); + return Ret; } void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) { @@ -2679,6 +3183,39 @@ LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) { return getTargetCodeGenInfo().getGlobalVarAddressSpace(*this, D); } +LangAS CodeGenModule::getStringLiteralAddressSpace() const { + // OpenCL v1.2 s6.5.3: a string literal is in the constant address space. + if (LangOpts.OpenCL) + return LangAS::opencl_constant; + if (auto AS = getTarget().getConstantAddressSpace()) + return AS.getValue(); + return LangAS::Default; +} + +// In address space agnostic languages, string literals are in default address +// space in AST. However, certain targets (e.g. amdgcn) request them to be +// emitted in constant address space in LLVM IR. To be consistent with other +// parts of AST, string literal global variables in constant address space +// need to be casted to default address space before being put into address +// map and referenced by other part of CodeGen. +// In OpenCL, string literals are in constant address space in AST, therefore +// they should not be casted to default address space. +static llvm::Constant * +castStringLiteralToDefaultAddressSpace(CodeGenModule &CGM, + llvm::GlobalVariable *GV) { + llvm::Constant *Cast = GV; + if (!CGM.getLangOpts().OpenCL) { + if (auto AS = CGM.getTarget().getConstantAddressSpace()) { + if (AS != LangAS::Default) + Cast = CGM.getTargetCodeGenInfo().performAddrSpaceCast( + CGM, GV, AS.getValue(), LangAS::Default, + GV->getValueType()->getPointerTo( + CGM.getContext().getTargetAddressSpace(LangAS::Default))); + } + } + return Cast; +} + template<typename SomeDecl> void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D, llvm::GlobalValue *GV) { @@ -2753,6 +3290,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, if (getLangOpts().OpenCL && ASTTy->isSamplerT()) return; + // If this is OpenMP device, check if it is legal to emit this global + // normally. + if (LangOpts.OpenMPIsDevice && OpenMPRuntime && + OpenMPRuntime->emitTargetGlobalVariable(D)) + return; + llvm::Constant *Init = nullptr; CXXRecordDecl *RD = ASTTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); bool NeedsGlobalCtor = false; @@ -2989,7 +3532,7 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context, return true; // A variable cannot be both common and exist in a section. - // We dont try to determine which is the right section in the front-end. + // We don't try to determine which is the right section in the front-end. // If no specialized section name is applicable, it will resort to default. if (D->hasAttr<PragmaClangBSSSectionAttr>() || D->hasAttr<PragmaClangDataSectionAttr>() || @@ -3261,18 +3804,18 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, // declarations). auto *Fn = cast<llvm::Function>(GV); setFunctionLinkage(GD, Fn); - setFunctionDLLStorageClass(GD, Fn); // FIXME: this is redundant with part of setFunctionDefinitionAttributes - setGlobalVisibility(Fn, D, ForDefinition); + setGVProperties(Fn, GD); MaybeHandleStaticInExternC(D, Fn); + maybeSetTrivialComdat(*D, *Fn); CodeGenFunction(*this).GenerateCode(D, Fn, FI); - setFunctionDefinitionAttributes(D, Fn); + setNonAliasAttributes(GD, Fn); SetLLVMFunctionAttributesForDefinition(D, Fn); if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>()) @@ -3281,6 +3824,15 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, AddGlobalDtor(Fn, DA->getPriority()); if (D->hasAttr<AnnotateAttr>()) AddGlobalAnnotations(D, Fn); + + if (D->isCPUSpecificMultiVersion()) { + auto *Spec = D->getAttr<CPUSpecificAttr>(); + // If there is another specific version we need to emit, do so here. + if (Spec->ActiveArgIndex + 1 < Spec->cpus_size()) { + ++Spec->ActiveArgIndex; + EmitGlobalFunctionDefinition(GD, nullptr); + } + } } void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { @@ -3356,7 +3908,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { if (VD->getTLSKind()) setTLSMode(GA, *VD); - setAliasAttributes(D, GA); + SetCommonAttributes(GD, GA); } void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) { @@ -3377,7 +3929,8 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) { GlobalDecl OtherGD; if (lookupRepresentativeDecl(MangledName, OtherGD) && DiagnosedConflictingDefinitions.insert(GD).second) { - Diags.Report(D->getLocation(), diag::err_duplicate_mangled_name); + Diags.Report(D->getLocation(), diag::err_duplicate_mangled_name) + << MangledName; Diags.Report(OtherGD.getDecl()->getLocation(), diag::note_previous_definition); } @@ -3415,7 +3968,7 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) { } else GIF->setName(MangledName); - SetCommonAttributes(D, GIF); + SetCommonAttributes(GD, GIF); } llvm::Function *CodeGenModule::getIntrinsic(unsigned IID, @@ -3477,14 +4030,13 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { if (!CFConstantStringClassRef) { llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy); Ty = llvm::ArrayType::get(Ty, 0); - llvm::Constant *GV = - CreateRuntimeVariable(Ty, "__CFConstantStringClassReference"); + llvm::GlobalValue *GV = cast<llvm::GlobalValue>( + CreateRuntimeVariable(Ty, "__CFConstantStringClassReference")); if (getTriple().isOSBinFormatCOFF()) { IdentifierInfo &II = getContext().Idents.get(GV->getName()); TranslationUnitDecl *TUDecl = getContext().getTranslationUnitDecl(); DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); - llvm::GlobalValue *CGV = cast<llvm::GlobalValue>(GV); const VarDecl *VD = nullptr; for (const auto &Result : DC->lookup(&II)) @@ -3492,13 +4044,14 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { break; if (!VD || !VD->hasAttr<DLLExportAttr>()) { - CGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); - CGV->setLinkage(llvm::GlobalValue::ExternalLinkage); + GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); + GV->setLinkage(llvm::GlobalValue::ExternalLinkage); } else { - CGV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); - CGV->setLinkage(llvm::GlobalValue::ExternalLinkage); + GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); + GV->setLinkage(llvm::GlobalValue::ExternalLinkage); } } + setDSOLocal(GV); // Decay array -> ptr CFConstantStringClassRef = @@ -3666,10 +4219,8 @@ static llvm::GlobalVariable * GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT, CodeGenModule &CGM, StringRef GlobalName, CharUnits Alignment) { - // OpenCL v1.2 s6.5.3: a string literal is in the constant address space. - unsigned AddrSpace = 0; - if (CGM.getLangOpts().OpenCL) - AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_constant); + unsigned AddrSpace = CGM.getContext().getTargetAddressSpace( + CGM.getStringLiteralAddressSpace()); llvm::Module &M = CGM.getModule(); // Create a global variable for this string @@ -3682,6 +4233,7 @@ GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT, assert(CGM.supportsCOMDAT() && "Only COFF uses weak string literals"); GV->setComdat(M.getOrInsertComdat(GV->getName())); } + CGM.setDSOLocal(GV); return GV; } @@ -3730,7 +4282,9 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S, SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "<string literal>", QualType()); - return ConstantAddress(GV, Alignment); + + return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), + Alignment); } /// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant @@ -3774,7 +4328,9 @@ ConstantAddress CodeGenModule::GetAddrOfConstantCString( GlobalName, Alignment); if (Entry) *Entry = GV; - return ConstantAddress(GV, Alignment); + + return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), + Alignment); } ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( @@ -3847,7 +4403,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( if (VD->isStaticDataMember() && VD->getAnyInitializer(InitVD) && isa<CXXRecordDecl>(InitVD->getLexicalDeclContext())) { // Temporaries defined inside a class get linkonce_odr linkage because the - // class can be defined in multipe translation units. + // class can be defined in multiple translation units. Linkage = llvm::GlobalVariable::LinkOnceODRLinkage; } else { // There is no need for this temporary to have external linkage if the @@ -3860,7 +4416,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(), /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); if (emitter) emitter->finalize(GV); - setGlobalVisibility(GV, VD, ForDefinition); + setGVProperties(GV, VD); GV->setAlignment(Align.getQuantity()); if (supportsCOMDAT() && GV->isWeakForLinker()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); @@ -3997,18 +4553,13 @@ void CodeGenModule::EmitDeclContext(const DeclContext *DC) { /// EmitTopLevelDecl - Emit code for a single top level declaration. void CodeGenModule::EmitTopLevelDecl(Decl *D) { // Ignore dependent declarations. - if (D->getDeclContext() && D->getDeclContext()->isDependentContext()) + if (D->isTemplated()) return; switch (D->getKind()) { case Decl::CXXConversion: case Decl::CXXMethod: case Decl::Function: - // Skip function templates - if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate() || - cast<FunctionDecl>(D)->isLateTemplateParsed()) - return; - EmitGlobal(cast<FunctionDecl>(D)); // Always provide some coverage mapping // even for the functions that aren't emitted. @@ -4021,10 +4572,6 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::Var: case Decl::Decomposition: - // Skip variable templates - if (cast<VarDecl>(D)->getDescribedVarTemplate()) - return; - LLVM_FALLTHROUGH; case Decl::VarTemplateSpecialization: EmitGlobal(cast<VarDecl>(D)); if (auto *DD = dyn_cast<DecompositionDecl>(D)) @@ -4083,16 +4630,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { DI->EmitUsingDirective(cast<UsingDirectiveDecl>(*D)); return; case Decl::CXXConstructor: - // Skip function templates - if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate() || - cast<FunctionDecl>(D)->isLateTemplateParsed()) - return; - getCXXABI().EmitCXXConstructors(cast<CXXConstructorDecl>(D)); break; case Decl::CXXDestructor: - if (cast<FunctionDecl>(D)->isLateTemplateParsed()) - return; getCXXABI().EmitCXXDestructors(cast<CXXDestructorDecl>(D)); break; @@ -4152,7 +4692,11 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { AppendLinkerOptions(PCD->getArg()); break; case PCK_Lib: - AddDependentLib(PCD->getArg()); + if (getTarget().getTriple().isOSBinFormatELF() && + !getTarget().getTriple().isPS4()) + AddELFLibDirective(PCD->getArg()); + else + AddDependentLib(PCD->getArg()); break; case PCK_Compiler: case PCK_ExeStr: @@ -4358,9 +4902,7 @@ static void EmitGlobalDeclMetadata(CodeGenModule &CGM, /// to such functions with an unmangled name from inline assembly within the /// same translation unit. void CodeGenModule::EmitStaticExternCAliases() { - // Don't do anything if we're generating CUDA device code -- the NVPTX - // assembly target doesn't support aliases. - if (Context.getTargetInfo().getTriple().isNVPTX()) + if (!getTargetCodeGenInfo().shouldEmitStaticExternCAliases()) return; for (auto &I : StaticExternCValues) { IdentifierInfo *Name = I.first; @@ -4504,7 +5046,7 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty, // Return a bogus pointer if RTTI is disabled, unless it's for EH. // FIXME: should we even be calling this method if RTTI is disabled // and it's not for EH? - if (!ForEH && !getLangOpts().RTTI) + if ((!ForEH && !getLangOpts().RTTI) || getLangOpts().CUDAIsDevice) return llvm::Constant::getNullValue(Int8PtrTy); if (ForEH && Ty->isObjCObjectPointerType() && @@ -4515,6 +5057,9 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty, } void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { + // Do not emit threadprivates in simd-only mode. + if (LangOpts.OpenMP && LangOpts.OpenMPSimd) + return; for (auto RefExpr : D->varlists()) { auto *VD = cast<VarDecl>(cast<DeclRefExpr>(RefExpr)->getDecl()); bool PerformInit = @@ -4529,8 +5074,10 @@ void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { } } -llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) { - llvm::Metadata *&InternalId = MetadataIdMap[T.getCanonicalType()]; +llvm::Metadata * +CodeGenModule::CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map, + StringRef Suffix) { + llvm::Metadata *&InternalId = Map[T.getCanonicalType()]; if (InternalId) return InternalId; @@ -4538,6 +5085,7 @@ llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) { std::string OutName; llvm::raw_string_ostream Out(OutName); getCXXABI().getMangleContext().mangleTypeName(T, Out); + Out << Suffix; InternalId = llvm::MDString::get(getLLVMContext(), Out.str()); } else { @@ -4548,6 +5096,15 @@ llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) { return InternalId; } +llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) { + return CreateMetadataIdentifierImpl(T, MetadataIdMap, ""); +} + +llvm::Metadata * +CodeGenModule::CreateMetadataIdentifierForVirtualMemPtrType(QualType T) { + return CreateMetadataIdentifierImpl(T, VirtualMetadataIdMap, ".virtual"); +} + // Generalize pointer types to a void pointer with the qualifiers of the // originally pointed-to type, e.g. 'const char *' and 'char * const *' // generalize to 'const void *' while 'char *' and 'const char **' generalize to @@ -4581,25 +5138,8 @@ static QualType GeneralizeFunctionType(ASTContext &Ctx, QualType Ty) { } llvm::Metadata *CodeGenModule::CreateMetadataIdentifierGeneralized(QualType T) { - T = GeneralizeFunctionType(getContext(), T); - - llvm::Metadata *&InternalId = GeneralizedMetadataIdMap[T.getCanonicalType()]; - if (InternalId) - return InternalId; - - if (isExternallyVisible(T->getLinkage())) { - std::string OutName; - llvm::raw_string_ostream Out(OutName); - getCXXABI().getMangleContext().mangleTypeName(T, Out); - Out << ".generalized"; - - InternalId = llvm::MDString::get(getLLVMContext(), Out.str()); - } else { - InternalId = llvm::MDNode::getDistinct(getLLVMContext(), - llvm::ArrayRef<llvm::Metadata *>()); - } - - return InternalId; + return CreateMetadataIdentifierImpl(GeneralizeFunctionType(getContext(), T), + GeneralizedMetadataIdMap, ".generalized"); } /// Returns whether this module needs the "all-vtables" type identifier. @@ -4634,22 +5174,28 @@ void CodeGenModule::AddVTableTypeMetadata(llvm::GlobalVariable *VTable, } } +TargetAttr::ParsedTargetAttr CodeGenModule::filterFunctionTargetAttrs(const TargetAttr *TD) { + assert(TD != nullptr); + TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); + + ParsedAttr.Features.erase( + llvm::remove_if(ParsedAttr.Features, + [&](const std::string &Feat) { + return !Target.isValidFeatureName( + StringRef{Feat}.substr(1)); + }), + ParsedAttr.Features.end()); + return ParsedAttr; +} + + // Fills in the supplied string map with the set of target features for the // passed in function. void CodeGenModule::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, const FunctionDecl *FD) { StringRef TargetCPU = Target.getTargetOpts().CPU; if (const auto *TD = FD->getAttr<TargetAttr>()) { - // If we have a TargetAttr build up the feature map based on that. - TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); - - ParsedAttr.Features.erase( - llvm::remove_if(ParsedAttr.Features, - [&](const std::string &Feat) { - return !Target.isValidFeatureName( - StringRef{Feat}.substr(1)); - }), - ParsedAttr.Features.end()); + TargetAttr::ParsedTargetAttr ParsedAttr = filterFunctionTargetAttrs(TD); // Make a copy of the features as passed on the command line into the // beginning of the additional features from the function to override. @@ -4667,6 +5213,12 @@ void CodeGenModule::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, // the attribute. Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, ParsedAttr.Features); + } else if (const auto *SD = FD->getAttr<CPUSpecificAttr>()) { + llvm::SmallVector<StringRef, 32> FeaturesTmp; + Target.getCPUSpecificCPUDispatchFeatures(SD->getCurCPUName()->getName(), + FeaturesTmp); + std::vector<std::string> Features(FeaturesTmp.begin(), FeaturesTmp.end()); + Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, Features); } else { Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, Target.getTargetOpts().Features); |