diff options
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/function.c | 64 | ||||
-rw-r--r-- | gcc/function.h | 8 | ||||
-rw-r--r-- | gcc/integrate.c | 19 | ||||
-rw-r--r-- | gcc/stmt.c | 15 |
6 files changed, 114 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a9d61aeefa..1f0d6e67bbb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +Fri Sep 17 15:19:01 1999 Mark Mitchell <mark@codesourcery.com> + + * functiion.h (struct function): Add x_whole_function_mode_p. + (retrofit_block): Declare. + * function.c (retrofit_block): New function. + (identify_blocks): Add assertions. Allow an incomplete set of + block notes if we're still generating code for the function. + * integrate.c: Include loop.h. + (expand_inline_function): Call find_loop_tree_blocks to map block + notes to blocks when in whole-function mode. Use retrofit_block + to insert new BLOCKs for the inlined function, rather than + insert_block. + * stmt.c (expand_fixup): Likewise. Don't use pushlevel/polevel. + * Makefile.in (integrate.o): Depend on loop.h. + Fri Sep 17 15:11:20 1999 Mark Mitchell <mark@codesourcery.com> * tree.h (warn_about_unused_variables): Declare. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index dd4fa3dc6cd..428f4f5d255 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1519,7 +1519,7 @@ emit-rtl.o : emit-rtl.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \ real.o : real.c $(CONFIG_H) system.h $(TREE_H) toplev.h integrate.o : integrate.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \ integrate.h insn-flags.h insn-config.h $(EXPR_H) real.h $(REGS_H) \ - intl.h function.h output.h $(RECOG_H) except.h toplev.h + intl.h function.h output.h $(RECOG_H) except.h toplev.h loop.h jump.o : jump.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h $(REGS_H) \ insn-config.h insn-flags.h $(RECOG_H) $(EXPR_H) real.h except.h function.h \ toplev.h insn-attr.h diff --git a/gcc/function.c b/gcc/function.c index 81a1ef16170..ffbcd0185c4 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -5381,6 +5381,49 @@ round_trampoline_addr (tramp) return tramp; } +/* 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 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG) + { + tree superblock; + + if (insn) + superblock = NOTE_BLOCK (insn); + else + superblock = DECL_INITIAL (current_function_decl); + + BLOCK_SUPERCONTEXT (block) = superblock; + BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (superblock); + BLOCK_SUBBLOCKS (superblock) = block; + } + else + { + tree prevblock = NOTE_BLOCK (insn); + + BLOCK_SUPERCONTEXT (block) = BLOCK_SUPERCONTEXT (prevblock); + BLOCK_CHAIN (block) = BLOCK_CHAIN (prevblock); + BLOCK_CHAIN (prevblock) = block; + } +} + /* 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 @@ -5423,15 +5466,30 @@ identify_blocks (block, insns) { tree b; + /* If there are more block notes than BLOCKs, something + is badly wrong. */ + if (current_block_number == n_blocks) + abort (); + b = block_vector[current_block_number++]; NOTE_BLOCK (insn) = b; block_stack[depth++] = b; } - if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END) - NOTE_BLOCK (insn) = block_stack[--depth]; + else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END) + { + if (depth == 0) + /* There are more NOTE_INSN_BLOCK_ENDs that + NOTE_INSN_BLOCK_BEGs. Something is badly wrong. */ + abort (); + + NOTE_BLOCK (insn) = block_stack[--depth]; + } } - if (n_blocks != current_block_number) + /* In whole-function mode, we might not have seen the whole function + yet, so we might not use up all the blocks. */ + if (n_blocks != current_block_number + && !current_function->x_whole_function_mode_p) abort (); free (block_vector); diff --git a/gcc/function.h b/gcc/function.h index 0d70b7d6aed..80053d20c30 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -293,6 +293,12 @@ struct function /* Number of function calls seen so far in current function. */ int x_function_call_count; + /* Nonzero if this function is being processed in function-at-a-time + mode. In other words, if all tree structure for this function, + including the BLOCK tree is created, before RTL generation + commences. */ + int x_whole_function_mode_p; + /* List (chain of TREE_LIST) of LABEL_DECLs for all nonlocal labels (labels to which there can be nonlocal gotos from nested functions) in this function. */ @@ -521,6 +527,8 @@ 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 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 3c278767ce0..e1b7990f21a 100644 --- a/gcc/integrate.c +++ b/gcc/integrate.c @@ -38,6 +38,7 @@ Boston, MA 02111-1307, USA. */ #include "function.h" #include "toplev.h" #include "intl.h" +#include "loop.h" #include "obstack.h" #define obstack_chunk_alloc xmalloc @@ -74,8 +75,6 @@ static void set_decl_origin_self PROTO((tree)); static void set_block_abstract_flags PROTO((tree, int)); static void process_reg_param PROTO((struct inline_remap *, rtx, rtx)); - - void set_decl_abstract_flags PROTO((tree, int)); static tree copy_and_set_decl_abstract_origin PROTO((tree)); @@ -742,6 +741,11 @@ 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 @@ -1279,7 +1283,16 @@ expand_inline_function (fndecl, parms, target, ignore, type, BLOCK_ABSTRACT_ORIGIN (block) = (DECL_ABSTRACT_ORIGIN (fndecl) == NULL ? fndecl : DECL_ABSTRACT_ORIGIN (fndecl)); inline_function_decl = 0; - insert_block (block); + + 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 + 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); /* End the scope containing the copied formal parameter variables and copied LABEL_DECLs. We pass NULL_TREE for the variables list diff --git a/gcc/stmt.c b/gcc/stmt.c index 51110b8a78d..5a9a25e1180 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -1016,13 +1016,24 @@ expand_fixup (tree_label, rtl_label, last_insn) register rtx original_before_jump = last_insn ? last_insn : get_last_insn (); rtx start; + tree block; + + block = make_node (BLOCK); + TREE_USED (block) = 1; + + if (current_function->x_whole_function_mode_p) + { + find_loop_tree_blocks (); + retrofit_block (block, original_before_jump); + } + else + insert_block (block); start_sequence (); - pushlevel (0); start = emit_note (NULL_PTR, NOTE_INSN_BLOCK_BEG); fixup->before_jump = emit_note (NULL_PTR, NOTE_INSN_DELETED); last_block_end_note = emit_note (NULL_PTR, NOTE_INSN_BLOCK_END); - fixup->context = poplevel (1, 0, 0); /* Create the BLOCK node now! */ + fixup->context = block; end_sequence (); emit_insns_after (start, original_before_jump); } |