This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: Add ifunc attribute


Hi,

This patch adds ifunc attribute for STT_GNU_IFUNC as specified in
ifunc.txt at

http://groups.google.com/group/generic-abi/files

Any comments?

Thanks.


H.J.
---
gcc/

2009-06-12  H.J. Lu  <hongjiu.lu@intel.com>

	* c-common.c (handle_ifunc_attribute): New.
	(c_common_attribute_table): Add "ifunc".

	* tree.c (decl_assembler_name): Handle ifunc attribute.

	* config/elfos.h (ASM_DECLARE_FUNCTION_NAME): Output
	"gnu_indirect_function" instead of "function" for ifunc
	attribute.

	* doc/extend.texi: Document ifunc attribute.

gcc/testsuite/

2009-06-12  H.J. Lu  <hongjiu.lu@intel.com>

	* gcc.dg/ifunc-1.c: New.

--- gcc/c-common.c.ifunc	2009-06-10 02:58:33.000000000 -0700
+++ gcc/c-common.c	2009-06-12 08:21:01.000000000 -0700
@@ -529,6 +529,7 @@ static tree handle_type_generic_attribut
 static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
 static tree handle_target_attribute (tree *, tree, tree, int, bool *);
 static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
+static tree handle_ifunc_attribute (tree *, tree, tree, int, bool *);
 
 static void check_function_nonnull (tree, int, tree *);
 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -817,6 +818,8 @@ const struct attribute_spec c_common_att
 			      handle_target_attribute },
   { "optimize",               1, -1, true, false, false,
 			      handle_optimize_attribute },
+  { "ifunc",                  1, 1, true,  false, false,
+			      handle_ifunc_attribute },
   { NULL,                     0, 0, false, false, false, NULL }
 };
 
@@ -6659,6 +6662,53 @@ handle_alias_attribute (tree *node, tree
   return NULL_TREE;
 }
 
+/* Handle an "ifunc" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_ifunc_attribute (tree *node, tree name, tree args,
+			int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  tree decl = *node;
+
+  if (TREE_CODE (decl) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+  else if (!TREE_PUBLIC (decl))
+    {
+      error ("static indirec function %q+D", decl);
+      *no_add_attrs = true;
+    }
+
+  /* Note that the very first time we process a nested declaration,
+     decl_function_context will not be set.  Indeed, *would* never
+     be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that
+     we do below.  After such frobbery, pushdecl would set the context.
+     In any case, this is never what we want.  */
+  else if (decl_function_context (decl) == 0
+	   && current_function_decl == NULL)
+    {
+      if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+	{
+	  error ("ifunc argument not a string");
+	  *no_add_attrs = true;
+	  return NULL_TREE;
+	}
+
+      /* Mark it as used.  */
+      TREE_USED (decl) = 1;
+    }
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "weakref" attribute; arguments as in struct
    attribute_spec.handler.  */
 
--- gcc/config/elfos.h.ifunc	2009-04-13 16:12:15.000000000 -0700
+++ gcc/config/elfos.h	2009-06-10 15:42:03.000000000 -0700
@@ -280,7 +280,11 @@ see the files COPYING3 and COPYING.RUNTI
 #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)		\
   do								\
     {								\
-      ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function");	\
+      if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (DECL)))	\
+	ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME,			\
+				   "gnu_indirect_function");	\
+      else							\
+	ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function");	\
       ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL));		\
       ASM_OUTPUT_LABEL (FILE, NAME);				\
     }								\
--- gcc/doc/extend.texi.ifunc	2009-06-10 02:58:10.000000000 -0700
+++ gcc/doc/extend.texi	2009-06-12 08:18:03.000000000 -0700
@@ -1874,6 +1874,25 @@ is not defined in the same translation u
 
 Not all target machines support this attribute.
 
+@item ifunc ("@var{function}")
+@cindex @code{ifunc} attribute
+The @code{ifunc} attribute only applies to global function definition,
+which causes the definition to be emitted as an indirec function.  For
+instance,
+
+@smallexample
+void* f_ifunc () __attribute__ ((ifunc ("f")));
+@end smallexample
+
+defines @samp{f_ifunc} to be an indirect function for @samp{f}. This
+attribute is ignored if @samp{f_ifunc} is undefined in the same
+translation unit.
+
+See @code{STT_GNU_IFUNC} specified in @file{ifunc.txt} at
+@uref{http://groups.google.com/group/generic-abi/files}.
+
+Not all target machines support this attribute.
+
 @item aligned (@var{alignment})
 @cindex @code{aligned} attribute
 This attribute specifies a minimum alignment for the function,
--- gcc/testsuite/gcc.dg/ifunc-1.c.ifunc	2009-06-10 16:03:27.000000000 -0700
+++ gcc/testsuite/gcc.dg/ifunc-1.c	2009-06-10 16:13:36.000000000 -0700
@@ -0,0 +1,18 @@
+/* { dg-do compile { target i?86-*-linux* x86_64-*-linux* } } */
+/* { dg-options "-w" } */
+
+static int
+zero (int x) 
+{
+  return 0;
+}
+
+void *
+__attribute__ ((ifunc ("foo")))
+foo_ifunc (void)
+{ 
+  return zero;
+}
+
+/* { dg-final { scan-assembler-not "foo_ifunc" } } */
+/* { dg-final { scan-assembler ".type\[ 	\]\+foo, .gnu_indirect_function" } } */
--- gcc/tree.c.ifunc	2009-06-10 15:31:10.000000000 -0700
+++ gcc/tree.c	2009-06-12 08:35:44.000000000 -0700
@@ -347,7 +347,19 @@ tree
 decl_assembler_name (tree decl)
 {
   if (!DECL_ASSEMBLER_NAME_SET_P (decl))
-    lang_hooks.set_decl_assembler_name (decl);
+    {
+      tree attr;
+
+      if (TREE_CODE (decl) == FUNCTION_DECL
+	  && (attr = lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl))))
+	{
+	  attr = TREE_VALUE (TREE_VALUE (attr));
+	  attr = get_identifier (TREE_STRING_POINTER (attr));
+	  SET_DECL_ASSEMBLER_NAME (decl, attr);
+	}
+      else
+	lang_hooks.set_decl_assembler_name (decl);
+    }
   return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name;
 }
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]