This is GCC Bugzilla
This is GCC Bugzilla Version 2.20+
View Bug Activity | Format For Printing | Clone This Bug
Binutils and glibc implemented STT_GNU_IFUNC: http://groups.google.com/group/generic-abi A new ifunc attribute can provide user access to this feature at C language level. Several options: 1. Ifunc attribute with argument: int foo (…); __typeof (foo) * __attribute__ ((ifunc ("foo"))) foo_ifunc (void) { <return address of foo_{1,2,3}> } foo_ifunc is a dummy place holder which isn't necessary. 2. Ifunc attribute without argument: void * __attribute__ ((ifunc)) foo (void) { <return address of foo_{1,2,3}> } We can't call foo in the same file where foo is defined since we need a different prototype when calling foo. 3. Ifunc attribute with prototype, but without argument: int __attribute__ ((ifunc)) foo (...) { <return address of foo_{1,2,3}> } We can call foo in the same file. Gcc checks the return value for foo.
With option 3, we can check the return value of an ifunc function since we know the return value is a pointer to the ifunc function. We don't need a separate prototype nor asm statement.
Created an attachment (id=18060) [edit] Ifunc examples Here are some ifunc examples with option 3.
Option 2) is certainly the least intrusive in the compiler and you can use it even with foo's prototype and calling it from the same CU, just use asm. __typeof (foo) * __attribute__ ((ifunc)) foo_ifunc (void) __asm ("foo") { <return address of foo_{1,2,3}> } If you don't have a prototype, you can use the variant originally mentioned in option 2). Most users will wrap this stuff in a macro anyway and in that case whether they use just an attribute or attribute and __asm is not a big deal.
(In reply to comment #3) > Option 2) is certainly the least intrusive in the compiler and you can use it > even with foo's prototype and calling it from the same CU, just use asm. > __typeof (foo) * > __attribute__ ((ifunc)) > foo_ifunc (void) __asm ("foo") > { > <return address of foo_{1,2,3}> > } > If you don't have a prototype, you can use the variant originally mentioned in > option 2). Most users will wrap this stuff in a macro anyway and in that case > whether they use just an attribute or attribute and __asm is not a big deal. I think we enforce type check on return value of ifunc function. This is a user feature. Option 3 is the most user friendly. We only need to change the return type to a pointer to function prototype inside ifunc function body. I have a patch for option 3. It isn't too bad.
What do you do if the function has arguments, because ifunc shouldn't have arguments? While C++ has unnamed arguments and you could perhaps enforce them, C does not. How do you handle option 3 with: __attribute__((ifunc)) int foo (int a, int b) { if (a) return foo_1; if (b) return foo_2; return foo_3; } ?
(In reply to comment #5) > What do you do if the function has arguments, because ifunc shouldn't have > arguments? While C++ has unnamed arguments and you could perhaps enforce them, For unnamed arguments, see ifunc-1.c in http://gcc.gnu.org/bugzilla/attachment.cgi?id=18060 > C does not. How do you handle option 3 with: > __attribute__((ifunc)) int > foo (int a, int b) > { > if (a) return foo_1; > if (b) return foo_2; > return foo_3; > } > ? > [hjl@gnu-6 examples]$ cat x.c int foo_1 (int, int); int foo_2 (int, int); int foo_3 (int, int); __attribute__((ifunc)) int foo (int a, int b) { if (a) return foo_1; if (b) return foo_2; return foo_3; } [hjl@gnu-6 examples]$ make x.s /export/build/gnu/gcc-work/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/gcc-work/build-x86_64-linux/gcc/ -S -o x.s -O2 -Wall -Wextra x.c x.c: In function ‘foo’: x.c:6:1: error: parameter ‘a’ used in indirect function ‘foo’ x.c:6:1: error: parameter ‘b’ used in indirect function ‘foo’ make: *** [x.s] Error 1 [hjl@gnu-6 examples]$
It is easier to support C++ with option 3.
For C++: class Foo { private: virtual void foo1 () { printf ("I am %s\n", __PRETTY_FUNCTION__); } public: virtual void __attribute__ ((ifunc)) foo () { return &Foo::foo1; } }; class Bar : public Foo { private: void foo1 () { printf ("I am %s\n", __PRETTY_FUNCTION__); } public: void foo () { return &Bar::foo1; } }; Should Bar::foo inherit the ifun attribute from Foo::foo?
Created an attachment (id=18076) [edit] Ifunc examples in C and C++ Here are some C/C++ examples with valid and invalid cases.
Created an attachment (id=18077) [edit] A C++ program with ifunc attribute
Created an attachment (id=18078) [edit] Static Linux/ia32 binary of prog.C I got [hjl@gnu-6 c++]$ ./static I have SSE4.2 I support 64bit. I have SSE4.2 I support 64bit. I have SSE4.2 I support 64bit. I have SSE4.2 I support 64bit. I have SSE4.2 I support 64bit. I am virtual void Foo::foo1() I am virtual void Bar::foo() I am virtual void X::foo1() I am virtual void Y::foo() [hjl@gnu-6 c++]$
Subject: Bug 40528 Author: hjl Date: Sun Jun 28 15:14:09 2009 New Revision: 149026 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=149026 Log: gcc/ 2009-06-28 H.J. Lu <hongjiu.lu@intel.com> PR c/40528 * c-common.c (handle_ifunc_attribute): New. (c_common_attribute_table): Add "ifunc". * c-decl.c (merge_decls): Only allow IFUNC attribute on definition. Merge the IFUNC information. (start_function): Use function_return_type to get function return type. (store_parm_decls_newstyle): Don't warn omitted parameter name on IFUNC function. (finish_function): Issue an error if control reaches end of IFUNC function. (c_write_global_declarations_1): Add an argument to indicate global scope. Issue an error for undefined IFUNC function. (c_write_global_declarations): Updated. * c-typeck.c (c_finish_return): Use function_return_type to get function return type. * gimplify.c (gimplify_return_expr): Likewise. * stmt.c (expand_return): Likewise. * cgraphunit.c (cgraph_finalize_function): Don't allow parameter usage in ifunc function. (process_function_and_variable_attributes): Check ifunc attribute. * tree-cfg.c (verify_gimple_return): Use function_return_type to get function return type. (execute_warn_function_return): Issue an error if control reaches end of ifunc function. * tree.h (tree_decl_with_vis): Add ifunc_flag. (DECL_IS_IFUNC): New. * varasm.c (default_binds_local_p_1): Return false for IFUNC function. * config/elfos.h (ASM_DECLARE_FUNCTION_NAME): Output "gnu_indirect_function" instead of "function" for IFUNC function. * doc/extend.texi: Document ifunc attribute. gcc/cp/ 2009-06-28 H.J. Lu <hongjiu.lu@intel.com> PR c/40528 * typeck.c (cp_build_unary_op): Take the address of non-static member function for IFUNC member function. (check_return_expr): Use function_return_type to get function return type. * decl.c (check_function_type): Change return type to bool. Return true if the function type is changed to void. (wrapup_globals_for_namespace): Check undefined IFUNC symbols. (duplicate_decls): Only allow IFUNC attribute on definition. Merge the IFUNC information. (start_preparsed_function): Use function_return_type to build the return declaration for the function if its type isn't changed to void. (finish_function): Use function_return_type to get function return type. Issue an error if control reaches end of IFUNC function. gcc/testsuite/ 2009-06-28 H.J. Lu <hongjiu.lu@intel.com> PR c/40528 * g++.dg/torture/ifunc-1.C: New. * g++.dg/torture/ifunc-2.C: Likewise. * g++.dg/torture/ifunc-3.C: Likewise. * g++.dg/torture/ifunc-4.C: Likewise. * g++.dg/torture/ifunc-5.C: Likewise. * g++.dg/torture/ifunc-6.C: Likewise. * g++.dg/torture/ifunc-7.C: Likewise. * g++.dg/torture/ifunc-8.C: Likewise. * g++.dg/torture/ifunc-9.C: Likewise. * g++.dg/torture/ifunc-10.C: Likewise. * g++.dg/torture/ifunc-11.C: Likewise. * g++.dg/torture/ifunc-12.C: Likewise. * g++.dg/torture/ifunc-13.C: Likewise. * g++.dg/torture/ifunc-14.C: Likewise. * g++.dg/torture/ifunc-15.C: Likewise. * g++.dg/torture/ifunc-16.C: Likewise. * g++.dg/torture/ifunc-17.C: Likewise. * g++.dg/torture/ifunc-18.C: Likewise. * g++.dg/torture/ifunc-19.C: Likewise. * g++.dg/torture/ifunc-20.C: Likewise. * gcc.dg/torture/ifunc-1.c: Likewise. * gcc.dg/torture/ifunc-2.c: Likewise. * gcc.dg/torture/ifunc-3.c: Likewise. * gcc.dg/torture/ifunc-4.c: Likewise. * gcc.dg/torture/ifunc-5.c: Likewise. * gcc.dg/torture/ifunc-6.c: Likewise. * gcc.dg/torture/ifunc-7.c: Likewise. * gcc.dg/torture/ifunc-8.c: Likewise. * gcc.dg/torture/ifunc-9.c: Likewise. * gcc.dg/torture/ifunc-10.c: Likewise. * gcc.dg/torture/ifunc-11.c: Likewise. * gcc.dg/torture/ifunc-12.c: Likewise. * gcc.dg/torture/ifunc-13.c: Likewise. * gcc.dg/torture/ifunc-14.c: Likewise. * gcc.dg/torture/ifunc-15.c: Likewise. * gcc.dg/torture/ifunc-16.c: Likewise. * gcc.dg/torture/ifunc-17.c: Likewise. * gcc.dg/torture/ifunc-18.c: Likewise. Added: branches/ifunc/gcc/ChangeLog.ifunc branches/ifunc/gcc/cp/ChangeLog.ifunc branches/ifunc/gcc/testsuite/ChangeLog.ifunc branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-1.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-10.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-11.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-12.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-13.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-14.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-15.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-16.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-17.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-18.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-19.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-2.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-20.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-3.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-4.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-5.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-6.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-7.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-8.C branches/ifunc/gcc/testsuite/g++.dg/torture/ifunc-9.C branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-1.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-10.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-11.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-12.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-13.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-14.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-15.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-16.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-17.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-18.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-2.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-3.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-4.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-5.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-6.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-7.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-8.c branches/ifunc/gcc/testsuite/gcc.dg/torture/ifunc-9.c Modified: branches/ifunc/gcc/c-common.c branches/ifunc/gcc/c-decl.c branches/ifunc/gcc/c-typeck.c branches/ifunc/gcc/cgraphunit.c branches/ifunc/gcc/config/elfos.h branches/ifunc/gcc/cp/decl.c branches/ifunc/gcc/cp/typeck.c branches/ifunc/gcc/doc/extend.texi branches/ifunc/gcc/gimplify.c branches/ifunc/gcc/stmt.c branches/ifunc/gcc/tree-cfg.c branches/ifunc/gcc/tree.h branches/ifunc/gcc/varasm.c
What is the status of this issue? Is option 3 implemented? Which versions of Linux and binutils support IFUNC? Any plans for BSD and Mac?
(In reply to comment #13) > What is the status of this issue? It is implemented on ifunc branch. > Is option 3 implemented? Yes, on ifunc branch. > Which versions of Linux and binutils support IFUNC? You need at least glibc 2.11 and binutils 2.20. > Any plans for BSD and Mac? > You have to ask BSD and Mac people since IFUNC support needs to be implemented in both binutils and the C library.