From eb344f43ef3115df9af589b4f2cac36f5de42bd7 Mon Sep 17 00:00:00 2001 From: rth Date: Tue, 22 Oct 2002 23:05:28 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@58424 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 51 ++++++++ gcc/config/alpha/alpha.c | 7 +- gcc/config/arm/arm.c | 6 +- gcc/config/cris/cris.c | 7 +- gcc/config/frv/frv.c | 8 +- gcc/config/i386/i386.c | 237 ++++++++++++++++++++++---------------- gcc/config/i960/i960.c | 8 +- gcc/config/ia64/ia64.c | 8 +- gcc/config/m68k/m68k.c | 8 +- gcc/config/mmix/mmix.c | 7 +- gcc/config/pa/pa.c | 8 +- gcc/config/rs6000/rs6000-protos.h | 1 - gcc/config/rs6000/rs6000.c | 33 ++++-- gcc/config/rs6000/sysv4.h | 32 ----- gcc/config/rs6000/xcoff.h | 6 +- gcc/config/s390/s390.c | 12 +- gcc/config/sparc/sparc.c | 8 +- gcc/config/stormy16/stormy16.c | 8 +- gcc/config/vax/vax-protos.h | 1 - gcc/config/vax/vax.c | 12 +- gcc/config/vax/vax.h | 8 -- gcc/cp/ChangeLog | 6 + gcc/cp/method.c | 35 +++--- gcc/hooks.c | 31 +++++ gcc/hooks.h | 7 ++ gcc/system.h | 3 +- gcc/target-def.h | 9 +- gcc/target.h | 26 ++++- 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 + + * 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 * 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 #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 + + * 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 * 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. */ -- 2.7.4