diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2017-07-25 04:43:05 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2017-07-27 09:43:30 -0700 |
commit | ebba3121c46092b238e9d337b160f03b6b106b6d (patch) | |
tree | d8b17b0cd4ea848cbe44e9c376f200e8f9d38916 | |
parent | d80a40e357bf8d4f52504933d90b17feaee27ff7 (diff) | |
download | gcc-hjl/pr79793/master.tar.gz |
Properly compute stack frame for exception handlerhjl/pr79793/master
-rw-r--r-- | gcc/config/i386/i386.c | 35 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/guality/pr68037-1.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/interrupt-5.c | 13 |
4 files changed, 31 insertions, 35 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index f1486ff3750..534a611a296 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -10422,25 +10422,20 @@ ix86_function_arg (cumulative_args_t cum_v, machine_mode omode, { /* This is the pointer argument. */ gcc_assert (TYPE_MODE (type) == Pmode); - if (cfun->machine->func_type == TYPE_INTERRUPT) - /* -WORD(AP) in the current frame in interrupt handler. */ - arg = plus_constant (Pmode, arg_pointer_rtx, - -UNITS_PER_WORD); - else - /* (AP) in the current frame in exception handler. */ - arg = arg_pointer_rtx; + /* -WORD(AP) in the current frame in interrupt handler. */ + arg = plus_constant (Pmode, arg_pointer_rtx, -UNITS_PER_WORD); } else { gcc_assert (cfun->machine->func_type == TYPE_EXCEPTION && TREE_CODE (type) == INTEGER_TYPE && TYPE_MODE (type) == word_mode); - /* The integer argument is the error code at -WORD(AP) in + /* The integer argument is the error code at -2 * WORD(AP) in the current frame in exception handler. */ arg = gen_rtx_MEM (word_mode, plus_constant (Pmode, arg_pointer_rtx, - -UNITS_PER_WORD)); + -2 * UNITS_PER_WORD)); } return arg; } @@ -12915,8 +12910,8 @@ ix86_compute_frame_layout (void) the registers need to be saved before allocating the frame. */ && flag_stack_check != STATIC_BUILTIN_STACK_CHECK); - /* Skip return address. */ - offset = UNITS_PER_WORD; + /* Skip return address and error code in exception handler. */ + offset = INCOMING_FRAME_SP_OFFSET; /* Skip pushed static chain. */ if (ix86_static_chain_on_stack) @@ -15221,8 +15216,9 @@ ix86_expand_epilogue (int style) m->fs.red_zone_offset = 0; if (ix86_using_red_zone () && crtl->args.pops_args < 65536) { - /* The red-zone begins below the return address. */ - m->fs.red_zone_offset = RED_ZONE_SIZE + UNITS_PER_WORD; + /* The red-zone begins below return address and error code in + exception handler. */ + m->fs.red_zone_offset = RED_ZONE_SIZE + INCOMING_FRAME_SP_OFFSET; /* When the register save area is in the aligned portion of the stack, determine the maximum runtime displacement that @@ -15517,18 +15513,7 @@ ix86_expand_epilogue (int style) } if (cfun->machine->func_type != TYPE_NORMAL) - { - /* Return with the "IRET" instruction from interrupt handler. - Pop the 'ERROR_CODE' off the stack before the 'IRET' - instruction in exception handler. */ - if (cfun->machine->func_type == TYPE_EXCEPTION) - { - rtx r = plus_constant (Pmode, stack_pointer_rtx, - UNITS_PER_WORD); - emit_insn (gen_rtx_SET (stack_pointer_rtx, r)); - } - emit_jump_insn (gen_interrupt_return ()); - } + emit_jump_insn (gen_interrupt_return ()); else if (crtl->args.pops_args && crtl->args.size) { rtx popc = GEN_INT (crtl->args.pops_args); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 682745ae06b..ddbd6759caf 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2177,8 +2177,10 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER]; /* PC is dbx register 8; let's use that column for RA. */ #define DWARF_FRAME_RETURN_COLUMN (TARGET_64BIT ? 16 : 8) -/* Before the prologue, the top of the frame is at 4(%esp). */ -#define INCOMING_FRAME_SP_OFFSET UNITS_PER_WORD +/* Before the prologue, there are return address and error code for + exception handler on the top of the frame. */ +#define INCOMING_FRAME_SP_OFFSET \ + (UNITS_PER_WORD * (1 + (cfun->machine->func_type == TYPE_EXCEPTION))) /* Describe how we implement __builtin_eh_return. */ #define EH_RETURN_DATA_REGNO(N) ((N) <= DX_REG ? (N) : INVALID_REGNUM) diff --git a/gcc/testsuite/gcc.dg/guality/pr68037-1.c b/gcc/testsuite/gcc.dg/guality/pr68037-1.c index 74f61ec5f96..44cab58659f 100644 --- a/gcc/testsuite/gcc.dg/guality/pr68037-1.c +++ b/gcc/testsuite/gcc.dg/guality/pr68037-1.c @@ -59,9 +59,9 @@ main () return 0; } -/* { dg-final { gdb-test 31 "error" "0x12345670" } } */ -/* { dg-final { gdb-test 31 "frame->ip" "0x12345671" } } */ -/* { dg-final { gdb-test 31 "frame->cs" "0x12345672" } } */ -/* { dg-final { gdb-test 31 "frame->flags" "0x12345673" } } */ -/* { dg-final { gdb-test 31 "frame->sp" "0x12345674" } } */ -/* { dg-final { gdb-test 31 "frame->ss" "0x12345675" } } */ +/* { dg-final { gdb-test 33 "error" "0x12345670" } } */ +/* { dg-final { gdb-test 33 "frame->ip" "0x12345671" } } */ +/* { dg-final { gdb-test 33 "frame->cs" "0x12345672" } } */ +/* { dg-final { gdb-test 33 "frame->flags" "0x12345673" } } */ +/* { dg-final { gdb-test 33 "frame->sp" "0x12345674" } } */ +/* { dg-final { gdb-test 33 "frame->ss" "0x12345675" } } */ diff --git a/gcc/testsuite/gcc.target/i386/interrupt-5.c b/gcc/testsuite/gcc.target/i386/interrupt-5.c index 803c0636299..5742b6f4743 100644 --- a/gcc/testsuite/gcc.target/i386/interrupt-5.c +++ b/gcc/testsuite/gcc.target/i386/interrupt-5.c @@ -7,12 +7,21 @@ extern void link_error (void); typedef unsigned int uword_t __attribute__ ((mode (__word__))); +struct interrupt_frame +{ + uword_t ip; + uword_t cs; + uword_t flags; + uword_t sp; + uword_t ss; +}; + __attribute__ ((used, interrupt)) void -foo (void *frame, uword_t error) +foo (struct interrupt_frame *frame, uword_t error) { void *ra = __builtin_return_address (0); - if ((uintptr_t) ra != (uintptr_t) error) + if ((uintptr_t) ra != (uintptr_t) frame->ip) link_error (); } |