diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-09-15 19:19:12 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-09-15 19:19:12 +0000 |
commit | ec37ccb4cc413884d02d17d3351b46d8f53ad63a (patch) | |
tree | 5f8b92560efd1078cbd16601e8b3502296539971 /gcc/libgcc2.c | |
parent | e393f69e6c3e1117ecd702fef8f20704f8bf88b0 (diff) | |
download | gcc-ec37ccb4cc413884d02d17d3351b46d8f53ad63a.tar.gz |
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@22436 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/libgcc2.c')
-rw-r--r-- | gcc/libgcc2.c | 148 |
1 files changed, 66 insertions, 82 deletions
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index 6f2fcfd9796..821387b3960 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -3492,31 +3492,71 @@ find_exception_handler (void *pc, exception_descriptor *table, void *eh_info) typedef int ptr_type __attribute__ ((mode (pointer))); -/* Get the value of register REG as saved in UDATA, where SUB_UDATA is a +#ifdef INCOMING_REGNO +/* Is the saved value for register REG in frame UDATA stored in a register + window in the previous frame? */ + +/* ??? The Sparc INCOMING_REGNO references TARGET_FLAT. This allows us + to use the macro here. One wonders, though, that perhaps TARGET_FLAT + compiled functions won't work with the frame-unwind stuff here. + Perhaps the entireity of in_reg_window should be conditional on having + seen a DW_CFA_GNU_window_save? */ +#define target_flags 0 + +static int +in_reg_window (int reg, frame_state *udata) +{ + if (udata->saved[reg] == REG_SAVED_REG) + return INCOMING_REGNO (reg) == reg; + if (udata->saved[reg] != REG_SAVED_OFFSET) + return 0; + +#ifdef STACK_GROWS_DOWNWARD + return udata->reg_or_offset[reg] > 0; +#else + return udata->reg_or_offset[reg] < 0; +#endif +} +#else +static inline int in_reg_window (int reg, frame_state *udata) { return 0; } +#endif /* INCOMING_REGNO */ + +/* Get the address of register REG as saved in UDATA, where SUB_UDATA is a frame called by UDATA or 0. */ -static void* -get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata) +static word_type * +get_reg_addr (unsigned reg, frame_state *udata, frame_state *sub_udata) { + while (udata->saved[reg] == REG_SAVED_REG) + { + reg = udata->reg_or_offset[reg]; + if (in_reg_window (reg, udata)) + { + udata = sub_udata; + sub_udata = NULL; + } + } if (udata->saved[reg] == REG_SAVED_OFFSET) - return (void *)(ptr_type) - *(word_type *)(udata->cfa + udata->reg_or_offset[reg]); - else if (udata->saved[reg] == REG_SAVED_REG && sub_udata) - return get_reg (udata->reg_or_offset[reg], sub_udata, 0); + return (word_type *)(udata->cfa + udata->reg_or_offset[reg]); else abort (); } +/* Get the value of register REG as saved in UDATA, where SUB_UDATA is a + frame called by UDATA or 0. */ + +static inline void * +get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata) +{ + return (void *)(ptr_type) *get_reg_addr (reg, udata, sub_udata); +} + /* Overwrite the saved value for register REG in frame UDATA with VAL. */ -static void +static inline void put_reg (unsigned reg, void *val, frame_state *udata) { - if (udata->saved[reg] == REG_SAVED_OFFSET) - *(word_type *)(udata->cfa + udata->reg_or_offset[reg]) - = (word_type)(ptr_type) val; - else - abort (); + *get_reg_addr (reg, udata, NULL) = (word_type)(ptr_type) val; } /* Copy the saved value for register REG from frame UDATA to frame @@ -3526,17 +3566,13 @@ put_reg (unsigned reg, void *val, frame_state *udata) static void copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata) { - if (udata->saved[reg] == REG_SAVED_OFFSET - && target_udata->saved[reg] == REG_SAVED_OFFSET) - memcpy (target_udata->cfa + target_udata->reg_or_offset[reg], - udata->cfa + udata->reg_or_offset[reg], - __builtin_dwarf_reg_size (reg)); - else - abort (); + word_type *preg = get_reg_addr (reg, udata, NULL); + word_type *ptreg = get_reg_addr (reg, target_udata, NULL); + + memcpy (ptreg, preg, __builtin_dwarf_reg_size (reg)); } -/* Retrieve the return address for frame UDATA, where SUB_UDATA is a - frame called by UDATA or 0. */ +/* Retrieve the return address for frame UDATA. */ static inline void * get_return_addr (frame_state *udata, frame_state *sub_udata) @@ -3576,24 +3612,6 @@ next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata) return caller_udata; } -#ifdef INCOMING_REGNO -/* Is the saved value for register REG in frame UDATA stored in a register - window in the previous frame? */ - -static int -in_reg_window (int reg, frame_state *udata) -{ - if (udata->saved[reg] != REG_SAVED_OFFSET) - return 0; - -#ifdef STACK_GROWS_DOWNWARD - return udata->reg_or_offset[reg] > 0; -#else - return udata->reg_or_offset[reg] < 0; -#endif -} -#endif /* INCOMING_REGNO */ - /* We first search for an exception handler, and if we don't find it, we call __terminate on the current stack frame so that we may use the debugger to walk the stack and understand why no handler @@ -3606,7 +3624,7 @@ void __throw () { struct eh_context *eh = (*get_eh_context) (); - void *saved_pc, *pc, *handler, *retaddr; + void *saved_pc, *pc, *handler; frame_state ustruct, ustruct2; frame_state *udata = &ustruct; frame_state *sub_udata = &ustruct2; @@ -3626,14 +3644,8 @@ label: if (! udata) __terminate (); - /* We need to get the value from the CFA register. At this point in - compiling __throw we don't know whether or not we will use the frame - pointer register for the CFA, so we check our unwind info. */ - if (udata->cfa_reg == __builtin_dwarf_fp_regnum ()) - udata->cfa = __builtin_fp (); - else - udata->cfa = __builtin_sp (); - udata->cfa += udata->cfa_offset; + /* We need to get the value from the CFA register. */ + udata->cfa = __builtin_dwarf_cfa (); memcpy (my_udata, udata, sizeof (*udata)); @@ -3712,7 +3724,6 @@ label: for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i) if (i != udata->retaddr_column && udata->saved[i]) { -#ifdef INCOMING_REGNO /* If you modify the saved value of the return address register on the SPARC, you modify the return address for your caller's frame. Don't do that here, as it will @@ -3721,14 +3732,12 @@ label: && udata->saved[udata->retaddr_column] == REG_SAVED_REG && udata->reg_or_offset[udata->retaddr_column] == i) continue; -#endif copy_reg (i, udata, my_udata); } pc = get_return_addr (udata, sub_udata) - 1; } -#ifdef INCOMING_REGNO /* But we do need to update the saved return address register from the last frame we unwind, or the handler frame will have the wrong return address. */ @@ -3738,42 +3747,17 @@ label: if (in_reg_window (i, udata)) copy_reg (i, udata, my_udata); } -#endif } - /* udata now refers to the frame called by the handler frame. */ - /* Emit the stub to adjust sp and jump to the handler. */ - if (new_exception_model) - retaddr = __builtin_eh_stub (); - else - retaddr = __builtin_eh_stub_old (); - - /* And then set our return address to point to the stub. */ - if (my_udata->saved[my_udata->retaddr_column] == REG_SAVED_OFFSET) - put_return_addr (retaddr, my_udata); - else - __builtin_set_return_addr_reg (retaddr); - - /* Set up the registers we use to communicate with the stub. - We check STACK_GROWS_DOWNWARD so the stub can use adjust_stack. */ - - if (new_exception_model) - __builtin_set_eh_regs ((void *)eh, -#ifdef STACK_GROWS_DOWNWARD - udata->cfa - my_udata->cfa -#else - my_udata->cfa - udata->cfa -#endif - + args_size); - else - __builtin_set_eh_regs (handler, + /* Now go! */ + __builtin_eh_return ((void *)eh, #ifdef STACK_GROWS_DOWNWARD - udata->cfa - my_udata->cfa + udata->cfa - my_udata->cfa, #else - my_udata->cfa - udata->cfa + my_udata->cfa - udata->cfa, #endif - + args_size); + handler); /* Epilogue: restore the handler frame's register values and return to the stub. */ |