summaryrefslogtreecommitdiff
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.cpp192
1 files changed, 99 insertions, 93 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index cb153066b28d..00b3bfcaa0bc 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3711,7 +3711,9 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// Forward declarations are emitted lazily on first use.
if (!FD->doesThisDeclarationHaveABody()) {
- if (!FD->doesDeclarationForceExternallyVisibleDefinition())
+ if (!FD->doesDeclarationForceExternallyVisibleDefinition() &&
+ (!FD->isMultiVersion() ||
+ !FD->getASTContext().getTargetInfo().getTriple().isAArch64()))
return;
StringRef MangledName = getMangledName(GD);
@@ -3993,10 +3995,11 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD,
auto *Spec = FD->getAttr<CPUSpecificAttr>();
for (unsigned I = 0; I < Spec->cpus_size(); ++I)
EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
- } else if (FD->isTargetClonesMultiVersion()) {
- auto *Clone = FD->getAttr<TargetClonesAttr>();
- for (unsigned I = 0; I < Clone->featuresStrs_size(); ++I)
- if (Clone->isFirstOfVersion(I))
+ } else if (auto *TC = FD->getAttr<TargetClonesAttr>()) {
+ for (unsigned I = 0; I < TC->featuresStrs_size(); ++I)
+ // AArch64 favors the default target version over the clone if any.
+ if ((!TC->isDefaultVersion(I) || !getTarget().getTriple().isAArch64()) &&
+ TC->isFirstOfVersion(I))
EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
// Ensure that the resolver function is also emitted.
GetOrCreateMultiVersionResolver(GD);
@@ -4092,6 +4095,23 @@ llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM,
return llvm::GlobalValue::WeakODRLinkage;
}
+static FunctionDecl *createDefaultTargetVersionFrom(const FunctionDecl *FD) {
+ DeclContext *DeclCtx = FD->getASTContext().getTranslationUnitDecl();
+ TypeSourceInfo *TInfo = FD->getTypeSourceInfo();
+ StorageClass SC = FD->getStorageClass();
+ DeclarationName Name = FD->getNameInfo().getName();
+
+ FunctionDecl *NewDecl =
+ FunctionDecl::Create(FD->getASTContext(), DeclCtx, FD->getBeginLoc(),
+ FD->getEndLoc(), Name, TInfo->getType(), TInfo, SC);
+
+ NewDecl->setIsMultiVersion();
+ NewDecl->addAttr(TargetVersionAttr::CreateImplicit(
+ NewDecl->getASTContext(), "default", NewDecl->getSourceRange()));
+
+ return NewDecl;
+}
+
void CodeGenModule::emitMultiVersionFunctions() {
std::vector<GlobalDecl> MVFuncsToEmit;
MultiVersionFuncs.swap(MVFuncsToEmit);
@@ -4099,96 +4119,79 @@ void CodeGenModule::emitMultiVersionFunctions() {
const auto *FD = cast<FunctionDecl>(GD.getDecl());
assert(FD && "Expected a FunctionDecl");
- bool EmitResolver = !FD->isTargetVersionMultiVersion();
- SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
- if (FD->isTargetMultiVersion()) {
- getContext().forEachMultiversionedFunctionVersion(
- FD, [this, &GD, &Options, &EmitResolver](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");
- }
- if (CurFD->getMultiVersionKind() == MultiVersionKind::Target) {
- 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 {
- const auto *TVA = CurFD->getAttr<TargetVersionAttr>();
- if (CurFD->isUsed() || (TVA->isDefaultVersion() &&
- CurFD->doesThisDeclarationHaveABody()))
- EmitResolver = true;
- llvm::SmallVector<StringRef, 8> Feats;
- TVA->getFeatures(Feats);
- Options.emplace_back(cast<llvm::Function>(Func),
- /*Architecture*/ "", 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");
+ auto createFunction = [&](const FunctionDecl *Decl, unsigned MVIdx = 0) {
+ GlobalDecl CurGD{Decl->isDefined() ? Decl->getDefinition() : Decl, MVIdx};
+ StringRef MangledName = getMangledName(CurGD);
+ llvm::Constant *Func = GetGlobalValue(MangledName);
+ if (!Func) {
+ if (Decl->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");
+ }
+ return cast<llvm::Function>(Func);
+ };
- StringRef Architecture;
- llvm::SmallVector<StringRef, 1> Feature;
+ bool HasDefaultDecl = !FD->isTargetVersionMultiVersion();
+ bool ShouldEmitResolver =
+ !getContext().getTargetInfo().getTriple().isAArch64();
+ SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
- if (getTarget().getTriple().isAArch64()) {
- if (Version != "default") {
- llvm::SmallVector<StringRef, 8> VerFeats;
- Version.split(VerFeats, "+");
- for (auto &CurFeat : VerFeats)
- Feature.push_back(CurFeat.trim());
- }
- } else {
- if (Version.starts_with("arch="))
- Architecture = Version.drop_front(sizeof("arch=") - 1);
- else if (Version != "default")
- Feature.push_back(Version);
- }
+ getContext().forEachMultiversionedFunctionVersion(
+ FD, [&](const FunctionDecl *CurFD) {
+ llvm::SmallVector<StringRef, 8> Feats;
+
+ if (const auto *TA = CurFD->getAttr<TargetAttr>()) {
+ TA->getAddedFeatures(Feats);
+ llvm::Function *Func = createFunction(CurFD);
+ Options.emplace_back(Func, TA->getArchitecture(), Feats);
+ } else if (const auto *TVA = CurFD->getAttr<TargetVersionAttr>()) {
+ bool HasDefaultDef = TVA->isDefaultVersion() &&
+ CurFD->doesThisDeclarationHaveABody();
+ HasDefaultDecl |= TVA->isDefaultVersion();
+ ShouldEmitResolver |= (CurFD->isUsed() || HasDefaultDef);
+ TVA->getFeatures(Feats);
+ llvm::Function *Func = createFunction(CurFD);
+ Options.emplace_back(Func, /*Architecture*/ "", Feats);
+ } else if (const auto *TC = CurFD->getAttr<TargetClonesAttr>()) {
+ ShouldEmitResolver |= CurFD->doesThisDeclarationHaveABody();
+ for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) {
+ if (!TC->isFirstOfVersion(I))
+ continue;
+
+ llvm::Function *Func = createFunction(CurFD, I);
+ StringRef Architecture;
+ Feats.clear();
+ if (getTarget().getTriple().isAArch64())
+ TC->getFeatures(Feats, I);
+ else {
+ StringRef Version = TC->getFeatureStr(I);
+ if (Version.starts_with("arch="))
+ Architecture = Version.drop_front(sizeof("arch=") - 1);
+ else if (Version != "default")
+ Feats.push_back(Version);
+ }
+ Options.emplace_back(Func, Architecture, Feats);
+ }
+ } else
+ llvm_unreachable("unexpected MultiVersionKind");
+ });
- Options.emplace_back(cast<llvm::Function>(Func), Architecture, Feature);
- }
- } else {
- assert(0 && "Expected a target or target_clones multiversion function");
+ if (!ShouldEmitResolver)
continue;
- }
- if (!EmitResolver)
- continue;
+ if (!HasDefaultDecl) {
+ FunctionDecl *NewFD = createDefaultTargetVersionFrom(FD);
+ llvm::Function *Func = createFunction(NewFD);
+ llvm::SmallVector<StringRef, 1> Feats;
+ Options.emplace_back(Func, /*Architecture*/ "", Feats);
+ }
llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD);
if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
@@ -4369,7 +4372,7 @@ void CodeGenModule::AddDeferredMultiVersionResolverToEmit(GlobalDecl GD) {
const auto *FD = cast<FunctionDecl>(GD.getDecl());
assert(FD && "Not a FunctionDecl?");
- if (FD->isTargetVersionMultiVersion()) {
+ if (FD->isTargetVersionMultiVersion() || FD->isTargetClonesMultiVersion()) {
std::string MangledName =
getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true);
if (!DeferredResolversToEmit.insert(MangledName).second)
@@ -4480,7 +4483,10 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
if (FD->isMultiVersion()) {
UpdateMultiVersionNames(GD, FD, MangledName);
- if (!IsForDefinition)
+ if (FD->getASTContext().getTargetInfo().getTriple().isAArch64() &&
+ !FD->isUsed())
+ AddDeferredMultiVersionResolverToEmit(GD);
+ else if (!IsForDefinition)
return GetOrCreateMultiVersionResolver(GD);
}
}
@@ -6275,7 +6281,7 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) {
// Resize the string to the right size, which is indicated by its type.
const ConstantArrayType *CAT = Context.getAsConstantArrayType(E->getType());
assert(CAT && "String literal not of constant array type!");
- Str.resize(CAT->getSize().getZExtValue());
+ Str.resize(CAT->getZExtSize());
return llvm::ConstantDataArray::getString(VMContext, Str, false);
}
@@ -7261,7 +7267,7 @@ void CodeGenFunction::EmitDeclMetadata() {
for (auto &I : LocalDeclMap) {
const Decl *D = I.first;
- llvm::Value *Addr = I.second.getPointer();
+ llvm::Value *Addr = I.second.emitRawPointer(*this);
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(Addr)) {
llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D);
Alloca->setMetadata(