target.h (gcc_target.asm_out): Merge output_mi_thunk and output_mi_vcall_thunk into...
authorRichard Henderson <rth@redhat.com>
Tue, 22 Oct 2002 23:05:28 +0000 (16:05 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 22 Oct 2002 23:05:28 +0000 (16:05 -0700)
gcc/
* target.h (gcc_target.asm_out): Merge output_mi_thunk and
output_mi_vcall_thunk into a single hook.  Add can_output_mi_thunk.
* target-def.h (TARGET_ASM_OUTPUT_MI_THUNK): Don't conditionalize.
(TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Remove.
(TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
(TARGET_ASM_OUT): Update.
* hooks.c (hook_bool_tree_hwi_hwi_tree_false): New.
(hook_bool_tree_hwi_hwi_tree_true): New.
(default_can_output_mi_thunk_no_vcall): New.
* hooks.h: Declare them.
* system.h (ASM_OUTPUT_MI_THUNK): Poison.

* config/alpha/alpha.c (TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
(alpha_output_mi_thunk_osf): Add VCALL_OFFSET parameter.
* config/arm/arm.c, config/cris/cris.c, config/frv/frv.c,
config/i960/i960.c, config/ia64/ia64.c, config/m68k/m68k.c,
config/mmix/mmix.c, config/pa/pa.c, config/sparc/sparc.c,
config/stormy16/stormy16.c: Similarly.

* config/i386/i386.c (x86_output_mi_thunk): Merge vcall_offset code.
Handle 64-bit properly.  Streamline.
(x86_output_mi_vcall_thunk): Remove.
(x86_this_parameter): Rename from ia32_this_parameter; handle 64-bit.
(x86_can_output_mi_thunk): New.
(TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Remove.
(TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
(override_options): Don't zap targetm.asm_out.output_mi_vcall_thunk.

* config/rs6000/rs6000.c (rs6000_output_mi_thunk): Rename from
output_mi_thunk; make static; always use function_section.
(TARGET_ASM_OUTPUT_MI_THUNK): New.
(TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
(rs6000_ra_ever_killed): Test no_new_pseudos not
targetm.asm_out.output_mi_thunk in conjunction with thunks.
* config/rs6000/rs6000-protos.h: Update.
* config/rs6000/sysv4.h (TARGET_ASM_OUTPUT_MI_THUNK): Remove.
* config/rs6000/xcoff.h (ASM_DECLARE_FUNCTION_NAME): Don't call
xcoffout_declare_function when using rs6000_output_mi_thunk.

* config/s390/s390.c (s390_output_mi_thunk): Rename from
s390_output_mi_vcall_thunk.
(TARGET_ASM_OUTPUT_MI_THUNK): Remove.
(TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.

* config/vax/vax.c (vax_output_mi_thunk): Static; add vcall_offset.
(TARGET_ASM_OUTPUT_MI_THUNK, TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
* config/vax/vax-protos.h: Update.
* config/vax/vax.h (ASM_OUTPUT_MI_THUNK): Remove.

gcc/cp/
        * method.c (use_thunk): Always compute vcall_value; assert that
        it is not zero.  Use can_output_mi_thunk; use output_mi_thunk
        for vcall thunks as well.

From-SVN: r58424

28 files changed:
gcc/ChangeLog
gcc/config/alpha/alpha.c
gcc/config/arm/arm.c
gcc/config/cris/cris.c
gcc/config/frv/frv.c
gcc/config/i386/i386.c
gcc/config/i960/i960.c
gcc/config/ia64/ia64.c
gcc/config/m68k/m68k.c
gcc/config/mmix/mmix.c
gcc/config/pa/pa.c
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/sysv4.h
gcc/config/rs6000/xcoff.h
gcc/config/s390/s390.c
gcc/config/sparc/sparc.c
gcc/config/stormy16/stormy16.c
gcc/config/vax/vax-protos.h
gcc/config/vax/vax.c
gcc/config/vax/vax.h
gcc/cp/ChangeLog
gcc/cp/method.c
gcc/hooks.c
gcc/hooks.h
gcc/system.h
gcc/target-def.h
gcc/target.h

index c1f445a23af74dc342fad6982bc4e8330e18714d..31d30a79b4b3ea3c5ea6edf3ca0875c0cb763c0c 100644 (file)
@@ -1,3 +1,54 @@
+2002-10-22  Richard Henderson  <rth@redhat.com>
+
+       * target.h (gcc_target.asm_out): Merge output_mi_thunk and
+       output_mi_vcall_thunk into a single hook.  Add can_output_mi_thunk.
+       * target-def.h (TARGET_ASM_OUTPUT_MI_THUNK): Don't conditionalize.
+       (TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Remove.
+       (TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
+       (TARGET_ASM_OUT): Update.
+       * hooks.c (hook_bool_tree_hwi_hwi_tree_false): New.
+       (hook_bool_tree_hwi_hwi_tree_true): New.
+       (default_can_output_mi_thunk_no_vcall): New.
+       * hooks.h: Declare them.
+       * system.h (ASM_OUTPUT_MI_THUNK): Poison.
+
+       * config/alpha/alpha.c (TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
+       (alpha_output_mi_thunk_osf): Add VCALL_OFFSET parameter.
+       * config/arm/arm.c, config/cris/cris.c, config/frv/frv.c,
+       config/i960/i960.c, config/ia64/ia64.c, config/m68k/m68k.c,
+       config/mmix/mmix.c, config/pa/pa.c, config/sparc/sparc.c,
+       config/stormy16/stormy16.c: Similarly.
+
+       * config/i386/i386.c (x86_output_mi_thunk): Merge vcall_offset code.
+       Handle 64-bit properly.  Streamline.
+       (x86_output_mi_vcall_thunk): Remove.
+       (x86_this_parameter): Rename from ia32_this_parameter; handle 64-bit.
+       (x86_can_output_mi_thunk): New.
+       (TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Remove.
+       (TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
+       (override_options): Don't zap targetm.asm_out.output_mi_vcall_thunk.
+
+       * config/rs6000/rs6000.c (rs6000_output_mi_thunk): Rename from
+       output_mi_thunk; make static; always use function_section.
+       (TARGET_ASM_OUTPUT_MI_THUNK): New.
+       (TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
+       (rs6000_ra_ever_killed): Test no_new_pseudos not
+       targetm.asm_out.output_mi_thunk in conjunction with thunks.
+       * config/rs6000/rs6000-protos.h: Update.
+       * config/rs6000/sysv4.h (TARGET_ASM_OUTPUT_MI_THUNK): Remove.
+       * config/rs6000/xcoff.h (ASM_DECLARE_FUNCTION_NAME): Don't call
+       xcoffout_declare_function when using rs6000_output_mi_thunk.
+
+       * config/s390/s390.c (s390_output_mi_thunk): Rename from 
+       s390_output_mi_vcall_thunk.
+       (TARGET_ASM_OUTPUT_MI_THUNK): Remove.
+       (TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
+
+       * config/vax/vax.c (vax_output_mi_thunk): Static; add vcall_offset.
+       (TARGET_ASM_OUTPUT_MI_THUNK, TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
+       * config/vax/vax-protos.h: Update.
+       * config/vax/vax.h (ASM_OUTPUT_MI_THUNK): Remove.
+
 Wed Oct 23 00:33:11 CEST 2002  Jan Hubicka  <jh@suse,cz>
 
        * i386.c (standard_sse_constant_p): Accept vector and integer zeros too.
index 8f900af4e5b8a5e72fe6455fba705690af81d1bd..5555aaebb180002a3845c9f6cee616b589c5be15 100644 (file)
@@ -197,7 +197,7 @@ static void alpha_write_linkage
 
 #if TARGET_ABI_OSF
 static void alpha_output_mi_thunk_osf
-  PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
+  PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
 #endif
 
 static struct machine_function * alpha_init_machine_status
@@ -300,6 +300,8 @@ static void unicosmk_unique_section PARAMS ((tree, int));
 #if TARGET_ABI_OSF
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK alpha_output_mi_thunk_osf
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
 #endif
 
 struct gcc_target targetm = TARGET_INITIALIZER;
@@ -7860,10 +7862,11 @@ alpha_end_function (file, fnname, decl)
    Not sure why this idea hasn't been explored before...  */
 
 static void
-alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function)
+alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, vcall_offset, function)
      FILE *file;
      tree thunk_fndecl ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree function;
 {
   HOST_WIDE_INT hi, lo;
index d6c1a027a29e0f00029c16d1a29c4e349c92386d..b06cb9bb3373f43a9fd45de1e58d31b3c8f67d87 100644 (file)
@@ -127,6 +127,7 @@ static void  arm_encode_section_info        PARAMS ((tree, int));
 static void     aof_globalize_label            PARAMS ((FILE *, const char *));
 #endif
 static void arm_output_mi_thunk                        PARAMS ((FILE *, tree,
+                                                        HOST_WIDE_INT,
                                                         HOST_WIDE_INT, tree));
 
 #undef Hint
@@ -192,6 +193,8 @@ static void arm_output_mi_thunk                     PARAMS ((FILE *, tree,
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK arm_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
@@ -11154,10 +11157,11 @@ arm_encode_section_info (decl, first)
    to FUNCTION.  Used for C++ multiple inheritance.  */
 
 static void
-arm_output_mi_thunk (file, thunk, delta, function)
+arm_output_mi_thunk (file, thunk, delta, vcall_offset, function)
      FILE *file;
      tree thunk ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree function;
 {
   int mi_delta = delta;
index 3d33a724594ee835a799a259874e046bbd2699a7..2eb864f065cf46360311289216b5ce687dce6c5f 100644 (file)
@@ -102,7 +102,7 @@ static void cris_encode_section_info PARAMS ((tree, int));
 static void cris_operand_lossage PARAMS ((const char *, rtx));
 
 static void cris_asm_output_mi_thunk
-  PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
+  PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
 
 
 /* The function cris_target_asm_function_epilogue puts the last insn to
@@ -159,6 +159,8 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK cris_asm_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -2580,10 +2582,11 @@ cris_override_options ()
 /* The TARGET_ASM_OUTPUT_MI_THUNK worker.  */
 
 static void
-cris_asm_output_mi_thunk (stream, thunkdecl, delta, funcdecl)
+cris_asm_output_mi_thunk (stream, thunkdecl, delta, vcall_offset, funcdecl)
      FILE *stream;
      tree thunkdecl ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree funcdecl;
 {
   if (delta > 0)
index 7ef2e1adbfba744185478c6c66bc7d0c7a5f22a5..d09533a5f1540f830ef2595f6dc41fd3d4d9cf90 100644 (file)
@@ -279,7 +279,8 @@ static void frv_encode_section_info         PARAMS ((tree, int));
 static void frv_init_builtins                  PARAMS ((void));
 static rtx frv_expand_builtin                  PARAMS ((tree, rtx, rtx, enum machine_mode, int));
 static bool frv_in_small_data_p                        PARAMS ((tree));
-static void frv_asm_output_mi_thunk            PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
+static void frv_asm_output_mi_thunk
+  PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
 \f
 /* Initialize the GCC target structure.  */
 #undef  TARGET_ASM_FUNCTION_PROLOGUE
@@ -301,6 +302,8 @@ static void frv_asm_output_mi_thunk         PARAMS ((FILE *, tree, HOST_WIDE_INT, tree)
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK frv_asm_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
@@ -1871,10 +1874,11 @@ frv_expand_epilogue (sibcall_p)
    varargs.  */
 
 static void
-frv_asm_output_mi_thunk (file, thunk_fndecl, delta, function)
+frv_asm_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
      FILE *file;
      tree thunk_fndecl ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree function;
 {
   const char *name_func = XSTR (XEXP (DECL_RTL (function), 0), 0);
index efce0f3238213af431ca7089e2f063a3ce978ce2..f3d5acc59b3d54d143d2db1f1e11a6718026d169 100644 (file)
@@ -750,10 +750,11 @@ static int ix86_variable_issue PARAMS ((FILE *, int, rtx, int));
 static int ia32_use_dfa_pipeline_interface PARAMS ((void));
 static int ia32_multipass_dfa_lookahead PARAMS ((void));
 static void ix86_init_mmx_sse_builtins PARAMS ((void));
-static rtx ia32_this_parameter PARAMS ((tree));
-static void x86_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
-static void x86_output_mi_vcall_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
-                                              HOST_WIDE_INT, tree));
+static rtx x86_this_parameter PARAMS ((tree));
+static void x86_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+                                        HOST_WIDE_INT, tree));
+static bool x86_can_output_mi_thunk PARAMS ((tree, HOST_WIDE_INT,
+                                            HOST_WIDE_INT, tree));
 
 struct ix86_address
 {
@@ -902,8 +903,8 @@ static enum x86_64_reg_class merge_classes PARAMS ((enum x86_64_reg_class,
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk
-#undef TARGET_ASM_OUTPUT_MI_VCALL_THUNK
-#define TARGET_ASM_OUTPUT_MI_VCALL_THUNK x86_output_mi_vcall_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK x86_can_output_mi_thunk
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
@@ -1305,10 +1306,6 @@ override_options ()
     internal_label_prefix_len = p - internal_label_prefix;
     *p = '\0';
   }
-
-  /* In 64-bit mode, we do not have support for vcall thunks.  */
-  if (TARGET_64BIT)
-    targetm.asm_out.output_mi_vcall_thunk = NULL;
 }
 \f
 void
@@ -14076,11 +14073,17 @@ x86_order_regs_for_local_alloc ()
    located on entry to the FUNCTION.  */
 
 static rtx
-ia32_this_parameter (function)
+x86_this_parameter (function)
      tree function;
 {
   tree type = TREE_TYPE (function);
 
+  if (TARGET_64BIT)
+    {
+      int n = aggregate_value_p (TREE_TYPE (type)) != 0;
+      return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
+    }
+
   if (ix86_fntype_regparm (type) > 0)
     {
       tree parm;
@@ -14088,7 +14091,7 @@ ia32_this_parameter (function)
       parm = TYPE_ARG_TYPES (type);
       /* Figure out whether or not the function has a variable number of
         arguments.  */
-      for (; parm; parm = TREE_CHAIN (parm))\
+      for (; parm; parm = TREE_CHAIN (parm))
        if (TREE_VALUE (parm) == void_type_node)
          break;
       /* If not, the this parameter is in %eax.  */
@@ -14102,122 +14105,152 @@ ia32_this_parameter (function)
     return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
 }
 
+/* Determine whether x86_output_mi_thunk can succeed.  */
+
+static bool
+x86_can_output_mi_thunk (thunk, delta, vcall_offset, function)
+     tree thunk ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT delta ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT vcall_offset;
+     tree function;
+{
+  /* 64-bit can handle anything.  */
+  if (TARGET_64BIT)
+    return true;
+
+  /* For 32-bit, everything's fine if we have one free register.  */
+  if (ix86_fntype_regparm (TREE_TYPE (function)) < 3)
+    return true;
+
+  /* Need a free register for vcall_offset.  */
+  if (vcall_offset)
+    return false;
+
+  /* Need a free register for GOT references.  */
+  if (flag_pic && !(*targetm.binds_local_p) (function))
+    return false;
+
+  /* Otherwise ok.  */
+  return true;
+}
+
+/* Output the assembler code for a thunk function.  THUNK_DECL is the
+   declaration for the thunk function itself, FUNCTION is the decl for
+   the target function.  DELTA is an immediate constant offset to be
+   added to THIS.  If VCALL_OFFSET is non-zero, the word at
+   *(*this + vcall_offset) should be added to THIS.  */
 
 static void
-x86_output_mi_vcall_thunk (file, thunk, delta, vcall_index, function)
-     FILE *file;
+x86_output_mi_thunk (file, thunk, delta, vcall_offset, function)
+     FILE *file ATTRIBUTE_UNUSED;
      tree thunk ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
-     HOST_WIDE_INT vcall_index;
+     HOST_WIDE_INT vcall_offset;
      tree function;
 {
   rtx xops[3];
+  rtx this = x86_this_parameter (function);
+  rtx this_reg, tmp;
 
-  if (TARGET_64BIT)
+  /* If VCALL_OFFSET, we'll need THIS in a register.  Might as well
+     pull it in now and let DELTA benefit.  */
+  if (REG_P (this))
+    this_reg = this;
+  else if (vcall_offset)
+    {
+      /* Put the this parameter into %eax.  */
+      xops[0] = this;
+      xops[1] = this_reg = gen_rtx_REG (Pmode, 0);
+      output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
+    }
+  else
+    this_reg = NULL_RTX;
+
+  /* Adjust the this parameter by a fixed constant.  */
+  if (delta)
     {
-      int n = aggregate_value_p (TREE_TYPE (TREE_TYPE (function))) != 0;
       xops[0] = GEN_INT (delta);
-      xops[1] = gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
-      output_asm_insn ("add{q} {%0, %1|%1, %0}", xops);
-      if (flag_pic)
+      xops[1] = this_reg ? this_reg : this;
+      if (TARGET_64BIT)
        {
-         fprintf (file, "\tjmp *");
-         assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
-         fprintf (file, "@GOTPCREL(%%rip)\n");
+         if (!x86_64_general_operand (xops[0], DImode))
+           {
+             tmp = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 2 /* R10 */);
+             xops[1] = tmp;
+             output_asm_insn ("mov{q}\t{%1, %0|%0, %1}", xops);
+             xops[0] = tmp;
+             xops[1] = this;
+           }
+         output_asm_insn ("add{q}\t{%0, %1|%1, %0}", xops);
        }
       else
-       {
-         fprintf (file, "\tjmp ");
-         assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
-         fprintf (file, "\n");
-       }
+       output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
     }
-  else
+
+  /* Adjust the this parameter by a value stored in the vtable.  */
+  if (vcall_offset)
     {
-      /* Adjust the this parameter by a fixed constant.  */
-      if (delta)
-       {
-         xops[0] = GEN_INT (delta);
-         xops[1] = ia32_this_parameter (function);
-         output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
-       }
+      if (TARGET_64BIT)
+       tmp = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 2 /* R10 */);
+      else
+       tmp = gen_rtx_REG (SImode, 2 /* ECX */);
 
-      /* Adjust the this parameter by a value stored in the vtable.  */
-      if (vcall_index)
-       {
-         rtx this_parm;
+      xops[0] = gen_rtx_MEM (Pmode, this_reg);
+      xops[1] = tmp;
+      if (TARGET_64BIT)
+       output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
+      else
+       output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
 
-         /* Put the this parameter into %eax.  */
-         this_parm = ia32_this_parameter (function);
-         if (!REG_P (this_parm))
-           {
-             xops[0] = this_parm;
-             xops[1] = gen_rtx_REG (Pmode, 0);
-             output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
-           }
-         /* Load the virtual table pointer into %edx.  */
-         if (ix86_fntype_regparm (TREE_TYPE (function)) > 2)
-           error ("virtual function `%D' cannot have more than two register parameters",
-                  function);
-         xops[0] = gen_rtx_MEM (Pmode, 
-                                gen_rtx_REG (Pmode, 0));
-         xops[1] = gen_rtx_REG (Pmode, 1);
-         output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
-         /* Adjust the this parameter.  */
-         xops[0] = gen_rtx_MEM (SImode, 
-                                plus_constant (gen_rtx_REG (Pmode, 1), 
-                                               vcall_index));
-         xops[1] = gen_rtx_REG (Pmode, 0);
-         output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
-         /* Put the this parameter back where it came from.  */
-         if (!REG_P (this_parm))
-           {
-             xops[0] = gen_rtx_REG (Pmode, 0);
-             xops[1] = ia32_this_parameter (function);
-             output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
-           }
+      /* Adjust the this parameter.  */
+      xops[0] = gen_rtx_MEM (Pmode, plus_constant (tmp, vcall_offset));
+      if (TARGET_64BIT && !memory_operand (xops[0], Pmode))
+       {
+         rtx tmp2 = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 3 /* R11 */);
+         xops[0] = GEN_INT (vcall_offset);
+         xops[1] = tmp2;
+         output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
+         xops[0] = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, tmp, tmp2));
        }
+      xops[1] = this_reg;
+      if (TARGET_64BIT)
+       output_asm_insn ("add{q}\t{%0, %1|%1, %0}", xops);
+      else
+       output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
+    }
 
-      if (flag_pic)
-       {
-         xops[0] = pic_offset_table_rtx;
-         xops[1] = gen_label_rtx ();
-         xops[2] = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME);
+  /* If necessary, drop THIS back to its stack slot.  */
+  if (this_reg && this_reg != this)
+    {
+      xops[0] = this_reg;
+      xops[1] = this;
+      output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
+    }
 
-         if (ix86_regparm > 2)
-           abort ();
-         output_asm_insn ("push{l}\t%0", xops);
-         output_asm_insn ("call\t%P1", xops);
-         ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1]));
-         output_asm_insn ("pop{l}\t%0", xops);
-         output_asm_insn
-           ("add{l}\t{%2+[.-%P1], %0|%0, OFFSET FLAT: %2+[.-%P1]}", xops);
-         xops[0] = gen_rtx_MEM (SImode, XEXP (DECL_RTL (function), 0));
-         output_asm_insn
-           ("mov{l}\t{%0@GOT(%%ebx), %%ecx|%%ecx, %0@GOT[%%ebx]}", xops);
-         asm_fprintf (file, "\tpop{l\t%%ebx|\t%%ebx}\n");
-         asm_fprintf (file, "\tjmp\t{*%%ecx|%%ecx}\n");
-       }
+  xops[0] = DECL_RTL (function);
+  if (TARGET_64BIT)
+    {
+      if (!flag_pic || (*targetm.binds_local_p) (function))
+       output_asm_insn ("jmp\t%P0", xops);
+      else
+       output_asm_insn ("jmp\t*%P0@GOTPCREL(%%rip)", xops);
+    }
+  else
+    {
+      if (!flag_pic || (*targetm.binds_local_p) (function))
+       output_asm_insn ("jmp\t%P0", xops);
       else
        {
-         fprintf (file, "\tjmp\t");
-         assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
-         fprintf (file, "\n");
+         tmp = gen_rtx_REG (SImode, 2 /* ECX */);
+         output_set_got (tmp);
+
+         xops[1] = tmp;
+         output_asm_insn ("mov{l}\t{%0@GOT(%1), %1|%1, %0@GOT[%1]}", xops);
+         output_asm_insn ("jmp\t{*}%1", xops);
        }
     }
 }
 
-static void
-x86_output_mi_thunk (file, thunk, delta, function)
-     FILE *file;
-     tree thunk;
-     HOST_WIDE_INT delta;
-     tree function;
-{
-  x86_output_mi_vcall_thunk (file, thunk, delta, /*vcall_index=*/0, 
-                            function);
-}
-
 int
 x86_field_alignment (field, computed)
      tree field;
index b15e27d9327d1fac0ee79a0effb60751172dee2e..102729e444b9b1b2ad7c56358cb52e43c0b4164b 100644 (file)
@@ -46,7 +46,8 @@ Boston, MA 02111-1307, USA.  */
 
 static void i960_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
 static void i960_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
-static void i960_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
+static void i960_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+                                         HOST_WIDE_INT, tree));
 
 /* Save the operands last given to a compare for use when we
    generate a scc or bcc insn.  */
@@ -101,6 +102,8 @@ static int ret_label = 0;
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK i960_output_mi_thunk
+#undef TARGET_CAN_ASM_OUTPUT_MI_THUNK
+#define TARGET_CAN_ASM_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
@@ -2830,10 +2833,11 @@ i960_scan_opcode (p)
 }
 
 static void
-i960_output_mi_thunk (file, thunk, delta, function)
+i960_output_mi_thunk (file, thunk, delta, vcall_offset, function)
      FILE *file;
      tree thunk ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree function;
 {
   int d = delta;
index 17c3fc61ac86a289a36ced2b5ba61c3e8ae85978..35db34b59864967367757b276710746402edfbdf 100644 (file)
@@ -161,7 +161,8 @@ static int ia64_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
 static int ia64_sched_reorder2 PARAMS ((FILE *, int, rtx *, int *, int));
 static int ia64_variable_issue PARAMS ((FILE *, int, rtx, int));
 
-static void ia64_output_mi_thunk PARAMS((FILE *, tree, HOST_WIDE_INT, tree));
+static void ia64_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+                                         HOST_WIDE_INT, tree));
 
 static void ia64_select_rtx_section PARAMS ((enum machine_mode, rtx,
                                             unsigned HOST_WIDE_INT));
@@ -248,6 +249,8 @@ static const struct attribute_spec ia64_attribute_table[] =
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK ia64_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
@@ -8165,10 +8168,11 @@ ia64_aix_select_rtx_section (mode, x, align)
 }
 
 static void
-ia64_output_mi_thunk (file, thunk, delta, function)
+ia64_output_mi_thunk (file, thunk, delta, vcall_offset, function)
      FILE *file;
      tree thunk ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree function;
 {
   if (CONST_OK_FOR_I (delta))                                          
index 9543e98f056576dc2dd7fbecfdb217bdf472750d..11654d6c6dc2572a3c965ed97b0694f9481b8a31 100644 (file)
@@ -65,7 +65,8 @@ static void m68k_coff_asm_named_section PARAMS ((const char *, unsigned int));
 #ifdef CTOR_LIST_BEGIN
 static void m68k_svr3_asm_out_constructor PARAMS ((rtx, int));
 #endif
-static void m68k_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
+static void m68k_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+                                         HOST_WIDE_INT, tree));
 \f
 
 /* Alignment to use for loops and jumps */
@@ -125,6 +126,8 @@ int m68k_last_compare_had_fp_operands;
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK m68k_output_mi_thunk
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
@@ -3841,10 +3844,11 @@ m68k_svr3_asm_out_constructor (symbol, priority)
 #endif
 
 static void
-m68k_output_mi_thunk (file, thunk, delta, function)
+m68k_output_mi_thunk (file, thunk, delta, vcall_offset, function)
      FILE *file;
      tree thunk ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree function;
 {
   rtx xops[1];
index 141ad2e56c30824a407905f1399c013192f0802b..0cc567d18a4071b51ab21d6f39108dbe70c3db5a 100644 (file)
@@ -131,7 +131,7 @@ static void mmix_target_asm_function_end_prologue PARAMS ((FILE *));
 static void mmix_target_asm_function_epilogue
   PARAMS ((FILE *, HOST_WIDE_INT));
 static void mmix_asm_output_mi_thunk
-  PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
+  PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
 
 
 /* Target structure macros.  Listed by node.  See `Using and Porting GCC'
@@ -166,6 +166,8 @@ static void mmix_asm_output_mi_thunk
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK mmix_asm_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -778,10 +780,11 @@ mmix_target_asm_function_epilogue (stream, locals_size)
 /* TARGET_ASM_OUTPUT_MI_THUNK.  */
 
 static void
-mmix_asm_output_mi_thunk (stream, fndecl, delta, func)
+mmix_asm_output_mi_thunk (stream, fndecl, delta, vcall_offset, func)
      FILE * stream;
      tree fndecl ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree func;
 {
   /* If you define STRUCT_VALUE to 0, rather than use STRUCT_VALUE_REGNUM,
index 48f4a38c5a27e2c73eaa64498e2b29c5f1a98ecf..58ba157fc24d65c43959c4a6ed16700d4c440a0b 100644 (file)
@@ -119,7 +119,8 @@ static void pa_encode_section_info PARAMS ((tree, int));
 static const char *pa_strip_name_encoding PARAMS ((const char *));
 static void pa_globalize_label PARAMS ((FILE *, const char *))
      ATTRIBUTE_UNUSED;
-static void pa_asm_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
+static void pa_asm_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+                                           HOST_WIDE_INT, tree));
 
 
 /* Save the operands last given to a compare for use when we
@@ -199,6 +200,8 @@ static size_t n_deferred_plabels = 0;
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK pa_asm_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
@@ -6556,10 +6559,11 @@ is_function_label_plus_const (op)
 /* Output assembly code for a thunk to FUNCTION.  */
 
 static void
-pa_asm_output_mi_thunk (file, thunk_fndecl, delta, function)
+pa_asm_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
      FILE *file;
      tree thunk_fndecl;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree function;
 {
   const char *target_name = XSTR (XEXP (DECL_RTL (function), 0), 0);
index 08540e37348c3f20dec9b9d47b297ed69572ab8a..d0431545364de5bd5b4ada786bd32c0f482b8497 100644 (file)
@@ -150,7 +150,6 @@ extern void setup_incoming_varargs PARAMS ((CUMULATIVE_ARGS *,
                                            enum machine_mode, tree,
                                            int *, int));
 extern struct rtx_def *rs6000_va_arg PARAMS ((tree, tree));
-extern void output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
 extern int function_ok_for_sibcall PARAMS ((tree));
 #ifdef ARGS_SIZE_RTX
 /* expr.h defines ARGS_SIZE_RTX and `enum direction' */
index cf930e9e0e5b6ff9bcdbaa8a541659cfc61ff008..4e625e825d6d13030305ee7c668e543f2fe92142 100644 (file)
@@ -194,6 +194,8 @@ const struct attribute_spec rs6000_attribute_table[];
 static void rs6000_set_default_type_attributes PARAMS ((tree));
 static void rs6000_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
 static void rs6000_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+static void rs6000_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+                                           HOST_WIDE_INT, tree));
 static rtx rs6000_emit_set_long_const PARAMS ((rtx,
   HOST_WIDE_INT, HOST_WIDE_INT));
 #if TARGET_ELF
@@ -311,6 +313,9 @@ static const char alt_reg_names[][8] =
 #ifndef MASK_STRICT_ALIGN
 #define MASK_STRICT_ALIGN 0
 #endif
+
+/* The VRSAVE bitmask puts bit %v0 as the most significant bit.  */
+#define ALTIVEC_REG_BIT(REGNO) (0x80000000 >> ((REGNO) - FIRST_ALTIVEC_REGNO))
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ATTRIBUTE_TABLE
@@ -373,8 +378,15 @@ static const char alt_reg_names[][8] =
 #undef TARGET_BINDS_LOCAL_P
 #define TARGET_BINDS_LOCAL_P rs6000_binds_local_p
 
-/* The VRSAVE bitmask puts bit %v0 as the most significant bit.  */
-#define ALTIVEC_REG_BIT(REGNO) (0x80000000 >> ((REGNO) - FIRST_ALTIVEC_REGNO))
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK rs6000_output_mi_thunk
+
+/* ??? Should work everywhere, but ask dje@watson.ibm.com before
+   enabling for AIX.  */
+#if TARGET_OBJECT_FORMAT != OBJECT_XCOFF
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+#endif
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
@@ -9463,7 +9475,11 @@ rs6000_ra_ever_killed ()
   rtx reg;
   rtx insn;
 
-  if (targetm.asm_out.output_mi_thunk && current_function_is_thunk)
+  /* Irritatingly, there are two kinds of thunks -- those created with
+     TARGET_ASM_OUTPUT_MI_THUNK and those with DECL_THUNK_P that go
+     through the regular part of the compiler.  This is a very hacky
+     way to tell them apart.  */
+  if (current_function_is_thunk && !no_new_pseudos)
     return 0;
 
   /* regs_ever_live has LR marked as used if any sibcalls are present,
@@ -11238,11 +11254,12 @@ rs6000_output_function_epilogue (file, size)
    calls FUNCTION instead of jumping to it.  The generic approach does
    not support varargs.  */
 
-void
-output_mi_thunk (file, thunk_fndecl, delta, function)
+static void
+rs6000_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
      FILE *file;
      tree thunk_fndecl ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree function;
 {
   const char *this_reg =
@@ -11348,10 +11365,7 @@ output_mi_thunk (file, thunk_fndecl, delta, function)
            }
          assemble_name (file, fname);
          putc ('\n', file);
-         if (TARGET_ELF)
-           function_section (current_function_decl);
-         else
-           text_section ();
+         function_section (current_function_decl);
          if (TARGET_MINIMAL_TOC)
            asm_fprintf (file, (TARGET_32BIT)
                         ? "\t{l|lwz} %s,%s(%s)\n" : "\tld %s,%s(%s)\n", r12,
@@ -11398,7 +11412,6 @@ output_mi_thunk (file, thunk_fndecl, delta, function)
        }
     }
 }
-
 \f
 /* A quick summary of the various types of 'constant-pool tables'
    under PowerPC:
index d393c8e653c88ab67b55f066392e1f5fe23e7308..4ea2c4f0d1cf7d695be6f62423f2bae9b0bd4bd2 100644 (file)
@@ -637,38 +637,6 @@ extern int rs6000_pic_labelno;
     ASM_OUTPUT_LABEL (FILE, NAME);                                     \
   } while (0)
 
-/* A C compound statement that outputs the assembler code for a thunk function,
-    used to implement C++ virtual function calls with multiple inheritance.  The
-    thunk acts as a wrapper around a virtual function, adjusting the implicit
-    object parameter before handing control off to the real function.
-
-    First, emit code to add the integer DELTA to the location that contains the
-    incoming first argument.  Assume that this argument contains a pointer, and
-    is the one used to pass the this' pointer in C++.  This is the incoming
-    argument *before* the function prologue, e.g. %o0' on a sparc.  The
-    addition must preserve the values of all other incoming arguments.
-
-    After the addition, emit code to jump to FUNCTION, which is a
-    FUNCTION_DECL'.  This is a direct pure jump, not a call, and does not touch
-    the return address.  Hence returning from FUNCTION will return to whoever
-    called the current thunk'.
-
-    The effect must be as if FUNCTION had been called directly with the adjusted
-    first argument.  This macro is responsible for emitting all of the code for
-    a thunk function; FUNCTION_PROLOGUE' and FUNCTION_EPILOGUE' are not
-    invoked.
-
-    The THUNK_FNDECL is redundant.  (DELTA and FUNCTION have already been
-    extracted from it.)  It might possibly be useful on some targets, but
-    probably not.
-
-    If you do not define this macro, the target-independent code in the C++
-    frontend will generate a less efficient heavyweight thunk that calls
-    FUNCTION instead of jumping to it.  The generic approach does not support
-    varargs.  */
-
-#define        TARGET_ASM_OUTPUT_MI_THUNK output_mi_thunk
-
 /* The USER_LABEL_PREFIX stuff is affected by the -fleading-underscore
    flag.  The LOCAL_LABEL_PREFIX variable is used by dbxelf.h.  */
 
index cad39819fff0e942372b473fc3ffe1d85b45b370..21d74a9e616df6608fb36de4bdc01cc086785dad 100644 (file)
@@ -296,7 +296,11 @@ toc_section ()                                             \
   putc ('.', FILE);                                            \
   RS6000_OUTPUT_BASENAME (FILE, NAME);                         \
   fputs (":\n", FILE);                                         \
-  if (write_symbols == XCOFF_DEBUG)                            \
+  if (write_symbols == XCOFF_DEBUG                             \
+      /* When called before targetm.asm_out.output_mi_thunk,   \
+        we won't be emitting the rest of the debug info that   \
+        goes along with this, leading to assembler errors.  */ \
+      && !(current_function_is_thunk && !no_new_pseudos))      \
     xcoffout_declare_function (FILE, DECL, NAME);              \
 }
 
index 4d4e325897b4f3c682be4f37fca476055d9b1eb5..39ea09c49d8094a6fe03f8e3f9561954ad81dfb5 100644 (file)
@@ -54,8 +54,8 @@ static int s390_adjust_priority PARAMS ((rtx, int));
 static void s390_select_rtx_section PARAMS ((enum machine_mode, rtx, 
                                             unsigned HOST_WIDE_INT));
 static void s390_encode_section_info PARAMS ((tree, int));
-static void s390_output_mi_vcall_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, 
-                                               HOST_WIDE_INT, tree));
+static void s390_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+                                         HOST_WIDE_INT, tree));
 
 #undef  TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
