From ba825241e117100f7314d8583a173c770e42707f Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 27 Jul 2005 06:32:46 +0000 Subject: [PATCH] gas/ 2005-07-27 Jan Beulich * config/tc-ia64.h (unw_r_record): Change type of fr_mem to unsigned int. (unw_p_record): Remove unused/redundant fields imask and rmask. Combine spoff and pspoff into a union. Combine gr and br into a union. Change type of grmask and brmask to unsigned char. Change type of frmask to unsigned int. (unw_x_record): Combine spoff, pspoff, and treg into a union. * config/tc-ia64.c (unwind): New field 'pending_saves'. (check_pending_save): New. (alloc_record): Clear out entire record. (output_psp_gr): Use renamed structure fields. (output_psp_sprel): Likewise. (output_rp_gr): Likewise. (output_rp_br): Likewise. (output_rp_psprel): Likewise. (output_rp_sprel): Likewise. (output_pfs_gr): Likewise. (output_pfs_psprel): Likewise. (output_pfs_sprel): Likewise. (output_preds_gr): Likewise. (output_preds_psprel): Likewise. (output_preds_sprel): Likewise. (output_spill_base): Likewise. (output_unat_gr): Likewise. (output_unat_psprel): Likewise. (output_unat_sprel): Likewise. (output_lc_gr): Likewise. (output_lc_psprel): Likewise. (output_lc_sprel): Likewise. (output_fpsr_gr): Likewise. (output_fpsr_psprel): Likewise. (output_fpsr_sprel): Likewise. (output_priunat_gr): Likewise. (output_priunat_psprel): Likewise. (output_priunat_sprel): Likewise. (output_bsp_gr): Likewise. (output_bsp_psprel): Likewise. (output_bsp_sprel): Likewise. (output_bspstore_gr): Likewise. (output_bspstore_psprel): Likewise. (output_bspstore_sprel): Likewise. (output_rnat_gr): Likewise. (output_rnat_psprel): Likewise. (output_rnat_sprel): Likewise. (output_spill_psprel): Likewise. (output_spill_sprel): Likewise. (output_spill_reg): Likewise. (output_fr_mem): Likewise. Allocate one unwind record per set mask bit. (output_frgr_mem): Likewise. (output_gr_mem): Likewise. (output_br_mem): Likewise. (output_gr_gr): Likewise. (output_br_gr): Likewise. (fixup_unw_records): Likewise. (process_one_record): Use renamed structure fields. For gr_gr and br_gr, collect mask from chain of records before output. (in_prologue): Simplify and eliminate early returns. Call check_pending_save. (in_body): Simplify and eliminate early returns. (dot_body): Call check_pending_save. (md_assemble): Update comment. Deal with pending saves. gas/testsuite/ 2005-07-27 Jan Beulich * gas/ia64/unwind-bad.l: Uncomment patterns matching new warnings. * gas/ia64/unwind-ok.d: Correct expectations. --- gas/ChangeLog | 65 +++++ gas/config/tc-ia64.c | 374 ++++++++++++++++++++-------- gas/config/tc-ia64.h | 34 ++- gas/testsuite/ChangeLog | 5 + gas/testsuite/gas/ia64/unwind-bad.l | 8 +- gas/testsuite/gas/ia64/unwind-ok.d | 4 +- 6 files changed, 374 insertions(+), 116 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 366981c57b8..0d0a3ff418a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,68 @@ +2005-07-27 Jan Beulich + + * config/tc-ia64.h (unw_r_record): Change type of fr_mem to unsigned + int. + (unw_p_record): Remove unused/redundant fields imask and rmask. + Combine spoff and pspoff into a union. Combine gr and br into a + union. Change type of grmask and brmask to unsigned char. Change type + of frmask to unsigned int. + (unw_x_record): Combine spoff, pspoff, and treg into a union. + * config/tc-ia64.c (unwind): New field 'pending_saves'. + (check_pending_save): New. + (alloc_record): Clear out entire record. + (output_psp_gr): Use renamed structure fields. + (output_psp_sprel): Likewise. + (output_rp_gr): Likewise. + (output_rp_br): Likewise. + (output_rp_psprel): Likewise. + (output_rp_sprel): Likewise. + (output_pfs_gr): Likewise. + (output_pfs_psprel): Likewise. + (output_pfs_sprel): Likewise. + (output_preds_gr): Likewise. + (output_preds_psprel): Likewise. + (output_preds_sprel): Likewise. + (output_spill_base): Likewise. + (output_unat_gr): Likewise. + (output_unat_psprel): Likewise. + (output_unat_sprel): Likewise. + (output_lc_gr): Likewise. + (output_lc_psprel): Likewise. + (output_lc_sprel): Likewise. + (output_fpsr_gr): Likewise. + (output_fpsr_psprel): Likewise. + (output_fpsr_sprel): Likewise. + (output_priunat_gr): Likewise. + (output_priunat_psprel): Likewise. + (output_priunat_sprel): Likewise. + (output_bsp_gr): Likewise. + (output_bsp_psprel): Likewise. + (output_bsp_sprel): Likewise. + (output_bspstore_gr): Likewise. + (output_bspstore_psprel): Likewise. + (output_bspstore_sprel): Likewise. + (output_rnat_gr): Likewise. + (output_rnat_psprel): Likewise. + (output_rnat_sprel): Likewise. + (output_spill_psprel): Likewise. + (output_spill_sprel): Likewise. + (output_spill_reg): Likewise. + (output_fr_mem): Likewise. Allocate one unwind record per set mask + bit. + (output_frgr_mem): Likewise. + (output_gr_mem): Likewise. + (output_br_mem): Likewise. + (output_gr_gr): Likewise. + (output_br_gr): Likewise. + (fixup_unw_records): Likewise. + (process_one_record): Use renamed structure fields. For gr_gr and + br_gr, collect mask from chain of records before output. + (in_prologue): Simplify and eliminate early returns. Call + check_pending_save. + (in_body): Simplify and eliminate early returns. + (dot_body): Call check_pending_save. + (md_assemble): Update comment. Deal with pending saves. + 2005-07-26 Jan Beulich * config/tc-i386.c (optimize_imm): Calculate candidate immediates diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c index 17b53d670fd..81e5cd56a0a 100644 --- a/gas/config/tc-ia64.c +++ b/gas/config/tc-ia64.c @@ -742,6 +742,9 @@ static struct unsigned int prologue_count; /* number of .prologues seen so far */ /* Prologue counts at previous .label_state directives. */ struct label_prologue_count * saved_prologue_counts; + + /* List of split up .save-s. */ + unw_p_record *pending_saves; } unwind; /* The input value is a negated offset from psp, and specifies an address @@ -1738,6 +1741,55 @@ output_X4_format (f, qp, ab, reg, x, y, treg, t) (*f) (count, bytes, NULL); } +/* This function checks whether there are any outstanding .save-s and + discards them if so. */ + +static void +check_pending_save (void) +{ + if (unwind.pending_saves) + { + unw_rec_list *cur, *prev; + + as_warn ("Previous .save incomplete"); + for (cur = unwind.list, prev = NULL; cur; ) + if (&cur->r.record.p == unwind.pending_saves) + { + if (prev) + prev->next = cur->next; + else + unwind.list = cur->next; + if (cur == unwind.tail) + unwind.tail = prev; + if (cur == unwind.current_entry) + unwind.current_entry = cur->next; + /* Don't free the first discarded record, it's being used as + terminator for (currently) br_gr and gr_gr processing, and + also prevents leaving a dangling pointer to it in its + predecessor. */ + cur->r.record.p.grmask = 0; + cur->r.record.p.brmask = 0; + cur->r.record.p.frmask = 0; + prev = cur->r.record.p.next; + cur->r.record.p.next = NULL; + cur = prev; + break; + } + else + { + prev = cur; + cur = cur->next; + } + while (cur) + { + prev = cur; + cur = cur->r.record.p.next; + free (prev); + } + unwind.pending_saves = NULL; + } +} + /* This function allocates a record list structure, and initializes fields. */ static unw_rec_list * @@ -1745,7 +1797,7 @@ alloc_record (unw_record_type t) { unw_rec_list *ptr; ptr = xmalloc (sizeof (*ptr)); - ptr->next = NULL; + memset (ptr, 0, sizeof (*ptr)); ptr->slot_number = SLOT_NUM_NOT_SET; ptr->r.type = t; return ptr; @@ -1809,7 +1861,7 @@ output_psp_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (psp_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -1818,7 +1870,7 @@ output_psp_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (psp_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -1834,7 +1886,7 @@ output_rp_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (rp_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -1843,7 +1895,7 @@ output_rp_br (br) unsigned int br; { unw_rec_list *ptr = alloc_record (rp_br); - ptr->r.record.p.br = br; + ptr->r.record.p.r.br = br; return ptr; } @@ -1852,7 +1904,7 @@ output_rp_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (rp_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -1861,7 +1913,7 @@ output_rp_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (rp_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -1877,7 +1929,7 @@ output_pfs_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (pfs_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -1886,7 +1938,7 @@ output_pfs_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (pfs_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -1895,7 +1947,7 @@ output_pfs_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (pfs_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -1911,7 +1963,7 @@ output_preds_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (preds_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -1920,7 +1972,7 @@ output_preds_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (preds_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -1929,7 +1981,7 @@ output_preds_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (preds_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -1938,8 +1990,24 @@ output_fr_mem (mask) unsigned int mask; { unw_rec_list *ptr = alloc_record (fr_mem); - ptr->r.record.p.rmask = mask; - return ptr; + unw_rec_list *cur = ptr; + + ptr->r.record.p.frmask = mask; + unwind.pending_saves = &ptr->r.record.p; + for (;;) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + mask &= ~(mask & (~mask + 1)); + if (!mask) + return ptr; + cur = alloc_record (fr_mem); + cur->r.record.p.frmask = mask; + /* Retain only least significant bit. */ + prev->r.record.p.frmask ^= mask; + prev->r.record.p.next = cur; + } } static unw_rec_list * @@ -1948,9 +2016,39 @@ output_frgr_mem (gr_mask, fr_mask) unsigned int fr_mask; { unw_rec_list *ptr = alloc_record (frgr_mem); - ptr->r.record.p.grmask = gr_mask; - ptr->r.record.p.frmask = fr_mask; - return ptr; + unw_rec_list *cur = ptr; + + unwind.pending_saves = &cur->r.record.p; + cur->r.record.p.frmask = fr_mask; + while (fr_mask) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + fr_mask &= ~(fr_mask & (~fr_mask + 1)); + if (!gr_mask && !fr_mask) + return ptr; + cur = alloc_record (frgr_mem); + cur->r.record.p.frmask = fr_mask; + /* Retain only least significant bit. */ + prev->r.record.p.frmask ^= fr_mask; + prev->r.record.p.next = cur; + } + cur->r.record.p.grmask = gr_mask; + for (;;) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + gr_mask &= ~(gr_mask & (~gr_mask + 1)); + if (!gr_mask) + return ptr; + cur = alloc_record (frgr_mem); + cur->r.record.p.grmask = gr_mask; + /* Retain only least significant bit. */ + prev->r.record.p.grmask ^= gr_mask; + prev->r.record.p.next = cur; + } } static unw_rec_list * @@ -1959,9 +2057,27 @@ output_gr_gr (mask, reg) unsigned int reg; { unw_rec_list *ptr = alloc_record (gr_gr); + unw_rec_list *cur = ptr; + ptr->r.record.p.grmask = mask; - ptr->r.record.p.gr = reg; - return ptr; + ptr->r.record.p.r.gr = reg; + unwind.pending_saves = &ptr->r.record.p; + for (;;) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + mask &= ~(mask & (~mask + 1)); + if (!mask) + return ptr; + cur = alloc_record (gr_gr); + cur->r.record.p.grmask = mask; + /* Indicate this record shouldn't be output. */ + cur->r.record.p.r.gr = REG_NUM; + /* Retain only least significant bit. */ + prev->r.record.p.grmask ^= mask; + prev->r.record.p.next = cur; + } } static unw_rec_list * @@ -1969,27 +2085,77 @@ output_gr_mem (mask) unsigned int mask; { unw_rec_list *ptr = alloc_record (gr_mem); - ptr->r.record.p.rmask = mask; - return ptr; + unw_rec_list *cur = ptr; + + ptr->r.record.p.grmask = mask; + unwind.pending_saves = &ptr->r.record.p; + for (;;) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + mask &= ~(mask & (~mask + 1)); + if (!mask) + return ptr; + cur = alloc_record (gr_mem); + cur->r.record.p.grmask = mask; + /* Retain only least significant bit. */ + prev->r.record.p.grmask ^= mask; + prev->r.record.p.next = cur; + } } static unw_rec_list * output_br_mem (unsigned int mask) { unw_rec_list *ptr = alloc_record (br_mem); + unw_rec_list *cur = ptr; + ptr->r.record.p.brmask = mask; - return ptr; + unwind.pending_saves = &ptr->r.record.p; + for (;;) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + mask &= ~(mask & (~mask + 1)); + if (!mask) + return ptr; + cur = alloc_record (br_mem); + cur->r.record.p.brmask = mask; + /* Retain only least significant bit. */ + prev->r.record.p.brmask ^= mask; + prev->r.record.p.next = cur; + } } static unw_rec_list * -output_br_gr (save_mask, reg) - unsigned int save_mask; +output_br_gr (mask, reg) + unsigned int mask; unsigned int reg; { unw_rec_list *ptr = alloc_record (br_gr); - ptr->r.record.p.brmask = save_mask; - ptr->r.record.p.gr = reg; - return ptr; + unw_rec_list *cur = ptr; + + ptr->r.record.p.brmask = mask; + ptr->r.record.p.r.gr = reg; + unwind.pending_saves = &ptr->r.record.p; + for (;;) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + mask &= ~(mask & (~mask + 1)); + if (!mask) + return ptr; + cur = alloc_record (br_gr); + cur->r.record.p.brmask = mask; + /* Indicate this record shouldn't be output. */ + cur->r.record.p.r.gr = REG_NUM; + /* Retain only least significant bit. */ + prev->r.record.p.brmask ^= mask; + prev->r.record.p.next = cur; + } } static unw_rec_list * @@ -1997,7 +2163,7 @@ output_spill_base (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (spill_base); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2013,7 +2179,7 @@ output_unat_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (unat_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2022,7 +2188,7 @@ output_unat_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (unat_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2031,7 +2197,7 @@ output_unat_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (unat_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2047,7 +2213,7 @@ output_lc_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (lc_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2056,7 +2222,7 @@ output_lc_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (lc_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2065,7 +2231,7 @@ output_lc_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (lc_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2081,7 +2247,7 @@ output_fpsr_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (fpsr_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2090,7 +2256,7 @@ output_fpsr_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (fpsr_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2099,7 +2265,7 @@ output_fpsr_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (fpsr_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2122,7 +2288,7 @@ output_priunat_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (priunat_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2131,7 +2297,7 @@ output_priunat_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (priunat_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2140,7 +2306,7 @@ output_priunat_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (priunat_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2156,7 +2322,7 @@ output_bsp_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (bsp_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2165,7 +2331,7 @@ output_bsp_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (bsp_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2174,7 +2340,7 @@ output_bsp_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (bsp_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2190,7 +2356,7 @@ output_bspstore_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (bspstore_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2199,7 +2365,7 @@ output_bspstore_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (bspstore_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2208,7 +2374,7 @@ output_bspstore_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (bspstore_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2224,7 +2390,7 @@ output_rnat_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (rnat_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2233,7 +2399,7 @@ output_rnat_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (rnat_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2242,7 +2408,7 @@ output_rnat_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (rnat_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2291,7 +2457,7 @@ output_spill_psprel (ab, reg, offset, predicate) unw_rec_list *ptr = alloc_record (predicate ? spill_psprel_p : spill_psprel); ptr->r.record.x.ab = ab; ptr->r.record.x.reg = reg; - ptr->r.record.x.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.x.where.pspoff = ENCODED_PSP_OFFSET (offset); ptr->r.record.x.qp = predicate; return ptr; } @@ -2306,7 +2472,7 @@ output_spill_sprel (ab, reg, offset, predicate) unw_rec_list *ptr = alloc_record (predicate ? spill_sprel_p : spill_sprel); ptr->r.record.x.ab = ab; ptr->r.record.x.reg = reg; - ptr->r.record.x.spoff = offset / 4; + ptr->r.record.x.where.spoff = offset / 4; ptr->r.record.x.qp = predicate; return ptr; } @@ -2322,7 +2488,7 @@ output_spill_reg (ab, reg, targ_reg, xy, predicate) unw_rec_list *ptr = alloc_record (predicate ? spill_reg_p : spill_reg); ptr->r.record.x.ab = ab; ptr->r.record.x.reg = reg; - ptr->r.record.x.treg = targ_reg; + ptr->r.record.x.where.reg = targ_reg; ptr->r.record.x.xy = xy; ptr->r.record.x.qp = predicate; return ptr; @@ -2336,7 +2502,7 @@ process_one_record (ptr, f) unw_rec_list *ptr; vbyte_func f; { - unsigned long fr_mask, gr_mask; + unsigned int fr_mask, gr_mask; switch (ptr->r.type) { @@ -2402,13 +2568,13 @@ process_one_record (ptr, f) case bsp_gr: case bspstore_gr: case rnat_gr: - output_P3_format (f, ptr->r.type, ptr->r.record.p.gr); + output_P3_format (f, ptr->r.type, ptr->r.record.p.r.gr); break; case rp_br: - output_P3_format (f, rp_br, ptr->r.record.p.br); + output_P3_format (f, rp_br, ptr->r.record.p.r.br); break; case psp_sprel: - output_P7_format (f, psp_sprel, ptr->r.record.p.spoff, 0); + output_P7_format (f, psp_sprel, ptr->r.record.p.off.sp, 0); break; case rp_when: case pfs_when: @@ -2425,7 +2591,7 @@ process_one_record (ptr, f) case lc_psprel: case fpsr_psprel: case spill_base: - output_P7_format (f, ptr->r.type, ptr->r.record.p.pspoff, 0); + output_P7_format (f, ptr->r.type, ptr->r.record.p.off.psp, 0); break; case rp_sprel: case pfs_sprel: @@ -2437,13 +2603,29 @@ process_one_record (ptr, f) case bsp_sprel: case bspstore_sprel: case rnat_sprel: - output_P8_format (f, ptr->r.type, ptr->r.record.p.spoff); + output_P8_format (f, ptr->r.type, ptr->r.record.p.off.sp); break; case gr_gr: - output_P9_format (f, ptr->r.record.p.grmask, ptr->r.record.p.gr); + if (ptr->r.record.p.r.gr < REG_NUM) + { + const unw_rec_list *cur = ptr; + + gr_mask = cur->r.record.p.grmask; + while ((cur = cur->r.record.p.next) != NULL) + gr_mask |= cur->r.record.p.grmask; + output_P9_format (f, gr_mask, ptr->r.record.p.r.gr); + } break; case br_gr: - output_P2_format (f, ptr->r.record.p.brmask, ptr->r.record.p.gr); + if (ptr->r.record.p.r.gr < REG_NUM) + { + const unw_rec_list *cur = ptr; + + gr_mask = cur->r.record.p.brmask; + while ((cur = cur->r.record.p.next) != NULL) + gr_mask |= cur->r.record.p.brmask; + output_P2_format (f, gr_mask, ptr->r.record.p.r.gr); + } break; case spill_mask: as_bad ("spill_mask record unimplemented."); @@ -2459,7 +2641,7 @@ process_one_record (ptr, f) case bsp_psprel: case bspstore_psprel: case rnat_psprel: - output_P8_format (f, ptr->r.type, ptr->r.record.p.pspoff); + output_P8_format (f, ptr->r.type, ptr->r.record.p.off.psp); break; case unwabi: output_P10_format (f, ptr->r.record.p.abi, ptr->r.record.p.context); @@ -2474,32 +2656,32 @@ process_one_record (ptr, f) case spill_psprel: output_X1_format (f, ptr->r.type, ptr->r.record.x.ab, ptr->r.record.x.reg, ptr->r.record.x.t, - ptr->r.record.x.pspoff); + ptr->r.record.x.where.pspoff); break; case spill_sprel: output_X1_format (f, ptr->r.type, ptr->r.record.x.ab, ptr->r.record.x.reg, ptr->r.record.x.t, - ptr->r.record.x.spoff); + ptr->r.record.x.where.spoff); break; case spill_reg: output_X2_format (f, ptr->r.record.x.ab, ptr->r.record.x.reg, ptr->r.record.x.xy >> 1, ptr->r.record.x.xy, - ptr->r.record.x.treg, ptr->r.record.x.t); + ptr->r.record.x.where.reg, ptr->r.record.x.t); break; case spill_psprel_p: output_X3_format (f, ptr->r.type, ptr->r.record.x.qp, ptr->r.record.x.ab, ptr->r.record.x.reg, - ptr->r.record.x.t, ptr->r.record.x.pspoff); + ptr->r.record.x.t, ptr->r.record.x.where.pspoff); break; case spill_sprel_p: output_X3_format (f, ptr->r.type, ptr->r.record.x.qp, ptr->r.record.x.ab, ptr->r.record.x.reg, - ptr->r.record.x.t, ptr->r.record.x.spoff); + ptr->r.record.x.t, ptr->r.record.x.where.spoff); break; case spill_reg_p: output_X4_format (f, ptr->r.record.x.qp, ptr->r.record.x.ab, ptr->r.record.x.reg, ptr->r.record.x.xy >> 1, - ptr->r.record.x.xy, ptr->r.record.x.treg, + ptr->r.record.x.xy, ptr->r.record.x.where.reg, ptr->r.record.x.t); break; default: @@ -2835,8 +3017,8 @@ fixup_unw_records (list, before_relax) as_bad ("fr_mem record before region record!"); return; } - region->r.record.r.mask.fr_mem |= ptr->r.record.p.rmask; - set_imask (region, ptr->r.record.p.rmask, t, 1); + region->r.record.r.mask.fr_mem |= ptr->r.record.p.frmask; + set_imask (region, ptr->r.record.p.frmask, t, 1); break; case gr_mem: if (!region) @@ -2844,8 +3026,8 @@ fixup_unw_records (list, before_relax) as_bad ("gr_mem record before region record!"); return; } - region->r.record.r.mask.gr_mem |= ptr->r.record.p.rmask; - set_imask (region, ptr->r.record.p.rmask, t, 2); + region->r.record.r.mask.gr_mem |= ptr->r.record.p.grmask; + set_imask (region, ptr->r.record.p.grmask, t, 2); break; case br_mem: if (!region) @@ -3174,18 +3356,11 @@ static int in_prologue (const char *directive) { int in = in_procedure (directive); - if (in) - { - /* We are in a procedure. Check if we are in a prologue. */ - if (unwind.prologue) - return 1; - /* We only want to issue one message. */ - if (in == 1) - return unwind_diagnostic ("prologue", directive); - else - return -1; - } - return 0; + + if (in > 0 && !unwind.prologue) + in = unwind_diagnostic ("prologue", directive); + check_pending_save (); + return in; } /* Return 1 if a directive is in a body, -1 if a directive isn't in @@ -3197,18 +3372,10 @@ static int in_body (const char *directive) { int in = in_procedure (directive); - if (in) - { - /* We are in a procedure. Check if we are in a body. */ - if (unwind.body) - return 1; - /* We only want to issue one message. */ - if (in == 1) - return unwind_diagnostic ("body region", directive); - else - return -1; - } - return 0; + + if (in > 0 && !unwind.body) + in = unwind_diagnostic ("body region", directive); + return in; } static void @@ -4306,6 +4473,7 @@ dot_body (dummy) return; if (!unwind.prologue && !unwind.body && unwind.insn) as_warn ("Initial .body should precede any instructions"); + check_pending_save (); unwind.prologue = 0; unwind.prologue_mask = 0; @@ -10774,12 +10942,24 @@ md_assemble (str) as_where (&CURR_SLOT.src_file, &CURR_SLOT.src_line); dwarf2_where (&CURR_SLOT.debug_line); - /* Add unwind entry, if there is one. */ + /* Add unwind entries, if there are any. */ if (unwind.current_entry) { CURR_SLOT.unwind_record = unwind.current_entry; unwind.current_entry = NULL; } + if (unwind.pending_saves) + { + if (unwind.pending_saves->next) + { + /* Attach the next pending save to the next slot so that its + slot number will get set correctly. */ + add_unwind_entry (unwind.pending_saves->next, NOT_A_CHAR); + unwind.pending_saves = &unwind.pending_saves->next->r.record.p; + } + else + unwind.pending_saves = NULL; + } if (unwind.proc_pending.sym && S_IS_DEFINED (unwind.proc_pending.sym)) unwind.insn = 1; diff --git a/gas/config/tc-ia64.h b/gas/config/tc-ia64.h index ad0a116397f..f322fbf16fc 100644 --- a/gas/config/tc-ia64.h +++ b/gas/config/tc-ia64.h @@ -241,7 +241,7 @@ typedef struct unw_r_record struct { unsigned char *i; - unsigned long fr_mem; + unsigned int fr_mem; unsigned char gr_mem; unsigned char br_mem; } mask; @@ -249,17 +249,22 @@ typedef struct unw_r_record typedef struct unw_p_record { - void *imask; + struct unw_rec_list *next; unsigned long t; unsigned long size; - unsigned long spoff; - unsigned long br; - unsigned long pspoff; - unsigned short gr; - unsigned short rmask; - unsigned short grmask; - unsigned long frmask; - unsigned short brmask; + union + { + unsigned long sp; + unsigned long psp; + } off; + union + { + unsigned short gr; + unsigned short br; + } r; + unsigned char grmask; + unsigned char brmask; + unsigned int frmask; unsigned char abi; unsigned char context; } unw_p_record; @@ -274,10 +279,13 @@ typedef struct unw_b_record typedef struct unw_x_record { unsigned long t; - unsigned long spoff; - unsigned long pspoff; + union + { + unsigned long spoff; + unsigned long pspoff; + unsigned int reg; + } where; unsigned short reg; - unsigned short treg; unsigned short qp; unsigned short ab; /* Value of the AB field.. */ unsigned short xy; /* Value of the XY field.. */ diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 892c77aa556..a1183a8b6b7 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-07-27 Jan Beulich + + * gas/ia64/unwind-bad.l: Uncomment patterns matching new warnings. + * gas/ia64/unwind-ok.d: Correct expectations. + 2005-07-26 Jan Beulich * gas/i386/immed32.[sd]: New. diff --git a/gas/testsuite/gas/ia64/unwind-bad.l b/gas/testsuite/gas/ia64/unwind-bad.l index 59a4b20e47c..7009fab54af 100644 --- a/gas/testsuite/gas/ia64/unwind-bad.l +++ b/gas/testsuite/gas/ia64/unwind-bad.l @@ -2,17 +2,17 @@ .*:8: Error: First operand to \.save\.g must be a positive 4-bit constant .*:10: Error: First operand to \.save\.g must be a positive 4-bit constant .*:12: Error: First operand to \.save\.g must be a positive 4-bit constant -#FIXME .*:16: Error: Previous spill incomplete +.*:16: Warning: Previous .save incomplete #FIXME .*:18: Error: Register r4 was already saved .*:20: Error: Operand to \.save\.f must be a positive 20-bit constant .*:22: Error: Operand to \.save\.f must be a positive 20-bit constant .*:24: Error: Operand to \.save\.f must be a positive 20-bit constant -#FIXME .*:28: Error: Previous spill incomplete +.*:28: Warning: Previous .save incomplete #FIXME .*:30: Error: Register f2 was already saved .*:32: Error: First operand to \.save\.b must be a positive 5-bit constant .*:34: Error: First operand to \.save\.b must be a positive 5-bit constant .*:36: Error: First operand to \.save\.b must be a positive 5-bit constant -#FIXME .*:40: Error: Previous spill incomplete +.*:40: Warning: Previous .save incomplete #FIXME .*:42: Error: Register b1 was already saved .*:44: Error: Operand 2 to \.spillreg must be a writable register .*:46: Error: Operand 1 to \.spillreg must be a preserved register @@ -32,7 +32,7 @@ .*:82: Error: Second operand to \.save\.gf must be a non-negative 20-bit constant .*:84: Error: First operand to \.save\.gf must be a non-negative 4-bit constant .*:86: Error: Second operand to \.save\.gf must be a non-negative 20-bit constant -#FIXME .*:90: Error: Previous spill incomplete +.*:90: Warning: Previous .save incomplete #FIXME .*:92: Error: Register r4 was already saved #FIXME .*:94: Error: Register f2 was already saved .*:98: Error: Epilogue count of 2 exceeds number of nested prologues \(1\) diff --git a/gas/testsuite/gas/ia64/unwind-ok.d b/gas/testsuite/gas/ia64/unwind-ok.d index d35d6dee7ad..e60c7cc94b8 100644 --- a/gas/testsuite/gas/ia64/unwind-ok.d +++ b/gas/testsuite/gas/ia64/unwind-ok.d @@ -13,7 +13,7 @@ Unwind section '\.IA_64\.unwind' at offset 0x[[:xdigit:]]+ contains 8 entries: [[:space:]]*P7:spill_base\(pspoff=0x10-0x10\) [[:space:]]*P3:rp_br\(reg=b7\) [[:space:]]*P10:unwabi\(abi=@svr4,context=0x00\) -[[:space:]]*R1:body\(rlen=[[:digit:]]+\) +[[:space:]]*R1:body\(rlen=25\) [[:space:]]*X2:spill_reg\(t=0,reg=r4,treg=r2\) [[:space:]]*X4:spill_reg_p\(qp=p1,t=1,reg=r7,treg=r31\) [[:space:]]*X1:spill_sprel\(reg=b1,t=2,spoff=0x8\) @@ -41,7 +41,7 @@ Unwind section '\.IA_64\.unwind' at offset 0x[[:xdigit:]]+ contains 8 entries: [[:space:]]*v[[:digit:]]+, flags=0x0( \(\))?, len=[[:digit:]]+ bytes [[:space:]]*R2:prologue_gr\(mask=\[rp,psp,pr\],grsave=r8,rlen=14\) [[:space:]]*P5:frgr_mem\(grmask=\[r4,r7\],frmask=\[f2,f31\]\) -[[:space:]]*P4:spill_mask\(imask=\[b-b,bb-,---,---,--\]\) +[[:space:]]*P4:spill_mask\(imask=\[frb,bfr,---,---,--\]\) [[:space:]]*P7:spill_base\(pspoff=0x10-0x10\) [[:space:]]*P2:br_gr\(brmask=\[b1,b5\],gr=r32\) [[:space:]]*X2:spill_reg\(t=6,reg=f31,treg=f31\) -- 2.30.2