PR gas/827
authorAlan Modra <amodra@gmail.com>
Sat, 9 Apr 2005 03:48:09 +0000 (03:48 +0000)
committerAlan Modra <amodra@gmail.com>
Sat, 9 Apr 2005 03:48:09 +0000 (03:48 +0000)
* 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.

gas/ChangeLog
gas/as.h
gas/read.c
gas/stabs.c
gas/symbols.c
gas/symbols.h

index 9e8a6c47dbeec062c8d5b84c1187789a93d05b15..ba7b8d5d5123e7ede63a9f7d981ede3d88dd1649 100644 (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
index cbd04721196388a7c72a4add7f4e33cc720ee3be..f3fde9b9a7d99976ed7496a14071efd8bc117383 100644 (file)
--- 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
index f2b01be804253caaae2f0719b7fe679677b34f25..414d3abf9a80eafc94abe5954680dc68d42de231 100644 (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 */
 }
 \f
 /*                     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.  */
index c63702f47c1cf203e696ad111446d3bdc2ae39b7..1afb2368a7fc2079dcce1202b87b2572df5665b7 100644 (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
index 3093c01548a268102b560c8e5fd0bbf3c840a6e5..bf47ebb745db5dd19c2d7669627b3533aedb6214 100644 (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
index b95ec248a25e97454d7bda6d71a9f6b97f67b812..eb5a85254aaeb820f2b9ab821b3a04728dbf9eab 100644 (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 *);