* 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:
parent
6b069ee70d
commit
9bc8bb33fe
3 changed files with 61 additions and 19 deletions
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
63
ld/ldexp.c
63
ld/ldexp.c
|
@ -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;
|
||||
/* 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;
|
||||
|
|
Loading…
Reference in a new issue