@@ -82,8 +82,10 @@ static void s390_output_mi_vcall_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
 #undef TARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO s390_encode_section_info
 
-#undef TARGET_ASM_OUTPUT_MI_VCALL_THUNK
-#define TARGET_ASM_OUTPUT_MI_VCALL_THUNK s390_output_mi_vcall_thunk
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK s390_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -5620,7 +5622,7 @@ s390_encode_section_info (decl, first)
    relative to the resulting this pointer.  */
 
 static void
-s390_output_mi_vcall_thunk (file, thunk, delta, vcall_offset, function)
+s390_output_mi_thunk (file, thunk, delta, vcall_offset, function)
      FILE *file;
      tree thunk ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
index 44fedc7b61c82d791a4f99873b1d8677652eb24b..9f608c352eb3185564a36ad000d8b6e6905a952f 100644 (file)
@@ -176,7 +176,8 @@ static void emit_soft_tfmode_cvt PARAMS ((enum rtx_code, rtx *));
 static void emit_hard_tfmode_operation PARAMS ((enum rtx_code, rtx *));
 
 static void sparc_encode_section_info PARAMS ((tree, int));
-static void sparc_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
+static void sparc_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+                                          HOST_WIDE_INT, tree));
 \f
 /* Option handling.  */
 
@@ -242,6 +243,8 @@ enum processor_type sparc_cpu;
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
@@ -8453,10 +8456,11 @@ sparc_encode_section_info (decl, first)
    Used for C++ multiple inheritance.  */
 
 static void
