This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Fix PR gas/827


On Wed, Apr 06, 2005 at 10:06:10AM -0400, Ian Lance Taylor wrote:
> Alan Modra <amodra@bigpond.net.au> writes:
> > on any assignment to section symbols.  Another oddity is special casing
> > sym1 = sym2 + const for const == 0.  When const != 0, the old code
> > created an expression symbol, and I can't see the reason for that.  Ian,
> > do you know why this was done?
> 
> No, I don't.  It's particularly odd since the subsequent code is
> careful to add in exp.X_add_number.

Yes, I noticed that.  This is what I'm going to commit.  Differs from
the last posted patch by disallowing undef=undef+const and always sets
segment and frag of symbol in s_set.  I pulled the common parts of s_set
and s_equal out into a new function too.

	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.

Index: gas/as.h
===================================================================
RCS file: /cvs/src/src/gas/as.h,v
retrieving revision 1.45
diff -u -p -r1.45 as.h
--- gas/as.h	30 Mar 2005 02:55:12 -0000	1.45
+++ gas/as.h	8 Apr 2005 06:04:49 -0000
@@ -324,10 +324,13 @@ extern segT text_section, data_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: gas/symbols.c
===================================================================
RCS file: /cvs/src/src/gas/symbols.c,v
retrieving revision 1.56
diff -u -p -r1.56 symbols.c
--- gas/symbols.c	2 Mar 2005 00:11:30 -0000	1.56
+++ gas/symbols.c	8 Apr 2005 06:04:53 -0000
@@ -2022,6 +2022,19 @@ symbol_set_value_expression (symbolS *s,
   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: gas/symbols.h
===================================================================
RCS file: /cvs/src/src/gas/symbols.h,v
retrieving revision 1.16
diff -u -p -r1.16 symbols.h
--- gas/symbols.h	8 Nov 2004 08:12:44 -0000	1.16
+++ gas/symbols.h	8 Apr 2005 06:04:53 -0000
@@ -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 *);
Index: gas/stabs.c
===================================================================
RCS file: /cvs/src/src/gas/stabs.c,v
retrieving revision 1.24
diff -u -p -r1.24 stabs.c
--- gas/stabs.c	3 Mar 2005 01:29:53 -0000	1.24
+++ gas/stabs.c	8 Apr 2005 07:18:27 -0000
@@ -150,11 +150,10 @@ aout_process_stab (what, string, type, o
      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: gas/read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.94
diff -u -p -r1.94 read.c
--- gas/read.c	1 Mar 2005 02:00:14 -0000	1.94
+++ gas/read.c	8 Apr 2005 07:18:27 -0000
@@ -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.  */

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]