* subsegs.h (struct frchain): Delete frch_seg.

(frchain_root): Delete.
	(seg_info): Define as macro.
	* subsegs.c (frchain_root): Delete.
	(abs_seg_info, und_seg_info, absolute_frchain): Delete.
	(subsegs_begin, subseg_change): Adjust for above.
	(subseg_set_rest): Likewise.  Add new frchain structs to seginfo
	rather than to one big list.
	(subseg_get): Don't special case abs, und sections.
	(subseg_new, subseg_force_new): Don't set frchainP here.
	(seg_info): Delete.
	(subsegs_print_statistics): Adjust frag chain control list traversal.
	* debug.c (dmp_frags):  Likewise.
	* dwarf2dbg.c (first_frag_for_seg): Don't start looking for frag
	at frchain_root.  Make use of known frchain ordering.
	(last_frag_for_seg): Likewise.
	(get_frag_fix): Likewise.  Add seg param.
	(process_entries, out_debug_aranges): Adjust get_frag_fix calls.
	* write.c (chain_frchains_together_1): Adjust for struct frchain.
	(SUB_SEGMENT_ALIGN): Likewise.
	(subsegs_finish): Adjust frchain list traversal.
	* config/tc-xtensa.c (xtensa_cleanup_align_frags): Likewise.
	(xtensa_fix_target_frags, xtensa_mark_narrow_branches): Likewise.
	(xtensa_mark_zcl_first_insns, xtensa_fix_a0_b_retw_frags): Likewise.
	(xtensa_fix_b_j_loop_end_frags): Likewise.
	(xtensa_fix_close_loop_end_frags): Likewise.
	(xtensa_fix_short_loop_frags, xtensa_sanity_check): Likewise.
	(retrieve_segment_info): Delete frch_seg initialisation.
This commit is contained in:
Alan Modra 2006-05-03 23:52:15 +00:00
parent 14b3d9c967
commit c9049d301b
7 changed files with 454 additions and 508 deletions

View file

@ -1,3 +1,34 @@
2006-05-04 Alan Modra <amodra@bigpond.net.au>
* subsegs.h (struct frchain): Delete frch_seg.
(frchain_root): Delete.
(seg_info): Define as macro.
* subsegs.c (frchain_root): Delete.
(abs_seg_info, und_seg_info, absolute_frchain): Delete.
(subsegs_begin, subseg_change): Adjust for above.
(subseg_set_rest): Likewise. Add new frchain structs to seginfo
rather than to one big list.
(subseg_get): Don't special case abs, und sections.
(subseg_new, subseg_force_new): Don't set frchainP here.
(seg_info): Delete.
(subsegs_print_statistics): Adjust frag chain control list traversal.
* debug.c (dmp_frags): Likewise.
* dwarf2dbg.c (first_frag_for_seg): Don't start looking for frag
at frchain_root. Make use of known frchain ordering.
(last_frag_for_seg): Likewise.
(get_frag_fix): Likewise. Add seg param.
(process_entries, out_debug_aranges): Adjust get_frag_fix calls.
* write.c (chain_frchains_together_1): Adjust for struct frchain.
(SUB_SEGMENT_ALIGN): Likewise.
(subsegs_finish): Adjust frchain list traversal.
* config/tc-xtensa.c (xtensa_cleanup_align_frags): Likewise.
(xtensa_fix_target_frags, xtensa_mark_narrow_branches): Likewise.
(xtensa_mark_zcl_first_insns, xtensa_fix_a0_b_retw_frags): Likewise.
(xtensa_fix_b_j_loop_end_frags): Likewise.
(xtensa_fix_close_loop_end_frags): Likewise.
(xtensa_fix_short_loop_frags, xtensa_sanity_check): Likewise.
(retrieve_segment_info): Delete frch_seg initialisation.
2006-05-03 Alan Modra <amodra@bigpond.net.au>
* subsegs.c (subseg_get): Don't call obj_sec_set_private_data.

View file

