summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>1999-12-16 17:50:29 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>1999-12-16 17:50:29 +0000
commit89689e23d8f4b3d0647da42364b9d943cb3ba91a (patch)
tree0e496457c98d2aabb71fdf3add8cb1bb884dc210
parentf27284b4420df797f8363d4f9218011a5424c9a5 (diff)
downloadgcc-89689e23d8f4b3d0647da42364b9d943cb3ba91a.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@30982 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog26
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/optimize.c38
-rw-r--r--gcc/cp/semantics.c15
-rw-r--r--gcc/function.c66
-rw-r--r--gcc/function.h6
-rw-r--r--gcc/integrate.c106
-rw-r--r--gcc/integrate.h2
-rw-r--r--gcc/stmt.c50
-rw-r--r--gcc/toplev.c8
-rw-r--r--gcc/tree.h4
12 files changed, 189 insertions, 144 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d2a65821335..5473179ef54 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,29 @@
+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>
* config/sparc/sparc.c (print_operand): Cast fprintf arguments
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 6e63925c91a..6f367cb26b0 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -748,7 +748,7 @@ DEMANGLE_H = $(srcdir)/../include/demangle.h
RECOG_H = recog.h
EXPR_H = expr.h insn-codes.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
#
# Language makefile fragments.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ff70df40b34..05f1618310e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+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>
* class.c (handle_using_decl): Get TYPE_FIELDS and TYPE_METHODS
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 7eae09df3fc..2dd151ccb01 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -53,8 +53,6 @@ typedef struct inline_data
inlining the body of `h', the stack will contain, `h', followed
by `g', followed by `f'. */
varray_type fns;
- /* The last SCOPE_STMT we have encountered. */
- tree scope_stmt;
/* The label to jump to when a return statement is encountered. */
tree ret_label;
/* The map from local declarations in the inlined function to
@@ -146,6 +144,7 @@ remap_block (scope_stmt, decls, id)
tree old_block;
tree new_block;
tree old_var;
+ tree fn;
/* Make the new block. */
old_block = SCOPE_STMT_BLOCK (scope_stmt);
@@ -175,13 +174,12 @@ remap_block (scope_stmt, decls, id)
}
/* We put the BLOCK_VARS in reverse order; fix that now. */
BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block));
- /* Graft the new block into the tree. */
- insert_block_after_note (new_block,
- SCOPE_STMT_BLOCK (id->scope_stmt),
- SCOPE_BEGIN_P (id->scope_stmt));
- /* Remember that this is now the last scope statement with
- an associated block. */
- id->scope_stmt = scope_stmt;
+ /* Attach this new block after the DECL_INITIAL block for the
+ function into which this block is being inlined. In
+ rest_of_compilation we will straighten out the BLOCK tree. */
+ fn = VARRAY_TREE (id->fns, 0);
+ BLOCK_CHAIN (new_block) = BLOCK_CHAIN (DECL_INITIAL (fn));
+ BLOCK_CHAIN (DECL_INITIAL (fn)) = new_block;
/* Remember the remapped block. */
splay_tree_insert (id->decl_map,
(splay_tree_key) old_block,
@@ -198,10 +196,6 @@ remap_block (scope_stmt, decls, id)
(splay_tree_key) SCOPE_STMT_BLOCK (scope_stmt));
my_friendly_assert (n != NULL, 19991203);
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)
id = (inline_data *) data;
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
inside the body of a TARGET_EXPR. */
if (TREE_CODE (*tp) == TARGET_EXPR)
@@ -608,11 +594,9 @@ expand_call_inline (tp, walk_subtrees, data)
remap_block (scope_stmt, DECL_ARGUMENTS (fn), id);
TREE_CHAIN (scope_stmt) = STMT_EXPR_STMT (expr);
STMT_EXPR_STMT (expr) = scope_stmt;
- id->scope_stmt = scope_stmt;
/* Tell the debugging backends that this block represents the
- outermost scope of the inlined function. FIXME what to do for
- inlines in cleanups? */
+ outermost scope of the inlined function. */
if (SCOPE_STMT_BLOCK (scope_stmt))
BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope_stmt)) = DECL_ORIGIN (fn);
@@ -723,12 +707,6 @@ optimize_function (fn)
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
functions. */
expand_calls_inline (&DECL_SAVED_TREE (fn), &id);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 339726fe7ed..5ac7bdb83f7 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2514,16 +2514,21 @@ expand_stmt (t)
if (!SCOPE_NO_CLEANUPS_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))
expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t),
SCOPE_PARTIAL_P (t));
}
else if (!SCOPE_NULLIFIED_P (t))
- emit_note (NULL,
- (SCOPE_BEGIN_P (t)
- ? NOTE_INSN_BLOCK_BEG
- : NOTE_INSN_BLOCK_END));
+ {
+ rtx note = emit_note (NULL,
+ (SCOPE_BEGIN_P (t)
+ ? NOTE_INSN_BLOCK_BEG
+ : NOTE_INSN_BLOCK_END));
+ NOTE_BLOCK (note) = SCOPE_STMT_BLOCK (t);
+ }
+
break;
case RETURN_INIT:
diff --git a/gcc/function.c b/gcc/function.c
index 321120457b9..02ee9fb14eb 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -5493,66 +5493,6 @@ round_trampoline_addr (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
reorder the tree of BLOCK nodes, for optimizers that reshuffle or
duplicate portions of the RTL code. Call identify_blocks before
@@ -5595,8 +5535,8 @@ identify_blocks (block, insns)
{
tree b;
- /* If there are more block notes than BLOCKs, something
- is badly wrong. */
+ /* If there are more block notes than BLOCKs, something
+ is badly wrong. */
if (current_block_number == n_blocks)
abort ();
@@ -5660,14 +5600,12 @@ reorder_blocks (block, insns)
BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
BLOCK_SUBBLOCKS (current_block) = block;
current_block = block;
- NOTE_SOURCE_FILE (insn) = 0;
}
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
{
BLOCK_SUBBLOCKS (current_block)
= blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
current_block = BLOCK_SUPERCONTEXT (current_block);
- NOTE_SOURCE_FILE (insn) = 0;
}
}
diff --git a/gcc/function.h b/gcc/function.h
index 0e2b7b8bf3a..a641189e5d1 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -543,12 +543,6 @@ extern struct function *outer_function_chain;
Also store in each NOTE for the beginning or end of a block
the index of that block in the vector. */
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.
This size counts from zero. It is not rounded to STACK_BOUNDARY;
diff --git a/gcc/integrate.c b/gcc/integrate.c
index f8253095872..c50c1d4923c 100644
--- a/gcc/integrate.c
+++ b/gcc/integrate.c
@@ -78,6 +78,8 @@ static void process_reg_param PROTO((struct inline_remap *, rtx,
void set_decl_abstract_flags PROTO((tree, int));
static rtx expand_inline_function_eh_labelmap PROTO((rtx));
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
function. Increasing values mean more agressive inlining.
@@ -505,6 +507,35 @@ expand_inline_function_eh_labelmap (label)
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
may wind up calling itself. Since the static variables are not
reentrant, we do not assign them until after the possibility
@@ -687,6 +718,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
map = (struct inline_remap *) xmalloc (sizeof (struct inline_remap));
map->fndecl = fndecl;
+ VARRAY_TREE_INIT (map->block_map, 10, "block_map");
map->reg_map = (rtx *) xcalloc (max_regno, sizeof (rtx));
/* 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,
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
reference to the argument will refer to the argument being passed.
We only replace REG with REG here. Any simplifications are done
@@ -1006,15 +1033,32 @@ expand_inline_function (fndecl, parms, target, ignore, type,
else
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
the labels. */
bzero ((char *) &map->label_map [min_labelno],
(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. */
emit_queue ();
@@ -1292,6 +1336,25 @@ expand_inline_function (fndecl, parms, target, ignore, type,
region. */
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
copy = 0;
@@ -1332,27 +1395,18 @@ expand_inline_function (fndecl, parms, target, ignore, type,
if (inl_f->calls_alloca)
emit_stack_restore (SAVE_BLOCK, stack_save, NULL_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_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
+ if (!current_function->x_whole_function_mode_p)
/* 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
can't do it the way it's done for function-at-a-time mode the
superblocks have not been created yet. */
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
and copied LABEL_DECLs. We pass NULL_TREE for the variables list
@@ -1392,6 +1446,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
free (real_label_map);
VARRAY_FREE (map->const_equiv_varray);
free (map->reg_map);
+ VARRAY_FREE (map->block_map);
free (map->insn_map);
free (map);
free (arg_vals);
@@ -1451,6 +1506,7 @@ integrate_decl_tree (let, map)
tree *next;
new_block = make_node (BLOCK);
+ VARRAY_PUSH_TREE (map->block_map, new_block);
next = &BLOCK_VARS (new_block);
for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
diff --git a/gcc/integrate.h b/gcc/integrate.h
index 88bcd53960b..4cc75fabbdc 100644
--- a/gcc/integrate.h
+++ b/gcc/integrate.h
@@ -42,6 +42,8 @@ struct inline_remap
union tree_node *fndecl;
/* Place to put insns needed at start of function. */
rtx insns_at_start;
+ /* Mapping from old BLOCKs to new BLOCKs. */
+ varray_type block_map;
/* Mapping from old registers to new registers.
It is allocated and deallocated in `expand_inline_function' */
rtx *reg_map;
diff --git a/gcc/stmt.c b/gcc/stmt.c
index e94c1e8a87a..826295ba5bb 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -1024,23 +1024,30 @@ expand_fixup (tree_label, rtl_label, last_insn)
register rtx original_before_jump
= last_insn ? last_insn : get_last_insn ();
rtx start;
+ rtx end;
tree block;
block = make_node (BLOCK);
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 ();
- retrofit_block (block, original_before_jump);
+ BLOCK_CHAIN (block)
+ = BLOCK_CHAIN (DECL_INITIAL (current_function_decl));
+ BLOCK_CHAIN (DECL_INITIAL (current_function_decl))
+ = block;
}
- else
- insert_block (block);
start_sequence ();
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);
- 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;
end_sequence ();
emit_insns_after (start, original_before_jump);
@@ -3198,20 +3205,36 @@ tail_recursion_args (actuals, formals)
will not create corresponding BLOCK nodes. (There should be
a one-to-one correspondence between NOTE_INSN_BLOCK_BEG notes
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
-expand_start_bindings (flags)
+expand_start_bindings_and_block (flags, block)
int flags;
+ tree block;
{
struct nesting *thisblock = ALLOC_NESTING ();
rtx note;
int exit_flag = ((flags & 1) != 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,
- block_flag ? NOTE_INSN_BLOCK_BEG : NOTE_INSN_DELETED);
-
+ /* Create a note to mark the beginning of the block. */
+ 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. */
thisblock->next = block_stack;
@@ -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. */
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
/* 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;
diff --git a/gcc/toplev.c b/gcc/toplev.c
index a880812daf8..892149fc4af 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -3605,6 +3605,14 @@ rest_of_compilation (decl)
collector to reclaim the memory used by the 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
at the end of compilation, skip the stuff for making it inline. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 4108042114c..e802e0ccc04 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2100,7 +2100,9 @@ extern int expand_exit_something PROTO((void));
extern void expand_null_return PROTO((void));
extern void expand_return PROTO((tree));
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 warn_about_unused_variables PROTO((tree));
extern void start_cleanup_deferral PROTO((void));