Hello, this patch fixes the long-standing failure: FAIL: g++.old-deja/g++.jason/thunk3.C (test for excess errors) by providing a TARGET_ASM_OUTPUT_MI_THUNK implementation for SPU.
Tested on spu-elf, committed to mainline. Bye, Ulrich ChangeLog: * config/spu/spu.c (TARGET_ASM_OUTPUT_MI_THUNK): Define. (TARGET_ASM_CAN_OUTPUT_MI_THUNK): Likewise. (spu_output_mi_thunk): New function. Index: gcc/config/spu/spu.c =================================================================== *** gcc/config/spu/spu.c (revision 169938) --- gcc/config/spu/spu.c (working copy) *************** static rtx spu_expand_load (rtx, rtx, rt *** 231,236 **** --- 231,238 ---- static void spu_trampoline_init (rtx, tree, rtx); static void spu_conditional_register_usage (void); static bool spu_ref_may_alias_errno (ao_ref *); + static void spu_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, + HOST_WIDE_INT, tree); /* Which instruction set architecture to use. */ int spu_arch; *************** static const struct attribute_spec spu_a *** 495,500 **** --- 497,507 ---- #undef TARGET_REF_MAY_ALIAS_ERRNO #define TARGET_REF_MAY_ALIAS_ERRNO spu_ref_may_alias_errno + #undef TARGET_ASM_OUTPUT_MI_THUNK + #define TARGET_ASM_OUTPUT_MI_THUNK spu_output_mi_thunk + #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK + #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true + struct gcc_target targetm = TARGET_INITIALIZER; static void *************** spu_ref_may_alias_errno (ao_ref *ref) *** 7191,7194 **** --- 7198,7287 ---- return default_ref_may_alias_errno (ref); } + /* Output thunk to FILE that implements a C++ virtual function call (with + multiple inheritance) to FUNCTION. The thunk adjusts the this pointer + by DELTA, and unless VCALL_OFFSET is zero, applies an additional adjustment + stored at VCALL_OFFSET in the vtable whose address is located at offset 0 + relative to the resulting this pointer. */ + + static void + spu_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, + HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, + tree function) + { + rtx op[8]; + + /* Make sure unwind info is emitted for the thunk if needed. */ + final_start_function (emit_barrier (), file, 1); + + /* Operand 0 is the target function. */ + op[0] = XEXP (DECL_RTL (function), 0); + + /* Operand 1 is the 'this' pointer. */ + if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) + op[1] = gen_rtx_REG (Pmode, FIRST_ARG_REGNUM + 1); + else + op[1] = gen_rtx_REG (Pmode, FIRST_ARG_REGNUM); + + /* Operands 2/3 are the low/high halfwords of delta. */ + op[2] = GEN_INT (trunc_int_for_mode (delta, HImode)); + op[3] = GEN_INT (trunc_int_for_mode (delta >> 16, HImode)); + + /* Operands 4/5 are the low/high halfwords of vcall_offset. */ + op[4] = GEN_INT (trunc_int_for_mode (vcall_offset, HImode)); + op[5] = GEN_INT (trunc_int_for_mode (vcall_offset >> 16, HImode)); + + /* Operands 6/7 are temporary registers. */ + op[6] = gen_rtx_REG (Pmode, 79); + op[7] = gen_rtx_REG (Pmode, 78); + + /* Add DELTA to this pointer. */ + if (delta) + { + if (delta >= -0x200 && delta < 0x200) + output_asm_insn ("ai\t%1,%1,%2", op); + else if (delta >= -0x8000 && delta < 0x8000) + { + output_asm_insn ("il\t%6,%2", op); + output_asm_insn ("a\t%1,%1,%6", op); + } + else + { + output_asm_insn ("ilhu\t%6,%3", op); + output_asm_insn ("iohl\t%6,%2", op); + output_asm_insn ("a\t%1,%1,%6", op); + } + } + + /* Perform vcall adjustment. */ + if (vcall_offset) + { + output_asm_insn ("lqd\t%7,0(%1)", op); + output_asm_insn ("rotqby\t%7,%7,%1", op); + + if (vcall_offset >= -0x200 && vcall_offset < 0x200) + output_asm_insn ("ai\t%7,%7,%4", op); + else if (vcall_offset >= -0x8000 && vcall_offset < 0x8000) + { + output_asm_insn ("il\t%6,%4", op); + output_asm_insn ("a\t%7,%7,%6", op); + } + else + { + output_asm_insn ("ilhu\t%6,%5", op); + output_asm_insn ("iohl\t%6,%4", op); + output_asm_insn ("a\t%7,%7,%6", op); + } + + output_asm_insn ("lqd\t%6,0(%7)", op); + output_asm_insn ("rotqby\t%6,%6,%7", op); + output_asm_insn ("a\t%1,%1,%6", op); + } + + /* Jump to target. */ + output_asm_insn ("br\t%0", op); + + final_end_function (); + } + #include "gt-spu.h" -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE ulrich.weig...@de.ibm.com