This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
IA-64 function epilogue unwind support
- To: gcc-patches at gcc dot gnu dot org
- Subject: IA-64 function epilogue unwind support
- From: Jim Wilson <wilson at cygnus dot com>
- Date: Thu, 08 Jun 2000 10:19:02 -0700
This adds unwind support for function epilogues. This is needed by the
linux kernel stack frame unwinder. This requires the gas change I made
earlier today.
2000-06-08 James E. Wilson <wilson@bletchleypark.cygnus.com>
* config/ia64/ia64-protos.h (ia64_output_end_prologue): Add.
(output_function_prologue): Fix mispelling.
(output_function_prologue, output_function_epilogue): Reorder to
match ia64.c definition order.
* config/ia64/ia64.c (ia64_expand_prologue): Add comment.
(ia64_expand_epilogue): Set RTX_FRAME_RELATED_P on stack restore insns.
Use r3 instead of r2 for large stack restores.
(ia64_output_end_prologue): New function.
(process_set): Emit ".restore sp" for epilogue stack restores.
* config/ia64/ia64.h (FUNCTION_END_PROLOGUE): Define.
Index: ia64-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64-protos.h,v
retrieving revision 1.7
diff -p -r1.7 ia64-protos.h
*** ia64-protos.h 2000/06/01 00:10:35 1.7
--- ia64-protos.h 2000/06/08 17:11:49
*************** extern void ia64_encode_section_info PAR
*** 92,102 ****
extern int ia64_epilogue_uses PARAMS((int));
extern void ia64_expand_prologue PARAMS((void));
extern void ia64_expand_epilogue PARAMS((void));
extern int ia64_direct_return PARAMS((void));
extern int ia64_rap_fp_offset PARAMS((void));
extern void ia64_init_builtins PARAMS((void));
extern void ia64_override_options PARAMS((void));
extern unsigned int ia64_compute_frame_size PARAMS((int));
extern void save_restore_insns PARAMS((int));
- extern void ia64_function_prologue PARAMS((FILE *, int));
- extern void ia64_funtion_epilogue PARAMS((FILE *, int));
--- 92,103 ----
extern int ia64_epilogue_uses PARAMS((int));
extern void ia64_expand_prologue PARAMS((void));
extern void ia64_expand_epilogue PARAMS((void));
+ extern void ia64_function_prologue PARAMS((FILE *, int));
+ extern void ia64_output_end_prologue PARAMS((FILE *));
+ extern void ia64_function_epilogue PARAMS((FILE *, int));
extern int ia64_direct_return PARAMS((void));
extern int ia64_rap_fp_offset PARAMS((void));
extern void ia64_init_builtins PARAMS((void));
extern void ia64_override_options PARAMS((void));
extern unsigned int ia64_compute_frame_size PARAMS((int));
extern void save_restore_insns PARAMS((int));
Index: ia64.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.c,v
retrieving revision 1.21
diff -p -r1.21 ia64.c
*** ia64.c 2000/06/07 02:27:51 1.21
--- ia64.c 2000/06/08 17:11:50
*************** ia64_expand_prologue ()
*** 1001,1006 ****
--- 1001,1008 ----
offset = GEN_INT (-frame_size);
else
{
+ /* ??? We use r2 to tell process_set that this is a stack pointer
+ decrement. See also ia64_expand_epilogue. */
offset = gen_rtx_REG (DImode, GR_REG (2));
insn = emit_insn (gen_movdi (offset, GEN_INT (-frame_size)));
RTX_FRAME_RELATED_P (insn) = 1;
*************** ia64_expand_prologue ()
*** 1033,1038 ****
--- 1035,1042 ----
void
ia64_expand_epilogue ()
{
+ rtx insn;
+
/* Restore registers from frame. */
save_restore_insns (0);
*************** ia64_expand_epilogue ()
*** 1053,1060 ****
/* If there is a frame pointer, then we need to make the stack pointer
restore depend on the frame pointer, so that the stack pointer
restore won't be moved up past fp-relative loads from the frame. */
! emit_insn (gen_epilogue_deallocate_stack (stack_pointer_rtx,
! hard_frame_pointer_rtx));
}
else
{
--- 1057,1066 ----
/* If there is a frame pointer, then we need to make the stack pointer
restore depend on the frame pointer, so that the stack pointer
restore won't be moved up past fp-relative loads from the frame. */
! insn
! = emit_insn (gen_epilogue_deallocate_stack (stack_pointer_rtx,
! hard_frame_pointer_rtx));
! RTX_FRAME_RELATED_P (insn) = 1;
}
else
{
*************** ia64_expand_epilogue ()
*** 1067,1077 ****
offset = GEN_INT (frame_size);
else
{
! offset = gen_rtx_REG (DImode, GR_REG (2));
emit_insn (gen_movdi (offset, GEN_INT (frame_size)));
}
! emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
! offset));
}
}
}
--- 1073,1086 ----
offset = GEN_INT (frame_size);
else
{
! /* ??? We use r3 to tell process_set that this is a stack
! pointer increment. See also ia64_expand_prologue. */
! offset = gen_rtx_REG (DImode, GR_REG (3));
emit_insn (gen_movdi (offset, GEN_INT (frame_size)));
}
! insn = emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
! offset));
! RTX_FRAME_RELATED_P (insn) = 1;
}
}
}
*************** ia64_function_prologue (file, size)
*** 1136,1141 ****
--- 1145,1162 ----
fprintf (file, "\t.prologue\n");
}
+ /* Emit the .body directive at the scheduled end of the prologue. */
+
+ void
+ ia64_output_end_prologue (file)
+ FILE *file;
+ {
+ if (!flag_unwind_tables && (!flag_exceptions || exceptions_via_longjmp))
+ return;
+
+ fputs ("\t.body\n", file);
+ }
+
/* Emit the function epilogue. */
void
*************** process_set (asm_out_file, pat)
*** 3021,3039 ****
rtx op1 = XEXP (src, 1);
if (op0 == dest && GET_CODE (op1) == CONST_INT)
{
! fputs ("\t.fframe ", asm_out_file);
! fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, -INTVAL (op1));
! fputc ('\n', asm_out_file);
! frame_size = INTVAL (op1);
! return 1;
}
else if (op0 == dest && GET_CODE (op1) == REG)
{
! fprintf (asm_out_file, "\t.vframe r%d\n", REGNO (op1));
! frame_size = 0;
! return 1;
}
}
}
/* Look for a frame offset. */
if (GET_CODE (dest) == REG)
--- 3042,3081 ----
rtx op1 = XEXP (src, 1);
if (op0 == dest && GET_CODE (op1) == CONST_INT)
{
! if (INTVAL (op1) < 0)
! {
! fputs ("\t.fframe ", asm_out_file);
! fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC,
! -INTVAL (op1));
! fputc ('\n', asm_out_file);
! frame_size = INTVAL (op1);
! }
! else
! fprintf (asm_out_file, "\t.restore sp\n");
}
else if (op0 == dest && GET_CODE (op1) == REG)
{
! /* ia64_expand_prologue uses r2 for stack pointer decrements,
! ia64_expand_epilogue uses r3 for stack pointer increments. */
! if (REGNO (op1) == GR_REG (2))
! {
! fprintf (asm_out_file, "\t.vframe r%d\n", REGNO (op1));
! frame_size = 0;
! }
! else if (REGNO (op1) == GR_REG (3))
! fprintf (asm_out_file, "\t.restore sp\n");
! else
! abort ();
}
+ else
+ abort ();
}
+ else if (GET_CODE (src) == REG && REGNO (src) == FRAME_POINTER_REGNUM)
+ fprintf (asm_out_file, "\t.restore sp\n");
+ else
+ abort ();
+
+ return 1;
}
/* Look for a frame offset. */
if (GET_CODE (dest) == REG)
Index: ia64.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.h,v
retrieving revision 1.16
diff -p -r1.16 ia64.h
*** ia64.h 2000/06/01 00:10:35 1.16
--- ia64.h 2000/06/08 17:11:50
*************** do { \
*** 1464,1469 ****
--- 1464,1473 ----
#define FUNCTION_PROLOGUE(FILE, SIZE) \
ia64_function_prologue (FILE, SIZE)
+ /* This macro notes the end of the prologue. */
+
+ #define FUNCTION_END_PROLOGUE(FILE) ia64_output_end_prologue (FILE)
+
/* Define this macro as a C expression that is nonzero if the return
instruction or the function epilogue ignores the value of the stack pointer;
in other words, if it is safe to delete an instruction to adjust the stack