Fix unwind info problems with .align.
authorJim Wilson <wilson@tuliptree.org>
Sat, 21 Feb 2004 00:24:15 +0000 (00:24 +0000)
committerJim Wilson <wilson@tuliptree.org>
Sat, 21 Feb 2004 00:24:15 +0000 (00:24 +0000)
* config/tc-ia64.c (slot_index): New arg before_relax.  Use instead of
finalize_syms.
(fixup_unw_records): New arg before_relax.  Pass to slot_index.
(ia64_estimate_size_before_relax): New.
(ia64_convert_frag): Pass 0 to fixup_unw_records.  Add comment.
(generate_unwind_image): Pass 1 to fixup_unw_records.
* config/tc-ia64.h (ia64_estimate_size_before_relax): Declare.
(md_estimate_size_before_relax): Call ia64_estimate_size_before_relax.

gas/ChangeLog
gas/config/tc-ia64.c
gas/config/tc-ia64.h

index 46d96b24b33c6e558c8974977f1e7131fd3bb371..ad04cee4a3069b6c5a1029535d25800d8ad4e728 100644 (file)
@@ -1,3 +1,14 @@
+2004-02-20  James E Wilson  <wilson@specifixinc.com>
+
+       * config/tc-ia64.c (slot_index): New arg before_relax.  Use instead of
+       finalize_syms.
+       (fixup_unw_records): New arg before_relax.  Pass to slot_index.
+       (ia64_estimate_size_before_relax): New.
+       (ia64_convert_frag): Pass 0 to fixup_unw_records.  Add comment.
+       (generate_unwind_image): Pass 1 to fixup_unw_records.
+       * config/tc-ia64.h (ia64_estimate_size_before_relax): Declare.
+       (md_estimate_size_before_relax): Call ia64_estimate_size_before_relax.
+
 2004-02-19  Jakub Jelinek  <jakub@redhat.com>
 
        * stabs.c (generate_asm_file): Avoid warning about use of
index 59cf5df9b9efd2bfe89dd98c139da5bb9b36d221..57a6b1d02251e1d6de30d12db08b4dd6425be60b 100644 (file)
@@ -898,9 +898,10 @@ 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 unsigned long slot_index PARAMS ((unsigned long, fragS *,
-                                        unsigned long, fragS *));
+                                        unsigned long, fragS *,
+                                        int));
 static unw_rec_list *optimize_unw_records PARAMS ((unw_rec_list *));
-static void fixup_unw_records PARAMS ((unw_rec_list *));
+static void fixup_unw_records PARAMS ((unw_rec_list *, int));
 static int convert_expr_to_ab_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
 static int convert_expr_to_xy_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
 static void generate_unwind_image PARAMS ((const char *));
@@ -2612,14 +2613,16 @@ set_imask (region, regmask, t, type)
 
 /* 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.  */
+   containing FIRST_ADDR.  If BEFORE_RELAX, then we use worst-case estimates
+   for frag sizes.  */
 
 unsigned long
-slot_index (slot_addr, slot_frag, first_addr, first_frag)
+slot_index (slot_addr, slot_frag, first_addr, first_frag, before_relax)
      unsigned long slot_addr;
      fragS *slot_frag;
      unsigned long first_addr;
      fragS *first_frag;
