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]

[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"
 
 /*


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