-sparc_output_mi_thunk (file, thunk_fndecl, delta, function)
+sparc_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
      FILE *file;
      tree thunk_fndecl ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree function;
 {
   rtx this, insn, funexp, delta_rtx, tmp;
index de0cc9037875a55f726e09bfa32684893cac026a..5c54155f6d9abe7414ac8b6185a59db6a7e14ce9 100644 (file)
@@ -51,7 +51,7 @@ static void xstormy16_asm_out_constructor PARAMS ((rtx, int));
 static void xstormy16_asm_out_destructor PARAMS ((rtx, int));
 static void xstormy16_encode_section_info PARAMS ((tree, int));
 static void xstormy16_asm_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
-                                                  tree));
+                                                  HOST_WIDE_INT, tree));
 
 /* Define the information needed to generate branch and scc insns.  This is
    stored from the compare operation.  */
@@ -1383,10 +1383,12 @@ xstormy16_function_value (valtype, func)
    probably not.  */
 
 static void
-xstormy16_asm_output_mi_thunk (file, thunk_fndecl, delta, function)
+xstormy16_asm_output_mi_thunk (file, thunk_fndecl, delta,
+                              vcall_offset, function)
      FILE *file;
      tree thunk_fndecl ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree function;
 {
   int regnum = FIRST_ARGUMENT_REGISTER;
@@ -2035,5 +2037,7 @@ xstormy16_handle_interrupt_attribute (node, name, args, flags, no_add_attrs)
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK xstormy16_asm_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
 
 struct gcc_target targetm = TARGET_INITIALIZER;
index 68723086f0878efaf7b684a743350ba9f0c59ed7..6e3a291c2287ba32b53b18b83e92b9fafea321c8 100644 (file)
@@ -36,7 +36,6 @@ extern int check_float_value PARAMS ((enum machine_mode, REAL_VALUE_TYPE *, int)
 
 #ifdef TREE_CODE
 extern void vms_check_external PARAMS ((tree, const char *, int));
-extern void vax_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
 #endif /* TREE_CODE */
 
 extern void vms_flush_pending_externals PARAMS ((FILE *));
index 43ad73cdece976f0b526f561b9c6022c11cd233e..7db62115683cd3a811f30a0457068a8b058b8dbc 100644 (file)
@@ -48,6 +48,8 @@ static void vms_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT));
 static void vms_encode_section_info PARAMS ((tree, int));
 static void vms_globalize_label PARAMS ((FILE *, const char *));
 #endif
