PATCH: Add ifunc attribute

classic Classic list List threaded Threaded
56 messages Options
123
Reply | Threaded
Open this post in threaded view
|

PATCH: Add ifunc attribute

H.J. Lu
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  <[hidden email]>

        * 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  <[hidden email]>

        * 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;
 }
 
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

Richard Biener
On Fri, Jun 12, 2009 at 5:40 PM, H.J. Lu<[hidden email]> wrote:
> 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?

Why does the attribute have an argument?  I see that you get around
all the issues of wrong optimizations when seeing the function body,
but at least the documentation needs to be more explicit about
this subtle difference.

Richard.

> Thanks.
>
>
> H.J.
> ---
> gcc/
>
> 2009-06-12  H.J. Lu  <[hidden email]>
>
>        * 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  <[hidden email]>
>
>        * 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;
>  }
>
>
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

H.J. Lu-30
On Fri, Jun 12, 2009 at 8:59 AM, Richard
Guenther<[hidden email]> wrote:

> On Fri, Jun 12, 2009 at 5:40 PM, H.J. Lu<[hidden email]> wrote:
>> 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?
>
> Why does the attribute have an argument?  I see that you get around

It is used to indicate which function this indirect function is
used for, like

---
static int
zero (int x)
{
  return 0;
}

void *
__attribute__ ((ifunc ("foo")))
foo_ifunc (void)
{
  return zero;
}

extern int foo (int);

int
bar (int x)
{
  return foo (x);
}
---

bar calls foo.  Since we mark foo_ifunc as the indirect function
for foo, bar will call *foo_ifunc () at run-time.


> all the issues of wrong optimizations when seeing the function body,
> but at least the documentation needs to be more explicit about
> this subtle difference.
>

How about this

