PR23800, .eqv doesn't always defer expression evaluation

Alan Modra amodra@gmail.com
Sat Oct 20 09:25:00 GMT 2018


.eqv (and ==) ought not simplify expressions involving dot or other
symbols set by .eqv.  If such simplification occurs, the value of dot
will be that at the assignment rather than at the place where the
symbol is used.

The new testcase fails on a number of targets:
am33_2.0-linux  +FAIL: eqv involving dot
crx-elf  +FAIL: eqv involving dot
h8300-elf  +FAIL: eqv involving dot
mep-elf  +FAIL: eqv involving dot
mn10200-elf  +FAIL: eqv involving dot
mn10300-elf  +FAIL: eqv involving dot
pdp11-dec-aout  +FAIL: eqv involving dot
tic30-unknown-aout  +FAIL: eqv involving dot
tic30-unknown-coff  +FAIL: eqv involving dot
tic54x-coff  +FAIL: eqv involving dot
xtensa-elf  +FAIL: eqv involving dot

They all look to be due to bugs in target reloc handling.

	PR 23800
	* expr.c (expr): Don't simplify expressions involving forward_ref
	symbols when mode is expr_defer.
	* config/tc-spu.c (spu_cons): Parse expression using normal
	expression evaluation if @ppu is not detected.
	* testsuite/gas/all/eqv-dot.d,
	* testsuite/gas/all/eqv-dot.s: New test.
	* testsuite/gas/all/gas.exp: Run it.

diff --git a/gas/config/tc-spu.c b/gas/config/tc-spu.c
index 474805bc26..6998e2b891 100644
--- a/gas/config/tc-spu.c
+++ b/gas/config/tc-spu.c
@@ -815,6 +815,11 @@ spu_cons (int nbytes)
 
   do
     {
+      char *save = input_line_pointer;
+
+      /* Use deferred_expression here so that an expression involving
+	 a symbol that happens to be defined already as an spu symbol,
+	 is not resolved.  */
       deferred_expression (&exp);
       if ((exp.X_op == O_symbol
 	   || exp.X_op == O_constant)
@@ -829,9 +834,12 @@ spu_cons (int nbytes)
 	    {
 	      expressionS new_exp;
 
+	      save = input_line_pointer;
 	      expression (&new_exp);
 	      if (new_exp.X_op == O_constant)
 		exp.X_add_number += new_exp.X_add_number;
+	      else
+		input_line_pointer = save;
 	    }
 
 	  reloc = nbytes == 4 ? BFD_RELOC_SPU_PPU32 : BFD_RELOC_SPU_PPU64;
@@ -839,7 +847,14 @@ spu_cons (int nbytes)
 		       &exp, 0, reloc);
 	}
       else
-	emit_expr (&exp, nbytes);
+	{
+	  /* Don't use deferred_expression for anything else.
+	     deferred_expression won't evaulate dot at the point it is
+	     used.  */
+	  input_line_pointer = save;
+	  expression (&exp);
+	  emit_expr (&exp, nbytes);
+	}
     }
   while (*input_line_pointer++ == ',');
 
diff --git a/gas/expr.c b/gas/expr.c
index 074e0b3f0b..bacfa4e9e8 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -1838,6 +1838,13 @@ expr (int rankarg,		/* Larger # is higher rank.  */
 	  right.X_op_symbol = NULL;
 	}
 
+      if (mode == expr_defer
+	  && ((resultP->X_add_symbol != NULL
+	       && S_IS_FORWARD_REF (resultP->X_add_symbol))
+	      || (right.X_add_symbol != NULL
+		  && S_IS_FORWARD_REF (right.X_add_symbol))))
+	goto general;
+
       /* Optimize common cases.  */
 #ifdef md_optimize_expr
       if (md_optimize_expr (resultP, op_left, &right))
diff --git a/gas/testsuite/gas/all/eqv-dot.d b/gas/testsuite/gas/all/eqv-dot.d
new file mode 100644
index 0000000000..154530348e
--- /dev/null
+++ b/gas/testsuite/gas/all/eqv-dot.d
@@ -0,0 +1,12 @@
+#objdump: -s -j .data
+#name: eqv involving dot
+# bfin doesn't support 'symbol = expression'
+# tic4x has 4 octets per byte
+#notarget: bfin-*-* tic4x-*-*
+
+.*: .*
+
+Contents of section \.data:
+ 0000 (0+00 0+01 0+02 0+0c|000+ 010+ 020+ 0c0+) .*
+ 0010 (0+10 0+14 0+10 0+1c|100+ 140+ 100+ 1c0+) .*
+#pass
diff --git a/gas/testsuite/gas/all/eqv-dot.s b/gas/testsuite/gas/all/eqv-dot.s
new file mode 100644
index 0000000000..cd8cb9198b
--- /dev/null
+++ b/gas/testsuite/gas/all/eqv-dot.s
@@ -0,0 +1,8 @@
+	.data
+x:	.long 0, 1, 2, . - x
+ y = . - x
+ z == . - x
+	.long y
+	.long z
+	.long y
+	.long z
diff --git a/gas/testsuite/gas/all/gas.exp b/gas/testsuite/gas/all/gas.exp
index c1237f9054..74988a1297 100644
--- a/gas/testsuite/gas/all/gas.exp
+++ b/gas/testsuite/gas/all/gas.exp
@@ -91,6 +91,7 @@ case $target_triplet in {
 
 gas_test "eqv-ok.s" "" "" ".eqv support"
 gas_test_error "eqv-bad.s" "" ".eqv for symbol already set"
+run_dump_test eqv-dot
 
 if { ![istarget "bfin-*-*"] } then {
     gas_test "assign-ok.s" "" "" "== assignment support"

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list