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]

Re: [PATCH] GAS relaxing bug


Replying to myself yet again.  This patch cuts to the heart of the matter,
simplifying code at the cost of an extra bit in struct frag.  Anybody have
any objections?

One possible problem that occurred to me was that if any of the relaxation
code creates new frags, the relax_marker bit would need to be copied from
the old frag.  As far as I could see, no new frags are created.

gas/ChangeLog
	* frags.h (struct frag): Add relax_marker.
	* write.c (is_dnrange): Delete.
	(relax_frag): Use correct types for `aim', `target', `address'.
	Delete `offset', `was_address'.  Test `relax_marker' instead of
	using fragile address test.
	(relax_segment): Init and flip `relax_marker'.

Index: frags.h
===================================================================
RCS file: /cvs/src/src/gas/frags.h,v
retrieving revision 1.9
diff -u -p -r1.9 frags.h
--- frags.h	2001/03/08 23:24:22	1.9
+++ frags.h	2001/03/19 08:23:30
@@ -1,5 +1,5 @@
 /* frags.h - Header file for the frag concept.
-   Copyright 1987, 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000
+   Copyright 1987, 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -61,6 +61,10 @@ struct frag {
 #ifndef NO_LISTING
   struct list_info_struct *line;
 #endif
+
+  /* Flipped each relax pass so we can easily determine whether
+     fr_address has been adjusted.  */
+  unsigned int relax_marker:1;
 
   /* What state is my tail in? */
   relax_stateT fr_type;
Index: write.c
===================================================================
RCS file: /cvs/src/src/gas/write.c,v
retrieving revision 1.27
diff -u -p -r1.27 write.c
--- write.c	2001/03/08 23:24:22	1.27
+++ write.c	2001/03/19 08:23:37
@@ -1996,28 +1996,6 @@ write_object_file ()
 
 #ifdef TC_GENERIC_RELAX_TABLE
 
-static int is_dnrange PARAMS ((fragS *, fragS *));
-
-/* Subroutines of relax_segment.  */
-
-static int
-is_dnrange (f1, f2)
-     fragS *f1;
-     fragS *f2;
-{
-  addressT f2addr;
-
-  f2addr = f2->fr_address;
-  for (; f1; f1 = f1->fr_next)
-    {
-      if (f1->fr_next == f2)
-	return 1;
-      if (f1->fr_address > f2addr)
-	break;
-    }
-  return 0;
-}
-
 /* Relax a fragment by scanning TC_GENERIC_RELAX_TABLE.  */
 
 long
@@ -2030,17 +2008,19 @@ relax_frag (segment, fragP, stretch)
   const relax_typeS *start_type;
   relax_substateT next_state;
   relax_substateT this_state;
-  long aim, target, growth;
-  symbolS *symbolP = fragP->fr_symbol;
-  long offset = fragP->fr_offset;
-  /* Recompute was_address by undoing "+= stretch" done by relax_segment.  */
-  unsigned long was_address = fragP->fr_address - stretch;
-  unsigned long address = fragP->fr_address;
-  const relax_typeS *table = TC_GENERIC_RELAX_TABLE;
-
+  long growth;
+  offsetT aim;
+  addressT target;
+  addressT address;
+  symbolS *symbolP;
+  const relax_typeS *table;
+
+  target = fragP->fr_offset;
+  address = fragP->fr_address;
+  table = TC_GENERIC_RELAX_TABLE;
   this_state = fragP->fr_subtype;
   start_type = this_type = table + this_state;
-  target = offset;
+  symbolP = fragP->fr_symbol;
 
   if (symbolP)
     {
@@ -2064,15 +2044,11 @@ relax_frag (segment, fragP, stretch)
       /* If frag has yet to be reached on this pass,
 	 assume it will move by STRETCH just as we did.
 	 If this is not so, it will be because some frag
-	 between grows, and that will force another pass.
-
-	 Beware zero-length frags.  */
+	 between grows, and that will force another pass.  */
 
       if (stretch != 0
-	  && S_GET_SEGMENT (symbolP) == segment
-	  && (sym_frag->fr_address > was_address
-	      || (sym_frag->fr_address == was_address
-		  && is_dnrange (fragP, sym_frag))))
+	  && sym_frag->relax_marker != fragP->relax_marker
+	  && S_GET_SEGMENT (symbolP) == segment)
 	{
 	  target += stretch;
 	}
@@ -2179,6 +2155,7 @@ relax_segment (segment_frag_root, segmen
   address = 0;
   for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next)
     {
+      fragP->relax_marker = 0;
       fragP->fr_address = address;
       address += fragP->fr_fix;
 
@@ -2264,6 +2241,7 @@ relax_segment (segment_frag_root, segmen
 	    offsetT offset;
 	    symbolS *symbolP;
 
+	    fragP->relax_marker ^= 1;
 	    was_address = fragP->fr_address;
 	    address = fragP->fr_address += stretch;
 	    symbolP = fragP->fr_symbol;

Alan
-- 
Linuxcare


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