Commit a20612aa by Richard Henderson Committed by Richard Henderson

dwarf2out.c (dw_val_class_offset): New.

	* dwarf2out.c (dw_val_class_offset): New.
	(struct dw_ranges_struct, dw_ranges_ref): New.
	(ranges_table, ranges_table_allocated): New.
	(ranges_table_in_use, RANGES_TABLE_INCREMENT): New.
	(add_AT_offset, add_ranges, output_ranges): New.
	(print_die, output_die): Handle dw_val_class_offset.
	(attr_checksum, size_of_die, value_format): Likewise.
	(gen_lexical_block_die): Handle non-contiguous blocks.
	(gen_block_die): Likewise.
	(dwarf2out_finish): Add a DW_AT_entry_pc to the compilation unit
	if needed.  Dump the ranges table.
	* final.c (final_start_function): Remove unnecessary notes and
	rebuild the block tree before numbering the blocks.
	* function.c (reorder_blocks_0): Walk the existing block tree
	to unmark all blocks.
	(reorder_blocks_1): Create block fragments when duplicate block
	notes are seen.
	(reorder_fix_fragments): New.
	(reorder_blocks): Call it.
	* tree.h (BLOCK_FRAGMENT_ORIGIN, BLOCK_FRAGMENT_CHAIN): New.

