From: Alan Modra Date: Sat, 9 Apr 2005 03:48:09 +0000 (+0000) Subject: PR gas/827 X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=be95a9c15d32e35e7529c6a4e035e60398184b99;p=deliverable%2Fbinutils-gdb.git 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. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 9e8a6c47db..ba7b8d5d51 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,21 @@ +2005-04-09 Alan Modra + + 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 * config/tc-xtensa.c (xtensa_create_xproperty_segments): Skip diff --git a/gas/as.h b/gas/as.h index cbd0472119..f3fde9b9a7 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 f2b01be804..414d3abf9a 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 c63702f47c..1afb2368a7 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 3093c01548..bf47ebb745 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 b95ec248a2..eb5a85254a 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 *);