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.cpp131
1 files changed, 71 insertions, 60 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index cb153066b28d..ac81df8cf7ad 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);
}
}