This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] ia64: spill_mask generation corrections


>This looks OK, though I think you are trying to be too clever in a few
>places.
>
>For instance, in check_pending_save, you have
>+       else
>+         cur = (prev = cur)->next;
>You are trying too hard to avoid using braces here.
>
>In 5 different places, you have inside a loop
>+      mask &= ~(mask & (~mask + 1));
>+      if (!mask)
>+       return ptr;
>+      cur = alloc_record (fr_mem);
>+      cur->r.record.p.frmask = mask;
>+      prev->r.record.p.frmask ^= mask;
>I understand why you wrote it that way, but I don't think you can
safely
>expect that everyone looking at this code in the next 20 years will
>understand it.  There should be comments explaining what it is doing.

>First you clear off the low order bit of mask.  Then you xor it into
>prev frmask so that prev frmask is left with only the low order bit. 
>Then you repeat until no bits are left.

Changed. Re-built and re-tested on ia64-unknown-linux-gnu.

Jan

gas/
2005-07-18  Jan Beulich  <jbeulich@novell.com>

	* 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-18  Jan Beulich  <jbeulich@novell.com>

	* gas/ia64/unwind-bad.l: Uncomment patterns matching new
warnings.
	* gas/ia64/unwind-ok.d: Correct expectations.

---
/home/jbeulich/src/binutils/mainline/2005-07-18/gas/config/tc-ia64.c	2005-07-05
13:53:32.000000000 +0200
+++ 2005-07-18/gas/config/tc-ia64.c	2005-07-18 12:25:34.036114131
+0200
@@ -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, 
   (*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, pr
   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, pre
   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,
   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;
 
---
/home/jbeulich/src/binutils/mainline/2005-07-18/gas/config/tc-ia64.h	2005-05-06
08:24:28.000000000 +0200
+++ 2005-07-18/gas/config/tc-ia64.h	2005-07-05 13:53:32.000000000
+0200
@@ -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..  */
---
/home/jbeulich/src/binutils/mainline/2005-07-18/gas/testsuite/gas/ia64/unwind-bad.l	2005-05-20
16:34:10.000000000 +0200
+++ 2005-07-18/gas/testsuite/gas/ia64/unwind-bad.l	2005-07-04
17:53:45.000000000 +0200
@@ -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\)
---
/home/jbeulich/src/binutils/mainline/2005-07-18/gas/testsuite/gas/ia64/unwind-ok.d	2005-06-27
11:37:32.000000000 +0200
+++ 2005-07-18/gas/testsuite/gas/ia64/unwind-ok.d	2005-07-18
12:21:34.503890503 +0200
@@ -13,7 +13,7 @@ Unwind section '\.IA_64\.unwind' at offs
 [[: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 offs
 [[: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\)

Attachment: binutils-mainline-ia64-unwind-spill-mask.patch
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]