public inbox for gas2@sourceware.org
 help / color / mirror / Atom feed
* Inconsistent behaviour (in resolve_symbol_value?)
@ 1996-08-05  9:31 Richard Earnshaw
  1996-08-07 12:34 ` Ian Lance Taylor
  0 siblings, 1 reply; 2+ messages in thread
From: Richard Earnshaw @ 1996-08-05  9:31 UTC (permalink / raw)
  To: raeburn; +Cc: gas2

The following ARM assembler file should generate errors for both lines, but
only generates an error for the second:

foo.s:
        mov     r0, #1 | bar
        mov     r1, # bar | 1
as.new foo.s
foo.s: Assembler messages:
foo.s:2: Error: L0 set to illegal operation on non-absolute symbols

The problem seems to be the code in resolve_symbol_value that handles
various binary operations.  I'm not sure what the code is trying to check
for so I'm not sure what the fix should be.  Both 'if' clauses involve
checks for undefined sections, but the cases are very specific.  Further,
after the logical operation has been performed the type of the node is
changed to O_constant, so it is no-longer possible to recover the
operation in the back end.

	...
        case O_bit_inclusive_or:
	...
        case O_logical_or:
          resolve_symbol_value (symp->sy_value.X_add_symbol);
          resolve_symbol_value (symp->sy_value.X_op_symbol);
          seg_left = S_GET_SEGMENT (symp->sy_value.X_add_symbol);
          seg_right = S_GET_SEGMENT (symp->sy_value.X_op_symbol);
          if (seg_left != seg_right
              && seg_left != undefined_section
              && seg_right != undefined_section)
            {
              char *file;
              unsigned int line;

              if (expr_symbol_where (symp, &file, &line))
                as_bad_where
                  (file, line,
                   "illegal operation on symbols in different sections");
              else
                as_bad
                  ("%s set to illegal operation on symbols in different section
                   S_GET_NAME (symp));
            }
          if ((S_GET_SEGMENT (symp->sy_value.X_add_symbol)
               != absolute_section)
              && symp->sy_value.X_op != O_subtract)
            {
              char *file;
              unsigned int line;

              if (expr_symbol_where (symp, &file, &line))
                as_bad_where (file, line,
                              "illegal operation on non-absolute symbols");
              else
                as_bad ("%s set to illegal operation on non-absolute symbols",
                        S_GET_NAME (symp));
            }
          left = S_GET_VALUE (symp->sy_value.X_add_symbol);
          right = S_GET_VALUE (symp->sy_value.X_op_symbol);
 	  ...

This is a serious problem for a user, since it quietly generating code that
is incorrect.





^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Inconsistent behaviour (in resolve_symbol_value?)
  1996-08-05  9:31 Inconsistent behaviour (in resolve_symbol_value?) Richard Earnshaw
@ 1996-08-07 12:34 ` Ian Lance Taylor
  0 siblings, 0 replies; 2+ messages in thread
From: Ian Lance Taylor @ 1996-08-07 12:34 UTC (permalink / raw)
  To: richard.earnshaw; +Cc: raeburn, richard.earnshaw, gas2

   Date: Mon, 05 Aug 1996 16:02:35 +0100
   From: Richard Earnshaw <rearnsha@armltd.co.uk>

   The problem seems to be the code in resolve_symbol_value that handles
   various binary operations.  I'm not sure what the code is trying to check
   for so I'm not sure what the fix should be.  Both 'if' clauses involve
   checks for undefined sections, but the cases are very specific.  Further,
   after the logical operation has been performed the type of the node is
   changed to O_constant, so it is no-longer possible to recover the
   operation in the back end.


That code doesn't really make any sense to me either, even though I
wrote it.

I think I'll apply this patch.  It requires that both operands of an
arithmetic operator be absolute, except in the special cases of adding
or subtracting a constant, or subtracting two symbols in the same
section.  Please let me know if this seems to have any problems.

Ian

Index: symbols.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gas/symbols.c,v
retrieving revision 1.86
diff -u -r1.86 symbols.c
--- symbols.c	1996/07/26 15:58:57	1.86
+++ symbols.c	1996/08/07 19:32:08
@@ -639,7 +639,35 @@
 
       symp->sy_resolving = 1;
 
-    reduce:
+      /* Simplify addition or subtraction of a constant by folding the
+         constant into X_add_number.  */
+      if (symp->sy_value.X_op == O_add
+	  || symp->sy_value.X_op == O_subtract)
+	{
+	  resolve_symbol_value (symp->sy_value.X_add_symbol);
+	  resolve_symbol_value (symp->sy_value.X_op_symbol);
+	  if (S_GET_SEGMENT (symp->sy_value.X_op_symbol) == absolute_section)
+	    {
+	      right = S_GET_VALUE (symp->sy_value.X_op_symbol);
+	      if (symp->sy_value.X_op == O_add)
+		symp->sy_value.X_add_number += right;
+	      else
+		symp->sy_value.X_add_number -= right;
+	      symp->sy_value.X_op = O_symbol;
+	      symp->sy_value.X_op_symbol = NULL;
+	    }
+	  else if ((S_GET_SEGMENT (symp->sy_value.X_add_symbol)
+		    == absolute_section)
+		   && symp->sy_value.X_op == O_add)
+	    {
+	      left = S_GET_VALUE (symp->sy_value.X_add_symbol);
+	      symp->sy_value.X_add_symbol = symp->sy_value.X_op_symbol;
+	      symp->sy_value.X_add_number += left;
+	      symp->sy_value.X_op = O_symbol;
+	      symp->sy_value.X_op_symbol = NULL;
+	    }
+	}
+
       switch (symp->sy_value.X_op)
 	{
 	case O_absent:
@@ -708,39 +736,6 @@
 	  resolved = symp->sy_value.X_add_symbol->sy_resolved;
 	  break;
 
-	case O_add:
-	  resolve_symbol_value (symp->sy_value.X_add_symbol);
-	  resolve_symbol_value (symp->sy_value.X_op_symbol);
-	  seg_left = S_GET_SEGMENT (symp->sy_value.X_add_symbol);
-	  seg_right = S_GET_SEGMENT (symp->sy_value.X_op_symbol);
-	  /* This case comes up with PIC support.  */
-	  {
-	    symbolS *s_left = symp->sy_value.X_add_symbol;
-	    symbolS *s_right = symp->sy_value.X_op_symbol;
-
-	    if (seg_left == absolute_section)
-	      {
-		symbolS *t;
-		segT ts;
-		t = s_left;
-		s_left = s_right;
-		s_right = t;
-		ts = seg_left;
-		seg_left = seg_right;
-		seg_right = ts;
-	      }
-	    if (seg_right == absolute_section
-		&& s_right->sy_resolved)
-	      {
-		symp->sy_value.X_add_number += S_GET_VALUE (s_right);
-		symp->sy_value.X_op_symbol = 0;
-		symp->sy_value.X_add_symbol = s_left;
-		symp->sy_value.X_op = O_symbol;
-		goto reduce;
-	      }
-	  }
-	  /* fall through */
-
 	case O_multiply:
 	case O_divide:
 	case O_modulus:
@@ -750,6 +745,7 @@
 	case O_bit_or_not:
 	case O_bit_exclusive_or:
 	case O_bit_and:
+	case O_add:
 	case O_subtract:
 	case O_eq:
 	case O_ne:
@@ -763,38 +759,30 @@
 	  resolve_symbol_value (symp->sy_value.X_op_symbol);
 	  seg_left = S_GET_SEGMENT (symp->sy_value.X_add_symbol);
 	  seg_right = S_GET_SEGMENT (symp->sy_value.X_op_symbol);
-	  if (seg_left != seg_right
-	      && seg_left != undefined_section
-	      && seg_right != undefined_section)
-	    {
-	      char *file;
-	      unsigned int line;
+	  left = S_GET_VALUE (symp->sy_value.X_add_symbol);
+	  right = S_GET_VALUE (symp->sy_value.X_op_symbol);
 
-	      if (expr_symbol_where (symp, &file, &line))
-		as_bad_where
-		  (file, line,
-		   "illegal operation on symbols in different sections");
-	      else
-		as_bad
-		  ("%s set to illegal operation on symbols in different sections",
-		   S_GET_NAME (symp));
-	    }
-	  if ((S_GET_SEGMENT (symp->sy_value.X_add_symbol)
-	       != absolute_section)
-	      && symp->sy_value.X_op != O_subtract)
+	  /* Subtraction is permitted if both operands are in the same
+	     section.  Otherwise, both operands must be absolute.  We
+	     already handled the case of addition or subtraction of a
+	     constant above.  This will probably need to be changed
+	     for an object file format which supports arbitrary
+	     expressions, such as IEEE-695.  */
+	  if ((seg_left != absolute_section
+	       || seg_right != absolute_section)
+	      && (symp->sy_value.X_op != O_subtract
+		  || seg_left != seg_right))
 	    {
 	      char *file;
 	      unsigned int line;
 
 	      if (expr_symbol_where (symp, &file, &line))
-		as_bad_where (file, line,
-			      "illegal operation on non-absolute symbols");
+		as_bad_where (file, line, "invalid section for operation");
 	      else
-		as_bad ("%s set to illegal operation on non-absolute symbols",
+		as_bad ("invalid section for operation setting %s",
 			S_GET_NAME (symp));
 	    }
-	  left = S_GET_VALUE (symp->sy_value.X_add_symbol);
-	  right = S_GET_VALUE (symp->sy_value.X_op_symbol);
+
 	  switch (symp->sy_value.X_op)
 	    {
 	    case O_multiply:		val = left * right; break;


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~1996-08-07 12:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-08-05  9:31 Inconsistent behaviour (in resolve_symbol_value?) Richard Earnshaw
1996-08-07 12:34 ` Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).