diff options
-rw-r--r-- | ld/ChangeLog | 7 | ||||
-rw-r--r-- | ld/ld.texinfo | 4 | ||||
-rw-r--r-- | ld/ldexp.c | 50 |
3 files changed, 39 insertions, 22 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index 8b22c50..dd20229 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,12 @@ 2016-10-04 Alan Modra <amodra@gmail.com> + * ld.texinfo (Expression Section): Update result of arithmetic + expressions. + * ldexp.c (arith_result_section): New function. + (fold_binary): Use it. + +2016-10-04 Alan Modra <amodra@gmail.com> + * ldexp.c (exp_value_fold): New function. (exp_unop, exp_binop, exp_trinop): Use it. diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 1303a0e..6528b6a 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -6032,7 +6032,9 @@ The result of comparisons, @samp{&&} and @samp{||} is also a number. @item The result of other binary arithmetic and logical operations on two relative addresses in the same section or two absolute addresses -(after above conversions) is also a number. +(after above conversions) is also a number when +@code{LD_FEATURE ("SANE_EXPR")} or inside an output section definition +but an absolute address otherwise. @item The result of other operations on relative addresses or one relative address and a number, is a relative address in the same @@ -417,6 +417,32 @@ fold_unary (etree_type *tree) } } +/* 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. */ +static void +arith_result_section (const etree_value_type *lhs) +{ + if (expld.result.section == lhs->section) + { + if (expld.section == bfd_abs_section_ptr + && !config.sane_expr) + /* Duplicate the insanity in exp_fold_tree_1 case etree_value. */ + expld.result.section = bfd_abs_section_ptr; + else + expld.result.section = NULL; + } +} + static void fold_binary (etree_type *tree) { @@ -483,26 +509,10 @@ fold_binary (etree_type *tree) switch (tree->type.node_code) { - /* 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; \ + arith_result_section (&lhs); \ break; /* Comparison operators, logical AND, and logical OR always @@ -536,8 +546,7 @@ fold_binary (etree_type *tree) % (bfd_signed_vma) expld.result.value); else if (expld.phase != lang_mark_phase_enum) einfo (_("%F%S %% by zero\n"), tree->binary.rhs); - if (expld.result.section == lhs.section) - expld.result.section = NULL; + arith_result_section (&lhs); break; case '/': @@ -546,8 +555,7 @@ fold_binary (etree_type *tree) / (bfd_signed_vma) expld.result.value); else if (expld.phase != lang_mark_phase_enum) einfo (_("%F%S / by zero\n"), tree->binary.rhs); - if (expld.result.section == lhs.section) - expld.result.section = NULL; + arith_result_section (&lhs); break; case MAX_K: |