[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