* ldexp.c (fold_binary): Evaluate rhs when lhs not valid.

This commit is contained in:
Alan Modra 2008-09-25 02:34:00 +00:00
parent 121a04390c
commit 4ac0c89885
2 changed files with 145 additions and 142 deletions

View File

@ -1,3 +1,7 @@
2008-09-25 Alan Modra <amodra@bigpond.net.au>
* ldexp.c (fold_binary): Evaluate rhs when lhs not valid.
2008-09-11 Jan Kratochvil <jan.kratochvil@redhat.com>
* configure.in: Call AC_SYS_LARGEFILE.

View File

@ -282,6 +282,7 @@ fold_unary (etree_type *tree)
static void
fold_binary (etree_type *tree)
{
etree_value_type lhs;
exp_fold_tree_1 (tree->binary.lhs);
/* The SEGMENT_START operator is special because its first
@ -304,169 +305,167 @@ fold_binary (etree_type *tree)
expld.result.section = expld.section;
break;
}
return;
}
else if (expld.result.valid_p)
lhs = expld.result;
exp_fold_tree_1 (tree->binary.rhs);
expld.result.valid_p &= lhs.valid_p;
if (expld.result.valid_p)
{
etree_value_type lhs = expld.result;
exp_fold_tree_1 (tree->binary.rhs);
if (expld.result.valid_p)
/* If the values are from different sections, or this is an
absolute expression, make both the source arguments
absolute. However, adding or subtracting an absolute
value from a relative value is meaningful, and is an
exception. */
if (expld.section != bfd_abs_section_ptr
&& lhs.section == bfd_abs_section_ptr
&& tree->type.node_code == '+')
{
/* If the values are from different sections, or this is an
absolute expression, make both the source arguments
absolute. However, adding or subtracting an absolute
value from a relative value is meaningful, and is an
exception. */
if (expld.section != bfd_abs_section_ptr
&& lhs.section == bfd_abs_section_ptr
&& tree->type.node_code == '+')
{
/* Keep the section of the rhs term. */
expld.result.value = lhs.value + expld.result.value;
return;
}
else if (expld.section != bfd_abs_section_ptr
&& expld.result.section == bfd_abs_section_ptr
&& (tree->type.node_code == '+'
|| tree->type.node_code == '-'))
{
/* Keep the section of the lhs term. */
expld.result.section = lhs.section;
}
else if (expld.result.section != lhs.section
|| expld.section == bfd_abs_section_ptr)
{
make_abs ();
lhs.value += lhs.section->vma;
}
/* Keep the section of the rhs term. */
expld.result.value = lhs.value + expld.result.value;
return;
}
else if (expld.section != bfd_abs_section_ptr
&& expld.result.section == bfd_abs_section_ptr
&& (tree->type.node_code == '+'
|| tree->type.node_code == '-'))
{
/* Keep the section of the lhs term. */
expld.result.section = lhs.section;
}
else if (expld.result.section != lhs.section
|| expld.section == bfd_abs_section_ptr)
{
make_abs ();
lhs.value += lhs.section->vma;
}
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;
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;
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;
#define BOP(x, y) \
case x: \
expld.result.value = lhs.value y expld.result.value; \
break;
BOP ('+', +);
BOP ('*', *);
BOP ('-', -);
BOP (LSHIFT, <<);
BOP (RSHIFT, >>);
BOP (EQ, ==);
BOP (NE, !=);
BOP ('<', <);
BOP ('>', >);
BOP (LE, <=);
BOP (GE, >=);
BOP ('&', &);
BOP ('^', ^);
BOP ('|', |);
BOP (ANDAND, &&);
BOP (OROR, ||);
BOP ('+', +);
BOP ('*', *);
BOP ('-', -);
BOP (LSHIFT, <<);
BOP (RSHIFT, >>);
BOP (EQ, ==);
BOP (NE, !=);
BOP ('<', <);
BOP ('>', >);
BOP (LE, <=);
BOP (GE, >=);
BOP ('&', &);
BOP ('^', ^);
BOP ('|', |);
BOP (ANDAND, &&);
BOP (OROR, ||);
case MAX_K:
if (lhs.value > expld.result.value)
expld.result.value = lhs.value;
break;
case MAX_K:
if (lhs.value > expld.result.value)
expld.result.value = lhs.value;
break;
case MIN_K:
if (lhs.value < expld.result.value)
expld.result.value = lhs.value;
break;
case MIN_K:
if (lhs.value < expld.result.value)
expld.result.value = lhs.value;
break;
case ALIGN_K:
expld.result.value = align_n (lhs.value, expld.result.value);
break;
case ALIGN_K:
expld.result.value = align_n (lhs.value, expld.result.value);
break;
case DATA_SEGMENT_ALIGN:
expld.dataseg.relro = exp_dataseg_relro_start;
if (expld.phase != lang_first_phase_enum
&& expld.section == bfd_abs_section_ptr
&& (expld.dataseg.phase == exp_dataseg_none
|| expld.dataseg.phase == exp_dataseg_adjust
|| expld.dataseg.phase == exp_dataseg_relro_adjust
|| expld.phase == lang_final_phase_enum))
case DATA_SEGMENT_ALIGN:
expld.dataseg.relro = exp_dataseg_relro_start;
if (expld.phase != lang_first_phase_enum
&& expld.section == bfd_abs_section_ptr
&& (expld.dataseg.phase == exp_dataseg_none
|| expld.dataseg.phase == exp_dataseg_adjust
|| expld.dataseg.phase == exp_dataseg_relro_adjust
|| expld.phase == lang_final_phase_enum))
{
bfd_vma maxpage = lhs.value;
bfd_vma commonpage = expld.result.value;
expld.result.value = align_n (expld.dot, maxpage);
if (expld.dataseg.phase == exp_dataseg_relro_adjust)
expld.result.value = expld.dataseg.base;
else if (expld.dataseg.phase != exp_dataseg_adjust)
{
bfd_vma maxpage = lhs.value;
bfd_vma commonpage = expld.result.value;
expld.result.value = align_n (expld.dot, maxpage);
if (expld.dataseg.phase == exp_dataseg_relro_adjust)
expld.result.value = expld.dataseg.base;
else if (expld.dataseg.phase != exp_dataseg_adjust)
expld.result.value += expld.dot & (maxpage - 1);
if (expld.phase == lang_allocating_phase_enum)
{
expld.result.value += expld.dot & (maxpage - 1);
if (expld.phase == lang_allocating_phase_enum)
{
expld.dataseg.phase = exp_dataseg_align_seen;
expld.dataseg.min_base = expld.dot;
expld.dataseg.base = expld.result.value;
expld.dataseg.pagesize = commonpage;
expld.dataseg.maxpagesize = maxpage;
expld.dataseg.relro_end = 0;
}
expld.dataseg.phase = exp_dataseg_align_seen;
expld.dataseg.min_base = expld.dot;
expld.dataseg.base = expld.result.value;
expld.dataseg.pagesize = commonpage;
expld.dataseg.maxpagesize = maxpage;
expld.dataseg.relro_end = 0;
}
else if (commonpage < maxpage)
expld.result.value += ((expld.dot + commonpage - 1)
& (maxpage - commonpage));
}
else
expld.result.valid_p = FALSE;
break;
case DATA_SEGMENT_RELRO_END:
expld.dataseg.relro = exp_dataseg_relro_end;
if (expld.phase != lang_first_phase_enum
&& (expld.dataseg.phase == exp_dataseg_align_seen
|| expld.dataseg.phase == exp_dataseg_adjust
|| expld.dataseg.phase == exp_dataseg_relro_adjust
|| expld.phase == lang_final_phase_enum))
{
if (expld.dataseg.phase == exp_dataseg_align_seen
|| expld.dataseg.phase == exp_dataseg_relro_adjust)
expld.dataseg.relro_end = lhs.value + expld.result.value;
if (expld.dataseg.phase == exp_dataseg_relro_adjust
&& (expld.dataseg.relro_end
& (expld.dataseg.pagesize - 1)))
{
expld.dataseg.relro_end += expld.dataseg.pagesize - 1;
expld.dataseg.relro_end &= ~(expld.dataseg.pagesize - 1);
expld.result.value = (expld.dataseg.relro_end
- expld.result.value);
}
else
expld.result.value = lhs.value;
if (expld.dataseg.phase == exp_dataseg_align_seen)
expld.dataseg.phase = exp_dataseg_relro_seen;
}
else
expld.result.valid_p = FALSE;
break;
default:
FAIL ();
else if (commonpage < maxpage)
expld.result.value += ((expld.dot + commonpage - 1)
& (maxpage - commonpage));
}
else
expld.result.valid_p = FALSE;
break;
case DATA_SEGMENT_RELRO_END:
expld.dataseg.relro = exp_dataseg_relro_end;
if (expld.phase != lang_first_phase_enum
&& (expld.dataseg.phase == exp_dataseg_align_seen
|| expld.dataseg.phase == exp_dataseg_adjust
|| expld.dataseg.phase == exp_dataseg_relro_adjust
|| expld.phase == lang_final_phase_enum))
{
if (expld.dataseg.phase == exp_dataseg_align_seen
|| expld.dataseg.phase == exp_dataseg_relro_adjust)
expld.dataseg.relro_end = lhs.value + expld.result.value;
if (expld.dataseg.phase == exp_dataseg_relro_adjust
&& (expld.dataseg.relro_end
& (expld.dataseg.pagesize - 1)))
{
expld.dataseg.relro_end += expld.dataseg.pagesize - 1;
expld.dataseg.relro_end &= ~(expld.dataseg.pagesize - 1);
expld.result.value = (expld.dataseg.relro_end
- expld.result.value);
}
else
expld.result.value = lhs.value;
if (expld.dataseg.phase == exp_dataseg_align_seen)
expld.dataseg.phase = exp_dataseg_relro_seen;
}
else
expld.result.valid_p = FALSE;
break;
default:
FAIL ();
}
else
expld.result.valid_p = FALSE;
}
}