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]

[IFUNC]: Support overloaded IFUNC member function


I am checking in this patch into ifunc branch to support overloaded
IFUNC member function.


H.J.
----
Index: testsuite/ChangeLog.ifunc
===================================================================
--- testsuite/ChangeLog.ifunc	(revision 149181)
+++ testsuite/ChangeLog.ifunc	(working copy)
@@ -1,3 +1,9 @@
+2009-07-05  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* g++.dg/torture/ifunc-21.C: New.
+	* g++.dg/torture/ifunc-22.C: Likewise.
+	* g++.dg/torture/ifunc-23.C: Likewise.
+
 2009-06-28  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR c/40528
Index: testsuite/g++.dg/torture/ifunc-21.C
===================================================================
--- testsuite/g++.dg/torture/ifunc-21.C	(revision 0)
+++ testsuite/g++.dg/torture/ifunc-21.C	(revision 0)
@@ -0,0 +1,46 @@
+/* { dg-do compile { target i?86-*-linux* x86_64-*-linux* } } */
+/* { dg-options "-Wall -Wextra" } */
+
+class ifunc
+{
+private:
+  static int foo1 (int);
+  static int foo1 (float);
+
+public:
+  static int foo (int);
+  static int foo (float);
+};
+
+int
+__attribute__ ((ifunc))
+ifunc::foo (int)
+{ 
+  return &ifunc::foo1;
+}
+
+int
+__attribute__ ((ifunc))
+ifunc::foo (float)
+{ 
+  return &ifunc::foo1;
+}
+
+int
+bar (int x)
+{
+  return ifunc::foo (x);
+}
+
+int
+bar (float x)
+{
+  return ifunc::foo (x);
+}
+
+/* { dg-final { scan-assembler-not ".type\[ 	\]\+_ZN5ifunc3fooEf, .function" } } */
+/* { dg-final { scan-assembler-not ".type\[ 	\]\+_ZN5ifunc3fooEi, .function" } } */
+/* { dg-final { scan-assembler "(call|jmp)\[ 	\]\+_ZN5ifunc3fooEi" } } */
+/* { dg-final { scan-assembler "(call|jmp)\[ 	\]\+_ZN5ifunc3fooEf" } } */
+/* { dg-final { scan-assembler ".type\[ 	\]\+_ZN5ifunc3fooEi, .gnu_indirect_function" } } */
+/* { dg-final { scan-assembler ".type\[ 	\]\+_ZN5ifunc3fooEf, .gnu_indirect_function" } } */
Index: testsuite/g++.dg/torture/ifunc-23.C
===================================================================
--- testsuite/g++.dg/torture/ifunc-23.C	(revision 0)
+++ testsuite/g++.dg/torture/ifunc-23.C	(revision 0)
@@ -0,0 +1,48 @@
+/* { dg-do compile { target i?86-*-linux* x86_64-*-linux* } } */
+/* { dg-options "-Wall -Wextra" } */
+
+class ifunc
+{
+private:
+  void foo1 (int);
+  void foo1 (float);
+
+public:
+  void foo (int);
+  void foo (float);
+  void bar (int);
+  void bar (float);
+};
+
+void
+__attribute__ ((ifunc))
+ifunc::foo (int)
+{ 
+  return &ifunc::foo1;
+}
+
+void
+__attribute__ ((ifunc))
+ifunc::foo (float)
+{ 
+  return &ifunc::foo1;
+}
+
+void
+ifunc::bar (int x)
+{
+  foo (x);
+}
+
+void
+ifunc::bar (float x)
+{
+  foo (x);
+}
+
+/* { dg-final { scan-assembler-not ".type\[ 	\]\+_ZN5ifunc3fooEi, .function" } } */
+/* { dg-final { scan-assembler-not ".type\[ 	\]\+_ZN5ifunc3fooEf, .function" } } */
+/* { dg-final { scan-assembler "(call|jmp)\[ 	\]\+_ZN5ifunc3fooEi" } } */
+/* { dg-final { scan-assembler "(call|jmp)\[ 	\]\+_ZN5ifunc3fooEf" } } */
+/* { dg-final { scan-assembler ".type\[ 	\]\+_ZN5ifunc3fooEi, .gnu_indirect_function" } } */
+/* { dg-final { scan-assembler ".type\[ 	\]\+_ZN5ifunc3fooEf, .gnu_indirect_function" } } */
Index: testsuite/g++.dg/torture/ifunc-22.C
===================================================================
--- testsuite/g++.dg/torture/ifunc-22.C	(revision 0)
+++ testsuite/g++.dg/torture/ifunc-22.C	(revision 0)
@@ -0,0 +1,48 @@
+/* { dg-do compile { target i?86-*-linux* x86_64-*-linux* } } */
+/* { dg-options "-Wall -Wextra" } */
+
+class ifunc
+{
+private:
+  int foo1 (int);
+  int foo1 (float);
+
+public:
+  int foo (int);
+  int foo (float);
+  int bar (int);
+  int bar (float);
+};
+
+int
+__attribute__ ((ifunc))
+ifunc::foo (int)
+{ 
+  return &ifunc::foo1;
+}
+
+int
+__attribute__ ((ifunc))
+ifunc::foo (float)
+{ 
+  return &ifunc::foo1;
+}
+
+int
+ifunc::bar (int x)
+{
+  return foo (x);
+}
+
+int
+ifunc::bar (float x)
+{
+  return foo (x);
+}
+
+/* { dg-final { scan-assembler-not ".type\[ 	\]\+_ZN5ifunc3fooEi, .function" } } */
+/* { dg-final { scan-assembler-not ".type\[ 	\]\+_ZN5ifunc3fooEf, .function" } } */
+/* { dg-final { scan-assembler "(call|jmp)\[ 	\]\+_ZN5ifunc3fooEi" } } */
+/* { dg-final { scan-assembler "(call|jmp)\[ 	\]\+" } } */
+/* { dg-final { scan-assembler ".type\[ 	\]\+_ZN5ifunc3fooEi, .gnu_indirect_function" } } */
+/* { dg-final { scan-assembler ".type\[ 	\]\+_ZN5ifunc3fooEf, .gnu_indirect_function" } } */
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 149181)
+++ cp/typeck.c	(working copy)
@@ -4786,6 +4786,17 @@ cp_build_unary_op (enum tree_code code, 
       if (TREE_CODE (argtype) == POINTER_TYPE
 	  && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
 	{
+	  if (current_function_decl != NULL
+	      && DECL_IS_IFUNC (current_function_decl)
+	      && DECL_NONSTATIC_MEMBER_FUNCTION_P (current_function_decl)
+	      && (TYPE_MAIN_VARIANT (argtype)
+		  == TYPE_MAIN_VARIANT (function_return_type (current_function_decl))))
+	    {
+	      /* IFUNC member function returns the address of another
+		 non-static member function.  */
+	      return val;
+	    }
+
 	  build_ptrmemfunc_type (argtype);
 	  val = build_ptrmemfunc (argtype, val, 0,
 				  /*c_cast_p=*/false);
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 149181)
+++ cp/class.c	(working copy)
@@ -5992,17 +5992,24 @@ resolve_address_of_overloaded_function (
 
   int is_ptrmem = 0;
   int is_reference = 0;
+  int is_ifunc;
   /* We store the matches in a TREE_LIST rooted here.  The functions
      are the TREE_PURPOSE, not the TREE_VALUE, in this list, for easy
      interoperability with most_specialized_instantiation.  */
   tree matches = NULL_TREE;
   tree fn;
 
+  is_ifunc = (current_function_decl != NULL
+	      && DECL_IS_IFUNC (current_function_decl)
+	      && DECL_NONSTATIC_MEMBER_FUNCTION_P (current_function_decl));
+
   /* By the time we get here, we should be seeing only real
      pointer-to-member types, not the internal POINTER_TYPE to
-     METHOD_TYPE representation.  */
+     METHOD_TYPE representation unless it is in an IFUNC member
+     function.  */
   gcc_assert (TREE_CODE (target_type) != POINTER_TYPE
-	      || TREE_CODE (TREE_TYPE (target_type)) != METHOD_TYPE);
+	      || TREE_CODE (TREE_TYPE (target_type)) != METHOD_TYPE
+	      || is_ifunc);
 
   gcc_assert (is_overloaded_fn (overload));
 
@@ -6019,6 +6026,8 @@ resolve_address_of_overloaded_function (
       target_type = build_reference_type (target_type);
       is_reference = 1;
     }
+  else if (is_ifunc && TYPE_PTRMEMIFUNC_P (target_type))
+    /* This is OK.  */;
   else
     {
       if (flags & tf_error)
@@ -6046,7 +6055,7 @@ resolve_address_of_overloaded_function (
 	    continue;
 
 	  if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
-	      != is_ptrmem)
+	      != (is_ptrmem | is_ifunc))
 	    /* We're looking for a non-static member, and this isn't
 	       one, or vice versa.  */
 	    continue;
@@ -6250,7 +6259,9 @@ resolve_address_of_overloaded_function (
       perform_or_defer_access_check (access_path, fn, fn);
     }
 
-  if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
+  if (TYPE_PTRFN_P (target_type)
+      || TYPE_PTRMEMFUNC_P (target_type)
+      || (is_ifunc && TYPE_PTRMEMIFUNC_P (target_type)))
     return cp_build_unary_op (ADDR_EXPR, fn, 0, flags);
   else
     {
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 149181)
+++ cp/call.c	(working copy)
@@ -710,7 +710,12 @@ standard_conversion (tree to, tree from,
   to = strip_top_quals (to);
   from = strip_top_quals (from);
 
-  if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to))
+  if ((TYPE_PTRFN_P (to)
+       || TYPE_PTRMEMFUNC_P (to)
+       || (current_function_decl != NULL
+	   && DECL_IS_IFUNC (current_function_decl)
+	   && DECL_NONSTATIC_MEMBER_FUNCTION_P (current_function_decl)
+	   && TYPE_PTRMEMIFUNC_P (to)))
       && expr && type_unknown_p (expr))
     {
       tsubst_flags_t tflags = tf_conv;
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 149181)
+++ cp/cp-tree.h	(working copy)
@@ -2909,6 +2909,12 @@ more_aggr_init_expr_args_p (const aggr_i
   (TREE_CODE (NODE) == REFERENCE_TYPE			\
    && TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE)
 
+/* Returns true if NODE is a pointer to a member function inside
+   the IFUNC function body.  */
+#define TYPE_PTRMEMIFUNC_P(NODE)			\
+  (TREE_CODE (NODE) == POINTER_TYPE			\
+   && TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE)
+
 /* Nonzero for _TYPE node means that this type is a pointer to member
    function type.  */
 #define TYPE_PTRMEMFUNC_P(NODE)		\
Index: cp/ChangeLog.ifunc
===================================================================
--- cp/ChangeLog.ifunc	(revision 149181)
+++ cp/ChangeLog.ifunc	(working copy)
@@ -1,3 +1,13 @@
+2009-07-05  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* call.c (standard_conversion): Support IFUNC member function.
+	* class.c (resolve_address_of_overloaded_function): Likewise.
+
+	* cp-tree.h (TYPE_PTRMEMIFUNC_P): New.
+
+	* typeck.c (cp_build_unary_op): Take the address of non-static
+	overloaded member function for IFUNC member function.
+
 2009-06-28  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR c/40528


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