diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp | 132 |
1 files changed, 124 insertions, 8 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp index 59f3e0270571..9ba1a5c25e81 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp @@ -710,10 +710,25 @@ void CodeGenModule::Release() { 1); } - if (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 || + // Add module metadata for return address signing (ignoring + // non-leaf/all) and stack tagging. These are actually turned on by function + // attributes, but we use module metadata to emit build attributes. This is + // 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. + 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)) + getModule().addModuleFlag(llvm::Module::Override, + "tag-stack-memory-buildattr", 1); + + if (Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb || + 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::Error, "branch-target-enforcement", LangOpts.BranchTargetEnforcement); getModule().addModuleFlag(llvm::Module::Error, "sign-return-address", @@ -722,9 +737,11 @@ void CodeGenModule::Release() { getModule().addModuleFlag(llvm::Module::Error, "sign-return-address-all", LangOpts.isSignReturnAddressScopeAll()); - getModule().addModuleFlag(llvm::Module::Error, - "sign-return-address-with-bkey", - !LangOpts.isSignReturnAddressWithAKey()); + if (Arch != llvm::Triple::thumb && Arch != llvm::Triple::thumbeb) { + getModule().addModuleFlag(llvm::Module::Error, + "sign-return-address-with-bkey", + !LangOpts.isSignReturnAddressWithAKey()); + } } if (!CodeGenOpts.MemoryProfileOutput.empty()) { @@ -1266,6 +1283,20 @@ static bool isUniqueInternalLinkageDecl(GlobalDecl GD, (CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage); } +static void AppendTargetClonesMangling(const CodeGenModule &CGM, + const TargetClonesAttr *Attr, + unsigned VersionIndex, + raw_ostream &Out) { + Out << '.'; + StringRef FeatureStr = Attr->getFeatureStr(VersionIndex); + if (FeatureStr.startswith("arch=")) + Out << "arch_" << FeatureStr.substr(sizeof("arch=") - 1); + else + Out << FeatureStr; + + Out << '.' << Attr->getMangledIndex(VersionIndex); +} + static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, const NamedDecl *ND, bool OmitMultiVersionMangling = false) { @@ -1319,6 +1350,10 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, case MultiVersionKind::Target: AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out); break; + case MultiVersionKind::TargetClones: + AppendTargetClonesMangling(CGM, FD->getAttr<TargetClonesAttr>(), + GD.getMultiVersionIndex(), Out); + break; case MultiVersionKind::None: llvm_unreachable("None multiversion type isn't valid here"); } @@ -1983,8 +2018,9 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD, FD = FD ? FD->getMostRecentDecl() : FD; const auto *TD = FD ? FD->getAttr<TargetAttr>() : nullptr; const auto *SD = FD ? FD->getAttr<CPUSpecificAttr>() : nullptr; + const auto *TC = FD ? FD->getAttr<TargetClonesAttr>() : nullptr; bool AddedAttr = false; - if (TD || SD) { + if (TD || SD || TC) { llvm::StringMap<bool> FeatureMap; getContext().getFunctionFeatureMap(FeatureMap, GD); @@ -3226,6 +3262,12 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD, 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); } else EmitGlobalFunctionDefinition(GD, GV); } @@ -3307,6 +3349,63 @@ 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); @@ -3511,8 +3610,25 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver( // 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()) + if (FD->isTargetMultiVersion()) 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()) { llvm::Type *ResolverType = llvm::FunctionType::get( |