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.
This commit is contained in:
Alan Modra 2005-04-09 03:48:09 +00:00
parent f0885a038a
commit be95a9c15d
6 changed files with 149 additions and 130 deletions

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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

View File

@ -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 *);