aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-10-22 16:05:28 -0700
committerRichard Henderson <rth@gcc.gnu.org>2002-10-22 16:05:28 -0700
commit3961e8fe9e9c8e3f6b07b38b88e12943c817e75c (patch)
tree47bcdb93a39b44ac06fdc677f9265a5d43739759 /gcc
parent0e67d46049a58b11d577736056157cc003c0f1d8 (diff)
downloadgcc-3961e8fe9e9c8e3f6b07b38b88e12943c817e75c.zip
gcc-3961e8fe9e9c8e3f6b07b38b88e12943c817e75c.tar.gz
gcc-3961e8fe9e9c8e3f6b07b38b88e12943c817e75c.tar.bz2
target.h (gcc_target.asm_out): Merge output_mi_thunk and output_mi_vcall_thunk into a single hook.
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog51
-rw-r--r--gcc/config/alpha/alpha.c7
-rw-r--r--gcc/config/arm/arm.c6
-rw-r--r--gcc/config/cris/cris.c7
-rw-r--r--gcc/config/frv/frv.c8
-rw-r--r--gcc/config/i386/i386.c237
-rw-r--r--gcc/config/i960/i960.c8
-rw-r--r--gcc/config/ia64/ia64.c8
-rw-r--r--gcc/config/m68k/m68k.c8
-rw-r--r--gcc/config/mmix/mmix.c7
-rw-r--r--gcc/config/pa/pa.c8
-rw-r--r--gcc/config/rs6000/rs6000-protos.h1
-rw-r--r--gcc/config/rs6000/rs6000.c33
-rw-r--r--gcc/config/rs6000/sysv4.h32
-rw-r--r--gcc/config/rs6000/xcoff.h6
-rw-r--r--gcc/config/s390/s390.c12
-rw-r--r--gcc/config/sparc/sparc.c8
-rw-r--r--gcc/config/stormy16/stormy16.c8
-rw-r--r--gcc/config/vax/vax-protos.h1
-rw-r--r--gcc/config/vax/vax.c12
-rw-r--r--gcc/config/vax/vax.h8
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/method.c35
-rw-r--r--gcc/hooks.c31
-rw-r--r--gcc/hooks.h7
-rw-r--r--gcc/system.h3
-rw-r--r--gcc/target-def.h9
-rw-r--r--gcc/target.h26
28 files changed, 378 insertions, 215 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c1f445a..31d30a7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 8f900af..5555aae 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -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;
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index d6c1a02..b06cb9b 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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;
@@ -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;
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 3d33a72..2eb864f 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -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)
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 7ef2e1a..d09533a 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -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));
/* 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;
@@ -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);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index efce0f3..f3d5acc 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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;
@@ -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;
}
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;
diff --git a/gcc/config/i960/i960.c b/gcc/config/i960/i960.c
index b15e27d..102729e 100644
--- a/gcc/config/i960/i960.c
+++ b/gcc/config/i960/i960.c
@@ -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;
@@ -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;
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 17c3fc6..35db34b 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -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;
@@ -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))
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 9543e98..11654d6 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -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));
/* 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;
@@ -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];
diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c
index 141ad2e..0cc567d 100644
--- a/gcc/config/mmix/mmix.c
+++ b/gcc/config/mmix/mmix.c
@@ -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,
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 48f4a38..58ba157 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -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;
@@ -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);
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 08540e3..d043154 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -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' */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index cf930e9..4e625e8 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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))
/* 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;
@@ -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)
}
}
}
-
/* A quick summary of the various types of 'constant-pool tables'
under PowerPC:
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index d393c8e..4ea2c4f 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -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. */
diff --git a/gcc/config/rs6000/xcoff.h b/gcc/config/rs6000/xcoff.h
index cad3981..21d74a9e 100644
--- a/gcc/config/rs6000/xcoff.h
+++ b/gcc/config/rs6000/xcoff.h
@@ -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); \
}
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 4d4e325..39ea09c 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -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;
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 44fedc7..9f608c3 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -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));
/* 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;
@@ -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;
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index de0cc90..5c54155 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -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;
diff --git a/gcc/config/vax/vax-protos.h b/gcc/config/vax/vax-protos.h
index 6872308..6e3a291 100644
--- a/gcc/config/vax/vax-protos.h
+++ b/gcc/config/vax/vax-protos.h
@@ -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 *));
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index 43ad73c..7db6211 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -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));
/* 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;
/* 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");
diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h
index 4484486..47a0f03 100644
--- a/gcc/config/vax/vax.h
+++ b/gcc/config/vax/vax.h
@@ -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'.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ed17618..6f73ad9 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index cb88833..60a0dce 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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;
diff --git a/gcc/hooks.c b/gcc/hooks.c
index 0eb0e14..977a3f1 100644
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -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;
+}
diff --git a/gcc/hooks.h b/gcc/hooks.h
index 4b80c32..34af50c 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -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
diff --git a/gcc/system.h b/gcc/system.h
index 260232f..5adbd32 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -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
diff --git a/gcc/target-def.h b/gcc/target-def.h
index b5a0345..46bc4a2 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -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. */
diff --git a/gcc/target.h b/gcc/target.h
index eb674c9..44e64a9 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -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. */