aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorCarlos O'Donell <carlos@codesourcery.com>2006-04-04 16:19:59 +0000
committerCarlos O'Donell <carlos@gcc.gnu.org>2006-04-04 16:19:59 +0000
commit2225b57c2884d2e674ccd5ad972a10a7c1316ec9 (patch)
tree320de322098272075404c4d8bf933e1c2b3bfa03 /gcc/config
parent41ed243ff0f5c098b930eb3fcc333077b346348a (diff)
downloadgcc-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.c49
-rw-r--r--gcc/config/sparc/sparc.md9
-rw-r--r--gcc/config/sparc/sparc.opt3
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