mirror of git://gcc.gnu.org/git/gcc.git
sparc-protos.h (sparc_skip_caller_unimp): New declaration.
* config/sparc/sparc-protos.h (sparc_skip_caller_unimp): New declaration. * config/sparc/sparc.c (SKIP_CALLERS_UNIMP_P): Delete. (sparc_skip_caller_unimp): New global variable. (sparc_function_epilogue): Set 'sparc_skip_caller_unimp'. Use it instead of SKIP_CALLERS_UNIMP_P. * config/sparc/sparc.md (call expander): Add sanity check. (call_address_struct_value_sp32): Re-sync with expander. (call_symbolic_struct_value_sp32): Likewise. (return peepholes): Use 'sparc_skip_caller_unimp' instead of custom predicate. From-SVN: r81617
This commit is contained in:
parent
92ff0c419a
commit
bfb23806b8
|
@ -1,3 +1,17 @@
|
||||||
|
2004-05-07 Eric Botcazou <ebotcazou@act-europe.fr>
|
||||||
|
|
||||||
|
* config/sparc/sparc-protos.h (sparc_skip_caller_unimp): New
|
||||||
|
declaration.
|
||||||
|
* config/sparc/sparc.c (SKIP_CALLERS_UNIMP_P): Delete.
|
||||||
|
(sparc_skip_caller_unimp): New global variable.
|
||||||
|
(sparc_function_epilogue): Set 'sparc_skip_caller_unimp'.
|
||||||
|
Use it instead of SKIP_CALLERS_UNIMP_P.
|
||||||
|
* config/sparc/sparc.md (call expander): Add sanity check.
|
||||||
|
(call_address_struct_value_sp32): Re-sync with expander.
|
||||||
|
(call_symbolic_struct_value_sp32): Likewise.
|
||||||
|
(return peepholes): Use 'sparc_skip_caller_unimp' instead
|
||||||
|
of custom predicate.
|
||||||
|
|
||||||
2004-05-07 Eric Botcazou <ebotcazou@libertysurf.fr>
|
2004-05-07 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||||
|
|
||||||
PR c++/14962
|
PR c++/14962
|
||||||
|
|
|
@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA. */
|
||||||
#define __SPARC_PROTOS_H__
|
#define __SPARC_PROTOS_H__
|
||||||
|
|
||||||
extern bool sparc_emitting_epilogue;
|
extern bool sparc_emitting_epilogue;
|
||||||
|
extern bool sparc_skip_caller_unimp;
|
||||||
|
|
||||||
#ifdef TREE_CODE
|
#ifdef TREE_CODE
|
||||||
extern struct rtx_def *function_value (tree, enum machine_mode, int);
|
extern struct rtx_def *function_value (tree, enum machine_mode, int);
|
||||||
|
|
|
@ -48,17 +48,6 @@ Boston, MA 02111-1307, USA. */
|
||||||
#include "target-def.h"
|
#include "target-def.h"
|
||||||
#include "cfglayout.h"
|
#include "cfglayout.h"
|
||||||
|
|
||||||
/* 1 if the caller has placed an "unimp" insn immediately after the call.
|
|
||||||
This is used in v8 code when calling a function that returns a structure.
|
|
||||||
v9 doesn't have this. Be careful to have this test be the same as that
|
|
||||||
used on the call. */
|
|
||||||
|
|
||||||
#define SKIP_CALLERS_UNIMP_P \
|
|
||||||
(!TARGET_ARCH64 && current_function_returns_struct \
|
|
||||||
&& ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl))) \
|
|
||||||
&& (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl))) \
|
|
||||||
== INTEGER_CST))
|
|
||||||
|
|
||||||
/* Global variables for machine-dependent things. */
|
/* Global variables for machine-dependent things. */
|
||||||
|
|
||||||
/* Size of frame. Need to know this to emit return insns from leaf procedures.
|
/* Size of frame. Need to know this to emit return insns from leaf procedures.
|
||||||
|
@ -81,6 +70,7 @@ rtx sparc_compare_op0, sparc_compare_op1;
|
||||||
/* Coordinate with the md file wrt special insns created by
|
/* Coordinate with the md file wrt special insns created by
|
||||||
sparc_function_epilogue. */
|
sparc_function_epilogue. */
|
||||||
bool sparc_emitting_epilogue;
|
bool sparc_emitting_epilogue;
|
||||||
|
bool sparc_skip_caller_unimp;
|
||||||
|
|
||||||
/* Vector to say how input registers are mapped to output registers.
|
/* Vector to say how input registers are mapped to output registers.
|
||||||
HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
|
HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
|
||||||
|
@ -4498,6 +4488,17 @@ sparc_function_epilogue (FILE *file,
|
||||||
{
|
{
|
||||||
const char *ret;
|
const char *ret;
|
||||||
|
|
||||||
|
/* True if the caller has placed an "unimp" insn immediately after the call.
|
||||||
|
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)));
|
||||||
|
|
||||||
if (current_function_epilogue_delay_list == 0)
|
if (current_function_epilogue_delay_list == 0)
|
||||||
{
|
{
|
||||||
/* If code does not drop into the epilogue, we need
|
/* If code does not drop into the epilogue, we need
|
||||||
|
@ -4532,9 +4533,9 @@ sparc_function_epilogue (FILE *file,
|
||||||
|
|
||||||
/* Work out how to skip the caller's unimp instruction if required. */
|
/* Work out how to skip the caller's unimp instruction if required. */
|
||||||
if (leaf_function)
|
if (leaf_function)
|
||||||
ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%o7+12" : "retl");
|
ret = (sparc_skip_caller_unimp ? "jmp\t%o7+12" : "retl");
|
||||||
else
|
else
|
||||||
ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%i7+12" : "ret");
|
ret = (sparc_skip_caller_unimp ? "jmp\t%i7+12" : "ret");
|
||||||
|
|
||||||
if (! leaf_function)
|
if (! leaf_function)
|
||||||
{
|
{
|
||||||
|
@ -4542,7 +4543,7 @@ sparc_function_epilogue (FILE *file,
|
||||||
{
|
{
|
||||||
if (current_function_epilogue_delay_list)
|
if (current_function_epilogue_delay_list)
|
||||||
abort ();
|
abort ();
|
||||||
if (SKIP_CALLERS_UNIMP_P)
|
if (sparc_skip_caller_unimp)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
fputs ("\trestore\n\tretl\n\tadd\t%sp, %g1, %sp\n", file);
|
fputs ("\trestore\n\tretl\n\tadd\t%sp, %g1, %sp\n", file);
|
||||||
|
@ -4555,7 +4556,7 @@ sparc_function_epilogue (FILE *file,
|
||||||
if (TARGET_V9 && ! epilogue_renumber (&delay, 1))
|
if (TARGET_V9 && ! epilogue_renumber (&delay, 1))
|
||||||
{
|
{
|
||||||
epilogue_renumber (&delay, 0);
|
epilogue_renumber (&delay, 0);
|
||||||
fputs (SKIP_CALLERS_UNIMP_P
|
fputs (sparc_skip_caller_unimp
|
||||||
? "\treturn\t%i7+12\n"
|
? "\treturn\t%i7+12\n"
|
||||||
: "\treturn\t%i7+8\n", file);
|
: "\treturn\t%i7+8\n", file);
|
||||||
final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
|
final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
|
||||||
|
@ -4588,7 +4589,7 @@ sparc_function_epilogue (FILE *file,
|
||||||
sparc_emitting_epilogue = false;
|
sparc_emitting_epilogue = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (TARGET_V9 && ! SKIP_CALLERS_UNIMP_P)
|
else if (TARGET_V9 && ! sparc_skip_caller_unimp)
|
||||||
fputs ("\treturn\t%i7+8\n\tnop\n", file);
|
fputs ("\treturn\t%i7+8\n\tnop\n", file);
|
||||||
else
|
else
|
||||||
fprintf (file, "\t%s\n\trestore\n", ret);
|
fprintf (file, "\t%s\n\trestore\n", ret);
|
||||||
|
|
|
@ -7321,9 +7321,12 @@
|
||||||
{
|
{
|
||||||
rtx fn_rtx;
|
rtx fn_rtx;
|
||||||
|
|
||||||
if (GET_MODE (operands[0]) != FUNCTION_MODE)
|
if (GET_MODE (operands[0]) != FUNCTION_MODE)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
|
if (GET_CODE (operands[3]) != CONST_INT)
|
||||||
|
abort();
|
||||||
|
|
||||||
if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
|
if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
|
||||||
{
|
{
|
||||||
/* This is really a PIC sequence. We want to represent
|
/* This is really a PIC sequence. We want to represent
|
||||||
|
@ -7333,6 +7336,7 @@
|
||||||
call-clobbered registers? We lose this if it is a JUMP_INSN.
|
call-clobbered registers? We lose this if it is a JUMP_INSN.
|
||||||
Why cannot we have delay slots filled if it were a CALL? */
|
Why cannot we have delay slots filled if it were a CALL? */
|
||||||
|
|
||||||
|
/* We accept negative sizes for untyped calls. */
|
||||||
if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
|
if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
|
||||||
emit_jump_insn
|
emit_jump_insn
|
||||||
(gen_rtx_PARALLEL
|
(gen_rtx_PARALLEL
|
||||||
|
@ -7353,6 +7357,7 @@
|
||||||
|
|
||||||
fn_rtx = operands[0];
|
fn_rtx = operands[0];
|
||||||
|
|
||||||
|
/* We accept negative sizes for untyped calls. */
|
||||||
if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
|
if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
|
||||||
emit_call_insn
|
emit_call_insn
|
||||||
(gen_rtx_PARALLEL
|
(gen_rtx_PARALLEL
|
||||||
|
@ -7419,7 +7424,7 @@
|
||||||
(match_operand 2 "immediate_operand" "")
|
(match_operand 2 "immediate_operand" "")
|
||||||
(clobber (reg:SI 15))]
|
(clobber (reg:SI 15))]
|
||||||
;;- Do not use operand 1 for most machines.
|
;;- Do not use operand 1 for most machines.
|
||||||
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
|
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
|
||||||
"call\t%a0, %1\n\tnop\n\tunimp\t%2"
|
"call\t%a0, %1\n\tnop\n\tunimp\t%2"
|
||||||
[(set_attr "type" "call_no_delay_slot")
|
[(set_attr "type" "call_no_delay_slot")
|
||||||
(set_attr "length" "3")])
|
(set_attr "length" "3")])
|
||||||
|
@ -7432,7 +7437,7 @@
|
||||||
(match_operand 2 "immediate_operand" "")
|
(match_operand 2 "immediate_operand" "")
|
||||||
(clobber (reg:SI 15))]
|
(clobber (reg:SI 15))]
|
||||||
;;- Do not use operand 1 for most machines.
|
;;- Do not use operand 1 for most machines.
|
||||||
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
|
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
|
||||||
"call\t%a0, %1\n\tnop\n\tunimp\t%2"
|
"call\t%a0, %1\n\tnop\n\tunimp\t%2"
|
||||||
[(set_attr "type" "call_no_delay_slot")
|
[(set_attr "type" "call_no_delay_slot")
|
||||||
(set_attr "length" "3")])
|
(set_attr "length" "3")])
|
||||||
|
@ -7450,7 +7455,8 @@
|
||||||
[(set_attr "type" "call_no_delay_slot")
|
[(set_attr "type" "call_no_delay_slot")
|
||||||
(set_attr "length" "3")])
|
(set_attr "length" "3")])
|
||||||
|
|
||||||
;; This is a call that wants a structure value.
|
;; This is a call that may want a structure value. This is used for
|
||||||
|
;; untyped_calls.
|
||||||
(define_insn "*call_symbolic_untyped_struct_value_sp32"
|
(define_insn "*call_symbolic_untyped_struct_value_sp32"
|
||||||
[(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
|
[(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
|
||||||
(match_operand 1 "" ""))
|
(match_operand 1 "" ""))
|
||||||
|
@ -8083,7 +8089,7 @@
|
||||||
(return)]
|
(return)]
|
||||||
"sparc_emitting_epilogue"
|
"sparc_emitting_epilogue"
|
||||||
{
|
{
|
||||||
if (! TARGET_ARCH64 && current_function_returns_struct)
|
if (sparc_skip_caller_unimp)
|
||||||
return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
|
return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
|
||||||
else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
|
else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
|
||||||
|| IN_OR_GLOBAL_P (operands[1])))
|
|| IN_OR_GLOBAL_P (operands[1])))
|
||||||
|
@ -8100,7 +8106,7 @@
|
||||||
(return)]
|
(return)]
|
||||||
"sparc_emitting_epilogue"
|
"sparc_emitting_epilogue"
|
||||||
{
|
{
|
||||||
if (! TARGET_ARCH64 && current_function_returns_struct)
|
if (sparc_skip_caller_unimp)
|
||||||
return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
|
return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
|
||||||
else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
|
else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
|
||||||
|| IN_OR_GLOBAL_P (operands[1])))
|
|| IN_OR_GLOBAL_P (operands[1])))
|
||||||
|
@ -8117,7 +8123,7 @@
|
||||||
(return)]
|
(return)]
|
||||||
"sparc_emitting_epilogue"
|
"sparc_emitting_epilogue"
|
||||||
{
|
{
|
||||||
if (! TARGET_ARCH64 && current_function_returns_struct)
|
if (sparc_skip_caller_unimp)
|
||||||
return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
|
return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
|
||||||
else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
|
else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
|
||||||
|| IN_OR_GLOBAL_P (operands[1])))
|
|| IN_OR_GLOBAL_P (operands[1])))
|
||||||
|
@ -8134,7 +8140,7 @@
|
||||||
(return)]
|
(return)]
|
||||||
"sparc_emitting_epilogue"
|
"sparc_emitting_epilogue"
|
||||||
{
|
{
|
||||||
if (! TARGET_ARCH64 && current_function_returns_struct)
|
if (sparc_skip_caller_unimp)
|
||||||
return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
|
return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
|
||||||
else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
|
else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
|
||||||
return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
|
return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
|
||||||
|
@ -8165,7 +8171,7 @@
|
||||||
(return)]
|
(return)]
|
||||||
"sparc_emitting_epilogue"
|
"sparc_emitting_epilogue"
|
||||||
{
|
{
|
||||||
if (! TARGET_ARCH64 && current_function_returns_struct)
|
if (sparc_skip_caller_unimp)
|
||||||
return "jmp\t%%i7+12\n\trestore %r1, %2, %Y0";
|
return "jmp\t%%i7+12\n\trestore %r1, %2, %Y0";
|
||||||
/* If operands are global or in registers, can use return */
|
/* If operands are global or in registers, can use return */
|
||||||
else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])
|
else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])
|
||||||
|
@ -8185,7 +8191,7 @@
|
||||||
(return)]
|
(return)]
|
||||||
"sparc_emitting_epilogue && ! TARGET_CM_MEDMID"
|
"sparc_emitting_epilogue && ! TARGET_CM_MEDMID"
|
||||||
{
|
{
|
||||||
if (! TARGET_ARCH64 && current_function_returns_struct)
|
if (sparc_skip_caller_unimp)
|
||||||
return "jmp\t%%i7+12\n\trestore %r1, %%lo(%a2), %Y0";
|
return "jmp\t%%i7+12\n\trestore %r1, %%lo(%a2), %Y0";
|
||||||
/* If operands are global or in registers, can use return */
|
/* If operands are global or in registers, can use return */
|
||||||
else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
|
else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
|
||||||
|
|
Loading…
Reference in New Issue