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> 2005-04-08 Bob Wilson <bob.wilson@acm.org>
* config/tc-xtensa.c (xtensa_create_xproperty_segments): Skip * 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 enum _relax_state
{ {
/* Dummy frag used by listing code. */
rs_dummy = 0,
/* Variable chars to be repeated fr_offset times. /* Variable chars to be repeated fr_offset times.
Fr_symbol unused. Used with fr_offset == 0 for a Fr_symbol unused. Used with fr_offset == 0 for a
constant length frag. */ constant length frag. */
rs_fill = 1, rs_fill,
/* Align. The fr_offset field holds the power of 2 to which to /* 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 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); 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 /* 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 this is .equiv, and it is an error if the symbol is already
defined. */ defined. */
@ -2754,10 +2810,9 @@ end_repeat (int extra)
void void
s_set (int equiv) s_set (int equiv)
{ {
register char *name; char *name;
register char delim; char delim;
register char *end_name; char *end_name;
register symbolS *symbolP;
/* Especial apologies for the random logic: /* Especial apologies for the random logic:
this just grew, and could be parsed much more simply! this just grew, and could be parsed much more simply!
@ -2788,59 +2843,8 @@ s_set (int equiv)
input_line_pointer++; input_line_pointer++;
*end_name = 0; *end_name = 0;
if (name[0] == '.' && name[1] == '\0') assign_symbol (name, equiv);
{
/* 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; *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);
*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 void
@ -3177,6 +3181,16 @@ discard_rest_of_line (void)
know (is_end_of_line[(unsigned char) input_line_pointer[-1]]); 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. /* In: Pointer to a symbol.
Input_line_pointer->expression. Input_line_pointer->expression.
@ -3188,14 +3202,12 @@ void
pseudo_set (symbolS *symbolP) pseudo_set (symbolS *symbolP)
{ {
expressionS exp; expressionS exp;
segT seg;
#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER) #if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
int ext; int ext;
#endif /* OBJ_AOUT or OBJ_BOUT */ #endif /* OBJ_AOUT or OBJ_BOUT */
know (symbolP); /* NULL pointer is logic error. */ 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); (void) expression (&exp);
@ -3220,6 +3232,15 @@ pseudo_set (symbolS *symbolP)
- S_GET_VALUE (exp.X_op_symbol)); - 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) switch (exp.X_op)
{ {
case O_illegal: case O_illegal:
@ -3229,53 +3250,55 @@ pseudo_set (symbolS *symbolP)
/* Fall through. */ /* Fall through. */
case O_constant: case O_constant:
S_SET_SEGMENT (symbolP, absolute_section); 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); S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
if (exp.X_op != O_constant) set_zero_frag (symbolP);
symbol_set_frag (symbolP, &zero_address_frag);
break; break;
case O_register: case O_register:
S_SET_SEGMENT (symbolP, reg_section); S_SET_SEGMENT (symbolP, reg_section);
S_SET_VALUE (symbolP, (valueT) exp.X_add_number); S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
symbol_set_frag (symbolP, &zero_address_frag); set_zero_frag (symbolP);
break; break;
case O_symbol: case O_symbol:
if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section seg = S_GET_SEGMENT (exp.X_add_symbol);
|| exp.X_add_number != 0) /* For x=undef+const, create an expression symbol.
symbol_set_value_expression (symbolP, &exp); For x=x+const, just update x except when x is an undefined symbol
else if (symbol_section_p (symbolP)) For x=defined+const, evaluate x. */
as_bad ("attempt to set value of section symbol"); if (symbolP == exp.X_add_symbol
else && (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; symbolS *s = exp.X_add_symbol;
S_SET_SEGMENT (symbolP, S_GET_SEGMENT (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;
}
/* Fall thru */
default:
/* The value is some complex expression.
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 (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
if (ext) if (ext)
S_SET_EXTERNAL (symbolP); S_SET_EXTERNAL (symbolP);
else else
S_CLEAR_EXTERNAL (symbolP); S_CLEAR_EXTERNAL (symbolP);
#endif /* OBJ_AOUT or OBJ_BOUT */ #endif /* OBJ_AOUT or OBJ_BOUT */
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;
default:
/* The value is some complex expression.
FIXME: Should we set the segment to anything? */
symbol_set_value_expression (symbolP, &exp);
break;
}
} }
/* cons() /* cons()
@ -4884,7 +4907,6 @@ is_it_end_of_statement (void)
void void
equals (char *sym_name, int reassign) equals (char *sym_name, int reassign)
{ {
register symbolS *symbolP; /* Symbol we are working with. */
char *stop = NULL; char *stop = NULL;
char stopc; char stopc;
@ -4898,48 +4920,11 @@ equals (char *sym_name, int reassign)
if (flag_mri) if (flag_mri)
stop = mri_comment_field (&stopc); stop = mri_comment_field (&stopc);
if (sym_name[0] == '.' && sym_name[1] == '\0') assign_symbol (sym_name, !reassign);
{
/* 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);
}
if (flag_mri) 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. */ /* .incbin -- include a file verbatim at the current location. */

View File

@ -1,6 +1,6 @@
/* Generic stabs parsing for gas. /* Generic stabs parsing for gas.
Copyright 1989, 1990, 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001 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. 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 ends in "\" and the debug info is continued in the next .stabs
directive) from being separated by other random symbols. */ directive) from being separated by other random symbols. */
symbol = symbol_create (string, undefined_section, 0, symbol = symbol_create (string, undefined_section, 0,
(struct frag *) NULL); &zero_address_frag);
if (what == 's' || what == 'n') if (what == 's' || what == 'n')
{ {
/* Pick up the value from the input line. */ /* Pick up the value from the input line. */
symbol_set_frag (symbol, &zero_address_frag);
pseudo_set (symbol); pseudo_set (symbol);
} }
else else

View File

@ -2022,6 +2022,19 @@ symbol_set_value_expression (symbolS *s, const expressionS *exp)
s->sy_value = *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. */ /* Set the value of SYM to the current position in the current segment. */
void void

View File

@ -1,6 +1,6 @@
/* symbols.h - /* symbols.h -
Copyright 1987, 1990, 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001, 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. 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 expressionS *symbol_get_value_expression (symbolS *);
extern void symbol_set_value_expression (symbolS *, const expressionS *); 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_value_now (symbolS *);
extern void symbol_set_frag (symbolS *, fragS *); extern void symbol_set_frag (symbolS *, fragS *);
extern fragS *symbol_get_frag (symbolS *); extern fragS *symbol_get_frag (symbolS *);