diff options
author | Dmitry Polukhin <dmitry.polukhin@gmail.com> | 2016-04-11 07:48:59 +0000 |
---|---|---|
committer | Dmitry Polukhin <dmitry.polukhin@gmail.com> | 2016-04-11 07:48:59 +0000 |
commit | 85eda12d093714bfc9f266d50254e82888c9e8c3 (patch) | |
tree | 9216c6a571a665d295ab1d8f783c27e121c349a4 /clang/test | |
parent | bbffeac569e89a61201ce159790f68b8493042b6 (diff) | |
download | bcm5719-llvm-85eda12d093714bfc9f266d50254e82888c9e8c3.tar.gz bcm5719-llvm-85eda12d093714bfc9f266d50254e82888c9e8c3.zip |
[GCC] Attribute ifunc support in clang
This patch add support for GCC attribute((ifunc("resolver"))) for
targets that use ELF as object file format. In general ifunc is a
special kind of function alias with type @gnu_indirect_function. LLVM
patch http://reviews.llvm.org/D15525
Differential Revision: http://reviews.llvm.org/D15524
llvm-svn: 265917
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CodeGen/ifunc.c | 41 | ||||
-rw-r--r-- | clang/test/Sema/attr-alias-elf.c | 2 | ||||
-rw-r--r-- | clang/test/Sema/attr-ifunc.c | 43 |
3 files changed, 85 insertions, 1 deletions
diff --git a/clang/test/CodeGen/ifunc.c b/clang/test/CodeGen/ifunc.c new file mode 100644 index 00000000000..a88bb1878f2 --- /dev/null +++ b/clang/test/CodeGen/ifunc.c @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -O2 -emit-llvm -o - %s | FileCheck %s + +int foo(int) __attribute__ ((ifunc("foo_ifunc"))); + +static int f1(int i) { + return i + 1; +} + +static int f2(int i) { + return i + 2; +} + +typedef int (*foo_t)(int); + +int global; + +static foo_t foo_ifunc() { + return global ? f1 : f2; +} + +int bar() { + return foo(1); +} + +extern void goo(void); + +void bar2(void) { + goo(); +} + +extern void goo(void) __attribute__ ((ifunc("goo_ifunc"))); + +void* goo_ifunc(void) { + return 0; +} +// CHECK: @foo = ifunc i32 (i32), bitcast (i32 (i32)* ()* @foo_ifunc to i32 (i32)*) +// CHECK: @goo = ifunc void (), bitcast (i8* ()* @goo_ifunc to void ()*) + +// CHECK: call i32 @foo(i32 +// CHECK: call void @goo() diff --git a/clang/test/Sema/attr-alias-elf.c b/clang/test/Sema/attr-alias-elf.c index f14514dccd2..e56f23e4fa5 100644 --- a/clang/test/Sema/attr-alias-elf.c +++ b/clang/test/Sema/attr-alias-elf.c @@ -55,7 +55,7 @@ typedef int b4; void test2_bar() {} void test2_foo() __attribute__((weak, alias("test2_bar"))); -void test2_zed() __attribute__((alias("test2_foo"))); // expected-warning {{alias will always resolve to test2_bar even if weak definition of alias test2_foo is overridden}} +void test2_zed() __attribute__((alias("test2_foo"))); // expected-warning {{alias will always resolve to test2_bar even if weak definition of test2_foo is overridden}} void test3_bar() { } void test3_foo() __attribute__((section("test"))); // expected-warning {{alias will not be in section 'test' but in the same section as the aliasee}} diff --git a/clang/test/Sema/attr-ifunc.c b/clang/test/Sema/attr-ifunc.c new file mode 100644 index 00000000000..76473c7e5cb --- /dev/null +++ b/clang/test/Sema/attr-ifunc.c @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm -DCHECK_ALIASES %s +// RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm %s + +#if defined(_WIN32) +void foo() {} +void bar() __attribute__((ifunc("foo"))); +//expected-warning@-1 {{'ifunc' attribute ignored}} + +#else +#if defined(CHECK_ALIASES) +void* f1_ifunc(); +void f1() __attribute__((ifunc("f1_ifunc"))); +//expected-error@-1 {{ifunc must point to a defined function}} + +void* f2_a() __attribute__((ifunc("f2_b"))); +//expected-error@-1 {{ifunc definition is part of a cycle}} +void* f2_b() __attribute__((ifunc("f2_a"))); +//expected-error@-1 {{ifunc definition is part of a cycle}} + +void* f3_a() __attribute__((ifunc("f3_b"))); +//expected-warning@-1 {{ifunc will always resolve to f3_c even if weak definition of f3_b is overridden}} +void* f3_b() __attribute__((weak, alias("f3_c"))); +void* f3_c() { return 0; } + +void f4_ifunc() {} +void f4() __attribute__((ifunc("f4_ifunc"))); +//expected-error@-1 {{ifunc resolver function must return a pointer}} + +void* f5_ifunc(int i) { return 0; } +void f5() __attribute__((ifunc("f5_ifunc"))); +//expected-error@-1 {{ifunc resolver function must have no parameters}} + +#else +void f1a() __asm("f1"); +void f1a() {} +//expected-note@-1 {{previous definition is here}} +void f1() __attribute__((ifunc("f1_ifunc"))); +//expected-error@-1 {{definition with same mangled name as another definition}} +void* f1_ifunc() { return 0; } + +#endif +#endif |