aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp132
1 files changed, 124 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 59f3e0270571..9ba1a5c25e81 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/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(