@ -6954,44 +6954,46 @@ static void
xtensa_cleanup_align_frags (void)
{
frchainS *frchP;
asection *s;
for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if ((fragP->fr_type == rs_align
|| fragP->fr_type == rs_align_code
|| (fragP->fr_type == rs_machine_dependent
&& (fragP->fr_subtype == RELAX_DESIRE_ALIGN
|| fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)))
&& fragP->fr_fix == 0)
{
fragS *next = fragP->fr_next;
for (s = stdoutput->sections; s; s = s->next)
for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if ((fragP->fr_type == rs_align
|| fragP->fr_type == rs_align_code
|| (fragP->fr_type == rs_machine_dependent
&& (fragP->fr_subtype == RELAX_DESIRE_ALIGN
|| fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)))
&& fragP->fr_fix == 0)
{
fragS *next = fragP->fr_next;
while (next
&& next->fr_fix == 0
&& next->fr_type == rs_machine_dependent
&& next->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
{
frag_wane (next);
next = next->fr_next;
}
}
/* If we don't widen branch targets, then they
will be easier to align. */
if (fragP->tc_frag_data.is_branch_target
&& fragP->fr_opcode == fragP->fr_literal
&& fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_SLOTS
&& fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
frag_wane (fragP);
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_UNREACHABLE)
fragP->tc_frag_data.is_unreachable = TRUE;
}
}
while (next
&& next->fr_fix == 0
&& next->fr_type == rs_machine_dependent
&& next->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
{
frag_wane (next);
next = next->fr_next;
}
}
/* If we don't widen branch targets, then they
will be easier to align. */
if (fragP->tc_frag_data.is_branch_target
&& fragP->fr_opcode == fragP->fr_literal
&& fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_SLOTS
&& fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
frag_wane (fragP);
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_UNREACHABLE)
fragP->tc_frag_data.is_unreachable = TRUE;
}
}
}
@ -7004,26 +7006,28 @@ static void
xtensa_fix_target_frags (void)
{
frchainS *frchP;
asection *s;
/* When this routine is called, all of the subsections are still intact
so we walk over subsections instead of sections. */
for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
for (s = stdoutput->sections; s; s = s->next)
for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
{
if (next_frag_is_branch_target (fragP))
fragP->fr_subtype = RELAX_DESIRE_ALIGN;
else
frag_wane (fragP);
}
}
}
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
{
if (next_frag_is_branch_target (fragP))
fragP->fr_subtype = RELAX_DESIRE_ALIGN;
else
frag_wane (fragP);
}
}
}
}
@ -7033,36 +7037,38 @@ static void
xtensa_mark_narrow_branches (void)
{
frchainS *frchP;
asection *s;
for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_SLOTS
&& fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED)
{
vliw_insn vinsn;
for (s = stdoutput->sections; s; s = s->next)
for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_SLOTS
&& fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED)
{
vliw_insn vinsn;
vinsn_from_chars (&vinsn, fragP->fr_opcode);
tinsn_immed_from_frag (&vinsn.slots[0], fragP, 0);
vinsn_from_chars (&vinsn, fragP->fr_opcode);
tinsn_immed_from_frag (&vinsn.slots[0], fragP, 0);
if (vinsn.num_slots == 1
&& xtensa_opcode_is_branch (xtensa_default_isa,
vinsn.slots[0].opcode)
&& xg_get_single_size (vinsn.slots[0].opcode) == 2
&& is_narrow_branch_guaranteed_in_range (fragP,
&vinsn.slots[0]))
{
fragP->fr_subtype = RELAX_SLOTS;
fragP->tc_frag_data.slot_subtypes[0] = RELAX_NARROW;
fragP->tc_frag_data.is_aligning_branch = 1;
}
}
}
}
if (vinsn.num_slots == 1
&& xtensa_opcode_is_branch (xtensa_default_isa,
vinsn.slots[0].opcode)
&& xg_get_single_size (vinsn.slots[0].opcode) == 2
&& is_narrow_branch_guaranteed_in_range (fragP,
&vinsn.slots[0]))
{
fragP->fr_subtype = RELAX_SLOTS;
fragP->tc_frag_data.slot_subtypes[0] = RELAX_NARROW;
fragP->tc_frag_data.is_aligning_branch = 1;
}
}
}
}
}
@ -7119,48 +7125,50 @@ static void
xtensa_mark_zcl_first_insns (void)
{
frchainS *frchP;
asection *s;
for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& (fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE
|| fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))
{
/* Find the loop frag. */
fragS *targ_frag = next_non_empty_frag (fragP);
/* Find the first insn frag. */
targ_frag = next_non_empty_frag (targ_frag);
for (s = stdoutput->sections; s; s = s->next)
for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& (fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE
|| fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))
{
/* Find the loop frag. */
fragS *targ_frag = next_non_empty_frag (fragP);
/* Find the first insn frag. */
targ_frag = next_non_empty_frag (targ_frag);
/* Of course, sometimes (mostly for toy test cases) a
zero-cost loop instruction is the last in a section. */
if (targ_frag)
{
targ_frag->tc_frag_data.is_first_loop_insn = TRUE;
/* Do not widen a frag that is the first instruction of a
zero-cost loop. It makes that loop harder to align. */
if (targ_frag->fr_type == rs_machine_dependent
&& targ_frag->fr_subtype == RELAX_SLOTS
&& (targ_frag->tc_frag_data.slot_subtypes[0]
== RELAX_NARROW))
{
if (targ_frag->tc_frag_data.is_aligning_branch)
targ_frag->tc_frag_data.slot_subtypes[0] = RELAX_IMMED;
else
{
frag_wane (targ_frag);
targ_frag->tc_frag_data.slot_subtypes[0] = 0;
}
}
}
if (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)
frag_wane (fragP);
}
}
}
/* Of course, sometimes (mostly for toy test cases) a
zero-cost loop instruction is the last in a section. */
if (targ_frag)
{
targ_frag->tc_frag_data.is_first_loop_insn = TRUE;
/* Do not widen a frag that is the first instruction of a
zero-cost loop. It makes that loop harder to align. */
if (targ_frag->fr_type == rs_machine_dependent
&& targ_frag->fr_subtype == RELAX_SLOTS
&& (targ_frag->tc_frag_data.slot_subtypes[0]
== RELAX_NARROW))
{
if (targ_frag->tc_frag_data.is_aligning_branch)
targ_frag->tc_frag_data.slot_subtypes[0] = RELAX_IMMED;
else
{
frag_wane (targ_frag);
targ_frag->tc_frag_data.slot_subtypes[0] = 0;
}
}
}
if (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)
frag_wane (fragP);
}
}
}
}
@ -7175,30 +7183,32 @@ static void
xtensa_fix_a0_b_retw_frags (void)
{
frchainS *frchP;
asection *s;
/* When this routine is called, all of the subsections are still intact
so we walk over subsections instead of sections. */
for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
for (s = stdoutput->sections; s; s = s->next)
for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_ADD_NOP_IF_A0_B_RETW)
{
if (next_instrs_are_b_retw (fragP))
{
if (fragP->tc_frag_data.is_no_transform)
as_bad (_("instruction sequence (write a0, branch, retw) may trigger hardware errata"));
else
relax_frag_add_nop (fragP);
}
frag_wane (fragP);
}
}
}
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_ADD_NOP_IF_A0_B_RETW)
{
if (next_instrs_are_b_retw (fragP))
{
if (fragP->tc_frag_data.is_no_transform)
as_bad (_("instruction sequence (write a0, branch, retw) may trigger hardware errata"));
else
relax_frag_add_nop (fragP);
}
frag_wane (fragP);
}
}
}
}
@ -7285,30 +7295,32 @@ static void
xtensa_fix_b_j_loop_end_frags (void)
{
frchainS *frchP;
asection *s;
/* When this routine is called, all of the subsections are still intact
so we walk over subsections instead of sections. */
for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
for (s = stdoutput->sections; s; s = s->next)
for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_ADD_NOP_IF_PRE_LOOP_END)
{
if (next_instr_is_loop_end (fragP))
{
if (fragP->tc_frag_data.is_no_transform)
as_bad (_("branching or jumping to a loop end may trigger hardware errata"));
else
relax_frag_add_nop (fragP);
}
frag_wane (fragP);
}
}
}
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_ADD_NOP_IF_PRE_LOOP_END)
{
if (next_instr_is_loop_end (fragP))
{
if (fragP->tc_frag_data.is_no_transform)
as_bad (_("branching or jumping to a loop end may trigger hardware errata"));
else
relax_frag_add_nop (fragP);
}
frag_wane (fragP);
}
}
}
}
@ -7349,66 +7361,68 @@ static void
xtensa_fix_close_loop_end_frags (void)
{
frchainS *frchP;
asection *s;
/* When this routine is called, all of the subsections are still intact
so we walk over subsections instead of sections. */
for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
for (s = stdoutput->sections; s; s = s->next)
for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
fragS *current_target = NULL;
fragS *current_target = NULL;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
|| (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)))
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
|| (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)))
current_target = symbol_get_frag (fragP->fr_symbol);
if (current_target
&& fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_ADD_NOP_IF_CLOSE_LOOP_END)
{
offsetT min_bytes;
int bytes_added = 0;
if (current_target
&& fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_ADD_NOP_IF_CLOSE_LOOP_END)
{
offsetT min_bytes;
int bytes_added = 0;
#define REQUIRED_LOOP_DIVIDING_BYTES 12
/* Max out at 12. */
min_bytes = min_bytes_to_other_loop_end
(fragP->fr_next, current_target, REQUIRED_LOOP_DIVIDING_BYTES);
/* Max out at 12. */
min_bytes = min_bytes_to_other_loop_end
(fragP->fr_next, current_target, REQUIRED_LOOP_DIVIDING_BYTES);
if (min_bytes < REQUIRED_LOOP_DIVIDING_BYTES)
{
if (fragP->tc_frag_data.is_no_transform)
as_bad (_("loop end too close to another loop end may trigger hardware errata"));
else
{
while (min_bytes + bytes_added
< REQUIRED_LOOP_DIVIDING_BYTES)
{
int length = 3;
if (min_bytes < REQUIRED_LOOP_DIVIDING_BYTES)
{
if (fragP->tc_frag_data.is_no_transform)
as_bad (_("loop end too close to another loop end may trigger hardware errata"));
else
{
while (min_bytes + bytes_added
< REQUIRED_LOOP_DIVIDING_BYTES)
{
int length = 3;
if (fragP->fr_var < length)
as_fatal (_("fr_var %lu < length %d"),
(long) fragP->fr_var, length);
else
{
assemble_nop (length,
fragP->fr_literal + fragP->fr_fix);
fragP->fr_fix += length;
fragP->fr_var -= length;
}
bytes_added += length;
}
}
}
frag_wane (fragP);
}
assert (fragP->fr_type != rs_machine_dependent
|| fragP->fr_subtype != RELAX_ADD_NOP_IF_CLOSE_LOOP_END);
}
}
if (fragP->fr_var < length)
as_fatal (_("fr_var %lu < length %d"),
(long) fragP->fr_var, length);
else
{
assemble_nop (length,
fragP->fr_literal + fragP->fr_fix);
fragP->fr_fix += length;
fragP->fr_var -= length;
}
bytes_added += length;
}
}
}
frag_wane (fragP);
}
assert (fragP->fr_type != rs_machine_dependent
|| fragP->fr_subtype != RELAX_ADD_NOP_IF_CLOSE_LOOP_END);
}
}
}
@ -7512,49 +7526,51 @@ static void
xtensa_fix_short_loop_frags (void)
{
frchainS *frchP;
asection *s;
/* When this routine is called, all of the subsections are still intact
so we walk over subsections instead of sections. */
for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
fragS *current_target = NULL;
xtensa_opcode current_opcode = XTENSA_UNDEFINED;
for (s = stdoutput->sections; s; s = s->next)
for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
fragS *current_target = NULL;
xtensa_opcode current_opcode = XTENSA_UNDEFINED;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
|| (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)))
{
TInsn t_insn;
fragS *loop_frag = next_non_empty_frag (fragP);
tinsn_from_chars (&t_insn, loop_frag->fr_opcode, 0);
current_target = symbol_get_frag (fragP->fr_symbol);
current_opcode = t_insn.opcode;
assert (xtensa_opcode_is_loop (xtensa_default_isa,
current_opcode));
}
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
if (fragP->fr_type == rs_machine_dependent
&& ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
|| (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)))
{
TInsn t_insn;
fragS *loop_frag = next_non_empty_frag (fragP);
tinsn_from_chars (&t_insn, loop_frag->fr_opcode, 0);
current_target = symbol_get_frag (fragP->fr_symbol);
current_opcode = t_insn.opcode;
assert (xtensa_opcode_is_loop (xtensa_default_isa,
current_opcode));
}
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP)
{
if (count_insns_to_loop_end (fragP->fr_next, TRUE, 3) < 3
&& (branch_before_loop_end (fragP->fr_next)
|| (workaround_all_short_loops
&& current_opcode != XTENSA_UNDEFINED
&& current_opcode != xtensa_loop_opcode)))
{
if (fragP->tc_frag_data.is_no_transform)
as_bad (_("loop containing less than three instructions may trigger hardware errata"));
else
relax_frag_add_nop (fragP);
}
frag_wane (fragP);
}
}
}
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP)
{
if (count_insns_to_loop_end (fragP->fr_next, TRUE, 3) < 3
&& (branch_before_loop_end (fragP->fr_next)
|| (workaround_all_short_loops
&& current_opcode != XTENSA_UNDEFINED
&& current_opcode != xtensa_loop_opcode)))
{
if (fragP->tc_frag_data.is_no_transform)
as_bad (_("loop containing less than three instructions may trigger hardware errata"));
else
relax_frag_add_nop (fragP);
}
frag_wane (fragP);
}
}
}
}
@ -7697,50 +7713,51 @@ xtensa_sanity_check (void)
{
char *file_name;
unsigned line;
frchainS *frchP;
asection *s;
as_where (&file_name, &line);
for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
for (s = stdoutput->sections; s; s = s->next)
for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
/* Currently we only check for empty loops here. */
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_IMMED)
{
static xtensa_insnbuf insnbuf = NULL;
TInsn t_insn;
/* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{
/* Currently we only check for empty loops here. */
if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_IMMED)
{
static xtensa_insnbuf insnbuf = NULL;
TInsn t_insn;
if (fragP->fr_opcode != NULL)
{
if (!insnbuf)
insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
tinsn_from_chars (&t_insn, fragP->fr_opcode, 0);
tinsn_immed_from_frag (&t_insn, fragP, 0);
if (fragP->fr_opcode != NULL)
{
if (!insnbuf)
insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
tinsn_from_chars (&t_insn, fragP->fr_opcode, 0);
tinsn_immed_from_frag (&t_insn, fragP, 0);
if (xtensa_opcode_is_loop (xtensa_default_isa,
t_insn.opcode) == 1)
{
if (is_empty_loop (&t_insn, fragP))
{
new_logical_line (fragP->fr_file, fragP->fr_line);
as_bad (_("invalid empty loop"));
}
if (!is_local_forward_loop (&t_insn, fragP))
{
new_logical_line (fragP->fr_file, fragP->fr_line);
as_bad (_("loop target does not follow "
"loop instruction in section"));
}
}
}
}
}
}
if (xtensa_opcode_is_loop (xtensa_default_isa,
t_insn.opcode) == 1)
{
if (is_empty_loop (&t_insn, fragP))
{
new_logical_line (fragP->fr_file, fragP->fr_line);
as_bad (_("invalid empty loop"));
}
if (!is_local_forward_loop (&t_insn, fragP))
{
new_logical_line (fragP->fr_file, fragP->fr_line);
as_bad (_("loop target does not follow "
"loop instruction in section"));
}
}
}
}
}
}
new_logical_line (file_name, line);
}
@ -10384,7 +10401,6 @@ retrieve_segment_info (segT seg)
frchainP->frch_root = NULL;
frchainP->frch_last = NULL;
frchainP->frch_next = NULL;
frchainP->frch_seg = seg;
frchainP->frch_subseg = 0;
frchainP->fix_root = NULL;
frchainP->fix_tail = NULL;

