Skip to content

Commit 73e0aa5

Browse files
authored
[CodeGen] Create IFUNCs in the program address space, not hard-coded 0 (llvm#105726)
Commit 0d527e5 ("GlobalIFunc: Make ifunc respect function address spaces") added support for this within LLVM, but Clang does not properly honour the target's address spaces when creating IFUNCs, crashing with RAUW and verifier assertion failures when compiling C code on a target with a non-zero program address space, so fix this.
1 parent 82113a4 commit 73e0aa5

File tree

2 files changed

+17
-12
lines changed

2 files changed

+17
-12
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4455,12 +4455,13 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
44554455
if (getTarget().supportsIFunc()) {
44564456
llvm::GlobalValue::LinkageTypes Linkage = getMultiversionLinkage(*this, GD);
44574457
auto *IFunc = cast<llvm::GlobalValue>(GetOrCreateMultiVersionResolver(GD));
4458+
unsigned AS = IFunc->getType()->getPointerAddressSpace();
44584459

44594460
// Fix up function declarations that were created for cpu_specific before
44604461
// cpu_dispatch was known
44614462
if (!isa<llvm::GlobalIFunc>(IFunc)) {
4462-
auto *GI = llvm::GlobalIFunc::create(DeclTy, 0, Linkage, "", ResolverFunc,
4463-
&getModule());
4463+
auto *GI = llvm::GlobalIFunc::create(DeclTy, AS, Linkage, "",
4464+
ResolverFunc, &getModule());
44644465
replaceDeclarationWith(IFunc, GI);
44654466
IFunc = GI;
44664467
}
@@ -4469,8 +4470,8 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
44694470
*this, GD, FD, /*OmitMultiVersionMangling=*/true);
44704471
llvm::Constant *AliasFunc = GetGlobalValue(AliasName);
44714472
if (!AliasFunc) {
4472-
auto *GA = llvm::GlobalAlias::create(DeclTy, 0, Linkage, AliasName, IFunc,
4473-
&getModule());
4473+
auto *GA = llvm::GlobalAlias::create(DeclTy, AS, Linkage, AliasName,
4474+
IFunc, &getModule());
44744475
SetCommonAttributes(GD, GA);
44754476
}
44764477
}
@@ -4542,15 +4543,14 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
45424543
// For cpu_specific, don't create an ifunc yet because we don't know if the
45434544
// cpu_dispatch will be emitted in this translation unit.
45444545
if (getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion()) {
4545-
llvm::Type *ResolverType = llvm::FunctionType::get(
4546-
llvm::PointerType::get(DeclTy,
4547-
getTypes().getTargetAddressSpace(FD->getType())),
4548-
false);
4546+
unsigned AS = getTypes().getTargetAddressSpace(FD->getType());
4547+
llvm::Type *ResolverType =
4548+
llvm::FunctionType::get(llvm::PointerType::get(DeclTy, AS), false);
45494549
llvm::Constant *Resolver = GetOrCreateLLVMFunction(
45504550
MangledName + ".resolver", ResolverType, GlobalDecl{},
45514551
/*ForVTable=*/false);
45524552
llvm::GlobalIFunc *GIF =
4553-
llvm::GlobalIFunc::create(DeclTy, 0, getMultiversionLinkage(*this, GD),
4553+
llvm::GlobalIFunc::create(DeclTy, AS, getMultiversionLinkage(*this, GD),
45544554
"", Resolver, &getModule());
45554555
GIF->setName(ResolverName);
45564556
SetCommonAttributes(FD, GIF);
@@ -6160,9 +6160,9 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
61606160
GetOrCreateLLVMFunction(IFA->getResolver(), VoidTy, {},
61616161
/*ForVTable=*/false);
61626162
llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
6163-
llvm::GlobalIFunc *GIF =
6164-
llvm::GlobalIFunc::create(DeclTy, 0, llvm::Function::ExternalLinkage,
6165-
"", Resolver, &getModule());
6163+
unsigned AS = getTypes().getTargetAddressSpace(D->getType());
6164+
llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create(
6165+
DeclTy, AS, llvm::Function::ExternalLinkage, "", Resolver, &getModule());
61666166
if (Entry) {
61676167
if (GIF->getResolver() == Entry) {
61686168
Diags.Report(IFA->getLocation(), diag::err_cyclic_alias) << 1;

clang/test/CodeGen/ifunc.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsanitize=thread -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN
1212
// RUN: %clang_cc1 -triple arm64-apple-macosx -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN
1313
// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN
14+
// RUN: %clang_cc1 -triple avr-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=AVR
1415

1516
/// The ifunc is emitted before its resolver.
1617
int foo(int) __attribute__ ((ifunc("foo_ifunc")));
@@ -55,6 +56,10 @@ extern void hoo(int) __attribute__ ((ifunc("hoo_ifunc")));
5556
// CHECK: @goo = ifunc void (), ptr @goo_ifunc
5657
// CHECK: @hoo = ifunc void (i32), ptr @hoo_ifunc
5758

59+
// AVR: @foo = ifunc i16 (i16), ptr addrspace(1) @foo_ifunc
60+
// AVR: @goo = ifunc void (), ptr addrspace(1) @goo_ifunc
61+
// AVR: @hoo = ifunc void (i16), ptr addrspace(1) @hoo_ifunc
62+
5863
// CHECK: call i32 @foo(i32
5964
// CHECK: call void @goo()
6065

0 commit comments

Comments
 (0)