This is the mail archive of the binutils@sourceware.org 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]

Optimise away eh_frame advance_loc 0


These can be generated when multiple cfi directives are emitted for an
instruction and the insn frag is closed off between directives, as
happens when listings are enabled.  No doubt the advance_loc of zero
could be avoided by backtracking over frags in dw2gencfi.c before
calling cfi_add_advance_loc, but that seems like more work than
cleaning up afterwards as this patch does.

Noticed when looking at the testcase in PR25125.

	PR 25125
	* dw2gencfi.c (output_cfi_insn): Don't output DW_CFA_advance_loc+0.
	* ehopt.c (eh_frame_estimate_size_before_relax): Return -1 for
	an advance_loc of zero.
	(eh_frame_relax_frag): Translate fr_subtype of 7 to size -1.
	(eh_frame_convert_frag): Handle fr_subtype of 7.  Abort on
	unexpected fr_subtype.

diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c
index 388123fd24..b01e4c4a9e 100644
--- a/gas/dw2gencfi.c
+++ b/gas/dw2gencfi.c
@@ -1598,7 +1598,9 @@ output_cfi_insn (struct cfi_insn_data *insn)
 	    addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
 	    addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;
 
-	    if (scaled <= 0x3F)
+	    if (scaled == 0)
+	      ;
+	    else if (scaled <= 0x3F)
 	      out_one (DW_CFA_advance_loc + scaled);
 	    else if (scaled <= 0xFF)
 	      {
diff --git a/gas/ehopt.c b/gas/ehopt.c
index 207e799405..bf65602f53 100644
--- a/gas/ehopt.c
+++ b/gas/ehopt.c
@@ -482,7 +482,9 @@ eh_frame_estimate_size_before_relax (fragS *frag)
 
   gas_assert (ca > 0);
   diff /= ca;
-  if (diff < 0x40)
+  if (diff == 0)
+    ret = -1;
+  else if (diff < 0x40)
     ret = 0;
   else if (diff < 0x100)
     ret = 1;
@@ -491,7 +493,7 @@ eh_frame_estimate_size_before_relax (fragS *frag)
   else
     ret = 4;
 
-  frag->fr_subtype = (frag->fr_subtype & ~7) | ret;
+  frag->fr_subtype = (frag->fr_subtype & ~7) | (ret & 7);
 
   return ret;
 }
@@ -506,6 +508,8 @@ eh_frame_relax_frag (fragS *frag)
   int oldsize, newsize;
 
   oldsize = frag->fr_subtype & 7;
+  if (oldsize == 7)
+    oldsize = -1;
   newsize = eh_frame_estimate_size_before_relax (frag);
   return newsize - oldsize;
 }
@@ -548,9 +552,17 @@ eh_frame_convert_frag (fragS *frag)
       md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2);
       break;
 
-    default:
+    case 4:
       md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4);
       break;
+
+    case 7:
+      gas_assert (diff == 0);
+      frag->fr_fix -= 8;
+      break;
+
+    default:
+      abort ();
     }
 
   frag->fr_fix += frag->fr_subtype & 7;

-- 
Alan Modra
Australia Development Lab, IBM


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