* ldexp.c (fold_binary): Set result section for arithmetic and
authorAlan Modra <amodra@gmail.com>
Fri, 21 Jan 2011 13:18:19 +0000 (13:18 +0000)
committerAlan Modra <amodra@gmail.com>
Fri, 21 Jan 2011 13:18:19 +0000 (13:18 +0000)
logical operations to NULL when both operands are in same section.
* ld.texinfo (Expression Section): Describe this.

ld/ChangeLog
ld/ld.texinfo
ld/ldexp.c

index 7a00e7d..fe66fb8 100644 (file)
@@ -1,3 +1,9 @@
+2011-01-21  Alan Modra  <amodra@gmail.com>
+
+       * ldexp.c (fold_binary): Set result section for arithmetic and
+       logical operations to NULL when both operands are in same section.
+       * ld.texinfo (Expression Section): Describe this.
+
 2011-01-14  Alan Modra  <amodra@gmail.com>
 
        * ldmain.c (main): Flush stdout before and stderr after printing
index 4ea720f..9957d03 100644 (file)
@@ -5567,8 +5567,13 @@ An operation involving only numbers results in a number.
 @item
 The result of comparisons, @samp{&&} and @samp{||} is also a number.
 @item
-The result of other operations on relative addresses (after above
-conversions) is a relative address in the same section as the operand(s).
+The result of other binary arithmetic and logical operations on two
+relative addresses in the same section or two absolute addresess
+(after above conversions) is also a number.
+@item
+The result of other operations on relative addresses or one
+relative address and a number, is a relative address in the same
+section as the relative operand(s).
 @item
 The result of other operations on absolute addresses (after above
 conversions) is an absolute address.
index b7dc171..fc18601 100644 (file)
@@ -335,36 +335,47 @@ fold_binary (etree_type *tree)
            {
              make_abs ();
              lhs.value += lhs.section->vma;
+             lhs.section = bfd_abs_section_ptr;
            }
 
          /* If the rhs is just a number, keep the lhs section.  */
          else if (expld.result.section == NULL)
-           expld.result.section = lhs.section;
+           {
+             expld.result.section = lhs.section;
+             /* Make this NULL so that we know one of the operands
+                was just a number, for later tests.  */
+             lhs.section = NULL;
+           }
        }
+      /* At this point we know that both operands have the same
+        section, or at least one of them is a plain number.  */
 
       switch (tree->type.node_code)
        {
-       case '%':
-         if (expld.result.value != 0)
-           expld.result.value = ((bfd_signed_vma) lhs.value
-                                 % (bfd_signed_vma) expld.result.value);
-         else if (expld.phase != lang_mark_phase_enum)
-           einfo (_("%F%S %% by zero\n"));
-         break;
-
-       case '/':
-         if (expld.result.value != 0)
-           expld.result.value = ((bfd_signed_vma) lhs.value
-                                 / (bfd_signed_vma) expld.result.value);
-         else if (expld.phase != lang_mark_phase_enum)
-           einfo (_("%F%S / by zero\n"));
-         break;
-
+         /* Arithmetic operators, bitwise AND, bitwise OR and XOR
+            keep the section of one of their operands only when the
+            other operand is a plain number.  Losing the section when
+            operating on two symbols, ie. a result of a plain number,
+            is required for subtraction and XOR.  It's justifiable
+            for the other operations on the grounds that adding,
+            multiplying etc. two section relative values does not
+            really make sense unless they are just treated as
+            numbers.
+            The same argument could be made for many expressions
+            involving one symbol and a number.  For example,
+            "1 << x" and "100 / x" probably should not be given the
+            section of x.  The trouble is that if we fuss about such
+            things the rules become complex and it is onerous to
+            document ld expression evaluation.  */
 #define BOP(x, y) \
        case x:                                                 \
          expld.result.value = lhs.value y expld.result.value;  \
+         if (expld.result.section == lhs.section)              \
+           expld.result.section = NULL;                        \
          break;
 
+         /* Comparison operators, logical AND, and logical OR always
+            return a plain number.  */
 #define BOPN(x, y) \
        case x:                                                 \
          expld.result.value = lhs.value y expld.result.value;  \
@@ -388,6 +399,26 @@ fold_binary (etree_type *tree)
          BOPN (ANDAND, &&);
          BOPN (OROR, ||);
 
+       case '%':
+         if (expld.result.value != 0)
+           expld.result.value = ((bfd_signed_vma) lhs.value
+                                 % (bfd_signed_vma) expld.result.value);
+         else if (expld.phase != lang_mark_phase_enum)
+           einfo (_("%F%S %% by zero\n"));
+         if (expld.result.section == lhs.section)
+           expld.result.section = NULL;
+         break;
+
+       case '/':
+         if (expld.result.value != 0)
+           expld.result.value = ((bfd_signed_vma) lhs.value
+                                 / (bfd_signed_vma) expld.result.value);
+         else if (expld.phase != lang_mark_phase_enum)
+           einfo (_("%F%S / by zero\n"));
+         if (expld.result.section == lhs.section)
+           expld.result.section = NULL;
+         break;
+
        case MAX_K:
          if (lhs.value > expld.result.value)
            expld.result.value = lhs.value;