aboutsummaryrefslogtreecommitdiff
path: root/ld/ldexp.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/ldexp.c')
-rw-r--r--ld/ldexp.c223
1 files changed, 132 insertions, 91 deletions
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 8e3ea63..e45c470 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -50,11 +50,21 @@ static etree_value_type new_rel
PARAMS ((bfd_vma, char *, lang_output_section_statement_type *section));
static etree_value_type new_rel_from_section
PARAMS ((bfd_vma value, lang_output_section_statement_type *section));
+static etree_value_type fold_unary
+ PARAMS ((etree_type *tree,
+ lang_output_section_statement_type *current_section,
+ lang_phase_type allocation_done,
+ bfd_vma dot, bfd_vma *dotp));
static etree_value_type fold_binary
PARAMS ((etree_type *tree,
lang_output_section_statement_type *current_section,
lang_phase_type allocation_done,
bfd_vma dot, bfd_vma *dotp));
+static etree_value_type fold_trinary
+ PARAMS ((etree_type *tree,
+ lang_output_section_statement_type *current_section,
+ lang_phase_type allocation_done,
+ bfd_vma dot, bfd_vma *dotp));
static etree_value_type fold_name
PARAMS ((etree_type *tree,
lang_output_section_statement_type *current_section,
@@ -247,6 +257,93 @@ new_rel_from_section (value, section)
}
static etree_value_type
+fold_unary (tree, current_section, allocation_done, dot, dotp)
+ etree_type *tree;
+ lang_output_section_statement_type *current_section;
+ lang_phase_type allocation_done;
+ bfd_vma dot;
+ bfd_vma *dotp;
+{
+ etree_value_type result;
+
+ result = exp_fold_tree (tree->unary.child,
+ current_section,
+ allocation_done, dot, dotp);
+ if (result.valid_p)
+ {
+ switch (tree->type.node_code)
+ {
+ case ALIGN_K:
+ if (allocation_done != lang_first_phase_enum)
+ result = new_rel_from_section (align_n (dot, result.value),
+ current_section);
+ else
+ result.valid_p = false;
+ break;
+
+ case ABSOLUTE:
+ if (allocation_done != lang_first_phase_enum)
+ {
+ result.value += result.section->bfd_section->vma;
+ result.section = abs_output_section;
+ }
+ else
+ result.valid_p = false;
+ break;
+
+ case '~':
+ make_abs (&result);
+ result.value = ~result.value;
+ break;
+
+ case '!':
+ make_abs (&result);
+ result.value = !result.value;
+ break;
+
+ case '-':
+ make_abs (&result);
+ result.value = -result.value;
+ break;
+
+ case NEXT:
+ /* Return next place aligned to value. */
+ if (allocation_done == lang_allocating_phase_enum)
+ {
+ make_abs (&result);
+ result.value = align_n (dot, result.value);
+ }
+ else
+ result.valid_p = false;
+ break;
+
+ case DATA_SEGMENT_END:
+ if (allocation_done != lang_first_phase_enum
+ && current_section == abs_output_section
+ && (exp_data_seg.phase == exp_dataseg_align_seen
+ || exp_data_seg.phase == exp_dataseg_adjust
+ || allocation_done != lang_allocating_phase_enum))
+ {
+ if (exp_data_seg.phase == exp_dataseg_align_seen)
+ {
+ exp_data_seg.phase = exp_dataseg_end_seen;
+ exp_data_seg.end = result.value;
+ }
+ }
+ else
+ result.valid_p = false;
+ break;
+
+ default:
+ FAIL ();
+ break;
+ }
+ }
+
+ return result;
+}
+
+static etree_value_type
fold_binary (tree, current_section, allocation_done, dot, dotp)
etree_type *tree;
lang_output_section_statement_type *current_section;
@@ -279,15 +376,14 @@ fold_binary (tree, current_section, allocation_done, dot, dotp)
&& (tree->type.node_code == '+'
|| tree->type.node_code == '-'))
{
- etree_value_type hold;
-
- /* If there is only one absolute term, make sure it is the
- second one. */
if (other.section != abs_output_section)
{
- hold = result;
- result = other;
- other = hold;
+ /* Keep the section of the other term. */
+ if (tree->type.node_code == '+')
+ other.value = result.value + other.value;
+ else
+ other.value = result.value - other.value;
+ return other;
}
}
else if (result.section != other.section
@@ -382,6 +478,28 @@ fold_binary (tree, current_section, allocation_done, dot, dotp)
return result;
}
+static etree_value_type
+fold_trinary (tree, current_section, allocation_done, dot, dotp)
+ etree_type *tree;
+ lang_output_section_statement_type *current_section;
+ lang_phase_type allocation_done;
+ bfd_vma dot;
+ bfd_vma *dotp;
+{
+ etree_value_type result;
+
+ result = exp_fold_tree (tree->trinary.cond, current_section,
+ allocation_done, dot, dotp);
+ if (result.valid_p)
+ result = exp_fold_tree ((result.value
+ ? tree->trinary.lhs
+ : tree->trinary.rhs),
+ current_section,
+ allocation_done, dot, dotp);
+
+ return result;
+}
+
etree_value_type
invalid ()
{
@@ -584,90 +702,8 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
break;
case etree_unary:
- result = exp_fold_tree (tree->unary.child,
- current_section,
- allocation_done, dot, dotp);
- if (result.valid_p)
- {
- switch (tree->type.node_code)
- {
- case ALIGN_K:
- if (allocation_done != lang_first_phase_enum)
- result = new_rel_from_section (align_n (dot, result.value),
- current_section);
- else
- result.valid_p = false;
- break;
-
- case ABSOLUTE:
- if (allocation_done != lang_first_phase_enum)
- {
- result.value += result.section->bfd_section->vma;
- result.section = abs_output_section;
- }
- else
- result.valid_p = false;
- break;
-
- case '~':
- make_abs (&result);
- result.value = ~result.value;
- break;
-
- case '!':
- make_abs (&result);
- result.value = !result.value;
- break;
-
- case '-':
- make_abs (&result);
- result.value = -result.value;
- break;
-
- case NEXT:
- /* Return next place aligned to value. */
- if (allocation_done == lang_allocating_phase_enum)
- {
- make_abs (&result);
- result.value = align_n (dot, result.value);
- }
- else
- result.valid_p = false;
- break;
-
- case DATA_SEGMENT_END:
- if (allocation_done != lang_first_phase_enum
- && current_section == abs_output_section
- && (exp_data_seg.phase == exp_dataseg_align_seen
- || exp_data_seg.phase == exp_dataseg_adjust
- || allocation_done != lang_allocating_phase_enum))
- {
- if (exp_data_seg.phase == exp_dataseg_align_seen)
- {
- exp_data_seg.phase = exp_dataseg_end_seen;
- exp_data_seg.end = result.value;
- }
- }
- else
- result.valid_p = false;
- break;
-
- default:
- FAIL ();
- break;
- }
- }
- break;
-
- case etree_trinary:
- result = exp_fold_tree (tree->trinary.cond, current_section,
- allocation_done, dot, dotp);
- if (result.valid_p)
- result = exp_fold_tree ((result.value
- ? tree->trinary.lhs
- : tree->trinary.rhs),
- current_section,
- allocation_done, dot, dotp);
+ result = fold_unary (tree, current_section, allocation_done,
+ dot, dotp);
break;
case etree_binary:
@@ -675,6 +711,11 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
dot, dotp);
break;
+ case etree_trinary:
+ result = fold_trinary (tree, current_section, allocation_done,
+ dot, dotp);
+ break;
+
case etree_assign:
case etree_provide:
case etree_provided: