This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [mn10300] return-in-a0-d0 ABI helper
> This situation is precisely why we support PARALLELs for return
> values (the need to return a value in multiple registers).
>
> It ought to "just work".
It just didn't.
../../gcc/gcc/testsuite/gcc.c-torture/compile/20000804-1.c:16: error: unrecognizable insn:
(insn 77 90 82 7 (set (parallel/i:SI [
(expr_list:REG_DEP_TRUE (reg:SI 4 a0)
(const_int 0 [0x0]))
(expr_list:REG_DEP_TRUE (reg:SI 0 d0)
(const_int 0 [0x0]))
])
(reg/f:SI 71 [ D.1210 ])) -1 (nil)
(nil))
If I manually try all the permutations of caller/callee/int/pointer,
they all work, and the code looks reasonable. Relevent portions of
the patch attached - see any obvious mistakes in it?
+/* Return the location of the function's value. This will be either
+ $d0 for integer functions, $a0 for pointers, or a PARALLEL of both
+ $d0 and $a0 if the -mreturn-pointer-on-do flag is set. Note that
+ we only return the PARALLEL for outgoing values; we do not want
+ callers relying on this extra copy. */
+
+rtx
+mn10300_function_value (tree valtype, tree func, int outgoing)
+{
+ rtx rv;
+ enum machine_mode mode = TYPE_MODE (valtype);
+
+ if (! POINTER_TYPE_P (valtype))
+ return gen_rtx_REG (mode, FIRST_DATA_REGNUM);
+ else if (! TARGET_PTR_A0D0 || ! outgoing)
+ return gen_rtx_REG (mode, FIRST_ADDRESS_REGNUM);
+
+ rv = gen_rtx_PARALLEL (mode, rtvec_alloc (2));
+ XVECEXP (rv, 0, 0)
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (mode, FIRST_ADDRESS_REGNUM),
+ GEN_INT (0));
+
+ XVECEXP (rv, 0, 1)
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (mode, FIRST_DATA_REGNUM),
+ GEN_INT (0));
+ return rv;
+}
#define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx_REG (TYPE_MODE (VALTYPE), POINTER_TYPE_P (VALTYPE) \
- ? FIRST_ADDRESS_REGNUM : FIRST_DATA_REGNUM)
+ mn10300_function_value (VALTYPE, FUNC, 0)
+#define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) \
+ mn10300_function_value (VALTYPE, FUNC, 1)