+static void vax_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+                                        HOST_WIDE_INT, tree));
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
@@ -65,6 +67,11 @@ static void vms_globalize_label PARAMS ((FILE *, const char *));
 #define TARGET_ASM_GLOBALIZE_LABEL vms_globalize_label
 #endif
 
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK vax_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Set global variables as needed for the options enabled.  */
@@ -993,11 +1000,12 @@ reg_was_0_p (insn, op)
          && ! reg_set_between_p (op, XEXP (link, 0), insn));
 }
 
-void
-vax_output_mi_thunk (file, thunk, delta, function)
+static void
+vax_output_mi_thunk (file, thunk, delta, vcall_offset, function)
      FILE *file;
      tree thunk ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
      tree function;
 {
   fprintf (file, "\t.word 0x0ffc\n");                                  
index 44844867831c85edaa734cb8ff3c197ba4d1eaa2..47a0f034e69a195955b3467de077d3ae75c607e4 100644 (file)
@@ -1155,14 +1155,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10),   \
   sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
 
-/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
-   Used for C++ multiple inheritance.
-       .mask   ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>     #conservative entry mask
-       addl2   $DELTA, 4(ap)   #adjust first argument
-       jmp     FUNCTION+2      #jump beyond FUNCTION's entry mask
- */
-#define ASM_OUTPUT_MI_THUNK vax_output_mi_thunk
-
 /* Print an instruction operand X on file FILE.
    CODE is the code from the %-spec that requested printing this operand;
    if `%z3' was used to print operand 3, then CODE is 'z'.
index ed176188426ceef7fa29f392cdb77f2a3f4b1ce1..6f73ad911d113cdb2ce3a966983ea6916f3eb35c 100644 (file)
@@ -1,3 +1,9 @@
+2002-10-22  Richard Henderson  <rth@redhat.com>
+
+       * method.c (use_thunk): Always compute vcall_value; assert that
+       it is not zero.  Use can_output_mi_thunk; use output_mi_thunk
+       for vcall thunks as well.
+
 2002-10-21  Mark Mitchell  <mark@codesourcery.com>
 
        * class.c (empty_base_at_nonzero_offset_p): New function.
index cb88833ab23e42bb4efcd27afebe0facc2d413e1..60a0dced61173f8dfef395c35cb94ef23b497b2c 100644 (file)
@@ -361,7 +361,7 @@ use_thunk (thunk_fndecl, emit_p)
   tree fnaddr;
   tree function;
   tree vcall_offset;
-  HOST_WIDE_INT delta;
+  HOST_WIDE_INT delta, vcall_value;
 
   if (TREE_ASM_WRITTEN (thunk_fndecl))
     return;
@@ -387,6 +387,17 @@ use_thunk (thunk_fndecl, emit_p)
   delta = THUNK_DELTA (thunk_fndecl);
   vcall_offset = THUNK_VCALL_OFFSET (thunk_fndecl);
 
+  if (vcall_offset)
+    {
+      vcall_value = tree_low_cst (vcall_offset, /*pos=*/0);
+
+      /* It is expected that a value of zero means no vcall.  */
+      if (!vcall_value)
+       abort ();
+    }
+  else
+    vcall_value = 0;
+
   /* And, if we need to emit the thunk, it's used.  */
   mark_used (thunk_fndecl);
   /* This thunk is actually defined.  */