`ifunc ("FUNCTION")'
     The `ifunc' attribute only applies to global function definition,
     which causes the definition to be emitted as an indirect function.
     For instance,

          void* f_ifunc () __attribute__ ((ifunc ("f")));

     defines `f_ifunc' to be an indirect function for `f'.  The
     indirect function `f_ifunc', which is used by static linker and
     dynamic linker, is never called directly in the program.  This
     attribute is ignored if `f_ifunc' is undefined in the same
     translation unit.

     See `STT_GNU_IFUNC' specified in `ifunc.txt' at
     `http://groups.google.com/group/generic-abi/files' for details.

     Not all target machines support this attribute.


--
H.J.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

Petr Baudis-2
Hi!

Shouldn't this mention what indirect function actually is?

On Fri, Jun 12, 2009 at 09:37:36AM -0700, H.J. Lu wrote:

> > all the issues of wrong optimizations when seeing the function body,
> > but at least the documentation needs to be more explicit about
> > this subtle difference.
> >
>
> How about this
>
> `ifunc ("FUNCTION")'
>      The `ifunc' attribute only applies to global function definition,
>      which causes the definition to be emitted as an indirect function.
>      For instance,
>
>           void* f_ifunc () __attribute__ ((ifunc ("f")));
>
>      defines `f_ifunc' to be an indirect function for `f'.  The
>      indirect function `f_ifunc', which is used by static linker and
>      dynamic linker, is never called directly in the program.

It is called the first time the `f' function would be called and returns
a pointer to the actual function that should be executed as `f'.


>      This attribute is ignored if `f_ifunc' is undefined in the same
>      translation unit.
>
>      See `STT_GNU_IFUNC' specified in `ifunc.txt' at
>      `http://groups.google.com/group/generic-abi/files' for details.
>
>      Not all target machines support this attribute.

--
                                Petr "Pasky" Baudis
The lyf so short, the craft so long to lerne. -- Chaucer
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

Ian Lance Taylor-3
In reply to this post by H.J. Lu
"H.J. Lu" <[hidden email]> writes:

> +@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.

This documentation needs to be much better.  I think most people reading
this would not understand the feature.  I would suggest something more
along these lines, but I would like to hear what other people think.

I started to write my own version of the documentation, but I realized
that I don't even understand this.  Which function is called by the
dynamic linker, "f" or "f_ifunc"?  Why is the attribute ignored if
"f_ifunc" is not defined; shouldn't it be an error?  I guess that means
that "f_ifunc" is called by the dynamic linker; in that case, what
happens if "func" is defined?

Ian
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

Richard Biener
On Sat, Jun 13, 2009 at 3:30 AM, Ian Lance Taylor<[hidden email]> wrote:

> "H.J. Lu" <[hidden email]> writes:
>
>> +@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.
>
> This documentation needs to be much better.  I think most people reading
> this would not understand the feature.  I would suggest something more
> along these lines, but I would like to hear what other people think.
>
> I started to write my own version of the documentation, but I realized
> that I don't even understand this.  Which function is called by the
> dynamic linker, "f" or "f_ifunc"?  Why is the attribute ignored if
> "f_ifunc" is not defined; shouldn't it be an error?  I guess that means
> that "f_ifunc" is called by the dynamic linker; in that case, what
> happens if "func" is defined?

Yeah.  I would have proposed that

void *foo (void) __attribute__((__ifunc__))
{
  return zero;
}

would simply generate foo with indirect function type.

This of course causes a problem if you have a declaration for
the real foo available - but then you should better not have that,
as the compiler will then derive wrong properties for the real foo
from the ifunc wrapper body.

That would at least not introduce the confusion with the extra name ...

Richard.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

H.J. Lu-30
On Sat, Jun 13, 2009 at 8:15 AM, Richard
Guenther<[hidden email]> wrote:

>>
>> I started to write my own version of the documentation, but I realized
>> that I don't even understand this.  Which function is called by the
>> dynamic linker, "f" or "f_ifunc"?  Why is the attribute ignored if
>> "f_ifunc" is not defined; shouldn't it be an error?  I guess that means
>> that "f_ifunc" is called by the dynamic linker; in that case, what
>> happens if "func" is defined?
>
> Yeah.  I would have proposed that
>
> void *foo (void) __attribute__((__ifunc__))
> {
>  return zero;
> }
>
> would simply generate foo with indirect function type.
>
> This of course causes a problem if you have a declaration for
> the real foo available - but then you should better not have that,
> as the compiler will then derive wrong properties for the real foo
> from the ifunc wrapper body.
>

Glibc has ifunc testcases with a declaration of foo in the same file.
This proposal won't work with them.

---
H.J.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

Richard Biener
On Sat, Jun 13, 2009 at 6:07 PM, H.J. Lu<[hidden email]> wrote:

> On Sat, Jun 13, 2009 at 8:15 AM, Richard
> Guenther<[hidden email]> wrote:
>
>>>
>>> I started to write my own version of the documentation, but I realized
>>> that I don't even understand this.  Which function is called by the
>>> dynamic linker, "f" or "f_ifunc"?  Why is the attribute ignored if
>>> "f_ifunc" is not defined; shouldn't it be an error?  I guess that means
>>> that "f_ifunc" is called by the dynamic linker; in that case, what
>>> happens if "func" is defined?
>>
>> Yeah.  I would have proposed that
>>
>> void *foo (void) __attribute__((__ifunc__))
>> {
>>  return zero;
>> }
>>
>> would simply generate foo with indirect function type.
>>
>> This of course causes a problem if you have a declaration for
>> the real foo available - but then you should better not have that,
>> as the compiler will then derive wrong properties for the real foo
>> from the ifunc wrapper body.
>>
>
> Glibc has ifunc testcases with a declaration of foo in the same file.
> This proposal won't work with them.

They would just need to be fixed then.

Richard.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

H.J. Lu-30
On Sat, Jun 13, 2009 at 9:18 AM, Richard
Guenther<[hidden email]> wrote:

> On Sat, Jun 13, 2009 at 6:07 PM, H.J. Lu<[hidden email]> wrote:
>> On Sat, Jun 13, 2009 at 8:15 AM, Richard
>> Guenther<[hidden email]> wrote:
>>
>>>>
>>>> I started to write my own version of the documentation, but I realized
>>>> that I don't even understand this.  Which function is called by the
>>>> dynamic linker, "f" or "f_ifunc"?  Why is the attribute ignored if
>>>> "f_ifunc" is not defined; shouldn't it be an error?  I guess that means
>>>> that "f_ifunc" is called by the dynamic linker; in that case, what
>>>> happens if "func" is defined?
>>>
>>> Yeah.  I would have proposed that
>>>
>>> void *foo (void) __attribute__((__ifunc__))
>>> {
>>>  return zero;
>>> }
>>>
>>> would simply generate foo with indirect function type.
>>>
>>> This of course causes a problem if you have a declaration for
>>> the real foo available - but then you should better not have that,
>>> as the compiler will then derive wrong properties for the real foo
>>> from the ifunc wrapper body.
>>>
>>
>> Glibc has ifunc testcases with a declaration of foo in the same file.
>> This proposal won't work with them.
>
> They would just need to be fixed then.
>

I don't think there are anything wrong with ifunc testcases in glibc.

void *foo (void) __attribute__((__ifunc__))

isn't a good idea since this isn't the real prototype for foo. It will lead
to many problems down the road. foo is usually declared in a header
file and you can't include such a header file in the implementations
of foo if 2 prototypes don't match.

--
H.J.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

Jakub Jelinek
On Sat, Jun 13, 2009 at 11:07:38AM -0700, H.J. Lu wrote:
> I don't think there are anything wrong with ifunc testcases in glibc.
>
> void *foo (void) __attribute__((__ifunc__))
>
> isn't a good idea since this isn't the real prototype for foo. It will lead
> to many problems down the road. foo is usually declared in a header
> file and you can't include such a header file in the implementations
> of foo if 2 prototypes don't match.

Yeah, I agree.  Having to tweak headers through ugly hacks to avoid the real
prototype to be visible in order to define ifunc function would be a very
bad idea.

        Jakub
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

Ulrich Drepper
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jakub Jelinek wrote:
> Yeah, I agree.  Having to tweak headers through ugly hacks to avoid the real
> prototype to be visible in order to define ifunc function would be a very
> bad idea.

The solution is simple: don't allow ifunc attribute for prototypes.
They only ever should be added to definitions.  No user of the function
should care about the function being IFUNC instead of FUNC.

- --
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAko0DXkACgkQ2ijCOnn/RHRiywCdHzIARtyleTruvvNjARZequjK
W9kAoImKrhben7r6j6kyaDlMSAFco7vx
=Af3I
-----END PGP SIGNATURE-----
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

H.J. Lu-30
In reply to this post by Richard Biener
On Sat, Jun 13, 2009 at 8:15 AM, Richard
Guenther<[hidden email]> wrote:

> On Sat, Jun 13, 2009 at 3:30 AM, Ian Lance Taylor<[hidden email]> wrote:
>> "H.J. Lu" <[hidden email]> writes:
>>
>>> +@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.
>>
>> This documentation needs to be much better.  I think most people reading
>> this would not understand the feature.  I would suggest something more
>> along these lines, but I would like to hear what other people think.
>>
>> I started to write my own version of the documentation, but I realized
>> that I don't even understand this.  Which function is called by the
>> dynamic linker, "f" or "f_ifunc"?  Why is the attribute ignored if
>> "f_ifunc" is not defined; shouldn't it be an error?  I guess that means
>> that "f_ifunc" is called by the dynamic linker; in that case, what
>> happens if "func" is defined?
>
> Yeah.  I would have proposed that
>
> void *foo (void) __attribute__((__ifunc__))
> {
>  return zero;
> }
>
> would simply generate foo with indirect function type.
>
> This of course causes a problem if you have a declaration for
> the real foo available - but then you should better not have that,
> as the compiler will then derive wrong properties for the real foo
> from the ifunc wrapper body.
>
> That would at least not introduce the confusion with the extra name ...
>
Here is the updated patch. I extended the ifunc attribute to
static functions and added testcases to show that we need
argument for ifunc attribute:

static foo_p
__attribute__ ((ifunc ("foo")))
foo_ifunc (void)
{
  return zero;
}

static int foo (int);

int
bar (int i)
{
  return foo (i);
}

I also updated document to say

`ifunc ("FUNCTION")'
     The `ifunc' attribute only applies to function definition, which
     causes the definition to be emitted as an indirec function.  For
     instance,

          void* f_ifunc () __attribute__ ((ifunc ("f")));

     defines `f_ifunc' to be an indirect function for `f'.  The
     indirect function `f_ifunc' is called by dynamic linker, and
     returns a pointer to the actual function that should be executed as
     `f'.  This attribute is ignored if `f_ifunc' is undefined in the
     same translation unit unless the symbol type is generated for
     undefined symbol.

