From: Alan Modra Date: Sat, 20 Oct 2018 00:42:46 +0000 (+1030) Subject: PR23800, .eqv doesn't always defer expression evaluation X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e4c2619ad1f31cf73d275b027e8c0cf9c6e9597a;p=binutils-gdb.git PR23800, .eqv doesn't always defer expression evaluation .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. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 0ae0206dd4c..71dd3b85bca 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,14 @@ +2018-10-20 Alan Modra + + 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 * testsuite/gas/arm/undefined-insn-arm.d: Widen pe skip. diff --git a/gas/config/tc-spu.c b/gas/config/tc-spu.c index 474805bc267..6998e2b8918 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 074e0b3f0b5..bacfa4e9e82 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 00000000000..154530348e1 --- /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 00000000000..cd8cb9198b0 --- /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 c1237f9054e..74988a1297d 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"