Commit a97901e6 by Mark Mitchell Committed by Mark Mitchell

Makefile.in (INTREGRATE_H): Rename to INTEGRATE_H.

	* Makefile.in (INTREGRATE_H): Rename to INTEGRATE_H.
	* function.c (insert_block_after_note): Remove.
	(retrofit_block): Likewise.
	(identify_blocks): Fix indentation.
	(reorder_blocks): Don't NULL out NOTE_SOURCE_FILE for a
	NOTE_INSN_BLOCK_BEG or NOTE_INSN_BLOCK_END.
	* function.h (insert_block_after_note): Remove prototype.
	(retrofit_block): Likewise.
	* integrate.c (expand_inline_function): Don't call
	find_loop_tree_blocks.  Use expand_start_bindings_and_block, not
	just expand_start_bindings.  Use the block_map to remap old
	NOTE_BLOCKs to new ones.
	(integrate_decl_tree): Keep track of remapped blocks.
	* integrate.h (struct inline_remap): Add block_map.
	* stmt.c (expand_fixup): Don't try to retrofit_blocks.  Just set
	NOTE_BLOCK on the notes.
	(expand_start_bindings): Rename to ...
	(expand_start_bindings_and_block): Add parameter.  Set NOTE_BLOCK.
	(expand_end_bindings): Set NOTE_BLOCK.
	* toplev.c (rest_of_compilation): In function-at-a-time-mode,
	reconstruct the BLOCK tree.
	* tree.h (expand_start_bindings): Macroize.  Call ...
	(expand_start_bindings_and_block): New function.

	* optimize.c (struct inline_data): Remove scope_stmt.
	(remap_block): Don't use insert_block_after_note.  Don't update
	scope_stmt.
	(expand_call_inline): Don't update scope_stmt.
	(optimize_function): Don't initialize scope_stmt.
	* semantics.c (expand_stmt): Set NOTE_BLOCK for newly emitted
	NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END notes.

