This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[patch] avoid infinite loops with .align/relax on RX
- From: DJ Delorie <dj at redhat dot com>
- To: binutils at sourceware dot org
- Date: Fri, 2 Jul 2010 16:24:26 -0400
- Subject: [patch] avoid infinite loops with .align/relax on RX
With enough small .aligns and with relaxation enabled, gas would get
caught in a loop of "grow this, now this can shrink, but then the
other one reaches, so shrink it, now you have to grow this other one
back..."
A simple "timeout" on this waffling back and forth, with a fallback to
"grow only", prevents this looping. Applied.
* config/tc-rx.c (rx_bytesT): Add grown/shrank counters for
relaxation.
(rx_relax_frag): Prevent infinite loops of grow/shrink/grow/etc.
Index: config/tc-rx.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-rx.c,v
retrieving revision 1.2
diff -p -U3 -r1.2 config/tc-rx.c
--- config/tc-rx.c 14 Dec 2009 10:59:37 -0000 1.2
+++ config/tc-rx.c 2 Jul 2010 19:59:27 -0000
@@ -624,6 +624,8 @@ typedef struct rx_bytesT
int n_relax;
int link_relax;
fixS *link_relax_fixP;
+ char times_grown;
+ char times_shrank;
} rx_bytesT;
static rx_bytesT rx_bytes;
@@ -1485,6 +1487,21 @@ rx_relax_frag (segT segment ATTRIBUTE_UN
break;
}
+ /* This prevents infinite loops in align-heavy sources. */
+ if (newsize < oldsize)
+ {
+ if (fragP->tc_frag_data->times_shrank > 10
+ && fragP->tc_frag_data->times_grown > 10)
+ newsize = oldsize;
+ if (fragP->tc_frag_data->times_shrank < 20)
+ fragP->tc_frag_data->times_shrank ++;
+ }
+ else if (newsize > oldsize)
+ {
+ if (fragP->tc_frag_data->times_grown < 20)
+ fragP->tc_frag_data->times_grown ++;
+ }
+
fragP->fr_subtype = newsize;
tprintf (" -> new %d old %d delta %d\n", newsize, oldsize, newsize-oldsize);
return newsize - oldsize;