aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog18
-rw-r--r--gas/as.h5
-rw-r--r--gas/read.c235
-rw-r--r--gas/stabs.c5
-rw-r--r--gas/symbols.c13
-rw-r--r--gas/symbols.h3
6 files changed, 149 insertions, 130 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 9e8a6c4..ba7b8d5 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,21 @@
+2005-04-09 Alan Modra <amodra@bigpond.net.au>
+
+ PR gas/827
+ * as.h (rs_dummy): Define.
+ * symbols.c (symbol_X_add_number): New function.
+ * symbols.h (symbol_X_add_number): Declare.
+ * stabs.c (aout_process_stab): Tidy symbol frag setting.
+ * read.c (assign_symbol): New function, split out from s_set.
+ Use symbol_find_or_make. Leave fr_type of dummy frag as rs_dummy.
+ Fix COFF hacks for multi-emulation gas.
+ (s_set): Call assign_symbol. Remove "register" keyword.
+ (set_zero_frag): New function.
+ (pseudo_set): Always check for assignment to section syms.
+ Always set segment and frag of symbol, and likewise extern for
+ aout/bout. Handle assignment of sym=sym+/-const specially. Don't
+ special case exp.X_add_number non-zero for O_symbol expressions.
+ (equals): Use assign_symbol.
+
2005-04-08 Bob Wilson <bob.wilson@acm.org>
* config/tc-xtensa.c (xtensa_create_xproperty_segments): Skip
diff --git a/gas/as.h b/gas/as.h
index cbd0472..f3fde9b 100644
--- a/gas/as.h
+++ b/gas/as.h
@@ -324,10 +324,13 @@ extern segT text_section, data_section, bss_section;
enum _relax_state
{
+ /* Dummy frag used by listing code. */
+ rs_dummy = 0,
+
/* Variable chars to be repeated fr_offset times.
Fr_symbol unused. Used with fr_offset == 0 for a
constant length frag. */
- rs_fill = 1,
+ rs_fill,
/* Align. The fr_offset field holds the power of 2 to which to
align. The fr_var field holds the number of characters in the
diff --git a/gas/read.c b/gas/read.c
index f2b01be..414d3ab 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -2747,6 +2747,62 @@ end_repeat (int extra)
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
+static void
+assign_symbol (const char *name, int no_reassign)
+{
+ symbolS *symbolP;
+
+ if (name[0] == '.' && name[1] == '\0')
+ {
+ /* Turn '. = mumble' into a .org mumble. */
+ segT segment;
+ expressionS exp;
+
+ segment = get_known_segmented_expression (&exp);
+
+ if (!need_pass_2)
+ do_org (segment, &exp, 0);
+
+ return;
+ }
+
+ if ((symbolP = symbol_find (name)) == NULL
+ && (symbolP = md_undefined_symbol (name)) == NULL)
+ {
+ symbolP = symbol_find_or_make (name);
+#ifndef NO_LISTING
+ /* When doing symbol listings, play games with dummy fragments living
+ outside the normal fragment chain to record the file and line info
+ for this symbol. */
+ if (listing & LISTING_SYMBOLS)
+ {
+ extern struct list_info_struct *listing_tail;
+ fragS *dummy_frag = (fragS *) xcalloc (sizeof (fragS));
+ dummy_frag->line = listing_tail;
+ dummy_frag->fr_symbol = symbolP;
+ symbol_set_frag (symbolP, dummy_frag);
+ }
+#endif
+#if defined (OBJ_COFF) || defined (OBJ_MAYBE_COFF)
+#if defined (BFD_ASSEMBLER) && defined (OBJ_MAYBE_COFF)
+ if (OUTPUT_FLAVOR == bfd_target_coff_flavour)
+#endif
+ /* "set" symbols are local unless otherwise specified. */
+ SF_SET_LOCAL (symbolP);
+#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);
+
+ pseudo_set (symbolP);
+
+ demand_empty_rest_of_line ();
+}
+
/* 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. */
@@ -2754,10 +2810,9 @@ end_repeat (int extra)
void
s_set (int equiv)
{
- register char *name;
- register char delim;
- register char *end_name;
- register symbolS *symbolP;
+ char *name;
+ char delim;
+ char *end_name;
/* Especial apologies for the random logic:
this just grew, and could be parsed much more simply!
@@ -2788,59 +2843,8 @@ s_set (int equiv)
input_line_pointer++;
*end_name = 0;
- if (name[0] == '.' && name[1] == '\0')
- {
- /* Turn '. = mumble' into a .org mumble. */
- register segT segment;
- expressionS exp;
-
- segment = get_known_segmented_expression (&exp);
-
- if (!need_pass_2)
- do_org (segment, &exp, 0);
-
- *end_name = delim;
- return;
- }
-
- if ((symbolP = symbol_find (name)) == NULL
- && (symbolP = md_undefined_symbol (name)) == NULL)
- {
-#ifndef NO_LISTING
- /* When doing symbol listings, play games with dummy fragments living
- outside the normal fragment chain to record the file and line info
- for this symbol. */
- if (listing & LISTING_SYMBOLS)
- {
- extern struct list_info_struct *listing_tail;
- fragS *dummy_frag = (fragS *) xmalloc (sizeof (fragS));
- memset (dummy_frag, 0, sizeof (fragS));
- dummy_frag->fr_type = rs_fill;
- dummy_frag->line = listing_tail;
- symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
- dummy_frag->fr_symbol = symbolP;
- }
- else
-#endif
- symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
-
-#ifdef OBJ_COFF
- /* "set" symbols are local unless otherwise specified. */
- SF_SET_LOCAL (symbolP);
-#endif /* OBJ_COFF */
- }
-
- symbol_table_insert (symbolP);
-
+ assign_symbol (name, equiv);
*end_name = delim;
-
- if (equiv
- && S_IS_DEFINED (symbolP)
- && S_GET_SEGMENT (symbolP) != reg_section)
- as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
-
- pseudo_set (symbolP);
- demand_empty_rest_of_line ();
}
void
@@ -3177,6 +3181,16 @@ discard_rest_of_line (void)
know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
}
+/* Sets frag for given symbol to zero_address_frag, except when the
+ symbol frag is already set to a dummy listing frag. */
+
+static void
+set_zero_frag (symbolS *symbolP)
+{
+ if (symbol_get_frag (symbolP)->fr_type != rs_dummy)
+ symbol_set_frag (symbolP, &zero_address_frag);
+}
+
/* In: Pointer to a symbol.
Input_line_pointer->expression.
@@ -3188,14 +3202,12 @@ void
pseudo_set (symbolS *symbolP)
{
expressionS exp;
+ segT seg;
#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
int ext;
#endif /* OBJ_AOUT or OBJ_BOUT */
know (symbolP); /* NULL pointer is logic error. */
-#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
- ext = S_IS_EXTERNAL (symbolP);
-#endif /* OBJ_AOUT or OBJ_BOUT */
(void) expression (&exp);
@@ -3220,6 +3232,15 @@ pseudo_set (symbolS *symbolP)
- S_GET_VALUE (exp.X_op_symbol));
}
+ if (symbol_section_p (symbolP))
+ {
+ as_bad ("attempt to set value of section symbol");
+ return;
+ }
+#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
+ ext = S_IS_EXTERNAL (symbolP);
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
switch (exp.X_op)
{
case O_illegal:
@@ -3229,53 +3250,55 @@ pseudo_set (symbolS *symbolP)
/* Fall through. */
case O_constant:
S_SET_SEGMENT (symbolP, absolute_section);
-#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
- if (ext)
- S_SET_EXTERNAL (symbolP);
- else
- S_CLEAR_EXTERNAL (symbolP);
-#endif /* OBJ_AOUT or OBJ_BOUT */
S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
- if (exp.X_op != O_constant)
- symbol_set_frag (symbolP, &zero_address_frag);
+ set_zero_frag (symbolP);
break;
case O_register:
S_SET_SEGMENT (symbolP, reg_section);
S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
- symbol_set_frag (symbolP, &zero_address_frag);
+ set_zero_frag (symbolP);
break;
case O_symbol:
- if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section
- || exp.X_add_number != 0)
- symbol_set_value_expression (symbolP, &exp);
- else if (symbol_section_p (symbolP))
- as_bad ("attempt to set value of section symbol");
- else
+ seg = S_GET_SEGMENT (exp.X_add_symbol);
+ /* For x=undef+const, create an expression symbol.
+ For x=x+const, just update x except when x is an undefined symbol
+ For x=defined+const, evaluate x. */
+ if (symbolP == exp.X_add_symbol
+ && (seg != undefined_section
+ || !symbol_constant_p (symbolP)))
+ {
+ *symbol_X_add_number (symbolP) += exp.X_add_number;
+ break;
+ }
+ else if (seg != undefined_section)
{
symbolS *s = exp.X_add_symbol;
- S_SET_SEGMENT (symbolP, S_GET_SEGMENT (s));
-#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
- if (ext)
- S_SET_EXTERNAL (symbolP);
- else
- S_CLEAR_EXTERNAL (symbolP);
-#endif /* OBJ_AOUT or OBJ_BOUT */
- S_SET_VALUE (symbolP,
- exp.X_add_number + S_GET_VALUE (s));
+ S_SET_SEGMENT (symbolP, seg);
+ S_SET_VALUE (symbolP, exp.X_add_number + S_GET_VALUE (s));
symbol_set_frag (symbolP, symbol_get_frag (s));
copy_symbol_attributes (symbolP, s);
+ break;
}
- break;
+ /* Fall thru */
default:
/* The value is some complex expression.
- FIXME: Should we set the segment to anything? */
+ Set segment and frag back to that of a newly created symbol. */
+ S_SET_SEGMENT (symbolP, undefined_section);
symbol_set_value_expression (symbolP, &exp);
+ set_zero_frag (symbolP);
break;
}
+
+#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
+ if (ext)
+ S_SET_EXTERNAL (symbolP);
+ else
+ S_CLEAR_EXTERNAL (symbolP);
+#endif /* OBJ_AOUT or OBJ_BOUT */
}
/* cons()
@@ -4884,7 +4907,6 @@ is_it_end_of_statement (void)
void
equals (char *sym_name, int reassign)
{
- register symbolS *symbolP; /* Symbol we are working with. */
char *stop = NULL;
char stopc;
@@ -4898,47 +4920,10 @@ equals (char *sym_name, int reassign)
if (flag_mri)
stop = mri_comment_field (&stopc);
- if (sym_name[0] == '.' && sym_name[1] == '\0')
- {
- /* Turn '. = mumble' into a .org mumble. */
- register segT segment;
- expressionS exp;
-
- segment = get_known_segmented_expression (&exp);
- if (!need_pass_2)
- do_org (segment, &exp, 0);
- }
- else
- {
-#ifdef OBJ_COFF
- int local;
-
- symbolP = symbol_find (sym_name);
- local = symbolP == NULL;
- if (local)
-#endif /* OBJ_COFF */
- symbolP = symbol_find_or_make (sym_name);
- /* Permit register names to be redefined. */
- if (!reassign
- && S_IS_DEFINED (symbolP)
- && S_GET_SEGMENT (symbolP) != reg_section)
- as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
-
-#ifdef OBJ_COFF
- /* "set" symbols are local unless otherwise specified. */
- if (local)
- SF_SET_LOCAL (symbolP);
-#endif /* OBJ_COFF */
-
- pseudo_set (symbolP);
- }
+ assign_symbol (sym_name, !reassign);
if (flag_mri)
- {
- /* Check garbage after the expression. */
- demand_empty_rest_of_line ();
- mri_comment_end (stop, stopc);
- }
+ mri_comment_end (stop, stopc);
}
/* .incbin -- include a file verbatim at the current location. */
diff --git a/gas/stabs.c b/gas/stabs.c
index c63702f..1afb236 100644
--- a/gas/stabs.c
+++ b/gas/stabs.c
@@ -1,6 +1,6 @@
/* Generic stabs parsing for gas.
Copyright 1989, 1990, 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001
- 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -150,11 +150,10 @@ aout_process_stab (what, string, type, other, desc)
ends in "\" and the debug info is continued in the next .stabs
directive) from being separated by other random symbols. */
symbol = symbol_create (string, undefined_section, 0,
- (struct frag *) NULL);
+ &zero_address_frag);
if (what == 's' || what == 'n')
{
/* Pick up the value from the input line. */
- symbol_set_frag (symbol, &zero_address_frag);
pseudo_set (symbol);
}
else
diff --git a/gas/symbols.c b/gas/symbols.c
index 3093c01..bf47ebb 100644
--- a/gas/symbols.c
+++ b/gas/symbols.c
@@ -2022,6 +2022,19 @@ symbol_set_value_expression (symbolS *s, const expressionS *exp)
s->sy_value = *exp;
}
+/* Return a pointer to the X_add_number component of a symbol. */
+
+valueT *
+symbol_X_add_number (symbolS *s)
+{
+#ifdef BFD_ASSEMBLER
+ if (LOCAL_SYMBOL_CHECK (s))
+ return &((struct local_symbol *) s)->lsy_value;
+#endif
+
+ return &s->sy_value.X_add_number;
+}
+
/* Set the value of SYM to the current position in the current segment. */
void
diff --git a/gas/symbols.h b/gas/symbols.h
index b95ec24..eb5a852 100644
--- a/gas/symbols.h
+++ b/gas/symbols.h
@@ -1,6 +1,6 @@
/* symbols.h -
Copyright 1987, 1990, 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001,
- 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -175,6 +175,7 @@ extern symbolS *symbol_next (symbolS *);
extern expressionS *symbol_get_value_expression (symbolS *);
extern void symbol_set_value_expression (symbolS *, const expressionS *);
+extern valueT *symbol_X_add_number (symbolS *);
extern void symbol_set_value_now (symbolS *);
extern void symbol_set_frag (symbolS *, fragS *);
extern fragS *symbol_get_frag (symbolS *);