@@ -4092,77 +4092,78 @@ llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM,
4092
4092
return llvm::GlobalValue::WeakODRLinkage;
4093
4093
}
4094
4094
4095
+ static FunctionDecl *createDefaultTargetVersionFrom (const FunctionDecl *FD) {
4096
+ DeclContext *DeclCtx = FD->getASTContext ().getTranslationUnitDecl ();
4097
+ TypeSourceInfo *TInfo = FD->getTypeSourceInfo ();
4098
+ StorageClass SC = FD->getStorageClass ();
4099
+ DeclarationName Name = FD->getNameInfo ().getName ();
4100
+
4101
+ FunctionDecl *NewDecl =
4102
+ FunctionDecl::Create (FD->getASTContext (), DeclCtx, FD->getBeginLoc (),
4103
+ FD->getEndLoc (), Name, TInfo->getType (), TInfo, SC);
4104
+
4105
+ NewDecl->setIsMultiVersion ();
4106
+ NewDecl->addAttr (TargetVersionAttr::CreateImplicit (
4107
+ NewDecl->getASTContext (), " default" , NewDecl->getSourceRange ()));
4108
+
4109
+ return NewDecl;
4110
+ }
4111
+
4095
4112
void CodeGenModule::emitMultiVersionFunctions () {
4096
4113
std::vector<GlobalDecl> MVFuncsToEmit;
4097
4114
MultiVersionFuncs.swap (MVFuncsToEmit);
4098
4115
for (GlobalDecl GD : MVFuncsToEmit) {
4099
4116
const auto *FD = cast<FunctionDecl>(GD.getDecl ());
4100
4117
assert (FD && " Expected a FunctionDecl" );
4101
4118
4102
- bool EmitResolver = !FD->isTargetVersionMultiVersion ();
4119
+ auto createFunction = [&](const FunctionDecl *Decl, unsigned MVIdx = 0 ) {
4120
+ GlobalDecl CurGD{Decl->isDefined () ? Decl->getDefinition () : Decl, MVIdx};
4121
+ StringRef MangledName = getMangledName (CurGD);
4122
+ llvm::Constant *Func = GetGlobalValue (MangledName);
4123
+ if (!Func) {
4124
+ if (Decl->isDefined ()) {
4125
+ EmitGlobalFunctionDefinition (CurGD, nullptr );
4126
+ Func = GetGlobalValue (MangledName);
4127
+ } else {
4128
+ const CGFunctionInfo &FI = getTypes ().arrangeGlobalDeclaration (CurGD);
4129
+ llvm::FunctionType *Ty = getTypes ().GetFunctionType (FI);
4130
+ Func = GetAddrOfFunction (CurGD, Ty, /* ForVTable=*/ false ,
4131
+ /* DontDefer=*/ false , ForDefinition);
4132
+ }
4133
+ assert (Func && " This should have just been created" );
4134
+ }
4135
+ return cast<llvm::Function>(Func);
4136
+ };
4137
+
4138
+ bool HasDefaultDecl = !FD->isTargetVersionMultiVersion ();
4139
+ bool ShouldEmitResolver = !FD->isTargetVersionMultiVersion ();
4103
4140
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10 > Options;
4104
4141
if (FD->isTargetMultiVersion ()) {
4105
4142
getContext ().forEachMultiversionedFunctionVersion (
4106
- FD, [this , &GD, &Options, &EmitResolver](const FunctionDecl *CurFD) {
4107
- GlobalDecl CurGD{
4108
- (CurFD->isDefined () ? CurFD->getDefinition () : CurFD)};
4109
- StringRef MangledName = getMangledName (CurGD);
4110
- llvm::Constant *Func = GetGlobalValue (MangledName);
4111
- if (!Func) {
4112
- if (CurFD->isDefined ()) {
4113
- EmitGlobalFunctionDefinition (CurGD, nullptr );
4114
- Func = GetGlobalValue (MangledName);
4115
- } else {
4116
- const CGFunctionInfo &FI =
4117
- getTypes ().arrangeGlobalDeclaration (GD);
4118
- llvm::FunctionType *Ty = getTypes ().GetFunctionType (FI);
4119
- Func = GetAddrOfFunction (CurGD, Ty, /* ForVTable=*/ false ,
4120
- /* DontDefer=*/ false , ForDefinition);
4121
- }
4122
- assert (Func && " This should have just been created" );
4123
- }
4124
- if (CurFD->getMultiVersionKind () == MultiVersionKind::Target) {
4125
- const auto *TA = CurFD->getAttr <TargetAttr>();
4126
- llvm::SmallVector<StringRef, 8 > Feats;
4143
+ FD, [&](const FunctionDecl *CurFD) {
4144
+ llvm::SmallVector<StringRef, 8 > Feats;
4145
+ llvm::Function *Func = createFunction (CurFD);
4146
+
4147
+ if (const auto *TA = CurFD->getAttr <TargetAttr>()) {
4127
4148
TA->getAddedFeatures (Feats);
4128
- Options.emplace_back (cast<llvm::Function>(Func),
4129
- TA->getArchitecture (), Feats);
4130
- } else {
4131
- const auto *TVA = CurFD->getAttr <TargetVersionAttr>();
4132
- if (CurFD->isUsed () || (TVA->isDefaultVersion () &&
4133
- CurFD->doesThisDeclarationHaveABody ()))
4134
- EmitResolver = true ;
4135
- llvm::SmallVector<StringRef, 8 > Feats;
4149
+ Options.emplace_back (Func, TA->getArchitecture (), Feats);
4150
+ } else if (const auto *TVA = CurFD->getAttr <TargetVersionAttr>()) {
4151
+ bool HasDefaultDef = TVA->isDefaultVersion () &&
4152
+ CurFD->doesThisDeclarationHaveABody ();
4153
+ HasDefaultDecl |= TVA->isDefaultVersion ();
4154
+ ShouldEmitResolver |= (CurFD->isUsed () || HasDefaultDef);
4136
4155
TVA->getFeatures (Feats);
4137
- Options.emplace_back (cast<llvm::Function>( Func),
4138
- /* Architecture */ " " , Feats);
4139
- }
4156
+ Options.emplace_back (Func, /* Architecture */ " " , Feats);
4157
+ } else
4158
+ llvm_unreachable ( " unexpected MultiVersionKind " );
4140
4159
});
4141
- } else if (FD->isTargetClonesMultiVersion ()) {
4142
- const auto *TC = FD->getAttr <TargetClonesAttr>();
4143
- for (unsigned VersionIndex = 0 ; VersionIndex < TC->featuresStrs_size ();
4144
- ++VersionIndex) {
4145
- if (!TC->isFirstOfVersion (VersionIndex))
4160
+ } else if (const auto *TC = FD->getAttr <TargetClonesAttr>()) {
4161
+ for (unsigned I = 0 ; I < TC->featuresStrs_size (); ++I) {
4162
+ if (!TC->isFirstOfVersion (I))
4146
4163
continue ;
4147
- GlobalDecl CurGD{(FD->isDefined () ? FD->getDefinition () : FD),
4148
- VersionIndex};
4149
- StringRef Version = TC->getFeatureStr (VersionIndex);
4150
- StringRef MangledName = getMangledName (CurGD);
4151
- llvm::Constant *Func = GetGlobalValue (MangledName);
4152
- if (!Func) {
4153
- if (FD->isDefined ()) {
4154
- EmitGlobalFunctionDefinition (CurGD, nullptr );
4155
- Func = GetGlobalValue (MangledName);
4156
- } else {
4157
- const CGFunctionInfo &FI =
4158
- getTypes ().arrangeGlobalDeclaration (CurGD);
4159
- llvm::FunctionType *Ty = getTypes ().GetFunctionType (FI);
4160
- Func = GetAddrOfFunction (CurGD, Ty, /* ForVTable=*/ false ,
4161
- /* DontDefer=*/ false , ForDefinition);
4162
- }
4163
- assert (Func && " This should have just been created" );
4164
- }
4165
4164
4165
+ llvm::Function *Func = createFunction (FD, I);
4166
+ StringRef Version = TC->getFeatureStr (I);
4166
4167
StringRef Architecture;
4167
4168
llvm::SmallVector<StringRef, 1 > Feature;
4168
4169
@@ -4180,16 +4181,23 @@ void CodeGenModule::emitMultiVersionFunctions() {
4180
4181
Feature.push_back (Version);
4181
4182
}
4182
4183
4183
- Options.emplace_back (cast<llvm::Function>( Func) , Architecture, Feature);
4184
+ Options.emplace_back (Func, Architecture, Feature);
4184
4185
}
4185
4186
} else {
4186
4187
assert (0 && " Expected a target or target_clones multiversion function" );
4187
4188
continue ;
4188
4189
}
4189
4190
4190
- if (!EmitResolver )
4191
+ if (!ShouldEmitResolver )
4191
4192
continue ;
4192
4193
4194
+ if (!HasDefaultDecl) {
4195
+ FunctionDecl *NewFD = createDefaultTargetVersionFrom (FD);
4196
+ llvm::Function *Func = createFunction (NewFD);
4197
+ llvm::SmallVector<StringRef, 1 > Feats;
4198
+ Options.emplace_back (Func, /* Architecture*/ " " , Feats);
4199
+ }
4200
+
4193
4201
llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver (GD);
4194
4202
if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
4195
4203
ResolverConstant = IFunc->getResolver ();
0 commit comments