forked from Imagelibrary/binutils-gdb
gas: equates of registers
There are two problems: symbol_equated_p() doesn't recognize equates of
registers, and S_CAN_BE_REDEFINED() goes by section rather than by
expression type. Both together undermine .eqv and .equiv clearly meaning
to guard the involved symbols against re-definition (both ways).
To compensate pseudo_set() now using O_symbol and S_CAN_BE_REDEFINED()
now checking for O_register,
- for targets creating register symbols through symbol_{new,create}() ->
symbol_init() -> S_SET_VALUE() (alpha, arc, dlx, ia64, m68k, mips,
mmix, tic4x, tic54x, plus anything using cgen or itbl-ops), have
symbol_init() set their expressions to O_register,
- x86'es parse_register() also can't go by section anymore when
trying to "look through" equates; probably symbol_equated_p() should
have been used there from the beginning, if only that had worked for
equates of registers,
- various targets need to "look through" equates when parsing insn
operands (which also helps transitive forward equates); perhaps even
more ought to, but many don't look to consider the possibility of
register equates in the first place.
This was uncovered by code reported in PR gas/30274 (duplicating
PR gas/30272), except that there .eqv was used when really .equ was
meant. Therefore that bug report is addressed here only in so far as
gas wouldn't crash anymore; the code there still won't assemble
successfully, just that now the issues there are properly diagnosed.
This commit is contained in:
25
gas/expr.c
25
gas/expr.c
@@ -2382,6 +2382,31 @@ resolve_expression (expressionS *expressionP)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* "Look through" register equates. */
|
||||
void resolve_register (expressionS *expP)
|
||||
{
|
||||
symbolS *sym;
|
||||
offsetT acc = 0;
|
||||
const expressionS *e = expP;
|
||||
|
||||
if (expP->X_op != O_symbol)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
sym = e->X_add_symbol;
|
||||
acc += e->X_add_number;
|
||||
e = symbol_get_value_expression (sym);
|
||||
}
|
||||
while (symbol_equated_p (sym));
|
||||
|
||||
if (e->X_op == O_register)
|
||||
{
|
||||
*expP = *e;
|
||||
expP->X_add_number += acc;
|
||||
}
|
||||
}
|
||||
|
||||
/* This lives here because it belongs equally in expr.c & read.c.
|
||||
expr.c is just a branch office read.c anyway, and putting it
|
||||
|
||||
Reference in New Issue
Block a user