PR23800, .eqv doesn't always defer expression evaluation
authorAlan Modra <amodra@gmail.com>
Sat, 20 Oct 2018 00:42:46 +0000 (11:12 +1030)
committerAlan Modra <amodra@gmail.com>
Sat, 20 Oct 2018 09:16:43 +0000 (19:46 +1030)
.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.

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.

gas/ChangeLog
gas/config/tc-spu.c
gas/expr.c
gas/testsuite/gas/all/eqv-dot.d [new file with mode: 0644]
gas/testsuite/gas/all/eqv-dot.s [new file with mode: 0644]
gas/testsuite/gas/all/gas.exp

index 0ae0206dd4c629569f9b93961a0f433d262fcb9e..71dd3b85bcaf8635b7e8c0fd3257dfacf941bc62 100644 (file)
@@ -1,3 +1,14 @@
+2018-10-20  Alan Modra  <amodra@gmail.com>
+
+       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.
+
 2018-10-19  Tamar Christina  <tamar.christina@arm.com>
 
        * testsuite/gas/arm/undefined-insn-arm.d: Widen pe skip.
index 474805bc26702aba094580e39987331dccaff3ab..6998e2b8918f17e0c0840248b4c1c60c8408a4dd 100644 (file)
@@ -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++ == ',');
 
index 074e0b3f0b5a93f29c79a77a2404946383f725db..bacfa4e9e8220c9dd72a70267a08712de303d31f 100644 (file)
@@ -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 (file)
index 0000000..1545303
--- /dev/null
@@ -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 (file)
index 0000000..cd8cb91
--- /dev/null
@@ -0,0 +1,8 @@
+       .data
+x:     .long 0, 1, 2, . - x
+ y = . - x
+ z == . - x
+       .long y
+       .long z
+       .long y
+       .long z
index c1237f9054e46a48e8ece84acf843e7a6ae9cc32..74988a1297d220f411b7335208f670fb5c2528fb 100644 (file)
@@ -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"