diff options
author | David Mosberger <davidm@hpl.hp.com> | 2002-03-15 01:55:49 +0000 |
---|---|---|
committer | Hans Boehm <hboehm@gcc.gnu.org> | 2002-03-15 01:55:49 +0000 |
commit | 5025a549a1e8387b314c36f24a0de8f8af7bcd1f (patch) | |
tree | 37c5df43f20092428f156e31511098dd0f6683ef /gcc | |
parent | 03e9dbc91c347697d6eecbd5154a545b56349157 (diff) | |
download | gcc-5025a549a1e8387b314c36f24a0de8f8af7bcd1f.zip gcc-5025a549a1e8387b314c36f24a0de8f8af7bcd1f.tar.gz gcc-5025a549a1e8387b314c36f24a0de8f8af7bcd1f.tar.bz2 |
unwind-ia64.c: Handle copy_state and label_state descriptors correctly.
* config/ia64/unwind-ia64.c: Handle copy_state and label_state
descriptors correctly.
From-SVN: r50789
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/config/ia64/unwind-ia64.c | 95 |
2 files changed, 77 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c4cf286..d003e7c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2002-03-14 David Mosberger <davidm@hpl.hp.com>, Hans Boehm <Hans_Boehm@hp.com> + + * config/ia64/unwind-ia64.c: Handle copy_state and label_state + descriptors correctly. + 2002-03-14 Michael Meissner <meissner@redhat.com> * params.def (PARAM_MAX_UNROLLED_INSNS): New macro, default to diff --git a/gcc/config/ia64/unwind-ia64.c b/gcc/config/ia64/unwind-ia64.c index bca3f23..b9bcf48 100644 --- a/gcc/config/ia64/unwind-ia64.c +++ b/gcc/config/ia64/unwind-ia64.c @@ -121,6 +121,17 @@ struct unw_reg_info int when; /* when the register gets saved */ }; +struct unw_reg_state { + struct unw_reg_state *next; /* next (outer) element on state stack */ + struct unw_reg_info reg[UNW_NUM_REGS]; /* register save locations */ +}; + +struct unw_labeled_state { + struct unw_labeled_state *next; /* next labeled state (or NULL) */ + unsigned long label; /* label for this state */ + struct unw_reg_state saved_state; +}; + typedef struct unw_state_record { unsigned int first_region : 1; /* is this the first region? */ @@ -141,11 +152,8 @@ typedef struct unw_state_record unsigned char gr_save_loc; /* next general register to use for saving */ unsigned char return_link_reg; /* branch register for return link */ - struct unw_reg_state { - struct unw_reg_state *next; - unsigned long label; /* label of this state record */ - struct unw_reg_info reg[UNW_NUM_REGS]; - } curr, *stack, *reg_state_list; + struct unw_labeled_state *labeled_states; /* list of all labeled states */ + struct unw_reg_state curr; /* current state */ _Unwind_Personality_Fn personality; @@ -226,7 +234,7 @@ static unsigned char const save_order[] = #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) -/* Unwind decoder routines */ +/* Routines to manipulate the state stack. */ static void push (struct unw_state_record *sr) @@ -235,20 +243,56 @@ push (struct unw_state_record *sr) rs = malloc (sizeof (struct unw_reg_state)); memcpy (rs, &sr->curr, sizeof (*rs)); - rs->next = sr->stack; - sr->stack = rs; + sr->curr.next = rs; } static void pop (struct unw_state_record *sr) { - struct unw_reg_state *rs; + struct unw_reg_state *rs = sr->curr.next; - rs = sr->stack; - sr->stack = rs->next; + if (!rs) + abort(); + memcpy(&sr->curr, rs, sizeof(*rs)); free (rs); } +/* Make a copy of the state stack. Non-recursive to avoid stack overflows. */ +static struct unw_reg_state * +dup_state_stack (struct unw_reg_state *rs) +{ + struct unw_reg_state *copy, *prev = NULL, *first = NULL; + + while (rs) + { + copy = malloc(sizeof(struct unw_state_record)); + memcpy(copy, rs, sizeof(*copy)); + if (first) + prev->next = copy; + else + first = copy; + rs = rs->next; + prev = copy; + } + return first; +} + +/* Free all stacked register states (but not RS itself). */ +static void +free_state_stack (struct unw_reg_state *rs) +{ + struct unw_reg_state *p, *next; + + for (p = rs->next; p != NULL; p = next) + { + next = p->next; + free(p); + } + rs->next = NULL; +} + +/* Unwind decoder routines */ + static enum unw_register_index __attribute__((const)) decode_abreg (unsigned char abreg, int memory) { @@ -396,7 +440,7 @@ desc_prologue (int body, unw_word rlen, unsigned char mask, sr->first_region = 0; /* Check if we're done. */ - if (body && sr->when_target < sr->region_start + sr->region_len) + if (sr->when_target < sr->region_start + sr->region_len) { sr->done = 1; return; @@ -631,13 +675,15 @@ desc_epilogue (unw_word t, unw_word ecount, struct unw_state_record *sr) static inline void desc_copy_state (unw_word label, struct unw_state_record *sr) { - struct unw_reg_state *rs; + struct unw_labeled_state *ls; - for (rs = sr->reg_state_list; rs; rs = rs->next) + for (ls = sr->labeled_states; ls; ls = ls->next) { - if (rs->label == label) - { - memcpy (&sr->curr, rs, sizeof(sr->curr)); + if (ls->label == label) + { + free_state_stack(&sr->curr); + memcpy(&sr->curr, &ls->saved_state, sizeof(sr->curr)); + sr->curr.next = dup_state_stack(ls->saved_state.next); return; } } @@ -647,13 +693,16 @@ desc_copy_state (unw_word label, struct unw_state_record *sr) static inline void desc_label_state (unw_word label, struct unw_state_record *sr) { - struct unw_reg_state *rs; + struct unw_labeled_state *ls; - rs = malloc (sizeof (struct unw_reg_state)); - memcpy (rs, &sr->curr, sizeof (*rs)); - rs->label = label; - rs->next = sr->reg_state_list; - sr->reg_state_list = rs; + ls = malloc(sizeof(struct unw_labeled_state)); + ls->label = label; + memcpy(&ls->saved_state, &sr->curr, sizeof(ls->saved_state)); + ls->saved_state.next = dup_state_stack(sr->curr.next); + + /* insert into list of labeled states: */ + ls->next = sr->labeled_states; + sr->labeled_states = ls; } /* |