From-SVN: r44444
parent 594280a3
2001-07-28 Richard Henderson <rth@redhat.com>
* dwarf2out.c (dw_val_class_offset): New.
(struct dw_ranges_struct, dw_ranges_ref): New.
(ranges_table, ranges_table_allocated): New.
(ranges_table_in_use, RANGES_TABLE_INCREMENT): New.
(add_AT_offset, add_ranges, output_ranges): New.
(print_die, output_die): Handle dw_val_class_offset.
(attr_checksum, size_of_die, value_format): Likewise.
(gen_lexical_block_die): Handle non-contiguous blocks.
(gen_block_die): Likewise.
(dwarf2out_finish): Add a DW_AT_entry_pc to the compilation unit
if needed. Dump the ranges table.
* final.c (final_start_function): Remove unnecessary notes and
rebuild the block tree before numbering the blocks.
* function.c (reorder_blocks_0): Walk the existing block tree
to unmark all blocks.
(reorder_blocks_1): Create block fragments when duplicate block
notes are seen.
(reorder_fix_fragments): New.
(reorder_blocks): Call it.
* tree.h (BLOCK_FRAGMENT_ORIGIN, BLOCK_FRAGMENT_CHAIN): New.
2001-07-28 Richard Henderson <rth@redhat.com>
* emit-rtl.c (adjust_address): Make a copy of the memory address.
2001-07-28 Richard Henderson <rth@redhat.com>
......
......@@ -1597,8 +1597,9 @@ final_start_function (first, file, optimize)
function. */
if (write_symbols)
{
number_blocks (current_function_decl);
remove_unnecessary_notes ();
reorder_blocks ();
number_blocks (current_function_decl);
/* We never actually put out begin/end notes for the top-level
block in the function. But, conceptually, that block is
always needed. */
......
......@@ -278,8 +278,9 @@ static void pad_below PARAMS ((struct args_size *, enum machine_mode,
static rtx round_trampoline_addr PARAMS ((rtx));
static rtx adjust_trampoline_addr PARAMS ((rtx));
static tree *identify_blocks_1 PARAMS ((rtx, tree *, tree *, tree *));
static void reorder_blocks_0 PARAMS ((rtx));
static void reorder_blocks_0 PARAMS ((tree));
static void reorder_blocks_1 PARAMS ((rtx, tree, varray_type *));
static void reorder_fix_fragments PARAMS ((tree));
static tree blocks_nreverse PARAMS ((tree));
static int all_blocks PARAMS ((tree, tree *));
static tree *get_block_vector PARAMS ((tree, int *));
......@@ -5819,8 +5820,11 @@ identify_blocks_1 (insns, block_vector, end_block_vector, orig_block_stack)
return block_vector;
}
/* Identify BLOCKs referenced by more than one
NOTE_INSN_BLOCK_{BEG,END}, and create duplicate blocks. */
/* Identify BLOCKs referenced by more than one NOTE_INSN_BLOCK_{BEG,END},
and create duplicate blocks. */
/* ??? Need an option to either create block fragments or to create
abstract origin duplicates of a source block. It really depends
on what optimization has been performed. */
void
reorder_blocks ()
......@@ -5833,47 +5837,34 @@ reorder_blocks ()
VARRAY_TREE_INIT (block_stack, 10, "block_stack");
/* Reset the TREE_ASM_WRITTEN bit for all blocks. */
reorder_blocks_0 (block);
/* Prune the old trees away, so that they don't get in the way. */
BLOCK_SUBBLOCKS (block) = NULL_TREE;
BLOCK_CHAIN (block) = NULL_TREE;
reorder_blocks_0 (get_insns ());
/* Recreate the block tree from the note nesting. */
reorder_blocks_1 (get_insns (), block, &block_stack);
BLOCK_SUBBLOCKS (block) = blocks_nreverse (BLOCK_SUBBLOCKS (block));
/* Remove deleted blocks from the block fragment chains. */
reorder_fix_fragments (block);
VARRAY_FREE (block_stack);
}
/* Helper function for reorder_blocks. Process the insn chain beginning
at INSNS. Recurse for CALL_PLACEHOLDER insns. */
/* Helper function for reorder_blocks. Reset TREE_ASM_WRITTEN. */
static void
reorder_blocks_0 (insns)
rtx insns;
reorder_blocks_0 (block)
tree block;
{
rtx insn;
for (insn = insns; insn; insn = NEXT_INSN (insn))
while (block)
{
if (GET_CODE (insn) == NOTE)
{
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
{
tree block = NOTE_BLOCK (insn);
TREE_ASM_WRITTEN (block) = 0;
}
}
else if (GET_CODE (insn) == CALL_INSN
&& GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
{
rtx cp = PATTERN (insn);
reorder_blocks_0 (XEXP (cp, 0));
if (XEXP (cp, 1))
reorder_blocks_0 (XEXP (cp, 1));
if (XEXP (cp, 2))
reorder_blocks_0 (XEXP (cp, 2));
}
TREE_ASM_WRITTEN (block) = 0;
reorder_blocks_0 (BLOCK_SUBBLOCKS (block));
block = BLOCK_CHAIN (block);
}
}
......@@ -5892,12 +5883,26 @@ reorder_blocks_1 (insns, current_block, p_block_stack)
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
{
tree block = NOTE_BLOCK (insn);
/* If we have seen this block before, copy it. */
/* If we have seen this block before, that means it now
spans multiple address regions. Create a new fragment. */
if (TREE_ASM_WRITTEN (block))
{
block = copy_node (block);
NOTE_BLOCK (insn) = block;
tree new_block = copy_node (block);
tree origin;
origin = (BLOCK_FRAGMENT_ORIGIN (block)
? BLOCK_FRAGMENT_ORIGIN (block)
: block);
BLOCK_FRAGMENT_ORIGIN (new_block) = origin;
BLOCK_FRAGMENT_CHAIN (new_block)
= BLOCK_FRAGMENT_CHAIN (origin);
BLOCK_FRAGMENT_CHAIN (origin) = new_block;
NOTE_BLOCK (insn) = new_block;
block = new_block;
}
BLOCK_SUBBLOCKS (block) = 0;
TREE_ASM_WRITTEN (block) = 1;
BLOCK_SUPERCONTEXT (block) = current_block;
......@@ -5928,6 +5933,62 @@ reorder_blocks_1 (insns, current_block, p_block_stack)
}
}
/* Rationalize BLOCK_FRAGMENT_ORIGIN. If an origin block no longer
appears in the block tree, select one of the fragments to become
the new origin block. */
static void
reorder_fix_fragments (block)
tree block;
{
while (block)
{
tree dup_origin = BLOCK_FRAGMENT_ORIGIN (block);
tree new_origin = NULL_TREE;
if (dup_origin)
{
if (! TREE_ASM_WRITTEN (dup_origin))
{
new_origin = BLOCK_FRAGMENT_CHAIN (dup_origin);
/* Find the first of the remaining fragments. There must
be at least one -- the current block. */
while (! TREE_ASM_WRITTEN (new_origin))
new_origin = BLOCK_FRAGMENT_CHAIN (new_origin);
BLOCK_FRAGMENT_ORIGIN (new_origin) = NULL_TREE;
}
}
else if (! dup_origin)
new_origin = block;
/* Re-root the rest of the fragments to the new origin. In the
case that DUP_ORIGIN was null, that means BLOCK was the origin
of a chain of fragments and we want to remove those fragments
that didn't make it to the output. */
if (new_origin)
{
tree *pp = &BLOCK_FRAGMENT_CHAIN (new_origin);
tree chain = *pp;
while (chain)
{
if (TREE_ASM_WRITTEN (chain))
{
BLOCK_FRAGMENT_ORIGIN (chain) = new_origin;
*pp = chain;
pp = &BLOCK_FRAGMENT_CHAIN (chain);
}
chain = BLOCK_FRAGMENT_CHAIN (chain);
}
*pp = NULL_TREE;
}
reorder_fix_fragments (BLOCK_SUBBLOCKS (block));
block = BLOCK_CHAIN (block);
}
}
/* Reverse the order of elements in the chain T of blocks,
and return the new head of the chain (old last element). */
......
......@@ -848,6 +848,33 @@ struct tree_exp
the debugging output format in use. */
#define BLOCK_NUMBER(NODE) (BLOCK_CHECK (NODE)->block.block_num)
/* If block reordering splits a lexical block into discontiguous
address ranges, we'll make a copy of the original block.
Note that this is logically distinct from BLOCK_ABSTRACT_ORIGIN.
In that case, we have one source block that has been replicated
(through inlining or unrolling) into many logical blocks, and that
these logical blocks have different physical variables in them.
In this case, we have one logical block split into several
non-contiguous address ranges. Most debug formats can't actually
represent this idea directly, so we fake it by creating multiple
logical blocks with the same variables in them. However, for those
that do support non-contiguous regions, these allow the original
logical block to be reconstructed, along with the set of address
ranges.
One of the logical block fragments is arbitrarily chosen to be
the ORIGIN. The other fragments will point to the origin via
BLOCK_FRAGMENT_ORIGIN; the origin itself will have this pointer
be null. The list of fragments will be chained through
BLOCK_FRAGMENT_CHAIN from the origin. */
#define BLOCK_FRAGMENT_ORIGIN(NODE) \
(BLOCK_CHECK (NODE)->block.fragment_origin)
#define BLOCK_FRAGMENT_CHAIN(NODE) \
(BLOCK_CHECK (NODE)->block.fragment_chain)
struct tree_block
{
struct tree_common common;
......@@ -860,6 +887,8 @@ struct tree_block
union tree_node *subblocks;
union tree_node *supercontext;
union tree_node *abstract_origin;
union tree_node *fragment_origin;
union tree_node *fragment_chain;
};
/* Define fields and accessors for nodes representing data types. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment