Skip to content

Commit cfce8b0

Browse files
committed
[CodeGen] Create IFUNCs in the program address space, not hard-coded 0
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 2c12c1e commit cfce8b0

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
@@ -4443,12 +4443,13 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
44434443
if (getTarget().supportsIFunc()) {
44444444
llvm::GlobalValue::LinkageTypes Linkage = getMultiversionLinkage(*this, GD);
44454445
auto *IFunc = cast<llvm::GlobalValue>(GetOrCreateMultiVersionResolver(GD));
4446+
unsigned AS = IFunc->getType()->getPointerAddressSpace();
44464447

44474448
// Fix up function declarations that were created for cpu_specific before
44484449
// cpu_dispatch was known
44494450
if (!isa<llvm::GlobalIFunc>(IFunc)) {
4450-
auto *GI = llvm::GlobalIFunc::create(DeclTy, 0, Linkage, "", ResolverFunc,
4451-
&getModule());
4451+
auto *GI = llvm::GlobalIFunc::create(DeclTy, AS, Linkage, "",
4452+
ResolverFunc, &getModule());
44524453
replaceDeclarationWith(IFunc, GI);
44534454
IFunc = GI;
44544455
}
@@ -4457,8 +4458,8 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
44574458
*this, GD, FD, /*OmitMultiVersionMangling=*/true);
44584459
llvm::Constant *AliasFunc = GetGlobalValue(AliasName);
44594460
if (!AliasFunc) {
4460-
auto *GA = llvm::GlobalAlias::create(DeclTy, 0, Linkage, AliasName, IFunc,
4461-
&getModule());
4461+
auto *GA = llvm::GlobalAlias::create(DeclTy, AS, Linkage, AliasName,
4462+
IFunc, &getModule());
44624463
SetCommonAttributes(GD, GA);
44634464
}
44644465
}
@@ -4530,15 +4531,14 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
45304531
// For cpu_specific, don't create an ifunc yet because we don't know if the
45314532
// cpu_dispatch will be emitted in this translation unit.
45324533
if (getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion()) {
4533-
llvm::Type *ResolverType = llvm::FunctionType::get(
4534-
llvm::PointerType::get(DeclTy,
4535-
getTypes().getTargetAddressSpace(FD->getType())),
4536-
false);
4534+
unsigned AS = getTypes().getTargetAddressSpace(FD->getType());
4535+
llvm::Type *ResolverType =
4536+
llvm::FunctionType::get(llvm::PointerType::get(DeclTy, AS), false);
45374537
llvm::Constant *Resolver = GetOrCreateLLVMFunction(
45384538
MangledName + ".resolver", ResolverType, GlobalDecl{},
45394539
/*ForVTable=*/false);
45404540
llvm::GlobalIFunc *GIF =
4541-
llvm::GlobalIFunc::create(DeclTy, 0, getMultiversionLinkage(*this, GD),
4541+
llvm::GlobalIFunc::create(DeclTy, AS, getMultiversionLinkage(*this, GD),
45424542
"", Resolver, &getModule());
45434543
GIF->setName(ResolverName);
45444544
SetCommonAttributes(FD, GIF);
@@ -6144,9 +6144,9 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
61446144
GetOrCreateLLVMFunction(IFA->getResolver(), VoidTy, {},
61456145
/*ForVTable=*/false);
61466146
llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
6147-
llvm::GlobalIFunc *GIF =
6148-
llvm::GlobalIFunc::create(DeclTy, 0, llvm::Function::ExternalLinkage,
6149-
"", Resolver, &getModule());
6147+
unsigned AS = getTypes().getTargetAddressSpace(D->getType());
6148+
llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create(
6149+
DeclTy, AS, llvm::Function::ExternalLinkage, "", Resolver, &getModule());
61506150
if (Entry) {
61516151
if (GIF->getResolver() == Entry) {
61526152
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)