Skip to content

Commit 56eb559

Browse files
authored
[clang][FMV] Fix crash with cpu_specific attribute. (#115762)
When dealing with cpu_specific GlobalDecl, GetOrCreateMultiVersionResolver should immediately return the already created llvm function if it exists. Fixes #115299.
1 parent 5e3f615 commit 56eb559

File tree

2 files changed

+12
-6
lines changed

2 files changed

+12
-6
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4562,15 +4562,17 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
45624562
ResolverName += ".resolver";
45634563
}
45644564

4565+
bool ShouldReturnIFunc =
4566+
getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion();
4567+
45654568
// If the resolver has already been created, just return it. This lookup may
45664569
// yield a function declaration instead of a resolver on AArch64. That is
45674570
// because we didn't know whether a resolver will be generated when we first
45684571
// encountered a use of the symbol named after this resolver. Therefore,
45694572
// targets which support ifuncs should not return here unless we actually
45704573
// found an ifunc.
45714574
llvm::GlobalValue *ResolverGV = GetGlobalValue(ResolverName);
4572-
if (ResolverGV &&
4573-
(isa<llvm::GlobalIFunc>(ResolverGV) || !getTarget().supportsIFunc()))
4575+
if (ResolverGV && (isa<llvm::GlobalIFunc>(ResolverGV) || !ShouldReturnIFunc))
45744576
return ResolverGV;
45754577

45764578
const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
@@ -4583,7 +4585,7 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
45834585

45844586
// For cpu_specific, don't create an ifunc yet because we don't know if the
45854587
// cpu_dispatch will be emitted in this translation unit.
4586-
if (getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion()) {
4588+
if (ShouldReturnIFunc) {
45874589
unsigned AS = getTypes().getTargetAddressSpace(FD->getType());
45884590
llvm::Type *ResolverType =
45894591
llvm::FunctionType::get(llvm::PointerType::get(DeclTy, AS), false);
@@ -4602,11 +4604,9 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
46024604

46034605
llvm::Constant *Resolver = GetOrCreateLLVMFunction(
46044606
ResolverName, DeclTy, GlobalDecl{}, /*ForVTable=*/false);
4605-
assert(isa<llvm::GlobalValue>(Resolver) &&
4607+
assert(isa<llvm::GlobalValue>(Resolver) && !ResolverGV &&
46064608
"Resolver should be created for the first time");
46074609
SetCommonAttributes(FD, cast<llvm::GlobalValue>(Resolver));
4608-
if (ResolverGV)
4609-
replaceDeclarationWith(ResolverGV, Resolver);
46104610
return Resolver;
46114611
}
46124612

clang/test/CodeGen/attr-cpuspecific.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ void usages(void) {
154154
CpuSpecificNoDispatch();
155155
// LINUX: @CpuSpecificNoDispatch.ifunc()
156156
// WINDOWS: @CpuSpecificNoDispatch()
157+
//
158+
// Adding another use of CpuSpecificNoDispatch reproduces the
159+
// crash in https://github.com/llvm/llvm-project/issues/115299
160+
CpuSpecificNoDispatch();
161+
// LINUX: @CpuSpecificNoDispatch.ifunc()
162+
// WINDOWS: @CpuSpecificNoDispatch()
157163
OrderDispatchUsageSpecific();
158164
// LINUX: @OrderDispatchUsageSpecific.ifunc()
159165
// WINDOWS: @OrderDispatchUsageSpecific()

0 commit comments

Comments
 (0)