* 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.
This commit is contained in:
Alan Modra
2011-01-21 13:18:19 +00:00
parent 6b069ee70d
commit 9bc8bb33fe
3 changed files with 61 additions and 19 deletions

View 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> 2011-01-14 Alan Modra <amodra@gmail.com>
* ldmain.c (main): Flush stdout before and stderr after printing * ldmain.c (main): Flush stdout before and stderr after printing

View File

@ -5567,8 +5567,13 @@ An operation involving only numbers results in a number.
@item @item
The result of comparisons, @samp{&&} and @samp{||} is also a number. The result of comparisons, @samp{&&} and @samp{||} is also a number.
@item @item
The result of other operations on relative addresses (after above The result of other binary arithmetic and logical operations on two
conversions) is a relative address in the same section as the operand(s). 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 @item
The result of other operations on absolute addresses (after above The result of other operations on absolute addresses (after above
conversions) is an absolute address. conversions) is an absolute address.

View File

@ -335,36 +335,47 @@ fold_binary (etree_type *tree)
{ {
make_abs (); make_abs ();
lhs.value += lhs.section->vma; lhs.value += lhs.section->vma;
lhs.section = bfd_abs_section_ptr;
} }
/* If the rhs is just a number, keep the lhs section. */ /* If the rhs is just a number, keep the lhs section. */
else if (expld.result.section == NULL) 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) switch (tree->type.node_code)
{ {
case '%': /* Arithmetic operators, bitwise AND, bitwise OR and XOR
if (expld.result.value != 0) keep the section of one of their operands only when the
expld.result.value = ((bfd_signed_vma) lhs.value other operand is a plain number. Losing the section when
% (bfd_signed_vma) expld.result.value); operating on two symbols, ie. a result of a plain number,
else if (expld.phase != lang_mark_phase_enum) is required for subtraction and XOR. It's justifiable
einfo (_("%F%S %% by zero\n")); for the other operations on the grounds that adding,
break; multiplying etc. two section relative values does not
really make sense unless they are just treated as
case '/': numbers.
if (expld.result.value != 0) The same argument could be made for many expressions
expld.result.value = ((bfd_signed_vma) lhs.value involving one symbol and a number. For example,
/ (bfd_signed_vma) expld.result.value); "1 << x" and "100 / x" probably should not be given the
else if (expld.phase != lang_mark_phase_enum) section of x. The trouble is that if we fuss about such
einfo (_("%F%S / by zero\n")); things the rules become complex and it is onerous to
break; document ld expression evaluation. */
#define BOP(x, y) \ #define BOP(x, y) \
case x: \ case x: \
expld.result.value = lhs.value y expld.result.value; \ expld.result.value = lhs.value y expld.result.value; \
if (expld.result.section == lhs.section) \
expld.result.section = NULL; \
break; break;
/* Comparison operators, logical AND, and logical OR always
return a plain number. */
#define BOPN(x, y) \ #define BOPN(x, y) \
case x: \ case x: \
expld.result.value = lhs.value y expld.result.value; \ expld.result.value = lhs.value y expld.result.value; \
@ -388,6 +399,26 @@ fold_binary (etree_type *tree)
BOPN (ANDAND, &&); BOPN (ANDAND, &&);
BOPN (OROR, ||); 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: case MAX_K:
if (lhs.value > expld.result.value) if (lhs.value > expld.result.value)
expld.result.value = lhs.value; expld.result.value = lhs.value;