Commit bfb23806 by Eric Botcazou Committed by Eric Botcazou

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
parent 92ff0c41
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. */ ...@@ -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. */ ...@@ -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; ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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]))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment