diff options
author | Carlos O'Donell <carlos@codesourcery.com> | 2006-04-04 16:19:59 +0000 |
---|---|---|
committer | Carlos O'Donell <carlos@gcc.gnu.org> | 2006-04-04 16:19:59 +0000 |
commit | 2225b57c2884d2e674ccd5ad972a10a7c1316ec9 (patch) | |
tree | 320de322098272075404c4d8bf933e1c2b3bfa03 /gcc/config | |
parent | 41ed243ff0f5c098b930eb3fcc333077b346348a (diff) | |
download | gcc-2225b57c2884d2e674ccd5ad972a10a7c1316ec9.zip gcc-2225b57c2884d2e674ccd5ad972a10a7c1316ec9.tar.gz gcc-2225b57c2884d2e674ccd5ad972a10a7c1316ec9.tar.bz2 |
tm.texi (TARGET_STRUCT_VALUE_RTX): Document new value 2 for incoming.
gcc/
2006-04-04 Carlos O'Donell <carlos@codesourcery.com>
* doc/tm.texi (TARGET_STRUCT_VALUE_RTX): Document
new value 2 for incoming.
* function.c (expand_function_start): Call struct_value_rtx
with incoming as 2.
* config/sparc/sparc.md: Comment updated_return.
* config/sparc/sparc.opt: Add -mstd-struct-return option.
* config/sparc/sparc.c (sparc_struct_value_rtx): Use standard
struct return if sparc_std_struct_return and incoming is 2.
(print_operand): Do not adjust return if
sparc_std_struct_return.
gcc/testsuite/
2006-04-04 Carlos O'Donell <carlos@codesourcery.com>
* gcc.target/sparc/struct-ret-check.c: New test.
From-SVN: r112672
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/sparc/sparc.c | 49 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.md | 9 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.opt | 3 |
3 files changed, 57 insertions, 4 deletions
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 709a92b..e880226 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -5425,7 +5425,7 @@ sparc_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED) Return where to find the structure return value address. */ static rtx -sparc_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED, int incoming) +sparc_struct_value_rtx (tree fndecl, int incoming) { if (TARGET_ARCH64) return 0; @@ -5440,6 +5440,46 @@ sparc_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED, int incoming) mem = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, STRUCT_VALUE_OFFSET)); + /* Only follow the SPARC ABI for fixed-size structure returns. + Variable size structure returns are handled per the normal + procedures in GCC. This is enabled by -mstd-struct-return */ + if (incoming == 2 + && sparc_std_struct_return + && TYPE_SIZE_UNIT (TREE_TYPE (fndecl)) + && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (fndecl))) == INTEGER_CST) + { + /* We must check and adjust the return address, as it is + optional as to whether the return object is really + provided. */ + rtx ret_rtx = gen_rtx_REG (Pmode, 31); + rtx scratch = gen_reg_rtx (SImode); + rtx endlab = gen_label_rtx (); + + /* Calculate the return object size */ + tree size = TYPE_SIZE_UNIT (TREE_TYPE (fndecl)); + rtx size_rtx = GEN_INT (TREE_INT_CST_LOW (size) & 0xfff); + /* Construct a temporary return value */ + rtx temp_val = assign_stack_local (Pmode, TREE_INT_CST_LOW (size), 0); + + /* Implement SPARC 32-bit psABI callee returns struck checking + requirements: + + Fetch the instruction where we will return to and see if + it's an unimp instruction (the most significant 10 bits + will be zero). */ + emit_move_insn (scratch, gen_rtx_MEM (SImode, + plus_constant (ret_rtx, 8))); + /* Assume the size is valid and pre-adjust */ + emit_insn (gen_add3_insn (ret_rtx, ret_rtx, GEN_INT (4))); + emit_cmp_and_jump_insns (scratch, size_rtx, EQ, const0_rtx, SImode, 0, endlab); + emit_insn (gen_sub3_insn (ret_rtx, ret_rtx, GEN_INT (4))); + /* Assign stack temp: + Write the address of the memory pointed to by temp_val into + the memory pointed to by mem */ + emit_move_insn (mem, XEXP (temp_val, 0)); + emit_label (endlab); + } + set_mem_alias_set (mem, struct_value_alias_set); return mem; } @@ -6639,9 +6679,14 @@ print_operand (FILE *file, rtx x, int code) so we have to account for it. 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. */ + as that used on the call. The exception here is that when + sparc_std_struct_return is enabled, the psABI is followed exactly + and the adjustment is made by the code in sparc_struct_value_rtx. + The call emitted is the same when sparc_std_struct_return is + present. */ if (! TARGET_ARCH64 && current_function_returns_struct + && ! sparc_std_struct_return && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl))) == INTEGER_CST) && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl)))) diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index b6ebb82..ed68f1e 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -7094,8 +7094,13 @@ DONE; }) -;; This is a bit of a hack. We're incrementing a fixed register (%i7), -;; and parts of the compiler don't want to believe that the add is needed. +;; Adjust the return address conditionally. If the value of op1 is equal +;; to all zero then adjust the return address i.e. op0 = op0 + 4. +;; This is technically *half* the check required by the 32-bit SPARC +;; psABI. This check only ensures that an "unimp" insn was written by +;; the caller, but doesn't check to see if the expected size matches +;; (this is encoded in the 12 lower bits). This check is obsolete and +;; only used by the above code "untyped_return". (define_insn "update_return" [(unspec:SI [(match_operand:SI 0 "register_operand" "r") diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt index da50e1a..8cdf11c 100644 --- a/gcc/config/sparc/sparc.opt +++ b/gcc/config/sparc/sparc.opt @@ -99,6 +99,9 @@ mcmodel= Target RejectNegative Joined Var(sparc_cmodel_string) Use given SPARC-V9 code model +mstd-struct-return +Target Report RejectNegative Var(sparc_std_struct_return) +Enable strict 32-bit psABI struct return checking. Mask(LITTLE_ENDIAN) ;; Generate code for little-endian |