From 5738bc242c501f8bc1344298398e89bdc2acac5e Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Thu, 5 Feb 2004 23:50:21 +0000 Subject: [PATCH] Fix region length calculations when regions end with .align padding. * config/tc-ia64.c (output_endp): New. (count_bits): Delete. (ia64_flush_insns, process_one_record, optimize_unw_records): Handle endp unwind records. (fixup_unw_records): Handle endp unwind records. Delete code for shortening prologue regions not followed by a body record. (dot_endp): Call add_unwind_entry to emit endp unwind record. * config/tc-ia64.h (unw_record_type): Add endp. --- gas/ChangeLog | 11 ++++++ gas/config/tc-ia64.c | 89 ++++++++++++++------------------------------ gas/config/tc-ia64.h | 2 +- 3 files changed, 40 insertions(+), 62 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index f589373c63f..3fae09f425a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,14 @@ +2004-02-05 James E Wilson + + * config/tc-ia64.c (output_endp): New. + (count_bits): Delete. + (ia64_flush_insns, process_one_record, optimize_unw_records): Handle + endp unwind records. + (fixup_unw_records): Handle endp unwind records. Delete code for + shortening prologue regions not followed by a body record. + (dot_endp): Call add_unwind_entry to emit endp unwind record. + * config/tc-ia64.h (unw_record_type): Add endp. + 2004-02-03 James E Wilson * config/tc-ia64.c (ia64_convert_frag): Call md_number_to_chars to diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c index 63eb5c09e8a..2082241d93f 100644 --- a/gas/config/tc-ia64.c +++ b/gas/config/tc-ia64.c @@ -822,6 +822,7 @@ static void output_X2_format PARAMS ((vbyte_func, int, int, int, int, int, unsig static void output_X3_format PARAMS ((vbyte_func, unw_record_type, int, int, int, unsigned long, unsigned long)); static void output_X4_format PARAMS ((vbyte_func, int, int, int, int, int, int, unsigned long)); +static unw_rec_list *output_endp PARAMS ((void)); static unw_rec_list *output_prologue PARAMS ((void)); static unw_rec_list *output_prologue_gr PARAMS ((unsigned int, unsigned int)); static unw_rec_list *output_body PARAMS ((void)); @@ -896,7 +897,6 @@ static void process_one_record PARAMS ((unw_rec_list *, vbyte_func)); static void process_unw_records PARAMS ((unw_rec_list *, vbyte_func)); static int calc_record_size PARAMS ((unw_rec_list *)); static void set_imask PARAMS ((unw_rec_list *, unsigned long, unsigned long, unsigned int)); -static int count_bits PARAMS ((unsigned long)); static unsigned long slot_index PARAMS ((unsigned long, fragS *, unsigned long, fragS *)); static unw_rec_list *optimize_unw_records PARAMS ((unw_rec_list *)); @@ -1088,12 +1088,12 @@ ia64_flush_insns () CURR_SLOT.tag_fixups = 0; /* In case there are unwind directives following the last instruction, - resolve those now. We only handle body and prologue directives here. - Give an error for others. */ + resolve those now. We only handle prologue, body, and endp directives + here. Give an error for others. */ for (ptr = unwind.current_entry; ptr; ptr = ptr->next) { if (ptr->r.type == prologue || ptr->r.type == prologue_gr - || ptr->r.type == body) + || ptr->r.type == body || ptr->r.type == endp) { ptr->slot_number = (unsigned long) frag_more (0); ptr->slot_frag = frag_now; @@ -1712,6 +1712,16 @@ alloc_record (unw_record_type t) return ptr; } +/* Dummy unwind record used for calculating the length of the last prologue or + body region. */ + +static unw_rec_list * +output_endp () +{ + unw_rec_list *ptr = alloc_record (endp); + return ptr; +} + static unw_rec_list * output_prologue () { @@ -2332,6 +2342,10 @@ process_one_record (ptr, f) switch (ptr->r.type) { + /* This is a dummy record that takes up no space in the output. */ + case endp: + break; + case gr_mem: case fr_mem: case br_mem: @@ -2574,19 +2588,6 @@ set_imask (region, regmask, t, type) } } -static int -count_bits (unsigned long mask) -{ - int n = 0; - - while (mask) - { - mask &= mask - 1; - ++n; - } - return n; -} - /* Return the number of instruction slots from FIRST_ADDR to SLOT_ADDR. SLOT_FRAG is the frag containing SLOT_ADDR, and FIRST_FRAG is the frag containing FIRST_ADDR. */ @@ -2680,8 +2681,8 @@ optimize_unw_records (list) /* If the only unwind record is ".prologue" or ".prologue" followed by ".body", then we can optimize the unwind directives away. */ if (list->r.type == prologue - && (list->next == NULL - || (list->next->r.type == body && list->next->next == NULL))) + && (list->next->r.type == endp + || (list->next->r.type == body && list->next->next->r.type == endp))) return NULL; return list; @@ -2713,59 +2714,23 @@ fixup_unw_records (list) case body: { unw_rec_list *last; - int size, dir_len = 0; - unsigned long last_addr; - fragS *last_frag; + int size; + unsigned long last_addr = 0; + fragS *last_frag = NULL; first_addr = ptr->slot_number; first_frag = ptr->slot_frag; /* Find either the next body/prologue start, or the end of - the list, and determine the size of the region. */ - last_addr = list->next_slot_number; - last_frag = list->next_slot_frag; + the function, and determine the size of the region. */ for (last = ptr->next; last != NULL; last = last->next) if (last->r.type == prologue || last->r.type == prologue_gr - || last->r.type == body) + || last->r.type == body || last->r.type == endp) { last_addr = last->slot_number; last_frag = last->slot_frag; break; } - else if (!last->next) - { - /* In the absence of an explicit .body directive, - the prologue ends after the last instruction - covered by an unwind directive. */ - if (ptr->r.type != body) - { - last_addr = last->slot_number; - last_frag = last->slot_frag; - switch (last->r.type) - { - case frgr_mem: - dir_len = (count_bits (last->r.record.p.frmask) - + count_bits (last->r.record.p.grmask)); - break; - case fr_mem: - case gr_mem: - dir_len += count_bits (last->r.record.p.rmask); - break; - case br_mem: - case br_gr: - dir_len += count_bits (last->r.record.p.brmask); - break; - case gr_gr: - dir_len += count_bits (last->r.record.p.grmask); - break; - default: - dir_len = 1; - break; - } - } - break; - } - size = (slot_index (last_addr, last_frag, first_addr, first_frag) - + dir_len); + size = slot_index (last_addr, last_frag, first_addr, first_frag); rlen = ptr->r.record.r.rlen = size; if (ptr->r.type == body) /* End of region. */ @@ -4081,6 +4046,8 @@ dot_endp (dummy) insn_group_break (1, 0, 0); + add_unwind_entry (output_endp ()); + /* If there wasn't a .handlerdata, we haven't generated an image yet. */ if (!unwind.info) generate_unwind_image (text_name); diff --git a/gas/config/tc-ia64.h b/gas/config/tc-ia64.h index 6fd049f0540..01f8219aa42 100644 --- a/gas/config/tc-ia64.h +++ b/gas/config/tc-ia64.h @@ -202,7 +202,7 @@ typedef enum bspstore_gr, bspstore_psprel, bspstore_sprel, rnat_when, rnat_gr, rnat_psprel, rnat_sprel, epilogue, label_state, copy_state, spill_psprel, spill_sprel, spill_reg, spill_psprel_p, spill_sprel_p, - spill_reg_p, unwabi + spill_reg_p, unwabi, endp } unw_record_type; /* These structures declare the fields that can be used in each of the -- 2.30.2