@@ -409,8 +420,8 @@ use_thunk (thunk_fndecl, emit_p)
   BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) 
     = DECL_ARGUMENTS (thunk_fndecl);
 
-  if (targetm.asm_out.output_mi_vcall_thunk
-      || (targetm.asm_out.output_mi_thunk && !vcall_offset))
+  if (targetm.asm_out.can_output_mi_thunk (thunk_fndecl, delta,
+                                          vcall_value, function))
     {
       const char *fnname;
       current_function_decl = thunk_fndecl;
@@ -420,22 +431,10 @@ use_thunk (thunk_fndecl, emit_p)
       init_function_start (thunk_fndecl, input_filename, lineno);
       current_function_is_thunk = 1;
       assemble_start_function (thunk_fndecl, fnname);
-      if (targetm.asm_out.output_mi_vcall_thunk)
-       {
-         HOST_WIDE_INT vcall_value;
 
-         if (vcall_offset)
-           vcall_value = tree_low_cst (vcall_offset, /*pos=*/0);
-         else
-           vcall_value = 0;
-         targetm.asm_out.output_mi_vcall_thunk (asm_out_file, 
-                                                thunk_fndecl, delta, 
-                                                vcall_value,
-                                                function);
-       }
-      else
-       targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, 
-                                        delta, function);
+      targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, delta,
+                                      vcall_value, function);
+
       assemble_end_function (thunk_fndecl, fnname);
       current_function_decl = 0;
       cfun = 0;