From-SVN: r30982
parent 0d9484c5
1999-12-16 Mark Mitchell <mark@codesourcery.com>
* Makefile.in (INTREGRATE_H): Rename to INTEGRATE_H.
* function.c (insert_block_after_note): Remove.
(retrofit_block): Likewise.
(identify_blocks): Fix indentation.
(reorder_blocks): Don't NULL out NOTE_SOURCE_FILE for a
NOTE_INSN_BLOCK_BEG or NOTE_INSN_BLOCK_END.
* function.h (insert_block_after_note): Remove prototype.
(retrofit_block): Likewise.
* integrate.c (expand_inline_function): Don't call
find_loop_tree_blocks. Use expand_start_bindings_and_block, not
just expand_start_bindings. Use the block_map to remap old
NOTE_BLOCKs to new ones.
(integrate_decl_tree): Keep track of remapped blocks.
* integrate.h (struct inline_remap): Add block_map.
* stmt.c (expand_fixup): Don't try to retrofit_blocks. Just set
NOTE_BLOCK on the notes.
(expand_start_bindings): Rename to ...
(expand_start_bindings_and_block): Add parameter. Set NOTE_BLOCK.
(expand_end_bindings): Set NOTE_BLOCK.
* toplev.c (rest_of_compilation): In function-at-a-time-mode,
reconstruct the BLOCK tree.
* tree.h (expand_start_bindings): Macroize. Call ...
(expand_start_bindings_and_block): New function.
1999-12-16 Jakub Jelinek <jakub@redhat.com> 1999-12-16 Jakub Jelinek <jakub@redhat.com>
* config/sparc/sparc.c (print_operand): Cast fprintf arguments * config/sparc/sparc.c (print_operand): Cast fprintf arguments
......
...@@ -748,7 +748,7 @@ DEMANGLE_H = $(srcdir)/../include/demangle.h ...@@ -748,7 +748,7 @@ DEMANGLE_H = $(srcdir)/../include/demangle.h
RECOG_H = recog.h RECOG_H = recog.h
EXPR_H = expr.h insn-codes.h EXPR_H = expr.h insn-codes.h
REGS_H = regs.h varray.h $(MACHMODE_H) REGS_H = regs.h varray.h $(MACHMODE_H)
INTREGRATE_H = integrate.h varray.h INTEGRATE_H = integrate.h varray.h
LOOP_H = loop.h varray.h LOOP_H = loop.h varray.h
# #
# Language makefile fragments. # Language makefile fragments.
......
1999-12-16 Mark Mitchell <mark@codesourcery.com>
* optimize.c (struct inline_data): Remove scope_stmt.
(remap_block): Don't use insert_block_after_note. Don't update
scope_stmt.
(expand_call_inline): Don't update scope_stmt.
(optimize_function): Don't initialize scope_stmt.
* semantics.c (expand_stmt): Set NOTE_BLOCK for newly emitted
NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END notes.
1999-12-15 Mark Mitchell <mark@codesourcery.com> 1999-12-15 Mark Mitchell <mark@codesourcery.com>
* class.c (handle_using_decl): Get TYPE_FIELDS and TYPE_METHODS * class.c (handle_using_decl): Get TYPE_FIELDS and TYPE_METHODS
......
...@@ -53,8 +53,6 @@ typedef struct inline_data ...@@ -53,8 +53,6 @@ typedef struct inline_data
inlining the body of `h', the stack will contain, `h', followed inlining the body of `h', the stack will contain, `h', followed
by `g', followed by `f'. */ by `g', followed by `f'. */
varray_type fns; varray_type fns;
/* The last SCOPE_STMT we have encountered. */
tree scope_stmt;
/* The label to jump to when a return statement is encountered. */ /* The label to jump to when a return statement is encountered. */
tree ret_label; tree ret_label;
/* The map from local declarations in the inlined function to /* The map from local declarations in the inlined function to
...@@ -146,6 +144,7 @@ remap_block (scope_stmt, decls, id) ...@@ -146,6 +144,7 @@ remap_block (scope_stmt, decls, id)
tree old_block; tree old_block;
tree new_block; tree new_block;
tree old_var; tree old_var;
tree fn;
/* Make the new block. */ /* Make the new block. */
old_block = SCOPE_STMT_BLOCK (scope_stmt); old_block = SCOPE_STMT_BLOCK (scope_stmt);
...@@ -175,13 +174,12 @@ remap_block (scope_stmt, decls, id) ...@@ -175,13 +174,12 @@ remap_block (scope_stmt, decls, id)
} }
/* We put the BLOCK_VARS in reverse order; fix that now. */ /* We put the BLOCK_VARS in reverse order; fix that now. */
BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block)); BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block));
/* Graft the new block into the tree. */ /* Attach this new block after the DECL_INITIAL block for the
insert_block_after_note (new_block, function into which this block is being inlined. In
SCOPE_STMT_BLOCK (id->scope_stmt), rest_of_compilation we will straighten out the BLOCK tree. */
SCOPE_BEGIN_P (id->scope_stmt)); fn = VARRAY_TREE (id->fns, 0);
/* Remember that this is now the last scope statement with BLOCK_CHAIN (new_block) = BLOCK_CHAIN (DECL_INITIAL (fn));
an associated block. */ BLOCK_CHAIN (DECL_INITIAL (fn)) = new_block;
id->scope_stmt = scope_stmt;
/* Remember the remapped block. */ /* Remember the remapped block. */
splay_tree_insert (id->decl_map, splay_tree_insert (id->decl_map,
(splay_tree_key) old_block, (splay_tree_key) old_block,
...@@ -198,10 +196,6 @@ remap_block (scope_stmt, decls, id) ...@@ -198,10 +196,6 @@ remap_block (scope_stmt, decls, id)
(splay_tree_key) SCOPE_STMT_BLOCK (scope_stmt)); (splay_tree_key) SCOPE_STMT_BLOCK (scope_stmt));
my_friendly_assert (n != NULL, 19991203); my_friendly_assert (n != NULL, 19991203);
SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value; SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value;
/* Remember that this is now the last scope statement with an
associated block. */
id->scope_stmt = scope_stmt;
} }
} }
...@@ -520,14 +514,6 @@ expand_call_inline (tp, walk_subtrees, data) ...@@ -520,14 +514,6 @@ expand_call_inline (tp, walk_subtrees, data)
id = (inline_data *) data; id = (inline_data *) data;
t = *tp; t = *tp;
/* Keep track of the last SCOPE_STMT we've seen. */
if (TREE_CODE (t) == SCOPE_STMT)
{
if (SCOPE_STMT_BLOCK (t) && !id->in_target_cleanup_p)
id->scope_stmt = t;
return NULL_TREE;
}
/* Recurse, but letting recursive invocations know that we are /* Recurse, but letting recursive invocations know that we are
inside the body of a TARGET_EXPR. */ inside the body of a TARGET_EXPR. */
if (TREE_CODE (*tp) == TARGET_EXPR) if (TREE_CODE (*tp) == TARGET_EXPR)
...@@ -608,11 +594,9 @@ expand_call_inline (tp, walk_subtrees, data) ...@@ -608,11 +594,9 @@ expand_call_inline (tp, walk_subtrees, data)
remap_block (scope_stmt, DECL_ARGUMENTS (fn), id); remap_block (scope_stmt, DECL_ARGUMENTS (fn), id);
TREE_CHAIN (scope_stmt) = STMT_EXPR_STMT (expr); TREE_CHAIN (scope_stmt) = STMT_EXPR_STMT (expr);
STMT_EXPR_STMT (expr) = scope_stmt; STMT_EXPR_STMT (expr) = scope_stmt;
id->scope_stmt = scope_stmt;
/* Tell the debugging backends that this block represents the /* Tell the debugging backends that this block represents the
outermost scope of the inlined function. FIXME what to do for outermost scope of the inlined function. */
inlines in cleanups? */
if (SCOPE_STMT_BLOCK (scope_stmt)) if (SCOPE_STMT_BLOCK (scope_stmt))
BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope_stmt)) = DECL_ORIGIN (fn); BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope_stmt)) = DECL_ORIGIN (fn);
...@@ -723,12 +707,6 @@ optimize_function (fn) ...@@ -723,12 +707,6 @@ optimize_function (fn)
prev_fn = s->function_decl; prev_fn = s->function_decl;
} }
/* Initialize id->scope_stmt with a fake SCOPE_STMT for the outermost
block of the function (i.e. the BLOCK with __FUNCTION__ et al). */
id.scope_stmt = build_min_nt (SCOPE_STMT,
BLOCK_SUBBLOCKS (DECL_INITIAL (fn)));
SCOPE_BEGIN_P (id.scope_stmt) = 1;
/* Replace all calls to inline functions with the bodies of those /* Replace all calls to inline functions with the bodies of those
functions. */ functions. */
expand_calls_inline (&DECL_SAVED_TREE (fn), &id); expand_calls_inline (&DECL_SAVED_TREE (fn), &id);
......
...@@ -2514,16 +2514,21 @@ expand_stmt (t) ...@@ -2514,16 +2514,21 @@ expand_stmt (t)
if (!SCOPE_NO_CLEANUPS_P (t)) if (!SCOPE_NO_CLEANUPS_P (t))
{ {
if (SCOPE_BEGIN_P (t)) if (SCOPE_BEGIN_P (t))
expand_start_bindings (2 * SCOPE_NULLIFIED_P (t)); expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t),
SCOPE_STMT_BLOCK (t));
else if (SCOPE_END_P (t)) else if (SCOPE_END_P (t))
expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t),
SCOPE_PARTIAL_P (t)); SCOPE_PARTIAL_P (t));
} }
else if (!SCOPE_NULLIFIED_P (t)) else if (!SCOPE_NULLIFIED_P (t))
emit_note (NULL, {
(SCOPE_BEGIN_P (t) rtx note = emit_note (NULL,
? NOTE_INSN_BLOCK_BEG (SCOPE_BEGIN_P (t)
: NOTE_INSN_BLOCK_END)); ? NOTE_INSN_BLOCK_BEG
: NOTE_INSN_BLOCK_END));
NOTE_BLOCK (note) = SCOPE_STMT_BLOCK (t);
}
break; break;
case RETURN_INIT: case RETURN_INIT:
......
...@@ -5493,66 +5493,6 @@ round_trampoline_addr (tramp) ...@@ -5493,66 +5493,6 @@ round_trampoline_addr (tramp)
return tramp; return tramp;
} }
/* Insert the BLOCK in the block-tree, knowing that the previous
block-note is for OLD_BLOCK. BEGIN_P is non-zero if the previous
block-note was the for the beginning of a BLOCK. */
void
insert_block_after_note (block, old_block, begin_p)
tree block;
tree old_block;
int begin_p;
{
if (begin_p)
{
/* If there was no previous block, something's gone terribly
wrong. We used to try to use DECL_INITIAL for the current
function, but that will never be correct, and completely
hoses the block structure. */
if (!old_block)
abort ();
BLOCK_SUPERCONTEXT (block) = old_block;
BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (old_block);
BLOCK_SUBBLOCKS (old_block) = block;
}
else
{
BLOCK_SUPERCONTEXT (block) = BLOCK_SUPERCONTEXT (old_block);
BLOCK_CHAIN (block) = BLOCK_CHAIN (old_block);
BLOCK_CHAIN (old_block) = block;
}
}
/* Insert the BLOCK in the block-tree before LAST_INSN. */
void
retrofit_block (block, last_insn)
tree block;
rtx last_insn;
{
rtx insn;
/* Now insert the new BLOCK at the right place in the block trees
for the function which called the inline function. We just look
backwards for a NOTE_INSN_BLOCK_{BEG,END}. If we find the
beginning of a block, then this new block becomes the first
subblock of that block. If we find the end of a block, then this
new block follows that block in the list of blocks. */
for (insn = last_insn; insn; insn = PREV_INSN (insn))
if (GET_CODE (insn) == NOTE
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END))
break;
if (insn == NULL_RTX)
abort ();
insert_block_after_note (block,
NOTE_BLOCK (insn),
NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG);
}
/* The functions identify_blocks and reorder_blocks provide a way to /* The functions identify_blocks and reorder_blocks provide a way to
reorder the tree of BLOCK nodes, for optimizers that reshuffle or reorder the tree of BLOCK nodes, for optimizers that reshuffle or
duplicate portions of the RTL code. Call identify_blocks before duplicate portions of the RTL code. Call identify_blocks before
...@@ -5595,8 +5535,8 @@ identify_blocks (block, insns) ...@@ -5595,8 +5535,8 @@ identify_blocks (block, insns)
{ {
tree b; tree b;
/* If there are more block notes than BLOCKs, something /* If there are more block notes than BLOCKs, something
is badly wrong. */ is badly wrong. */
if (current_block_number == n_blocks) if (current_block_number == n_blocks)
abort (); abort ();
...@@ -5660,14 +5600,12 @@ reorder_blocks (block, insns) ...@@ -5660,14 +5600,12 @@ reorder_blocks (block, insns)
BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block); BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
BLOCK_SUBBLOCKS (current_block) = block; BLOCK_SUBBLOCKS (current_block) = block;
current_block = block; current_block = block;
NOTE_SOURCE_FILE (insn) = 0;
} }
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END) if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
{ {
BLOCK_SUBBLOCKS (current_block) BLOCK_SUBBLOCKS (current_block)
= blocks_nreverse (BLOCK_SUBBLOCKS (current_block)); = blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
current_block = BLOCK_SUPERCONTEXT (current_block); current_block = BLOCK_SUPERCONTEXT (current_block);
NOTE_SOURCE_FILE (insn) = 0;
} }
} }
......
...@@ -543,12 +543,6 @@ extern struct function *outer_function_chain; ...@@ -543,12 +543,6 @@ extern struct function *outer_function_chain;
Also store in each NOTE for the beginning or end of a block Also store in each NOTE for the beginning or end of a block
the index of that block in the vector. */ the index of that block in the vector. */
extern void identify_blocks PROTO((tree, rtx)); extern void identify_blocks PROTO((tree, rtx));
/* Insert the BLOCK in the block-tree, knowing that the previous
block-note is for OLD_BLOCK. BEGIN_P is non-zero if the previous
block-note was the for the beginning of a BLOCK. */
extern void insert_block_after_note PROTO((tree, tree, int));
/* Insert a new BLOCK at an appropriate place in the block tree. */
extern void retrofit_block PROTO((tree, rtx));
/* Return size needed for stack frame based on slots so far allocated. /* Return size needed for stack frame based on slots so far allocated.
This size counts from zero. It is not rounded to STACK_BOUNDARY; This size counts from zero. It is not rounded to STACK_BOUNDARY;
......
...@@ -78,6 +78,8 @@ static void process_reg_param PROTO((struct inline_remap *, rtx, ...@@ -78,6 +78,8 @@ static void process_reg_param PROTO((struct inline_remap *, rtx,
void set_decl_abstract_flags PROTO((tree, int)); void set_decl_abstract_flags PROTO((tree, int));
static rtx expand_inline_function_eh_labelmap PROTO((rtx)); static rtx expand_inline_function_eh_labelmap PROTO((rtx));
static void mark_stores PROTO((rtx, rtx, void *)); static void mark_stores PROTO((rtx, rtx, void *));
static int compare_blocks PROTO((const PTR, const PTR));
static int find_block PROTO((const PTR, const PTR));
/* The maximum number of instructions accepted for inlining a /* The maximum number of instructions accepted for inlining a
function. Increasing values mean more agressive inlining. function. Increasing values mean more agressive inlining.
...@@ -505,6 +507,35 @@ expand_inline_function_eh_labelmap (label) ...@@ -505,6 +507,35 @@ expand_inline_function_eh_labelmap (label)
return get_label_from_map (eif_eh_map, index); return get_label_from_map (eif_eh_map, index);
} }
/* Compare two BLOCKs for qsort. The key we sort on is the
BLOCK_ABSTRACT_ORIGIN of the blocks. */
static int
compare_blocks (v1, v2)
const PTR v1;
const PTR v2;
{
tree b1 = *((tree *) v1);
tree b2 = *((tree *) v2);
return ((char *) BLOCK_ABSTRACT_ORIGIN (b1)
- (char *) BLOCK_ABSTRACT_ORIGIN (b2));
}
/* Compare two BLOCKs for bsearch. The first pointer corresponds to
an original block; the second to a remapped equivalent. */
static int
find_block (v1, v2)
const PTR v1;
const PTR v2;
{
tree b1 = (tree) v1;
tree b2 = *((tree *) v2);
return ((char *) b1 - (char *) BLOCK_ABSTRACT_ORIGIN (b2));
}
/* Integrate the procedure defined by FNDECL. Note that this function /* Integrate the procedure defined by FNDECL. Note that this function
may wind up calling itself. Since the static variables are not may wind up calling itself. Since the static variables are not
reentrant, we do not assign them until after the possibility reentrant, we do not assign them until after the possibility
...@@ -687,6 +718,7 @@ expand_inline_function (fndecl, parms, target, ignore, type, ...@@ -687,6 +718,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
map = (struct inline_remap *) xmalloc (sizeof (struct inline_remap)); map = (struct inline_remap *) xmalloc (sizeof (struct inline_remap));
map->fndecl = fndecl; map->fndecl = fndecl;
VARRAY_TREE_INIT (map->block_map, 10, "block_map");
map->reg_map = (rtx *) xcalloc (max_regno, sizeof (rtx)); map->reg_map = (rtx *) xcalloc (max_regno, sizeof (rtx));
/* We used to use alloca here, but the size of what it would try to /* We used to use alloca here, but the size of what it would try to
...@@ -757,11 +789,6 @@ expand_inline_function (fndecl, parms, target, ignore, type, ...@@ -757,11 +789,6 @@ expand_inline_function (fndecl, parms, target, ignore, type,
RTX_INTEGRATED_P (note) = 1; RTX_INTEGRATED_P (note) = 1;
} }
/* Figure out where the blocks are if we're going to have to insert
new BLOCKs into the existing block tree. */
if (current_function->x_whole_function_mode_p)
find_loop_tree_blocks ();
/* Process each argument. For each, set up things so that the function's /* Process each argument. For each, set up things so that the function's
reference to the argument will refer to the argument being passed. reference to the argument will refer to the argument being passed.
We only replace REG with REG here. Any simplifications are done We only replace REG with REG here. Any simplifications are done
...@@ -1006,15 +1033,32 @@ expand_inline_function (fndecl, parms, target, ignore, type, ...@@ -1006,15 +1033,32 @@ expand_inline_function (fndecl, parms, target, ignore, type,
else else
abort (); abort ();
/* Make a fresh binding contour that we can easily remove. Do this after
expanding our arguments so cleanups are properly scoped. */
expand_start_bindings (0);
/* Initialize label_map. get_label_from_map will actually make /* Initialize label_map. get_label_from_map will actually make
the labels. */ the labels. */
bzero ((char *) &map->label_map [min_labelno], bzero ((char *) &map->label_map [min_labelno],
(max_labelno - min_labelno) * sizeof (rtx)); (max_labelno - min_labelno) * sizeof (rtx));
/* Make copies of the decls of the symbols in the inline function, so that
the copies of the variables get declared in the current function. Set
up things so that lookup_static_chain knows that to interpret registers
in SAVE_EXPRs for TYPE_SIZEs as local. */
inline_function_decl = fndecl;
integrate_parm_decls (DECL_ARGUMENTS (fndecl), map, arg_vector);
block = integrate_decl_tree (inl_f->original_decl_initial, map);
BLOCK_ABSTRACT_ORIGIN (block) = DECL_ORIGIN (fndecl);
inline_function_decl = 0;
/* Make a fresh binding contour that we can easily remove. Do this after
expanding our arguments so cleanups are properly scoped. */
expand_start_bindings_and_block (0, block);
/* Sort the block-map so that it will be easy to find remapped
blocks later. */
qsort (&VARRAY_TREE (map->block_map, 0),
map->block_map->elements_used,
sizeof (tree),
compare_blocks);
/* Perform postincrements before actually calling the function. */ /* Perform postincrements before actually calling the function. */
emit_queue (); emit_queue ();
...@@ -1292,6 +1336,25 @@ expand_inline_function (fndecl, parms, target, ignore, type, ...@@ -1292,6 +1336,25 @@ expand_inline_function (fndecl, parms, target, ignore, type,
region. */ region. */
NOTE_EH_HANDLER (copy) = CODE_LABEL_NUMBER (label); NOTE_EH_HANDLER (copy) = CODE_LABEL_NUMBER (label);
} }
else if (copy
&& (NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_BEG
|| NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_END)
&& NOTE_BLOCK (insn))
{
tree *mapped_block_p;
mapped_block_p
= (tree *) bsearch (NOTE_BLOCK (insn),
&VARRAY_TREE (map->block_map, 0),
map->block_map->elements_used,
sizeof (tree),
find_block);
if (!mapped_block_p)
abort ();
else
NOTE_BLOCK (copy) = *mapped_block_p;
}
} }
else else
copy = 0; copy = 0;
...@@ -1332,27 +1395,18 @@ expand_inline_function (fndecl, parms, target, ignore, type, ...@@ -1332,27 +1395,18 @@ expand_inline_function (fndecl, parms, target, ignore, type,
if (inl_f->calls_alloca) if (inl_f->calls_alloca)
emit_stack_restore (SAVE_BLOCK, stack_save, NULL_RTX); emit_stack_restore (SAVE_BLOCK, stack_save, NULL_RTX);
/* Make copies of the decls of the symbols in the inline function, so that if (!current_function->x_whole_function_mode_p)
the copies of the variables get declared in the current function. Set
up things so that lookup_static_chain knows that to interpret registers
in SAVE_EXPRs for TYPE_SIZEs as local. */
inline_function_decl = fndecl;
integrate_parm_decls (DECL_ARGUMENTS (fndecl), map, arg_vector);
block = integrate_decl_tree (inl_f->original_decl_initial, map);
BLOCK_ABSTRACT_ORIGIN (block) = (DECL_ABSTRACT_ORIGIN (fndecl) == NULL
? fndecl : DECL_ABSTRACT_ORIGIN (fndecl));
inline_function_decl = 0;
if (current_function->x_whole_function_mode_p)
/* Insert the block into the already existing block-tree. */
retrofit_block (block, map->insns_at_start);
else
/* In statement-at-a-time mode, we just tell the front-end to add /* In statement-at-a-time mode, we just tell the front-end to add
this block to the list of blocks at this binding level. We this block to the list of blocks at this binding level. We
can't do it the way it's done for function-at-a-time mode the can't do it the way it's done for function-at-a-time mode the
superblocks have not been created yet. */ superblocks have not been created yet. */
insert_block (block); insert_block (block);
else
{
BLOCK_CHAIN (block)
= BLOCK_CHAIN (DECL_INITIAL (current_function_decl));
BLOCK_CHAIN (DECL_INITIAL (current_function_decl)) = block;
}
/* End the scope containing the copied formal parameter variables /* End the scope containing the copied formal parameter variables
and copied LABEL_DECLs. We pass NULL_TREE for the variables list and copied LABEL_DECLs. We pass NULL_TREE for the variables list
...@@ -1392,6 +1446,7 @@ expand_inline_function (fndecl, parms, target, ignore, type, ...@@ -1392,6 +1446,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
free (real_label_map); free (real_label_map);
VARRAY_FREE (map->const_equiv_varray); VARRAY_FREE (map->const_equiv_varray);
free (map->reg_map); free (map->reg_map);
VARRAY_FREE (map->block_map);
free (map->insn_map); free (map->insn_map);
free (map); free (map);
free (arg_vals); free (arg_vals);
...@@ -1451,6 +1506,7 @@ integrate_decl_tree (let, map) ...@@ -1451,6 +1506,7 @@ integrate_decl_tree (let, map)
tree *next; tree *next;
new_block = make_node (BLOCK); new_block = make_node (BLOCK);
VARRAY_PUSH_TREE (map->block_map, new_block);
next = &BLOCK_VARS (new_block); next = &BLOCK_VARS (new_block);
for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t)) for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
......
...@@ -42,6 +42,8 @@ struct inline_remap ...@@ -42,6 +42,8 @@ struct inline_remap
union tree_node *fndecl; union tree_node *fndecl;
/* Place to put insns needed at start of function. */ /* Place to put insns needed at start of function. */
rtx insns_at_start; rtx insns_at_start;
/* Mapping from old BLOCKs to new BLOCKs. */
varray_type block_map;
/* Mapping from old registers to new registers. /* Mapping from old registers to new registers.
It is allocated and deallocated in `expand_inline_function' */ It is allocated and deallocated in `expand_inline_function' */
rtx *reg_map; rtx *reg_map;
......
...@@ -1024,23 +1024,30 @@ expand_fixup (tree_label, rtl_label, last_insn) ...@@ -1024,23 +1024,30 @@ expand_fixup (tree_label, rtl_label, last_insn)
register rtx original_before_jump register rtx original_before_jump
= last_insn ? last_insn : get_last_insn (); = last_insn ? last_insn : get_last_insn ();
rtx start; rtx start;
rtx end;
tree block; tree block;
block = make_node (BLOCK); block = make_node (BLOCK);
TREE_USED (block) = 1; TREE_USED (block) = 1;
if (current_function->x_whole_function_mode_p) if (!current_function->x_whole_function_mode_p)
insert_block (block);
else
{ {
find_loop_tree_blocks (); BLOCK_CHAIN (block)
retrofit_block (block, original_before_jump); = BLOCK_CHAIN (DECL_INITIAL (current_function_decl));
BLOCK_CHAIN (DECL_INITIAL (current_function_decl))
= block;
} }
else
insert_block (block);
start_sequence (); start_sequence ();
start = emit_note (NULL_PTR, NOTE_INSN_BLOCK_BEG); start = emit_note (NULL_PTR, NOTE_INSN_BLOCK_BEG);
if (current_function->x_whole_function_mode_p)
NOTE_BLOCK (start) = block;
fixup->before_jump = emit_note (NULL_PTR, NOTE_INSN_DELETED); fixup->before_jump = emit_note (NULL_PTR, NOTE_INSN_DELETED);
emit_note (NULL_PTR, NOTE_INSN_BLOCK_END); end = emit_note (NULL_PTR, NOTE_INSN_BLOCK_END);
if (current_function->x_whole_function_mode_p)
NOTE_BLOCK (end) = block;
fixup->context = block; fixup->context = block;
end_sequence (); end_sequence ();
emit_insns_after (start, original_before_jump); emit_insns_after (start, original_before_jump);
...@@ -3198,20 +3205,36 @@ tail_recursion_args (actuals, formals) ...@@ -3198,20 +3205,36 @@ tail_recursion_args (actuals, formals)
will not create corresponding BLOCK nodes. (There should be will not create corresponding BLOCK nodes. (There should be
a one-to-one correspondence between NOTE_INSN_BLOCK_BEG notes a one-to-one correspondence between NOTE_INSN_BLOCK_BEG notes
and BLOCKs.) If this flag is set, MARK_ENDS should be zero and BLOCKs.) If this flag is set, MARK_ENDS should be zero
when expand_end_bindings is called. */ when expand_end_bindings is called.
If we are creating a NOTE_INSN_BLOCK_BEG note, a BLOCK may
optionally be supplied. If so, it becomes the NOTE_BLOCK for the
note. */
void void
expand_start_bindings (flags) expand_start_bindings_and_block (flags, block)
int flags; int flags;
tree block;
{ {
struct nesting *thisblock = ALLOC_NESTING (); struct nesting *thisblock = ALLOC_NESTING ();
rtx note; rtx note;
int exit_flag = ((flags & 1) != 0); int exit_flag = ((flags & 1) != 0);
int block_flag = ((flags & 2) == 0); int block_flag = ((flags & 2) == 0);
/* If a BLOCK is supplied, then the caller should be requesting a
NOTE_INSN_BLOCK_BEG note. */
if (!block_flag && block)
abort ();
note = emit_note (NULL_PTR, /* Create a note to mark the beginning of the block. */
block_flag ? NOTE_INSN_BLOCK_BEG : NOTE_INSN_DELETED); if (block_flag)
{
note = emit_note (NULL_PTR, NOTE_INSN_BLOCK_BEG);
NOTE_BLOCK (note) = block;
}
else
note = emit_note (NULL_PTR, NOTE_INSN_DELETED);
/* Make an entry on block_stack for the block we are entering. */ /* Make an entry on block_stack for the block we are entering. */
thisblock->next = block_stack; thisblock->next = block_stack;
...@@ -3659,7 +3682,10 @@ expand_end_bindings (vars, mark_ends, dont_jump_in) ...@@ -3659,7 +3682,10 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
just going out of scope, so they are in scope for their cleanups. */ just going out of scope, so they are in scope for their cleanups. */
if (mark_ends) if (mark_ends)
emit_note (NULL_PTR, NOTE_INSN_BLOCK_END); {
rtx note = emit_note (NULL_PTR, NOTE_INSN_BLOCK_END);
NOTE_BLOCK (note) = NOTE_BLOCK (thisblock->data.block.first_insn);
}
else else
/* Get rid of the beginning-mark if we don't make an end-mark. */ /* Get rid of the beginning-mark if we don't make an end-mark. */
NOTE_LINE_NUMBER (thisblock->data.block.first_insn) = NOTE_INSN_DELETED; NOTE_LINE_NUMBER (thisblock->data.block.first_insn) = NOTE_INSN_DELETED;
......
...@@ -3605,6 +3605,14 @@ rest_of_compilation (decl) ...@@ -3605,6 +3605,14 @@ rest_of_compilation (decl)
collector to reclaim the memory used by the notes. */ collector to reclaim the memory used by the notes. */
remove_unncessary_notes (); remove_unncessary_notes ();
/* In function-at-a-time mode, we do not attempt to keep the BLOCK
tree in sensible shape. So, we just recalculate it here. */
if (current_function->x_whole_function_mode_p)
{
find_loop_tree_blocks ();
unroll_block_trees ();
}
/* If we are reconsidering an inline function /* If we are reconsidering an inline function
at the end of compilation, skip the stuff for making it inline. */ at the end of compilation, skip the stuff for making it inline. */
......
...@@ -2100,7 +2100,9 @@ extern int expand_exit_something PROTO((void)); ...@@ -2100,7 +2100,9 @@ extern int expand_exit_something PROTO((void));
extern void expand_null_return PROTO((void)); extern void expand_null_return PROTO((void));
extern void expand_return PROTO((tree)); extern void expand_return PROTO((tree));
extern int optimize_tail_recursion PROTO((tree, struct rtx_def *)); extern int optimize_tail_recursion PROTO((tree, struct rtx_def *));
extern void expand_start_bindings PROTO((int)); extern void expand_start_bindings_and_block PROTO((int, tree));
#define expand_start_bindings(flags) \
expand_start_bindings_and_block(flags, NULL_TREE)
extern void expand_end_bindings PROTO((tree, int, int)); extern void expand_end_bindings PROTO((tree, int, int));
extern void warn_about_unused_variables PROTO((tree)); extern void warn_about_unused_variables PROTO((tree));
extern void start_cleanup_deferral PROTO((void)); extern void start_cleanup_deferral PROTO((void));
......
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