View file

@ -1,5 +1,5 @@
/* This file is debug.c
Copyright 1987, 1988, 1989, 1990, 1991, 1992, 2000
Copyright 1987, 1988, 1989, 1990, 1991, 1992, 2000, 2006
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@ -25,26 +25,28 @@
dmp_frags ()
{
asection *s;
frchainS *chp;
char *p;
for (chp = frchain_root; chp; chp = chp->frch_next)
{
switch (chp->frch_seg)
{
case SEG_DATA:
p = "Data";
break;
case SEG_TEXT:
p = "Text";
break;
default:
p = "???";
break;
}
printf ("\nSEGMENT %s %d\n", p, chp->frch_subseg);
dmp_frag (chp->frch_root, "\t");
}
for (s = stdoutput->sections; s; s = s->next)
for (chp = seg_info (s)->frchainP; chp; chp = chp->frch_next)
{
switch (s)
{
case SEG_DATA:
p = "Data";
break;
case SEG_TEXT:
p = "Text";
break;
default:
p = "???";
break;
}
printf ("\nSEGMENT %s %d\n", p, chp->frch_subseg);
dmp_frag (chp->frch_root, "\t");
}
}
dmp_frag (fp, indent)

View file

@ -169,7 +169,7 @@ static void out_two (int);
static void out_four (int);
static void out_abbrev (int, int);
static void out_uleb128 (addressT);
static offsetT get_frag_fix (fragS *);
static offsetT get_frag_fix (fragS *, segT);
static void out_set_addr (symbolS *);
static int size_inc_line_addr (int, addressT);
static void emit_inc_line_addr (int, addressT, char *, int);
@ -670,27 +670,18 @@ dwarf2_directive_loc_mark_labels (int dummy ATTRIBUTE_UNUSED)
static struct frag *
first_frag_for_seg (segT seg)
{
frchainS *f, *first = NULL;
for (f = frchain_root; f; f = f->frch_next)
if (f->frch_seg == seg
&& (! first || first->frch_subseg > f->frch_subseg))
first = f;
return first ? first->frch_root : NULL;
return seg_info (seg)->frchainP->frch_root;
}
static struct frag *
last_frag_for_seg (segT seg)
{
frchainS *f, *last = NULL;
frchainS *f = seg_info (seg)->frchainP;
for (f = frchain_root; f; f = f->frch_next)
if (f->frch_seg == seg
&& (! last || last->frch_subseg < f->frch_subseg))
last= f;
while (f->frch_next != NULL)
f = f->frch_next;
return last ? last->frch_last : NULL;
return f->frch_last;
}
/* Emit a single byte into the current segment. */
@ -745,7 +736,7 @@ out_abbrev (int name, int form)
/* Get the size of a fragment. */
static offsetT
get_frag_fix (fragS *frag)
get_frag_fix (fragS *frag, segT seg)
{
frchainS *fr;
@ -755,7 +746,7 @@ get_frag_fix (fragS *frag)
/* If a fragment is the last in the chain, special measures must be
taken to find its size before relaxation, since it may be pending
on some subsegment chain. */
for (fr = frchain_root; fr; fr = fr->frch_next)
for (fr = seg_info (seg)->frchainP; fr; fr = fr->frch_next)
if (fr->frch_last == frag)
return (char *) obstack_next_free (&fr->frch_obstack) - frag->fr_literal;
@ -1134,7 +1125,7 @@ process_entries (segT seg, struct line_entry *e)
/* Emit a DW_LNE_end_sequence for the end of the section. */
frag = last_frag_for_seg (seg);
frag_ofs = get_frag_fix (frag);
frag_ofs = get_frag_fix (frag, seg);
if (frag == last_frag)
out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs);
else
@ -1332,7 +1323,7 @@ out_debug_aranges (segT aranges_seg, segT info_seg)
s->text_start = beg;
frag = last_frag_for_seg (s->seg);
end = symbol_temp_new (s->seg, get_frag_fix (frag), frag);
end = symbol_temp_new (s->seg, get_frag_fix (frag, s->seg), frag);
s->text_end = end;
expr.X_op = O_symbol;

View file

@ -27,20 +27,12 @@
#include "subsegs.h"
#include "obstack.h"
frchainS *frchain_root, *frchain_now;
frchainS *frchain_now;
static struct obstack frchains;
/* Gas segment information for bfd_abs_section_ptr and
bfd_und_section_ptr. */
static segment_info_type *abs_seg_info;
static segment_info_type *und_seg_info;
static void subseg_set_rest (segT, subsegT);
static fragS dummy_frag;
static frchainS absolute_frchain;
void
subsegs_begin (void)
@ -50,16 +42,8 @@ subsegs_begin (void)
obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
#endif
frchain_root = NULL;
frchain_now = NULL; /* Warn new_subseg() that we are booting. */
frag_now = &dummy_frag;
absolute_frchain.frch_seg = absolute_section;
absolute_frchain.frch_subseg = 0;
absolute_frchain.fix_root = absolute_frchain.fix_tail = 0;
absolute_frchain.frch_frag_now = &zero_address_frag;
absolute_frchain.frch_root = absolute_frchain.frch_last = &zero_address_frag;
}
/*
@ -75,14 +59,10 @@ subsegs_begin (void)
void
subseg_change (register segT seg, register int subseg)
{
segment_info_type *seginfo;
segment_info_type *seginfo = seg_info (seg);
now_seg = seg;
now_subseg = subseg;
if (now_seg == absolute_section)
return;
seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
if (! seginfo)
{
seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
@ -91,21 +71,17 @@ subseg_change (register segT seg, register int subseg)
seginfo->fix_tail = NULL;
seginfo->bfd_section = seg;
seginfo->sym = 0;
if (seg == bfd_abs_section_ptr)
abs_seg_info = seginfo;
else if (seg == bfd_und_section_ptr)
und_seg_info = seginfo;
else
bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
}
}
static void
subseg_set_rest (segT seg, subsegT subseg)
{
register frchainS *frcP; /* crawl frchain chain */
register frchainS **lastPP; /* address of last pointer */
frchainS *frcP; /* crawl frchain chain */
frchainS **lastPP; /* address of last pointer */
frchainS *newP; /* address of new frchain */
segment_info_type *seginfo;
mri_common_symbol = NULL;
@ -113,72 +89,26 @@ subseg_set_rest (segT seg, subsegT subseg)
frchain_now->frch_frag_now = frag_now;
assert (frchain_now == 0
|| now_seg == undefined_section
|| now_seg == absolute_section
|| frchain_now->frch_last == frag_now);
subseg_change (seg, (int) subseg);
if (seg == absolute_section)
{
frchain_now = &absolute_frchain;
frag_now = &zero_address_frag;
return;
}
seginfo = seg_info (seg);
assert (frchain_now == 0
|| now_seg == undefined_section
|| frchain_now->frch_last == frag_now);
/*
* Attempt to find or make a frchain for that sub seg.
* Crawl along chain of frchainSs, begins @ frchain_root.
* If we need to make a frchainS, link it into correct
* position of chain rooted in frchain_root.
*/
for (frcP = *(lastPP = &frchain_root);
frcP && frcP->frch_seg <= seg;
/* Attempt to find or make a frchain for that subsection.
We keep the list sorted by subsection number. */
for (frcP = *(lastPP = &seginfo->frchainP);
frcP != NULL;
frcP = *(lastPP = &frcP->frch_next))
if (frcP->frch_subseg >= subseg)
break;
if (frcP == NULL || frcP->frch_subseg != subseg)
{
if (frcP->frch_seg == seg
&& frcP->frch_subseg >= subseg)
{
break;
}
}
/*
* frcP: Address of the 1st frchainS in correct segment with
* frch_subseg >= subseg.
* We want to either use this frchainS, or we want
* to insert a new frchainS just before it.
*
* If frcP==NULL, then we are at the end of the chain
* of frchainS-s. A NULL frcP means we fell off the end
* of the chain looking for a
* frch_subseg >= subseg, so we
* must make a new frchainS.
*
* If we ever maintain a pointer to
* the last frchainS in the chain, we change that pointer
* ONLY when frcP==NULL.
*
* lastPP: Address of the pointer with value frcP;
* Never NULL.
* May point to frchain_root.
*
*/
if (!frcP
|| (frcP->frch_seg > seg
|| frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
{
/*
* This should be the only code that creates a frchainS.
*/
segment_info_type *seginfo;
/* This should be the only code that creates a frchainS. */
newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
newP->frch_subseg = subseg;
newP->frch_seg = seg;
newP->fix_root = NULL;
newP->fix_tail = NULL;
obstack_begin (&newP->frch_obstack, chunksize);
@ -191,17 +121,10 @@ subseg_set_rest (segT seg, subsegT subseg)
newP->frch_root = newP->frch_last = newP->frch_frag_now;
*lastPP = newP;
newP->frch_next = frcP; /* perhaps NULL */
seginfo = seg_info (seg);
if (seginfo && (!seginfo->frchainP || seginfo->frchainP == frcP))
seginfo->frchainP = newP;
newP->frch_next = frcP;
frcP = newP;
}
/*
* Here with frcP pointing to the frchainS for subseg.
*/
frchain_now = frcP;
frag_now = frcP->frch_frag_now;
@ -221,7 +144,6 @@ subseg_set_rest (segT seg, subsegT subseg)
* Out: now_subseg, now_seg updated.
* Frchain_now points to the (possibly new) struct frchain for this
* sub-segment.
* Frchain_root updated if needed.
*/
segT
@ -247,21 +169,13 @@ subseg_get (const char *segname, int force_new)
seginfo = seg_info (secptr);
if (! seginfo)
{
/* Check whether output_section is set first because secptr may
be bfd_abs_section_ptr. */
if (secptr->output_section != secptr)
secptr->output_section = secptr;
secptr->output_section = secptr;
seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
memset ((PTR) seginfo, 0, sizeof (*seginfo));
seginfo->fix_root = NULL;
seginfo->fix_tail = NULL;
seginfo->bfd_section = secptr;
if (secptr == bfd_abs_section_ptr)
abs_seg_info = seginfo;
else if (secptr == bfd_und_section_ptr)
und_seg_info = seginfo;
else
bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
seginfo->frchainP = NULL;
seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
seginfo->sym = NULL;
@ -274,13 +188,9 @@ segT
subseg_new (const char *segname, subsegT subseg)
{
segT secptr;
segment_info_type *seginfo;
secptr = subseg_get (segname, 0);
subseg_set_rest (secptr, subseg);
seginfo = seg_info (secptr);
if (! seginfo->frchainP)
seginfo->frchainP = frchain_now;
return secptr;
}
@ -290,13 +200,9 @@ segT
subseg_force_new (const char *segname, subsegT subseg)
{
segT secptr;
segment_info_type *seginfo;
secptr = subseg_get (segname, 1);
subseg_set_rest (secptr, subseg);
seginfo = seg_info (secptr);
if (! seginfo->frchainP)
seginfo->frchainP = frchain_now;
return secptr;
}
@ -312,19 +218,6 @@ subseg_set (segT secptr, subsegT subseg)
#define obj_sec_sym_ok_for_reloc(SEC) 0
#endif
/* Get the gas information we are storing for a section. */
segment_info_type *
seg_info (segT sec)
{
if (sec == bfd_abs_section_ptr)
return abs_seg_info;
else if (sec == bfd_und_section_ptr)
return und_seg_info;
else
return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
}
symbolS *
section_symbol (segT sec)
{
@ -414,28 +307,33 @@ void
subsegs_print_statistics (FILE *file)
{
frchainS *frchp;
fprintf (file, "frag chains:\n");
for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
{
int count = 0;
fragS *fragp;
asection *s;
/* If frch_subseg is non-zero, it's probably been chained onto
the end of a previous subsection. Don't count it again. */
if (frchp->frch_subseg != 0)
continue;
fprintf (file, "frag chains:\n");
for (s = stdoutput->sections; s; s = s->next)
{
segment_info_type *seginfo;
/* Skip gas-internal sections. */
if (segment_name (frchp->frch_seg)[0] == '*')
if (segment_name (s)[0] == '*')
continue;
for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
seginfo = seg_info (s);
if (!seginfo)
continue;
for (frchp = seginfo->frchainP; frchp; frchp = frchp->frch_next)
{
count++;
int count = 0;
fragS *fragp;
for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
count++;
fprintf (file, "\n");
fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
segment_name (s), count);
}
fprintf (file, "\n");
fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
segment_name (frchp->frch_seg), count);
}
}

View file

@ -1,6 +1,6 @@
/* subsegs.h -> subsegs.c
Copyright 1987, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2003, 2005
Free Software Foundation, Inc.
Copyright 1987, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2003, 2005,
2006 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@ -45,7 +45,6 @@ struct frchain /* control building of a frag chain */
struct frag *frch_root; /* 1st struct frag in chain, or NULL */
struct frag *frch_last; /* last struct frag in chain, or NULL */
struct frchain *frch_next; /* next in chain of struct frchain-s */
segT frch_seg; /* SEG_TEXT or SEG_DATA. */
subsegT frch_subseg; /* subsegment number of this chain */
fixS *fix_root; /* Root of fixups for this subsegment. */
fixS *fix_tail; /* Last fixup for this subsegment. */
@ -55,9 +54,6 @@ struct frchain /* control building of a frag chain */
typedef struct frchain frchainS;
/* All subsegments' chains hang off here. NULL means no frchains yet. */
extern frchainS *frchain_root;
/* Frchain we are assembling into now. That is, the current segment's
frag chain, even if it contains no (complete) frags. */
extern frchainS *frchain_now;
@ -109,7 +105,10 @@ typedef struct segment_info_struct {
#endif
} segment_info_type;
extern segment_info_type *seg_info (segT);
#define seg_info(sec) \
((segment_info_type *) bfd_get_section_userdata (stdoutput, sec))
extern symbolS *section_symbol (segT);
extern void subsegs_print_statistics (FILE *);

View file

@ -1,6 +1,6 @@
/* write.c - emit .o file
Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@ -379,7 +379,7 @@ chain_frchains_together_1 (segT section, struct frchain *frchp)
fragS dummy, *prev_frag = &dummy;
fixS fix_dummy, *prev_fix = &fix_dummy;
for (; frchp && frchp->frch_seg == section; frchp = frchp->frch_next)
for (; frchp; frchp = frchp->frch_next)
{
prev_frag->fr_next = frchp->frch_root;
prev_frag = frchp->frch_last;
@ -1136,8 +1136,7 @@ set_symtab (void)
of the section. This allows proper nop-filling at the end of
code-bearing sections. */
#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \
(!(FRCHAIN)->frch_next || (FRCHAIN)->frch_next->frch_seg != (SEG) \
? get_recorded_alignment (SEG) : 0)
(!(FRCHAIN)->frch_next ? get_recorded_alignment (SEG) : 0)
#else
#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0
#endif
@ -1147,48 +1146,58 @@ void
subsegs_finish (void)
{
struct frchain *frchainP;
asection *s;
for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next)
for (s = stdoutput->sections; s; s = s->next)
{
int alignment = 0;
segment_info_type *seginfo = seg_info (s);
if (!seginfo)
continue;
subseg_set (frchainP->frch_seg, frchainP->frch_subseg);
/* This now gets called even if we had errors. In that case,
any alignment is meaningless, and, moreover, will look weird
if we are generating a listing. */
if (!had_errors ())
for (frchainP = seginfo->frchainP;
frchainP != NULL;
frchainP = frchainP->frch_next)
{
alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP);
if ((bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE)
&& now_seg->entsize)
int alignment = 0;
subseg_set (s, frchainP->frch_subseg);
/* This now gets called even if we had errors. In that case,
any alignment is meaningless, and, moreover, will look weird
if we are generating a listing. */
if (!had_errors ())
{
unsigned int entsize = now_seg->entsize;
int entalign = 0;
while ((entsize & 1) == 0)
alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP);
if ((bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE)
&& now_seg->entsize)
{
++entalign;
entsize >>= 1;
unsigned int entsize = now_seg->entsize;
int entalign = 0;
while ((entsize & 1) == 0)
{
++entalign;
entsize >>= 1;
}
if (entalign > alignment)
alignment = entalign;
}
if (entalign > alignment)
alignment = entalign;
}
if (subseg_text_p (now_seg))
frag_align_code (alignment, 0);
else
frag_align (alignment, 0, 0);
/* frag_align will have left a new frag.
Use this last frag for an empty ".fill".
For this segment ...
Create a last frag. Do not leave a "being filled in frag". */
frag_wane (frag_now);
frag_now->fr_fix = 0;
know (frag_now->fr_next == NULL);
}
if (subseg_text_p (now_seg))
frag_align_code (alignment, 0);
else
frag_align (alignment, 0, 0);
/* frag_align will have left a new frag.
Use this last frag for an empty ".fill".
For this segment ...
Create a last frag. Do not leave a "being filled in frag". */
frag_wane (frag_now);
frag_now->fr_fix = 0;
know (frag_now->fr_next == NULL);
}
}