index 0eb0e149ec6bd4ba2ed856de3bcdbb5bfaf7418d..977a3f1ce7e28f29c6b1884eb59134e3858b68c1 100644 (file)
@@ -62,3 +62,34 @@ hook_FILEptr_constcharptr_void (a, b)
      const char *b ATTRIBUTE_UNUSED;
 {
 }
+
+/* Used for the TARGET_ASM_CAN_OUTPUT_MI_THUNK hook.  */
+bool
+hook_bool_tree_hwi_hwi_tree_false (a, b, c, d)
+     tree a ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT b ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT c ATTRIBUTE_UNUSED;
+     tree d ATTRIBUTE_UNUSED;
+{
+  return false;
+}
+
+bool
+hook_bool_tree_hwi_hwi_tree_true (a, b, c, d)
+     tree a ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT b ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT c ATTRIBUTE_UNUSED;
+     tree d ATTRIBUTE_UNUSED;
+{
+  return true;
+}
+
+bool
+default_can_output_mi_thunk_no_vcall (a, b, c, d)
+     tree a ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT b ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT c;
+     tree d ATTRIBUTE_UNUSED;
+{
+  return c == 0;
+}
index 4b80c321ef8ee1c1f4a679073cf541ac2ff6261c..34af50c6da2451e0deb416784f8b59d42b581b00 100644 (file)
@@ -27,5 +27,12 @@ bool hook_tree_bool_false PARAMS ((tree));
 void hook_tree_int_void PARAMS ((tree, int));
 void hook_void_void PARAMS ((void));
 void hook_FILEptr_constcharptr_void PARAMS ((FILE *, const char *));
