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@-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@-1 {{previous definition is here}} +void f1(void) __attribute__((ifunc(PREFIX "f1_ifunc"))) __asm("f1"); +// expected-error@-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@-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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits