From: Eric Botcazou Date: Mon, 7 Jun 2004 20:58:33 +0000 (+0200) Subject: re PR target/15783 (ICE with union assignment in 64-bit mode) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=85bbb21f8f810152bf51558180f7c6520aca6571;p=gcc.git re PR target/15783 (ICE with union assignment in 64-bit mode) PR target/15783 * config/sparc/sparc.c (function_arg_union_value): Add 'mode' parameter. Enumerate the registers inside the PARALLEL. (function_arg): Adjust call to function_arg_union_value. (function_value): Likewise. From-SVN: r82722 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a119116e04b..0be308243f8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2004-06-07 Eric Botcazou + + PR target/15783 + * config/sparc/sparc.c (function_arg_union_value): Add 'mode' + parameter. Enumerate the registers inside the PARALLEL. + (function_arg): Adjust call to function_arg_union_value. + (function_value): Likewise. + + * config/sparc/sparc.c (sparc_function_epilogue): Properly format. + 2004-06-07 Roger Sayle * real.c (real_copysign): New function to implement libm's copysign. diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 30fbb878b66..0d197271456 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -4514,12 +4514,12 @@ sparc_function_epilogue (FILE *file, This insn is used in the 32-bit ABI when calling a function that returns a non zero-sized structure. The 64-bit ABI doesn't have it. Be careful to have this test be the same as that used on the call. */ - sparc_skip_caller_unimp = - ! TARGET_ARCH64 - && current_function_returns_struct - && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl))) - == INTEGER_CST) - && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl))); + sparc_skip_caller_unimp + = ! TARGET_ARCH64 + && current_function_returns_struct + && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl))) + == INTEGER_CST) + && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl))); if (current_function_epilogue_delay_list == 0) { @@ -5129,7 +5129,7 @@ static void function_arg_record_value_2 static void function_arg_record_value_1 (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *, bool); static rtx function_arg_record_value (tree, enum machine_mode, int, int, int); -static rtx function_arg_union_value (int, int); +static rtx function_arg_union_value (int, enum machine_mode, int); /* A subroutine of function_arg_record_value. Traverse the structure recursively and determine how many registers will be required. */ @@ -5471,26 +5471,25 @@ function_arg_record_value (tree type, enum machine_mode mode, FUNCTION_ARG and FUNCTION_VALUE. SIZE is the size in bytes of the union. + MODE is the argument's machine mode. REGNO is the hard register the union will be passed in. */ static rtx -function_arg_union_value (int size, int regno) +function_arg_union_value (int size, enum machine_mode mode, int regno) { - enum machine_mode mode; - rtx reg; + int nwords = ROUND_ADVANCE (size), i; + rtx regs; - if (size <= UNITS_PER_WORD) - mode = word_mode; - else - mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0); + /* Unions are passed left-justified. */ + regs = gen_rtx_PARALLEL (mode, rtvec_alloc (nwords)); - reg = gen_rtx_REG (mode, regno); + for (i = 0; i < nwords; i++) + XVECEXP (regs, 0, i) + = gen_rtx_EXPR_LIST (VOIDmode, + gen_rtx_REG (word_mode, regno + i), + GEN_INT (UNITS_PER_WORD * i)); - /* Unions are passed left-justified. */ - return gen_rtx_PARALLEL (mode, - gen_rtvec (1, gen_rtx_EXPR_LIST (VOIDmode, - reg, - const0_rtx))); + return regs; } /* Handle the FUNCTION_ARG macro. @@ -5547,7 +5546,7 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode, if (size > 16) abort (); /* shouldn't get here */ - return function_arg_union_value (size, regno); + return function_arg_union_value (size, mode, regno); } /* v9 fp args in reg slots beyond the int reg slots get passed in regs but also have the slot allocated for them. @@ -5872,7 +5871,7 @@ function_value (tree type, enum machine_mode mode, int incoming_p) if (size > 32) abort (); /* shouldn't get here */ - return function_arg_union_value (size, regbase); + return function_arg_union_value (size, mode, regbase); } else if (AGGREGATE_TYPE_P (type)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 35bf511e71d..055cd69bf8e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-06-07 Eric Botcazou + + * gcc.dg/union-1.c: New test. + 2004-06-07 Roger Sayle * gcc.dg/builtins-41.c: New test case. @@ -22718,3 +22722,4 @@ rlsruhe.de> correspond to c-torture 1.11. * New file. + diff --git a/gcc/testsuite/gcc.dg/union-1.c b/gcc/testsuite/gcc.dg/union-1.c new file mode 100644 index 00000000000..0dd2df9b064 --- /dev/null +++ b/gcc/testsuite/gcc.dg/union-1.c @@ -0,0 +1,22 @@ +/* PR target/15783 */ +/* Origin: Paul Pluzhnikov */ + +/* This used to ICE on SPARC 64-bit because the back-end was + returning an invalid construct for the return value of fu2. */ + +/* { dg-do compile } */ + +union u2 { + struct + { + int u2s_a, u2s_b, u2s_c, u2s_d, u2s_e; + } u2_s; + double u2_d; +} u2a; + +union u2 fu2(); + +void unions() +{ + u2a = fu2(); +}