diff options
Diffstat (limited to 'ld/ldexp.c')
-rw-r--r-- | ld/ldexp.c | 223 |
1 files changed, 132 insertions, 91 deletions
@@ -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: |