aboutsummaryrefslogtreecommitdiff
path: root/gas/read.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2005-10-11 11:16:17 +0000
committerNick Clifton <nickc@redhat.com>2005-10-11 11:16:17 +0000
commit9497f5ac6bc10bdd65ea471787619bde1edca77d (patch)
tree7f36b3cb6f0d84b058dfba51242bd900edde9503 /gas/read.c
parent1334d4d50c52bc295dace4982442369838f478b3 (diff)
downloadfsf-binutils-gdb-9497f5ac6bc10bdd65ea471787619bde1edca77d.zip
fsf-binutils-gdb-9497f5ac6bc10bdd65ea471787619bde1edca77d.tar.gz
fsf-binutils-gdb-9497f5ac6bc10bdd65ea471787619bde1edca77d.tar.bz2
This adjusts equate handling by
- allowing true forward references (which will always assume the referenced symbols have at the point of use) through the new .eqv pseudo-op and the new == operator - disallowing changing .equiv-generated equates (so that the protection this provides is both forward and backward) - snapshotting equates when their value gets changed so that previous uses don't get affected by the new value. - allowing expressions in places where absolute expressions (or register names) are needed which were not completely resolvable at the point of their definition but which are fully resolvable at the point of use In addition it fixes PR/288.
Diffstat (limited to 'gas/read.c')
-rw-r--r--gas/read.c66
1 files changed, 52 insertions, 14 deletions
diff --git a/gas/read.c b/gas/read.c
index 8e4e1bc..00f676f 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -323,6 +323,7 @@ static const pseudo_typeS potable[] = {
/* endef */
{"equ", s_set, 0},
{"equiv", s_set, 1},
+ {"eqv", s_set, -1},
{"err", s_err, 0},
{"error", s_errwarn, 1},
{"exitm", s_mexit, 0},
@@ -441,7 +442,7 @@ static const pseudo_typeS potable[] = {
static offsetT
get_absolute_expr (expressionS *exp)
{
- expression (exp);
+ expression_and_evaluate (exp);
if (exp->X_op != O_constant)
{
if (exp->X_op != O_absent)
@@ -787,6 +788,14 @@ read_a_source_file (char *name)
/* Input_line_pointer->after ':'. */
SKIP_WHITESPACE ();
}
+ else if (input_line_pointer[1] == '='
+ && (c == '='
+ || ((c == ' ' || c == '\t')
+ && input_line_pointer[2] == '=')))
+ {
+ equals (s, -1);
+ demand_empty_rest_of_line ();
+ }
else if ((c == '='
|| ((c == ' ' || c == '\t')
&& input_line_pointer[1] == '='))
@@ -2210,7 +2219,7 @@ s_lsym (int ignore ATTRIBUTE_UNUSED)
}
input_line_pointer++;
- expression (&exp);
+ expression_and_evaluate (&exp);
if (exp.X_op != O_constant
&& exp.X_op != O_register)
@@ -2743,7 +2752,7 @@ end_repeat (int extra)
}
static void
-assign_symbol (char *name, int no_reassign)
+assign_symbol (char *name, int mode)
{
symbolS *symbolP;
@@ -2784,18 +2793,37 @@ assign_symbol (char *name, int no_reassign)
#endif
}
- /* Permit register names to be redefined. */
- if (no_reassign
- && S_IS_DEFINED (symbolP)
- && S_GET_SEGMENT (symbolP) != reg_section)
- as_bad (_("symbol `%s' is already defined"), name);
+ if (S_IS_DEFINED (symbolP))
+ {
+ /* Permit register names to be redefined. */
+ if ((mode != 0 || !S_IS_VOLATILE (symbolP))
+ && S_GET_SEGMENT (symbolP) != reg_section)
+ {
+ as_bad (_("symbol `%s' is already defined"), name);
+ symbolP = symbol_clone (symbolP, 0);
+ }
+ /* If the symbol is volatile, copy the symbol and replace the
+ original with the copy, so that previous uses of the symbol will
+ retain the value of the symbol at the point of use. */
+ else if (S_IS_VOLATILE (symbolP)
+ /* This could be avoided when the symbol wasn't used so far, but
+ the comment in struc-symbol.h says this flag isn't reliable. */
+ && (1 || symbol_used_p (symbolP)))
+ symbolP = symbol_clone (symbolP, 1);
+ }
+
+ if (mode == 0)
+ S_SET_VOLATILE (symbolP);
+ else if (mode < 0)
+ S_SET_FORWARD_REF (symbolP);
pseudo_set (symbolP);
}
-/* Handle the .equ, .equiv and .set directives. If EQUIV is 1, then
- this is .equiv, and it is an error if the symbol is already
- defined. */
+/* Handle the .equ, .equiv, .eqv, and .set directives. If EQUIV is 1,
+ then this is .equiv, and it is an error if the symbol is already
+ defined. If EQUIV is -1, the symbol additionally is a forward
+ reference. */
void
s_set (int equiv)
@@ -2917,6 +2945,7 @@ s_space (int mult)
|| val.X_add_number > 0xff
|| (mult != 0 && mult != 1 && val.X_add_number != 0))
{
+ resolve_expression (&exp);
if (exp.X_op != O_constant)
as_bad (_("unsupported variable size or fill value"));
else
@@ -2932,6 +2961,9 @@ s_space (int mult)
}
else
{
+ if (now_seg == absolute_section || mri_common_symbol != NULL)
+ resolve_expression (&exp);
+
if (exp.X_op == O_constant)
{
long repeat;
@@ -3185,7 +3217,10 @@ pseudo_set (symbolS *symbolP)
know (symbolP); /* NULL pointer is logic error. */
- (void) expression (&exp);
+ if (!S_IS_FORWARD_REF (symbolP))
+ (void) expression (&exp);
+ else
+ (void) deferred_expression (&exp);
if (exp.X_op == O_illegal)
as_bad (_("illegal expression"));
@@ -3199,6 +3234,7 @@ pseudo_set (symbolS *symbolP)
as_bad (_("floating point number invalid"));
}
else if (exp.X_op == O_subtract
+ && !S_IS_FORWARD_REF (symbolP)
&& SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol))
&& (symbol_get_frag (exp.X_add_symbol)
== symbol_get_frag (exp.X_op_symbol)))
@@ -3245,7 +3281,7 @@ pseudo_set (symbolS *symbolP)
*symbol_X_add_number (symbolP) += exp.X_add_number;
break;
}
- else if (seg != undefined_section)
+ else if (!S_IS_FORWARD_REF (symbolP) && seg != undefined_section)
{
symbolS *s = exp.X_add_symbol;
@@ -4838,6 +4874,8 @@ equals (char *sym_name, int reassign)
input_line_pointer++;
if (*input_line_pointer == '=')
input_line_pointer++;
+ if (reassign < 0 && *input_line_pointer == '=')
+ input_line_pointer++;
while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
input_line_pointer++;
@@ -4845,7 +4883,7 @@ equals (char *sym_name, int reassign)
if (flag_mri)
stop = mri_comment_field (&stopc);
- assign_symbol (sym_name, !reassign);
+ assign_symbol (sym_name, reassign >= 0 ? !reassign : reassign);
if (flag_mri)
{