This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 2/4] GAS: Make new fake labels when cloning a symbol
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: binutils at sourceware dot org
- Cc: Richard Sandiford <rdsandiford at googlemail dot com>, Catherine Moore <clm at codesourcery dot com>, gnu-mips-sgxx at codesourcery dot com
- Date: Mon, 26 Jul 2010 11:47:21 +0100 (BST)
- Subject: [PATCH 2/4] GAS: Make new fake labels when cloning a symbol
Hi,
Equated symbols (defined with .eqv) aka forward references are defined to
reevaluate the expression they are defined to whenever they are referred
to. This does not happen for the special "dot" symbol -- the value
calculated the first time the equated symbol has been used is then used
over and over again.
The reason is each time a reference to the "dot" symbol is made a special
fake label is created. This label is then recorded in the chain of
symbols the equated symbol is defined to and never reevaluated. The
solution is to create a new fake label each time the equated symbol is
used.
Additionally symbol_clone_if_forward_ref() would only be called
recursively for internal symbols referring to the special expression
section. It should happen for all symbols.
Overall with symbol definitions like this:
.data
.eqv fnord, .
.eqv foobar, fnord + 4
.eqv foobaz, foobar - 16
.word 0
.word fnord
.word fnord
.word foobaz
.word foobaz
the "dot" symbol would only be calculated once, with the second .word
directive, i.e. both the second and the third word emitted would have the
same value (address of the second word).
This would also cause "foobaz" to be calculated (as a forward reference)
with the third .eqv directive and then cloned each time when used with
.word. Howeved "foobar" would only be calculated with the second and the
third .eqv directive, but not with the .word directives, thus fixed at
the value of the first rather than each use.
In the end data emitted would be:
0, 0, 0, -12, -12
as if .set was used, rather than:
0, 4, 8, 0, 4
as expected.
2010-07-26 Maciej W. Rozycki <macro@codesourcery.com>
gas/
* symbols.c (symbol_clone_if_forward_ref): Don't limit cloning
to expr_section symbols. Make fresh fake labels.
* write.c (TC_FAKE_LABEL): Move over to...
* write.h (TC_FAKE_LABEL): ... here.
OK to apply?
Maciej
binutils-gas-eqv-dot.diff
Index: binutils-fsf-trunk-quilt/gas/symbols.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/gas/symbols.c 2010-07-24 02:25:04.000000000 +0100
+++ binutils-fsf-trunk-quilt/gas/symbols.c 2010-07-24 02:25:12.000000000 +0100
@@ -645,7 +645,7 @@ symbol_clone_if_forward_ref (symbolS *sy
/* Re-using sy_resolving here, as this routine cannot get called from
symbol resolution code. */
- if (symbolP->bsym->section == expr_section && !symbolP->sy_resolving)
+ if (!symbolP->sy_resolving)
{
symbolP->sy_resolving = 1;
add_symbol = symbol_clone_if_forward_ref (add_symbol, is_forward);
@@ -656,7 +656,23 @@ symbol_clone_if_forward_ref (symbolS *sy
if (symbolP->sy_forward_ref
|| add_symbol != symbolP->sy_value.X_add_symbol
|| op_symbol != symbolP->sy_value.X_op_symbol)
- symbolP = symbol_clone (symbolP, 0);
+ {
+ symbolS *temp_symbol;
+ int is_temp_add;
+ int is_temp_op;
+
+ symbolP = symbol_clone (symbolP, 0);
+ is_temp_add = add_symbol && TC_FAKE_LABEL (S_GET_NAME (add_symbol));
+ is_temp_op = op_symbol && TC_FAKE_LABEL (S_GET_NAME (op_symbol));
+ if (is_temp_add || is_temp_op)
+ {
+ temp_symbol = symbol_temp_new_now ();
+ if (is_temp_add)
+ add_symbol = temp_symbol;
+ if (is_temp_op)
+ op_symbol = temp_symbol;
+ }
+ }
symbolP->sy_value.X_add_symbol = add_symbol;
symbolP->sy_value.X_op_symbol = op_symbol;
Index: binutils-fsf-trunk-quilt/gas/write.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/gas/write.c 2010-07-24 02:25:04.000000000 +0100
+++ binutils-fsf-trunk-quilt/gas/write.c 2010-07-24 02:25:12.000000000 +0100
@@ -102,10 +102,6 @@
#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from (FIX)
#endif
-#ifndef TC_FAKE_LABEL
-#define TC_FAKE_LABEL(NAME) (strcmp ((NAME), FAKE_LABEL_NAME) == 0)
-#endif
-
/* Positive values of TC_FX_SIZE_SLACK allow a target to define
fixups that far past the end of a frag. Having such fixups
is of course most most likely a bug in setting fx_size correctly.
Index: binutils-fsf-trunk-quilt/gas/write.h
===================================================================
--- binutils-fsf-trunk-quilt.orig/gas/write.h 2010-07-24 02:25:04.000000000 +0100
+++ binutils-fsf-trunk-quilt/gas/write.h 2010-07-24 02:25:12.000000000 +0100
@@ -29,6 +29,10 @@
#define FAKE_LABEL_NAME "L0\001"
#endif
+#ifndef TC_FAKE_LABEL
+#define TC_FAKE_LABEL(NAME) (strcmp ((NAME), FAKE_LABEL_NAME) == 0)
+#endif
+
#include "bit_fix.h"
/*