+bool hook_bool_tree_hwi_hwi_tree_false
+  PARAMS ((tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
+bool hook_bool_tree_hwi_hwi_tree_true
+  PARAMS ((tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
+
+bool default_can_output_mi_thunk_no_vcall
+  PARAMS ((tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
 
 #endif
index 260232f9b99c9ed7759cde8083c75adb90ab0092..5adbd32b9c6010ce0486ebeb7321cbb2eb7adc47 100644 (file)
@@ -599,7 +599,8 @@ typedef char _Bool;
        MD_INIT_BUILTINS MD_EXPAND_BUILTIN ASM_OUTPUT_CONSTRUCTOR       \
        ASM_OUTPUT_DESTRUCTOR SIGNED_CHAR_SPEC MAX_CHAR_TYPE_SIZE       \
        WCHAR_UNSIGNED UNIQUE_SECTION SELECT_SECTION SELECT_RTX_SECTION \
-       ENCODE_SECTION_INFO STRIP_NAME_ENCODING ASM_GLOBALIZE_LABEL
+       ENCODE_SECTION_INFO STRIP_NAME_ENCODING ASM_GLOBALIZE_LABEL     \
+       ASM_OUTPUT_MI_THUNK
 
 /* Other obsolete target macros, or macros that used to be in target
    headers and were not used, and may be obsolete or may never have
index b5a0345fdd3d0a528d1bcbb070af29edc238ce4b..46bc4a250c7912ba2b820bf1008e82df51d34103 100644 (file)
@@ -103,13 +103,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 # endif
 #endif
 
-#ifndef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK NULL
-#endif
-
-#ifndef TARGET_ASM_OUTPUT_MI_VCALL_THUNK
-#define TARGET_ASM_OUTPUT_MI_VCALL_THUNK NULL
-#endif
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_false
 
 #if defined(TARGET_ASM_CONSTRUCTOR) && defined(TARGET_ASM_DESTRUCTOR)
 #define TARGET_HAVE_CTORS_DTORS true
@@ -183,7 +178,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
                        TARGET_ASM_CONSTRUCTOR,                 \
                        TARGET_ASM_DESTRUCTOR,                  \
                         TARGET_ASM_OUTPUT_MI_THUNK,             \
-                        TARGET_ASM_OUTPUT_MI_VCALL_THUNK }
+                        TARGET_ASM_CAN_OUTPUT_MI_THUNK }
 
 /* Scheduler hooks.  All of these default to null pointers, which
    haifa-sched.c looks for and handles.  */
index eb674c943f1f2af49ca213319524ff9ec9400872..44e64a9903ac599e8fc3224d2671c0bea368c912 100644 (file)
@@ -120,12 +120,26 @@ struct gcc_target
     /* Output a destructor for a symbol with a given priority.  */
     void (* destructor) PARAMS ((rtx, int));
 
-    /* Output the assembler code for a thunk function.  */
-    void (* output_mi_thunk) PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
-
-    /* Output the assembler code for a thunk function with a vcall offset.  */
-    void (* output_mi_vcall_thunk) PARAMS ((FILE *, tree, HOST_WIDE_INT,
-                                           HOST_WIDE_INT, tree));
+    /* Output the assembler code for a thunk function.  THUNK_DECL is the
+       declaration for the thunk function itself, FUNCTION is the decl for
+       the target function.  DELTA is an immediate constant offset to be
+       added to THIS.  If VCALL_OFFSET is non-zero, the word at
+       *(*this + vcall_offset) should be added to THIS.  */
+    void (* output_mi_thunk) PARAMS ((FILE *file, tree thunk_decl,
+                                     HOST_WIDE_INT delta,
+                                     HOST_WIDE_INT vcall_offset,
+                                     tree function_decl));
+
+    /* Determine whether output_mi_thunk would succeed.  */
+    /* ??? Ideally, this hook would not exist, and success or failure
+       would be returned from output_mi_thunk directly.  But there's
+       too much undo-able setup involved in invoking output_mi_thunk.
+       Could be fixed by making output_mi_thunk emit rtl instead of
+       text to the output file.  */
+    bool (* can_output_mi_thunk) PARAMS ((tree thunk_decl,
+                                         HOST_WIDE_INT delta,
+                                         HOST_WIDE_INT vcall_offset,
+                                         tree function_decl));
   } asm_out;
 
   /* Functions relating to instruction scheduling.  */