aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
authorAlexandros Lamprineas <alexandros.lamprineas@arm.com>2024-03-25 09:43:41 +0000
committerGitHub <noreply@github.com>2024-03-25 09:43:41 +0000
commit772e316457ef94759804d9f4da0af70d8d2ca4d4 (patch)
tree8f51a0a11e4e1b3961197282120c342e71698575 /clang/lib/CodeGen/CodeGenModule.cpp
parent8263a883342d9925a4a1fd9752efc8deda5840fc (diff)
downloadllvm-772e316457ef94759804d9f4da0af70d8d2ca4d4.zip
llvm-772e316457ef94759804d9f4da0af70d8d2ca4d4.tar.gz
llvm-772e316457ef94759804d9f4da0af70d8d2ca4d4.tar.bz2
[FMV] Allow multi versioning without default declaration. (#85454)
This was a limitation which has now been lifted. Please read the thread below for more details: https://github.com/llvm/llvm-project/pull/84405#discussion_r1525583647 Basically it allows to separate versioned implementations across different TUs without having to share private header files which contain the default declaration. The ACLE spec has been updated accordingly to make this explicit: "Each version declaration should be visible at the translation unit in which the corresponding function version resides." https://github.com/ARM-software/acle/pull/310 If a resolver is required (because there is a caller in the TU), then a default declaration is implicitly generated.
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp131
1 files changed, 71 insertions, 60 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index cb15306..ac81df8 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3711,7 +3711,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// Forward declarations are emitted lazily on first use.
if (!FD->doesThisDeclarationHaveABody()) {
- if (!FD->doesDeclarationForceExternallyVisibleDefinition())
+ if (!FD->doesDeclarationForceExternallyVisibleDefinition() &&
+ !FD->isTargetVersionMultiVersion())
return;
StringRef MangledName = getMangledName(GD);
@@ -4092,6 +4093,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,70 +4117,54 @@ void CodeGenModule::emitMultiVersionFunctions() {
const auto *FD = cast<FunctionDecl>(GD.getDecl());
assert(FD && "Expected a FunctionDecl");
- bool EmitResolver = !FD->isTargetVersionMultiVersion();
+ 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);
+ };
+
+ bool HasDefaultDecl = !FD->isTargetVersionMultiVersion();
+ bool ShouldEmitResolver = !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;
+ FD, [&](const FunctionDecl *CurFD) {
+ llvm::SmallVector<StringRef, 8> Feats;
+ llvm::Function *Func = createFunction(CurFD);
+
+ if (const auto *TA = CurFD->getAttr<TargetAttr>()) {
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;
+ 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);
- Options.emplace_back(cast<llvm::Function>(Func),
- /*Architecture*/ "", Feats);
- }
+ Options.emplace_back(Func, /*Architecture*/ "", Feats);
+ } else
+ llvm_unreachable("unexpected MultiVersionKind");
});
- } else if (FD->isTargetClonesMultiVersion()) {
- const auto *TC = FD->getAttr<TargetClonesAttr>();
- for (unsigned VersionIndex = 0; VersionIndex < TC->featuresStrs_size();
- ++VersionIndex) {
- if (!TC->isFirstOfVersion(VersionIndex))
+ } else if (const auto *TC = FD->getAttr<TargetClonesAttr>()) {
+ for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) {
+ if (!TC->isFirstOfVersion(I))
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");
- }
+ llvm::Function *Func = createFunction(FD, I);
+ StringRef Version = TC->getFeatureStr(I);
StringRef Architecture;
llvm::SmallVector<StringRef, 1> Feature;
@@ -4180,16 +4182,23 @@ void CodeGenModule::emitMultiVersionFunctions() {
Feature.push_back(Version);
}
- Options.emplace_back(cast<llvm::Function>(Func), Architecture, Feature);
+ Options.emplace_back(Func, Architecture, Feature);
}
} else {
assert(0 && "Expected a target or target_clones multiversion function");
continue;
}
- if (!EmitResolver)
+ if (!ShouldEmitResolver)
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)) {
ResolverConstant = IFunc->getResolver();
@@ -4480,7 +4489,9 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
if (FD->isMultiVersion()) {
UpdateMultiVersionNames(GD, FD, MangledName);
- if (!IsForDefinition)
+ if (FD->isTargetVersionMultiVersion() && !FD->isUsed())
+ AddDeferredMultiVersionResolverToEmit(GD);
+ else if (!IsForDefinition)
return GetOrCreateMultiVersionResolver(GD);
}
}