[clang] acf9aa3 - [clang] Support __attribute__((ifunc(...))) on Darwin platforms
via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 14 13:52:39 PST 2023
Author: Jon Roelofs
Date: 2023-12-14T14:52:35-07:00
New Revision: acf9aa3c22d6fe88abba848d2804da1a732d205a
URL: https://github.com/llvm/llvm-project/commit/acf9aa3c22d6fe88abba848d2804da1a732d205a
DIFF: https://github.com/llvm/llvm-project/commit/acf9aa3c22d6fe88abba848d2804da1a732d205a.diff
LOG: [clang] Support __attribute__((ifunc(...))) on Darwin platforms
Unlike ELF targets, MachO does not support the same kind of dynamic symbol
resolution at load time. Instead, the corresponding MachO feature resolves
symbols lazily on first call.
Reviewers:
JDevlieghere, dmpolukhin, ahmedbougacha, tahonermann, echristo, MaskRay, erichkeane
Reviewed By: MaskRay, echristo, ahmedbougacha
Pull Request: https://github.com/llvm/llvm-project/pull/73687
Added:
clang/test/SemaCXX/ifunc-has-attribute.cpp
Modified:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/test/CodeGen/attr-ifunc.c
clang/test/CodeGen/attr-ifunc.cpp
clang/test/CodeGen/ifunc.c
clang/test/CodeGenCXX/externc-ifunc-resolver.cpp
clang/test/SemaCXX/externc-ifunc-resolver.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 5943583d92773a..2b57058d3f1c75 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -455,6 +455,9 @@ def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch6
def TargetELF : TargetSpec {
let ObjectFormats = ["ELF"];
}
+def TargetELFOrMachO : TargetSpec {
+ let ObjectFormats = ["ELF", "MachO"];
+}
def TargetSupportsInitPriority : TargetSpec {
let CustomCode = [{ !Target.getTriple().isOSzOS() }];
@@ -1665,7 +1668,7 @@ def IBOutletCollection : InheritableAttr {
let Documentation = [Undocumented];
}
-def IFunc : Attr, TargetSpecificAttr<TargetELF> {
+def IFunc : Attr, TargetSpecificAttr<TargetELFOrMachO> {
let Spellings = [GCC<"ifunc">];
let Args = [StringArgument<"Resolver">];
let Subjects = SubjectList<[Function]>;
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 77950ab6d877ea..90041fa8dbb30b 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -5535,7 +5535,9 @@ considered inline.
Not all targets support this attribute. ELF target support depends on both the
linker and runtime linker, and is available in at least lld 4.0 and later,
binutils 2.20.1 and later, glibc v2.11.1 and later, and FreeBSD 9.1 and later.
-Non-ELF targets currently do not support this attribute.
+Mach-O targets support it, but with slightly
diff erent semantics: the resolver
+is run at first call, instead of at load time by the runtime linker. Targets
+other than ELF and Mach-O currently do not support this attribute.
}];
}
diff --git a/clang/test/CodeGen/attr-ifunc.c b/clang/test/CodeGen/attr-ifunc.c
index 4f8fe13530fdb7..2ad41edf20dfa0 100644
--- a/clang/test/CodeGen/attr-ifunc.c
+++ b/clang/test/CodeGen/attr-ifunc.c
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm-only -DCHECK_ALIASES %s
// RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm-only %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsyntax-only -verify -emit-llvm-only %s
#if defined(_WIN32)
void foo(void) {}
@@ -36,6 +37,25 @@ void *f6_resolver(void) __attribute__((ifunc("f6_resolver_resolver")));
void f6(void) __attribute__((ifunc("f6_resolver")));
// expected-error at -1 {{ifunc must point to a defined function}}
+#elif defined(__APPLE__)
+
+// NOTE: aliases are not supported on Darwin, so the above tests are not relevant.
+
+#define STR2(X) #X
+#define STR(X) STR2(X)
+#define PREFIX STR(__USER_LABEL_PREFIX__)
+
+void f1a(void) __asm("f1");
+void f1a(void) {}
+// expected-note at -1 {{previous definition is here}}
+void f1(void) __attribute__((ifunc(PREFIX "f1_ifunc"))) __asm("f1");
+// expected-error at -1 {{definition with same mangled name '<U+0001>f1' as another definition}}
+void *f1_ifunc(void) { return 0; }
+
+void *f6_ifunc(int i);
+void __attribute__((ifunc(PREFIX "f6_ifunc"))) f6(void) {}
+// expected-error at -1 {{definition 'f6' cannot also be an ifunc}}
+
#else
void f1a(void) __asm("f1");
void f1a(void) {}
diff --git a/clang/test/CodeGen/attr-ifunc.cpp b/clang/test/CodeGen/attr-ifunc.cpp
index 5b5b2c14b4074b..b6e342df46eb58 100644
--- a/clang/test/CodeGen/attr-ifunc.cpp
+++ b/clang/test/CodeGen/attr-ifunc.cpp
@@ -1,5 +1,9 @@
// RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm-only %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsyntax-only -verify -emit-llvm-only %s
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify -emit-llvm-only %s
// RUN: not %clang_cc1 -triple x86_64-linux -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -triple x86_64-apple-macosx -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -triple arm64-apple-macosx -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
void *f1_ifunc(void) { return nullptr; }
void f1(void) __attribute__((ifunc("f1_ifunc")));
diff --git a/clang/test/CodeGen/ifunc.c b/clang/test/CodeGen/ifunc.c
index 0b0a0549620f8b..a29b500e80bd50 100644
--- a/clang/test/CodeGen/ifunc.c
+++ b/clang/test/CodeGen/ifunc.c
@@ -3,6 +3,14 @@
// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -fsanitize=thread -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN
// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN
// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -fsanitize=memory -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN
+// RUN: %clang_cc1 -triple arm64-apple-macosx -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-macosx -O2 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -O2 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsanitize=thread -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=MACSAN
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsanitize=thread -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=MACSAN
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=MACSAN
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=MACSAN
int foo(int) __attribute__ ((ifunc("foo_ifunc")));
@@ -44,9 +52,13 @@ void* goo_ifunc(void) {
// CHECK: call void @goo()
// SAN: define internal nonnull ptr @foo_ifunc() #[[#FOO_IFUNC:]] {
+// MACSAN: define internal nonnull ptr @foo_ifunc() #[[#FOO_IFUNC:]] {
// SAN: define dso_local noalias ptr @goo_ifunc() #[[#GOO_IFUNC:]] {
+// MACSAN: define noalias ptr @goo_ifunc() #[[#GOO_IFUNC:]] {
// SAN-DAG: attributes #[[#FOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
+// MACSAN-DAG: attributes #[[#FOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
// SAN-DAG: attributes #[[#GOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
+// MACSAN-DAG: attributes #[[#GOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
diff --git a/clang/test/CodeGenCXX/externc-ifunc-resolver.cpp b/clang/test/CodeGenCXX/externc-ifunc-resolver.cpp
index 0518a8dcc831dd..be4453ae7eb08c 100644
--- a/clang/test/CodeGenCXX/externc-ifunc-resolver.cpp
+++ b/clang/test/CodeGenCXX/externc-ifunc-resolver.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-macosx -emit-llvm -o - %s | FileCheck %s
extern "C" {
__attribute__((used)) static void *resolve_foo() { return 0; }
diff --git a/clang/test/SemaCXX/externc-ifunc-resolver.cpp b/clang/test/SemaCXX/externc-ifunc-resolver.cpp
index aa44525bde2cae..6c6c262c5f09d8 100644
--- a/clang/test/SemaCXX/externc-ifunc-resolver.cpp
+++ b/clang/test/SemaCXX/externc-ifunc-resolver.cpp
@@ -1,5 +1,9 @@
// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-linux-gnu -verify %s
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-apple-macosx -verify %s
+// RUN: %clang_cc1 -emit-llvm-only -triple arm64-apple-macosx -verify %s
// RUN: not %clang_cc1 -triple x86_64-linux -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -triple x86_64-apple-macosx -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -triple arm64-apple-macosx -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
extern "C" {
__attribute__((used)) static void *resolve_foo() { return 0; }
diff --git a/clang/test/SemaCXX/ifunc-has-attribute.cpp b/clang/test/SemaCXX/ifunc-has-attribute.cpp
new file mode 100644
index 00000000000000..242f3b621745f5
--- /dev/null
+++ b/clang/test/SemaCXX/ifunc-has-attribute.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-linux-gnu -verify %s -DSUPPORTED=1
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-apple-macosx -verify %s -DSUPPORTED=1
+// RUN: %clang_cc1 -emit-llvm-only -triple arm64-apple-macosx -verify %s -DSUPPORTED=1
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-pc-win32 -verify %s -DNOT_SUPPORTED=1
+
+// expected-no-diagnostics
+
+#if __has_attribute(ifunc)
+# if NOT_SUPPORTED
+# error "ifunc appears to be supported on this platform, but shouldn't be"
+# endif
+#else
+# if SUPPORTED
+# error "ifunc should be supported on this platform, but isn't"
+# endif
+#endif
More information about the cfe-commits
mailing list