* [stack] PATCH: Handle __builtin_eh_return with stack realignment
@ 2008-04-14 23:28 H.J. Lu
0 siblings, 0 replies; only message in thread
From: H.J. Lu @ 2008-04-14 23:28 UTC (permalink / raw)
To: GCC Patches, Ye, Joey, Guo, Xuepeng
[-- Attachment #1: Type: text/plain, Size: 1432 bytes --]
Hi,
__builtin_eh_return is a very special case. If a function calls
__builtin_eh_return, ix86_expand_epilogue will be called
before ix86_expand_prologue. Also __builtin_eh_return
doesn't use normal unwind info. I am checking this patch
into stack branch to handle it properly.
H.J.
----
2008-04-14 Xuepeng Guo <xuepeng.guo@intel.com>
Joey Ye <joey.ye@intel.com>
H.J. Lu <hongjiu.lu@intel.com>
* dwarf2out.c (struct dw_fde_struct): Rename is_stack_realign
to stack_realign and is_drap_reg_saved to drap_reg_saved. Add
calls_eh_return.
(add_cfi): Updated.
(dwarf2out_frame_debug_expr): Likewise.
(dwarf2out_begin_prologue): Initialize calls_eh_return.
(reg_save_with_expression): Don't generate unwind information
for restoring the stack pointer if __builtin_eh_return is called.
* cfgexpand.c (handle_drap): Need drap if functon calls
__builtin_eh_return.
* config/i386/i386.c (find_drap_reg): Use DI_REG if function
calls __builtin_eh_return.
(ix86_internal_arg_pointer): Remove setting incoming stack
boundary to preferred when __builtin_eh_return is called.
(ix86_finalize_stack_realign_flags): New.
(ix86_expand_prologue): Call ix86_finalize_stack_realign_flags.
(ix86_expand_epilogue): Likewise. Handle __builtin_eh_return
with stack realignment.
[-- Attachment #2: eh.txt --]
[-- Type: text/plain, Size: 11669 bytes --]
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c (.../fsf/branches/stack) (revision 2169)
+++ gcc/dwarf2out.c (.../branches/stack-test) (revision 2169)
@@ -249,11 +249,13 @@ typedef struct dw_fde_struct GTY(())
unsigned nothrow : 1;
unsigned uses_eh_lsda : 1;
/* Whether we did stack realign in this call frame.*/
- unsigned is_stack_realign : 1;
+ unsigned stack_realign : 1;
/* Whether stack realign is drap. */
unsigned is_drap : 1;
/* Whether we saved this drap register. */
- unsigned is_drap_reg_saved : 1;
+ unsigned drap_reg_saved : 1;
+ /* Whether called __builtin_eh_return */
+ unsigned calls_eh_return : 1;
}
dw_fde_node;
@@ -634,7 +636,7 @@ add_cfi (dw_cfi_ref *list_head, dw_cfi_r
/* If stack is realigned, accessing the stored register via CFA+offset will
be invalid. Here we will use a series of expressions in dwarf2 to simulate
the stack realign and represent the location of the stored register. */
- if (fde_table_in_use && (CUR_FDE.is_stack_realign || CUR_FDE.is_drap)
+ if (fde_table_in_use && (CUR_FDE.stack_realign || CUR_FDE.is_drap)
&& cfi->dw_cfi_opc == DW_CFA_offset)
reg_save_with_expression (cfi);
@@ -1557,11 +1559,11 @@ static dw_cfa_location cfa_temp;
Rule 16:
(set sp (and: sp <const_int>))
- effects: CUR_FDE.is_stack_realign = 1
+ effects: CUR_FDE.stack_realign = 1
cfa_store.offset = 0
if cfa_store.offset >= UNITS_PER_WORD
- effects: CUR_FDE.is_drap_reg_saved = 1
+ effects: CUR_FDE.drap_reg_saved = 1
Rule 17:
(set (mem ({pre_inc, pre_dec} sp)) (mem (plus (cfa.reg) (const_int))))
@@ -1569,8 +1571,8 @@ static dw_cfa_location cfa_temp;
Rule 18:
(set (mem({pre_inc, pre_dec} sp)) fp)
- constraints: CUR_FDE.is_stack_realign == 1
- effects: CUR_FDE.is_stack_realign = 0
+ constraints: CUR_FDE.stack_realign == 1
+ effects: CUR_FDE.stack_realign = 0
CUR_FDE.is_drap = 1
CUR_FDE.drap_regnum = cfa.reg
@@ -1815,12 +1817,12 @@ dwarf2out_frame_debug_expr (rtx expr, co
assume the stack is realigned and we extract the alignment. */
if (XEXP (src, 0) == stack_pointer_rtx && fde_table_in_use)
{
- CUR_FDE.is_stack_realign = 1;
+ CUR_FDE.stack_realign = 1;
CUR_FDE.stack_realignment = INTVAL (XEXP (src, 1));
/* If we didn't push anything to stack before stack is realigned,
we assume the drap register isn't saved. */
if (cfa_store.offset > UNITS_PER_WORD)
- CUR_FDE.is_drap_reg_saved = 1;
+ CUR_FDE.drap_reg_saved = 1;
cfa_store.offset = 0;
}
return;
@@ -1869,10 +1871,10 @@ dwarf2out_frame_debug_expr (rtx expr, co
/* Rule 18 */
/* If we push FP after stack is realigned, we assume this realignment
is drap, we will recorde the drap register. */
- if (fde_table_in_use && CUR_FDE.is_stack_realign
+ if (fde_table_in_use && CUR_FDE.stack_realign
&& REGNO (src) == HARD_FRAME_POINTER_REGNUM)
{
- CUR_FDE.is_stack_realign = 0;
+ CUR_FDE.stack_realign = 0;
CUR_FDE.is_drap = 1;
CUR_FDE.drap_regnum = DWARF_FRAME_REGNUM (cfa.reg);
}
@@ -2752,6 +2754,7 @@ dwarf2out_begin_prologue (unsigned int l
fde->nothrow = TREE_NOTHROW (current_function_decl);
fde->uses_eh_lsda = cfun->uses_eh_lsda;
fde->all_throwers_are_sibcalls = cfun->all_throwers_are_sibcalls;
+ fde->calls_eh_return = cfun->calls_eh_return;
args_size = old_args_size = 0;
@@ -15549,7 +15552,7 @@ reg_save_with_expression (dw_cfi_ref cfi
int reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
unsigned int dwarf_sp = (unsigned)DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
- if (CUR_FDE.is_stack_realign)
+ if (CUR_FDE.stack_realign)
{
head = tmp = new_loc_descr (DW_OP_const4s, 2 * UNITS_PER_WORD, 0);
tmp = tmp->dw_loc_next = new_loc_descr (DW_OP_minus, 0, 0);
@@ -15565,8 +15568,8 @@ reg_save_with_expression (dw_cfi_ref cfi
cfi->dw_cfi_oprnd1.dw_cfi_loc = head;
}
- /* We need restore drap register through dereference. If we needn't to restore
- the drap register we just ignore. */
+ /* We need restore drap register through dereference. If we needn't
+ to restore the drap register, we just ignore it. */
if (CUR_FDE.is_drap && reg == CUR_FDE.drap_regnum)
{
@@ -15575,7 +15578,7 @@ reg_save_with_expression (dw_cfi_ref cfi
cfi->dw_cfi_opc = DW_CFA_expression;
head = tmp = new_loc_descr (DW_OP_const4s, offset, 0);
tmp = tmp->dw_loc_next = new_loc_descr (DW_OP_minus, 0, 0);
- if (CUR_FDE.is_drap_reg_saved)
+ if (CUR_FDE.drap_reg_saved)
{
tmp = tmp->dw_loc_next = new_loc_descr (DW_OP_deref, 0, 0);
tmp = tmp->dw_loc_next = new_loc_descr (DW_OP_const4s,
@@ -15585,13 +15588,23 @@ reg_save_with_expression (dw_cfi_ref cfi
cfi->dw_cfi_oprnd2.dw_cfi_reg_num = reg;
cfi->dw_cfi_oprnd1.dw_cfi_loc = head;
- /* We also need restore the sp. */
- head = tmp = new_loc_descr (DW_OP_const4s, offset, 0);
- tmp = tmp->dw_loc_next = new_loc_descr (DW_OP_minus, 0, 0);
- cfi2->dw_cfi_opc = DW_CFA_expression;
- cfi2->dw_cfi_oprnd2.dw_cfi_reg_num = dwarf_sp;
- cfi2->dw_cfi_oprnd1.dw_cfi_loc = head;
- cfi->dw_cfi_next = cfi2;
+ /* We also need to properly restore the caller's stack pointer.
+ But if callee calls __builtin_eh_return, the calculation of
+ offset from exception handling function (typically is
+ _Unwind_RaiseException) to target function during unwinding
+ will conflict with this mechanism. It will simply set offset
+ to zero. So here if functions call __builtin_eh_return,
+ there will be no unwind information for restoring the stack
+ pointer. */
+ if (!CUR_FDE.calls_eh_return)
+ {
+ head = tmp = new_loc_descr (DW_OP_const4s, offset, 0);
+ tmp = tmp->dw_loc_next = new_loc_descr (DW_OP_minus, 0, 0);
+ cfi2->dw_cfi_opc = DW_CFA_expression;
+ cfi2->dw_cfi_oprnd2.dw_cfi_reg_num = dwarf_sp;
+ cfi2->dw_cfi_oprnd1.dw_cfi_loc = head;
+ cfi->dw_cfi_next = cfi2;
+ }
}
}
#else
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c (.../fsf/branches/stack) (revision 2169)
+++ gcc/cfgexpand.c (.../branches/stack-test) (revision 2169)
@@ -1882,7 +1882,8 @@ handle_drap (void)
if (current_function_calls_alloca
|| cfun->has_nonlocal_label
- || current_function_has_nonlocal_goto)
+ || current_function_has_nonlocal_goto
+ || current_function_calls_eh_return)
cfun->need_drap = true;
/* Call targetm.calls.internal_arg_pointer again. This time it will
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c (.../fsf/branches/stack) (revision 2169)
+++ gcc/config/i386/i386.c (.../branches/stack-test) (revision 2169)
@@ -6353,7 +6353,7 @@ find_drap_reg (void)
&& !DECL_NO_STATIC_CHAIN (cfun->decl))
return DI_REG;
- if (cfun->tail_call_emit)
+ if (cfun->tail_call_emit || current_function_calls_eh_return)
return DI_REG;
param_reg_num = ix86_function_regparm (TREE_TYPE (cfun->decl),
@@ -6383,12 +6383,6 @@ ix86_internal_arg_pointer (void)
? ix86_user_incoming_stack_boundary
: ix86_default_incoming_stack_boundary);
- /* Current stack realign doesn't support eh_return. Assume
- function who calls eh_return is aligned. There will be sanity
- check if stack realign happens together with eh_return later. */
- if (current_function_calls_eh_return)
- ix86_incoming_stack_boundary = PREFERRED_STACK_BOUNDARY;
-
/* Incoming stack alignment can be changed on individual functions
via force_align_arg_pointer attribute. We use the smallest
incoming stack boundary. */
@@ -6481,6 +6475,31 @@ ix86_dwarf_handle_frame_unspec (const ch
}
}
+/* Finalize stack_realign_really flag, which will guide prologue/epilogue
+ to be generated in correct form. */
+static void
+ix86_finalize_stack_realign_flags (void)
+{
+ /* Check if stack realign is really needed after reload, and
+ stores result in cfun */
+ unsigned int stack_realign = (ix86_incoming_stack_boundary
+ < (current_function_is_leaf
+ ? cfun->stack_alignment_used
+ : cfun->stack_alignment_needed));
+
+ if (cfun->stack_realign_finalized)
+ {
+ /* After stack_realign_really is finalized, we can't no longer
+ change it. */
+ gcc_assert (cfun->stack_realign_really == stack_realign);
+ }
+ else
+ {
+ cfun->stack_realign_really = stack_realign;
+ cfun->stack_realign_finalized = true;
+ }
+}
+
/* Expand the prologue into a bunch of separate insns. */
void
@@ -6492,18 +6511,11 @@ ix86_expand_prologue (void)
HOST_WIDE_INT allocate;
rtx (*gen_andsp) (rtx, rtx, rtx);
+ ix86_finalize_stack_realign_flags ();
+
/* DRAP should not coexist with stack_realign_fp */
gcc_assert (!(crtl->drap_reg && stack_realign_fp));
- /* Check if stack realign is really needed after reload, and
- stores result in cfun */
- cfun->stack_realign_really = (ix86_incoming_stack_boundary
- < (current_function_is_leaf
- ? cfun->stack_alignment_used
- : cfun->stack_alignment_needed));
-
- cfun->stack_realign_finalized = true;
-
ix86_compute_frame_layout (&frame);
/* Emit prologue code to adjust stack alignment and setup DRAP, in case
@@ -6752,13 +6764,17 @@ void
ix86_expand_epilogue (int style)
{
int regno;
- /* When stack realign may happen, SP must be valid. */
- int sp_valid = (!frame_pointer_needed
- || current_function_sp_is_unchanging
- || (stack_realign_fp && cfun->stack_realign_really));
+ int sp_valid;
struct ix86_frame frame;
HOST_WIDE_INT offset;
+ ix86_finalize_stack_realign_flags ();
+
+ /* When stack is realigned, SP must be valid. */
+ sp_valid = (!frame_pointer_needed
+ || current_function_sp_is_unchanging
+ || (stack_realign_fp && cfun->stack_realign_really));
+
ix86_compute_frame_layout (&frame);
/* Calculate start of saved registers relative to ebp. Special care
@@ -6812,13 +6828,18 @@ ix86_expand_epilogue (int style)
if (style == 2)
{
rtx tmp, sa = EH_RETURN_STACKADJ_RTX;
-
- if (cfun->stack_realign_really)
- {
- error("Stack realign has conflict with eh_return");
- }
if (frame_pointer_needed)
{
+ if (cfun->stack_realign_really)
+ {
+ gcc_assert (!stack_realign_fp);
+ gcc_assert (cfun->calls_eh_return);
+ tmp = plus_constant (crtl->drap_reg,
+ 2 * (-UNITS_PER_WORD));
+ tmp = gen_rtx_MEM (Pmode, tmp);
+ emit_move_insn (crtl->drap_reg, tmp);
+ }
+
tmp = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, sa);
tmp = plus_constant (tmp, UNITS_PER_WORD);
emit_insn (gen_rtx_SET (VOIDmode, sa, tmp));
@@ -6909,7 +6930,9 @@ ix86_expand_epilogue (int style)
}
}
- if (crtl->drap_reg && cfun->stack_realign_really)
+ if (style != 2
+ && crtl->drap_reg
+ && cfun->stack_realign_really)
{
int param_ptr_offset = (cfun->save_param_ptr_reg
? STACK_BOUNDARY / BITS_PER_UNIT : 0);
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2008-04-14 21:25 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-04-14 23:28 [stack] PATCH: Handle __builtin_eh_return with stack realignment H.J. Lu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).