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]

[PATCH] ia64: spill_mask generation corrections


Besides dealing with the improper generation of spill_mask when
.save.g,
.save.gf, .save.f, or .save.b have more than one bit set in their
operand(s),
and besides adding another diagnostic for improper unwind directive
usage,
this patch also reduces the size of some of the tracking structures by
combining a few fields that can never be used simultaneously into
unions.

Built and tested on ia64-unknown-linux-gnu.

Jan

gas/
2005-07-05  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-05  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-05/gas/config/tc-ia64.c	2005-06-27
12:04:26.000000000 +0200
+++ 2005-07-05/gas/config/tc-ia64.c	2005-07-05 13:53:32.029990405
+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,52 @@ 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
+	  cur = (prev = 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 +1794,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 +1858,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 +1867,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 +1883,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 +1892,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 +1901,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 +1910,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 +1926,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 +1935,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 +1944,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 +1960,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 +1969,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 +1978,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 +1987,22 @@ 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;
+
+      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;
+      prev->r.record.p.next = cur;
+    }
 }
 
 static unw_rec_list *
@@ -1948,9 +2011,35 @@ 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;
+
+      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;
+      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;
+
+      gr_mask &= ~(gr_mask & (~gr_mask + 1));
+      if (!gr_mask)
+	return ptr;
+      cur = alloc_record (frgr_mem);
+      cur->r.record.p.grmask = gr_mask;
+      prev->r.record.p.grmask ^= gr_mask;
+      prev->r.record.p.next = cur;
+    }
 }
 
 static unw_rec_list *
@@ -1959,9 +2048,25 @@ 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;
+
+      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;
+      prev->r.record.p.grmask ^= mask;
+      prev->r.record.p.next = cur;
+    }
 }
 
 static unw_rec_list *
@@ -1969,27 +2074,71 @@ 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;
+
+      mask &= ~(mask & (~mask + 1));
+      if (!mask)
+	return ptr;
+      cur = alloc_record (gr_mem);
+      cur->r.record.p.grmask = mask;
+      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;
+
+      mask &= ~(mask & (~mask + 1));
+      if (!mask)
+	return ptr;
+      cur = alloc_record (br_mem);
+      cur->r.record.p.brmask = mask;
+      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;
+
+      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;
+      prev->r.record.p.brmask ^= mask;
+      prev->r.record.p.next = cur;
+    }
 }
 
 static unw_rec_list *
@@ -1997,7 +2146,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 +2162,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 +2171,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 +2180,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 +2196,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 +2205,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 +2214,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 +2230,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 +2239,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 +2248,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 +2271,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 +2280,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 +2289,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 +2305,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 +2314,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 +2323,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 +2339,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 +2348,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 +2357,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 +2373,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 +2382,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 +2391,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 +2440,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 +2455,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 +2471,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 +2485,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 +2551,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 +2574,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 +2586,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 +2624,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 +2639,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 +3000,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 +3009,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 +3339,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 +3355,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 +4456,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 +10925,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-05/gas/config/tc-ia64.h	2005-05-06
08:24:28.000000000 +0200
+++ 2005-07-05/gas/config/tc-ia64.h	2005-07-05 13:53:32.030966968
+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-05/gas/testsuite/gas/ia64/unwind-bad.l	2005-05-20
16:34:10.000000000 +0200
+++ 2005-07-05/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-05/gas/testsuite/gas/ia64/unwind-ok.d	2005-06-27
11:37:32.000000000 +0200
+++ 2005-07-05/gas/testsuite/gas/ia64/unwind-ok.d	2005-07-05
13:59:59.921587216 +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]