+     int before_relax;
 {
   unsigned long index = 0;
 
@@ -2634,10 +2637,10 @@ slot_index (slot_addr, slot_frag, first_addr, first_frag)
     {
       unsigned long start_addr = (unsigned long) &first_frag->fr_literal;
 
-      if (finalize_syms)
+      if (! before_relax)
        {
-         /* We can get the final addresses only after relaxation is
-            done. */
+         /* We can get the final addresses only during and after
+            relaxation.  */
          if (first_frag->fr_next && first_frag->fr_next->fr_address)
            index += 3 * ((first_frag->fr_next->fr_address
                           - first_frag->fr_address
@@ -2716,8 +2719,9 @@ optimize_unw_records (list)
    within each record to generate an image.  */
 
 static void
-fixup_unw_records (list)
+fixup_unw_records (list, before_relax)
      unw_rec_list *list;
+     int before_relax;
 {
   unw_rec_list *ptr, *region = 0;
   unsigned long first_addr = 0, rlen = 0, t;
@@ -2728,7 +2732,7 @@ fixup_unw_records (list)
       if (ptr->slot_number == SLOT_NUM_NOT_SET)
        as_bad (" Insn slot not set in unwind record.");
       t = slot_index (ptr->slot_number, ptr->slot_frag,
-                     first_addr, first_frag);
+                     first_addr, first_frag, before_relax);
       switch (ptr->r.type)
        {
        case prologue:
@@ -2752,7 +2756,8 @@ fixup_unw_records (list)
                  last_frag = last->slot_frag;
                  break;
                }
-           size = slot_index (last_addr, last_frag, first_addr, first_frag);
+           size = slot_index (last_addr, last_frag, first_addr, first_frag,
+                              before_relax);
            rlen = ptr->r.record.r.rlen = size;
            if (ptr->r.type == body)
              /* End of region.  */
@@ -2852,6 +2857,35 @@ fixup_unw_records (list)
     }
 }
 
+/* Estimate the size of a frag before relaxing.  We only have one type of frag
+   to handle here, which is the unwind info frag.  */
+
+int
+ia64_estimate_size_before_relax (fragS *frag,
+                                asection *segtype ATTRIBUTE_UNUSED)
+{
+  unw_rec_list *list;
+  int len, size, pad;
+
+  /* ??? This code is identical to the first part of ia64_convert_frag.  */
+  list = (unw_rec_list *) frag->fr_opcode;
+  fixup_unw_records (list, 0);
+
+  len = calc_record_size (list);
+  /* pad to pointer-size boundary.  */
+  pad = len % md.pointer_size;
+  if (pad != 0)
+    len += md.pointer_size - pad;
+  /* Add 8 for the header + a pointer for the personality offset.  */
+  size = len + 8 + md.pointer_size;
+
+  /* fr_var carries the max_chars that we created the fragment with.
+     We must, of course, have allocated enough memory earlier.  */
+  assert (frag->fr_var >= size);
+
+  return frag->fr_fix + size;
+}
+
 /* This function converts a rs_machine_dependent variant frag into a
   normal fill frag with the unwind image from the the record list.  */
 void
@@ -2861,8 +2895,9 @@ ia64_convert_frag (fragS *frag)
   int len, size, pad;
   valueT flag_value;
 
+  /* ??? This code is identical to ia64_estimate_size_before_relax.  */
   list = (unw_rec_list *) frag->fr_opcode;
-  fixup_unw_records (list);
+  fixup_unw_records (list, 0);
 
   len = calc_record_size (list);
   /* pad to pointer-size boundary.  */
@@ -3286,7 +3321,7 @@ generate_unwind_image (text_name)
 
   /* Generate the unwind record.  */
   list = optimize_unw_records (unwind.list);
-  fixup_unw_records (list);
+  fixup_unw_records (list, 1);
   size = calc_record_size (list);
 
   if (size > 0 || unwind.force_unwind_entry)
index d1a04ee0187fef53f9f28c1478f074b0ce7dee58..e27f5e052bb0a8fb562a2411cd26d77e7e121834 100644 (file)
@@ -115,6 +115,7 @@ extern void ia64_handle_align PARAMS ((fragS *f));
 extern void ia64_after_parse_args PARAMS ((void));
 extern void ia64_dwarf2_emit_offset PARAMS ((symbolS *, unsigned int));
 extern void ia64_check_label PARAMS ((symbolS *));
+extern int ia64_estimate_size_before_relax (fragS *, asection *);
 extern void ia64_convert_frag (fragS *);
 
 #define md_end()                               ia64_end_of_source ()
@@ -138,7 +139,7 @@ extern void ia64_convert_frag (fragS *);
 #define md_create_short_jump(p,f,t,fr,s) \
                                        as_fatal ("ia64_create_short_jump")
 #define md_estimate_size_before_relax(f,s) \
-                                       (f)->fr_var
+                                       ia64_estimate_size_before_relax(f,s)
 #define md_elf_section_letter          ia64_elf_section_letter
 #define md_elf_section_flags           ia64_elf_section_flags
 #define TC_FIX_TYPE                    struct ia64_fix