This patch also addressed the IFUNC symbol binding, which should
always be global since it needs to go through PLT.  I reused one bit
in base for TREE_IFUNC_NAME. Any comments?

Thanks.


--
H.J.
---
gcc/

2009-06-19  H.J. Lu  <[hidden email]>

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

        * c-decl.c (c_write_global_declarations_1): Don't warn undefined
        IFUNC symbol.

        * cgraphunit.c (process_function_and_variable_attributes): Check
        TREE_USED.
        * ipa-pure-const.c (check_decl): Likewise.
        * ipa-reference.c (has_proper_scope_for_analysis): Likewise.
        * ipa-type-escape.c (has_proper_scope_for_analysis): Likewise.

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

        * tree.h (TREE_IFUNC_NAME): New.

        * varasm.c (default_binds_local_p_1): Return false for
        TREE_IFUNC_NAME.

        * 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-19  H.J. Lu  <[hidden email]>

        * gcc.dg/torture/ifunc-1.c: New.
        * gcc.dg/torture/ifunc-2.c: Likewise.
        * gcc.dg/torture/ifunc-3.c: Likewise.
        * gcc.dg/torture/ifunc-4.c: Likewise.

gcc-ifunc-3.patch (18K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

Jakub Jelinek
On Fri, Jun 19, 2009 at 03:00:04PM -0700, H.J. Lu wrote:

> > Yeah.  I would have proposed that
> >
> > void *foo (void) __attribute__((__ifunc__))
> > {
> >  return zero;
> > }
> >
> > would simply generate foo with indirect function type.
> >
> > This of course causes a problem if you have a declaration for
> > the real foo available - but then you should better not have that,
> > as the compiler will then derive wrong properties for the real foo
> > from the ifunc wrapper body.
> >
> > That would at least not introduce the confusion with the extra name ...
> >
>
> Here is the updated patch. I extended the ifunc attribute to
> static functions and added testcases to show that we need
> argument for ifunc attribute:

I agree with Richard here, ifunc attribute shouldn't have any arguments
and should just mean the function has gnu_indirect_function type instead
of function, nothing else.  That way users can combine it with other
extensions to get the behavior they want, rather than having weird
unexpected effects (in your case foo_ifunc is for some surprisingly
not defined at all).

If you don't have foo's prorotype in the current translation unit, you can
just use ifunc attribute alone, if you do have the prototype, it is not
much harder, e.g.

__typeof (foo) *foo_ifunc (void) __asm ("foo") __attribute__((ifunc))
{
  return foo_impl1;
}

will work just fine.  In this case you don't need to teach GCC about special
properties of ifunc attribute, foo for GCC isn't defined in the current
translation unit (it doesn't look at DECL_ASSEMBLER_NAME for inlining and
similar purposes).

        Jakub
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

H.J. Lu-30
On Sun, Jun 21, 2009 at 2:23 AM, Jakub Jelinek<[hidden email]> wrote:

> On Fri, Jun 19, 2009 at 03:00:04PM -0700, H.J. Lu wrote:
>> > Yeah.  I would have proposed that
>> >
>> > void *foo (void) __attribute__((__ifunc__))
>> > {
>> >  return zero;
>> > }
>> >
>> > would simply generate foo with indirect function type.
>> >
>> > This of course causes a problem if you have a declaration for
>> > the real foo available - but then you should better not have that,
>> > as the compiler will then derive wrong properties for the real foo
>> > from the ifunc wrapper body.
>> >
>> > That would at least not introduce the confusion with the extra name ...
>> >
>>
>> Here is the updated patch. I extended the ifunc attribute to
>> static functions and added testcases to show that we need
>> argument for ifunc attribute:
>
> I agree with Richard here, ifunc attribute shouldn't have any arguments
> and should just mean the function has gnu_indirect_function type instead
> of function, nothing else.  That way users can combine it with other
> extensions to get the behavior they want, rather than having weird
> unexpected effects (in your case foo_ifunc is for some surprisingly
> not defined at all).
>
> If you don't have foo's prorotype in the current translation unit, you can
> just use ifunc attribute alone, if you do have the prototype, it is not
> much harder, e.g.
>
> __typeof (foo) *foo_ifunc (void) __asm ("foo") __attribute__((ifunc))
> {
>  return foo_impl1;
> }
>
> will work just fine.  In this case you don't need to teach GCC about special
> properties of ifunc attribute, foo for GCC isn't defined in the current
> translation unit (it doesn't look at DECL_ASSEMBLER_NAME for inlining and
> similar purposes).

Using

static __typeof (foo) *foo_ifunc (void) __asm ("foo") __attribute__((ifunc))

is not much better than

static __typeof (foo) * foo_ifunc (void) __asm__ ("foo");
__asm__(".type foo, %gnu_indirect_function");

Also, I am getting

ifunc-2.c:3:12: warning: 'foo' used but never defined

on static ifunc.  It is not a new problem:

[hjl@gnu-6 tmp]$ cat foo.c
static int foo ();
static int foo_ifunc (void) __asm__ ("foo");
static int
foo_ifunc (void)
{
  return 0;
}
int
bar ()
{
  return foo ();
}
[hjl@gnu-6 tmp]$ gcc foo.c -S
foo.c:1: warning: âfooâ used but never defined
[hjl@gnu-6 tmp]$

How can we solve this?

--
H.J.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

Richard Biener
On Sun, Jun 21, 2009 at 4:19 PM, H.J. Lu<[hidden email]> wrote:

> On Sun, Jun 21, 2009 at 2:23 AM, Jakub Jelinek<[hidden email]> wrote:
>> On Fri, Jun 19, 2009 at 03:00:04PM -0700, H.J. Lu wrote:
>>> > Yeah.  I would have proposed that
>>> >
>>> > void *foo (void) __attribute__((__ifunc__))
>>> > {
>>> >  return zero;
>>> > }
>>> >
>>> > would simply generate foo with indirect function type.
>>> >
>>> > This of course causes a problem if you have a declaration for
>>> > the real foo available - but then you should better not have that,
>>> > as the compiler will then derive wrong properties for the real foo
>>> > from the ifunc wrapper body.
>>> >
>>> > That would at least not introduce the confusion with the extra name ...
>>> >
>>>
>>> Here is the updated patch. I extended the ifunc attribute to
>>> static functions and added testcases to show that we need
>>> argument for ifunc attribute:
>>
>> I agree with Richard here, ifunc attribute shouldn't have any arguments
>> and should just mean the function has gnu_indirect_function type instead
>> of function, nothing else.  That way users can combine it with other
>> extensions to get the behavior they want, rather than having weird
>> unexpected effects (in your case foo_ifunc is for some surprisingly
>> not defined at all).
>>
>> If you don't have foo's prorotype in the current translation unit, you can
>> just use ifunc attribute alone, if you do have the prototype, it is not
>> much harder, e.g.
>>
>> __typeof (foo) *foo_ifunc (void) __asm ("foo") __attribute__((ifunc))
>> {
>>  return foo_impl1;
>> }
>>
>> will work just fine.  In this case you don't need to teach GCC about special
>> properties of ifunc attribute, foo for GCC isn't defined in the current
>> translation unit (it doesn't look at DECL_ASSEMBLER_NAME for inlining and
>> similar purposes).
>
> Using
>
> static __typeof (foo) *foo_ifunc (void) __asm ("foo") __attribute__((ifunc))
>
> is not much better than
>
> static __typeof (foo) * foo_ifunc (void) __asm__ ("foo");
> __asm__(".type foo, %gnu_indirect_function");

Does that work reliably without -fno-toplevel-reorder?  Where is  your
implementation of foo_ifunc in this case?  A trivial example yields

#APP
        .type foo, %gnu_indirect_function
#NO_APP
        .text
        .p2align 4,,15
        .type   foo, @function
foo:
        pushl   %ebp
...

I wonder if that would be well-defined.

> Also, I am getting
>
> ifunc-2.c:3:12: warning: 'foo' used but never defined
>
> on static ifunc.  It is not a new problem:
>
> [hjl@gnu-6 tmp]$ cat foo.c
> static int foo ();
> static int foo_ifunc (void) __asm__ ("foo");
> static int
> foo_ifunc (void)
> {
>  return 0;
> }
> int
> bar ()
> {
>  return foo ();
> }
> [hjl@gnu-6 tmp]$ gcc foo.c -S
> foo.c:1: warning: âfooâ used but never defined
> [hjl@gnu-6 tmp]$
>
> How can we solve this?

By not declaring foo static.  It would be wrong to do so, as it
doesn't really bind locally and gcc would not be allowed to
do optimizations on it that it could do with a locally binding
function.

Richard.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

H.J. Lu-30
On Sun, Jun 21, 2009 at 8:34 AM, Richard
Guenther<[hidden email]> wrote:

> On Sun, Jun 21, 2009 at 4:19 PM, H.J. Lu<[hidden email]> wrote:
>> On Sun, Jun 21, 2009 at 2:23 AM, Jakub Jelinek<[hidden email]> wrote:
>>> On Fri, Jun 19, 2009 at 03:00:04PM -0700, H.J. Lu wrote:
>>>> > Yeah.  I would have proposed that
>>>> >
>>>> > void *foo (void) __attribute__((__ifunc__))
>>>> > {
>>>> >  return zero;
>>>> > }
>>>> >
>>>> > would simply generate foo with indirect function type.
>>>> >
>>>> > This of course causes a problem if you have a declaration for
>>>> > the real foo available - but then you should better not have that,
>>>> > as the compiler will then derive wrong properties for the real foo
>>>> > from the ifunc wrapper body.
>>>> >
>>>> > That would at least not introduce the confusion with the extra name ...
>>>> >
>>>>
>>>> Here is the updated patch. I extended the ifunc attribute to
>>>> static functions and added testcases to show that we need
>>>> argument for ifunc attribute:
>>>
>>> I agree with Richard here, ifunc attribute shouldn't have any arguments
>>> and should just mean the function has gnu_indirect_function type instead
>>> of function, nothing else.  That way users can combine it with other
>>> extensions to get the behavior they want, rather than having weird
>>> unexpected effects (in your case foo_ifunc is for some surprisingly
>>> not defined at all).
>>>
>>> If you don't have foo's prorotype in the current translation unit, you can
>>> just use ifunc attribute alone, if you do have the prototype, it is not
>>> much harder, e.g.
>>>
>>> __typeof (foo) *foo_ifunc (void) __asm ("foo") __attribute__((ifunc))
>>> {
>>>  return foo_impl1;
>>> }
>>>
>>> will work just fine.  In this case you don't need to teach GCC about special
>>> properties of ifunc attribute, foo for GCC isn't defined in the current
>>> translation unit (it doesn't look at DECL_ASSEMBLER_NAME for inlining and
>>> similar purposes).
>>
>> Using
>>
>> static __typeof (foo) *foo_ifunc (void) __asm ("foo") __attribute__((ifunc))
>>
>> is not much better than
>>
>> static __typeof (foo) * foo_ifunc (void) __asm__ ("foo");
>> __asm__(".type foo, %gnu_indirect_function");
>
> Does that work reliably without -fno-toplevel-reorder?  Where is  your
> implementation of foo_ifunc in this case?  A trivial example yields
>
> #APP
>        .type foo, %gnu_indirect_function
> #NO_APP
>        .text
>        .p2align 4,,15
>        .type   foo, @function
> foo:
>        pushl   %ebp
> ...
>
> I wonder if that would be well-defined.
I got

[hjl@gnu-6 gcc]$ cat /tmp/i.c
static int
zero (int x)
{
  return 0;
}

static void * foo_ifunc (void) __asm__ ("foo") __attribute__ ((used));
static void * foo_ifunc (void) { return zero ; }
__asm__(".type foo, %gnu_indirect_function");
[hjl@gnu-6 gcc]$ gcc -O2 -S /tmp/i.c -ftoplevel-reorder
[hjl@gnu-6 gcc]$ cat i.s
        .file "i.c"
#APP
        .type foo, %gnu_indirect_function
#NO_APP
        .text
        .p2align 4,,15
        .type zero, @function
zero:
.LFB2:
        xorl %eax, %eax
        ret
.LFE2:
        .size zero, .-zero
        .p2align 4,,15
        .type foo, @function
foo:
.LFB3:
        movl $zero, %eax
        ret
.LFE3:
        .size foo, .-foo

I don't see why it should be a problem.

>> Also, I am getting
>>
>> ifunc-2.c:3:12: warning: 'foo' used but never defined
>>
>> on static ifunc.  It is not a new problem:
>>
>> [hjl@gnu-6 tmp]$ cat foo.c
>> static int foo ();
>> static int foo_ifunc (void) __asm__ ("foo");
>> static int
>> foo_ifunc (void)
>> {
>>  return 0;
>> }
>> int
>> bar ()
>> {
>>  return foo ();
>> }
>> [hjl@gnu-6 tmp]$ gcc foo.c -S
>> foo.c:1: warning: âfooâ used but never defined
>> [hjl@gnu-6 tmp]$
>>
>> How can we solve this?
>
> By not declaring foo static.  It would be wrong to do so, as it
> doesn't really bind locally and gcc would not be allowed to
> do optimizations on it that it could do with a locally binding
> function.
>
I added static ifunc support to binutils under request from Jakub.
I am enclosing my current gcc patch, which handles static ifunc
correctly. With static ifunc, you can have 2 ifunc foo in 2 different
files in a library and you don't have to worry if someone else
defines a normal global foo for total different purpose, which
may override your foo.

Thanks.

--
H.J.

gcc-ifunc-6.patch (15K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

Richard Biener
On Sun, Jun 21, 2009 at 6:41 PM, H.J. Lu<[hidden email]> wrote:

> On Sun, Jun 21, 2009 at 8:34 AM, Richard
> Guenther<[hidden email]> wrote:
>> On Sun, Jun 21, 2009 at 4:19 PM, H.J. Lu<[hidden email]> wrote:
>>> On Sun, Jun 21, 2009 at 2:23 AM, Jakub Jelinek<[hidden email]> wrote:
>>>> On Fri, Jun 19, 2009 at 03:00:04PM -0700, H.J. Lu wrote:
>>>>> > Yeah.  I would have proposed that
>>>>> >
>>>>> > void *foo (void) __attribute__((__ifunc__))
>>>>> > {
>>>>> >  return zero;
>>>>> > }
>>>>> >
>>>>> > would simply generate foo with indirect function type.
>>>>> >
>>>>> > This of course causes a problem if you have a declaration for
>>>>> > the real foo available - but then you should better not have that,
>>>>> > as the compiler will then derive wrong properties for the real foo
>>>>> > from the ifunc wrapper body.
>>>>> >
>>>>> > That would at least not introduce the confusion with the extra name ...
>>>>> >
>>>>>
>>>>> Here is the updated patch. I extended the ifunc attribute to
>>>>> static functions and added testcases to show that we need
>>>>> argument for ifunc attribute:
>>>>
>>>> I agree with Richard here, ifunc attribute shouldn't have any arguments
>>>> and should just mean the function has gnu_indirect_function type instead
>>>> of function, nothing else.  That way users can combine it with other
>>>> extensions to get the behavior they want, rather than having weird
>>>> unexpected effects (in your case foo_ifunc is for some surprisingly
>>>> not defined at all).
>>>>
>>>> If you don't have foo's prorotype in the current translation unit, you can
>>>> just use ifunc attribute alone, if you do have the prototype, it is not
>>>> much harder, e.g.
>>>>
>>>> __typeof (foo) *foo_ifunc (void) __asm ("foo") __attribute__((ifunc))
>>>> {
>>>>  return foo_impl1;
>>>> }
>>>>
>>>> will work just fine.  In this case you don't need to teach GCC about special
>>>> properties of ifunc attribute, foo for GCC isn't defined in the current
>>>> translation unit (it doesn't look at DECL_ASSEMBLER_NAME for inlining and
>>>> similar purposes).
>>>
>>> Using
>>>
>>> static __typeof (foo) *foo_ifunc (void) __asm ("foo") __attribute__((ifunc))
>>>
>>> is not much better than
>>>
>>> static __typeof (foo) * foo_ifunc (void) __asm__ ("foo");
>>> __asm__(".type foo, %gnu_indirect_function");
>>
>> Does that work reliably without -fno-toplevel-reorder?  Where is  your
>> implementation of foo_ifunc in this case?  A trivial example yields
>>
>> #APP
>>        .type foo, %gnu_indirect_function
>> #NO_APP
>>        .text
>>        .p2align 4,,15
>>        .type   foo, @function
>> foo:
>>        pushl   %ebp
>> ...
>>
>> I wonder if that would be well-defined.
>
> I got
>
> [hjl@gnu-6 gcc]$ cat /tmp/i.c
> static int
> zero (int x)
> {
>  return 0;
> }
>
> static void * foo_ifunc (void) __asm__ ("foo") __attribute__ ((used));
> static void * foo_ifunc (void) { return zero ; }
> __asm__(".type foo, %gnu_indirect_function");
> [hjl@gnu-6 gcc]$ gcc -O2 -S /tmp/i.c -ftoplevel-reorder
> [hjl@gnu-6 gcc]$ cat i.s
>        .file   "i.c"
> #APP
>        .type foo, %gnu_indirect_function
> #NO_APP
>        .text
>        .p2align 4,,15
>        .type   zero, @function
> zero:
> .LFB2:
>        xorl    %eax, %eax
>        ret
> .LFE2:
>        .size   zero, .-zero
>        .p2align 4,,15
>        .type   foo, @function
> foo:
> .LFB3:
>        movl    $zero, %eax
>        ret
> .LFE3:
>        .size   foo, .-foo
>
> I don't see why it should be a problem.

Because there are two .type for foo.  If you say that is well-defined, ok ...

>>> Also, I am getting
>>>
>>> ifunc-2.c:3:12: warning: 'foo' used but never defined
>>>
>>> on static ifunc.  It is not a new problem:
>>>
>>> [hjl@gnu-6 tmp]$ cat foo.c
>>> static int foo ();
>>> static int foo_ifunc (void) __asm__ ("foo");
>>> static int
>>> foo_ifunc (void)
>>> {
>>>  return 0;
>>> }
>>> int
>>> bar ()
>>> {
>>>  return foo ();
>>> }
>>> [hjl@gnu-6 tmp]$ gcc foo.c -S
>>> foo.c:1: warning: âfooâ used but never defined
>>> [hjl@gnu-6 tmp]$
>>>
>>> How can we solve this?
>>
>> By not declaring foo static.  It would be wrong to do so, as it
>> doesn't really bind locally and gcc would not be allowed to
>> do optimizations on it that it could do with a locally binding
>> function.
>>
>
> I added static ifunc support to binutils under request from Jakub.
> I am enclosing my current gcc patch, which handles static ifunc
> correctly. With static ifunc, you can have 2 ifunc foo in 2 different
> files in a library and you don't have to worry if someone else
> defines a normal global foo for total different purpose, which
> may override your foo.

Ok, so for the static case we could either overload the used or
unused attributes or invent a new defined attribute:

static int foo () __attribute__((defined));

that would also solve the general case with asm renaming.  Or
simply recognize the asm name as something that is defined
properly.

Richard.

> Thanks.
>
> --
> H.J.
>
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

H.J. Lu-30
Hi,

I opened a bug report:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40528

with the third proposal:

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.

Any comments?

Thanks.

--
H.J.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

Richard Biener
On Tue, Jun 23, 2009 at 7:19 PM, H.J. Lu<[hidden email]> wrote:

> Hi,
>
> I opened a bug report:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40528
>
> with the third proposal:
>
> 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.
>
> Any comments?

I don't understand this third proposal.

Richard.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: Add ifunc attribute

Paolo Bonzini-2
Richard Guenther wrote:

> On Tue, Jun 23, 2009 at 7:19 PM, H.J. Lu<[hidden email]> wrote:
>> Hi,
>>
>> I opened a bug report:
>>
>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40528
>>
>> with the third proposal:
>>
>> 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.
>>
>> Any comments?
>
> I don't understand this third proposal.

"int foo (...)" is only declared as a prototype and with the ifunc
attribute dropped.  The body of the function is actually compiled to
.ifunc.foo or something like that, with a signature

__typeof(foo) __attribute__ ((ifunc)) .ifunc.foo(void)

and with ".gnu.indirect.function .ifunc.foo" emitted in the assembly
instead of ".function".

Via some magic mechanism, a further redeclaration of foo is prohibited.

Looks a bit too like DWIM and too little like a specification.  I think
I prefer option 1, in some cases you may want to call the trampoline and
having it accessible can help.  With

__typeof (foo) *
__attribute__ ((ifunc ("foo")))
foo_ifunc (void)
{
   <return address of foo_{1,2,3}>
}

you could call foo_ifunc if you wish in principle, and the header file
only has the prototype of foo as expected.

Paolo
123