aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>1998-11-03 20:24:34 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>1998-11-03 20:24:34 +0000
commit5106338e8c59391943a1ad51e61527d2ab957889 (patch)
tree3eacc26ce046eaa6379b125c284a8e98e76e7ef5
parentcf7b0b09a6bb4735f1670573b3316d4b6f1b89d8 (diff)
Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
200k patch to move things out of global variables and into struct function. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/egcs_gc_branch@23515 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.GC390
-rw-r--r--gcc/Makefile.in53
-rw-r--r--gcc/alias.c1
-rw-r--r--gcc/c-decl.c10
-rw-r--r--gcc/c-lang.c2
-rw-r--r--gcc/c-parse.c761
-rw-r--r--gcc/c-parse.in9
-rw-r--r--gcc/c-parse.y27
-rw-r--r--gcc/c-tree.h2
-rw-r--r--gcc/caller-save.c1
-rw-r--r--gcc/calls.c13
-rw-r--r--gcc/combine.c3
-rw-r--r--gcc/config/i386/i386.c63
-rw-r--r--gcc/config/i386/i386.h2
-rw-r--r--gcc/cse.c1
-rw-r--r--gcc/emit-rtl.c270
-rw-r--r--gcc/except.c230
-rw-r--r--gcc/except.h22
-rw-r--r--gcc/explow.c1
-rw-r--r--gcc/expr.c65
-rw-r--r--gcc/expr.h69
-rw-r--r--gcc/final.c1
-rw-r--r--gcc/flags.h13
-rw-r--r--gcc/flow.c4
-rw-r--r--gcc/function.c817
-rw-r--r--gcc/function.h489
-rw-r--r--gcc/gcse.c5
-rw-r--r--gcc/genemit.c1
-rw-r--r--gcc/ggc-simple.c41
-rw-r--r--gcc/ggc.h14
-rw-r--r--gcc/global.c1
-rw-r--r--gcc/haifa-sched.c6
-rw-r--r--gcc/integrate.c971
-rw-r--r--gcc/integrate.h4
-rw-r--r--gcc/jump.c5
-rw-r--r--gcc/local-alloc.c1
-rw-r--r--gcc/loop.c1
-rw-r--r--gcc/optabs.c2
-rw-r--r--gcc/output.h108
-rw-r--r--gcc/print-tree.c4
-rw-r--r--gcc/profile.c13
-rw-r--r--gcc/reg-stack.c3
-rw-r--r--gcc/regclass.c1
-rw-r--r--gcc/regmove.c3
-rw-r--r--gcc/regs.h18
-rw-r--r--gcc/reload.c1
-rw-r--r--gcc/reload1.c4
-rw-r--r--gcc/rtl.h74
-rw-r--r--gcc/stmt.c346
-rw-r--r--gcc/stor-layout.c25
-rw-r--r--gcc/stupid.c1
-rw-r--r--gcc/toplev.c99
-rw-r--r--gcc/tree.h14
-rw-r--r--gcc/unroll.c5
-rw-r--r--gcc/varasm.c13
55 files changed, 2001 insertions, 3102 deletions
diff --git a/gcc/ChangeLog.GC b/gcc/ChangeLog.GC
index 46db44f9e36..e807d7458a4 100644
--- a/gcc/ChangeLog.GC
+++ b/gcc/ChangeLog.GC
@@ -1,3 +1,393 @@
+Tue Nov 3 20:14:33 1998 Richard Henderson <rth@cygnus.com>
+
+ * alpha.h (alpha_eh_epilogue_sp_ofs): Remove.
+ (struct machine_function): Define here. Add eh epilogue bits.
+ * alpha.c (struct machine_function): Remove.
+ (alpha_return_addr_rtx, alpha_eh_epilogue_sp_ofs): Remove.
+ (alpha_init_machine_status): Create from corpse of save_machine_status.
+ (alpha_restore_machine_status): Do nothing.
+ (alpha_init_expanders): Update for save->init change.
+ (alpha_return_addr): Use current_function->machine directly.
+ (alpha_ra_ever_killed): Likewise.
+ (alpha_expand_epilogue): Likewise.
+ * alpha.md (eh_epilogue): Likewise.
+
+Tue Nov 3 20:13:06 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * function.h (struct var_refs_queue): Delete definition.
+ (struct function_status): New structure, broken out of struct
+ function.
+ (struct emit_status): Likewise.
+ (struct expr_status): Likewise.
+ (struct function): Break out most elements into separate structures.
+ Add next_global, func, stmt, emit, expr, inlinable, max_label_num,
+ original_arg_vector, original_decl_initial and can_garbage_collect
+ elements.
+ (current_function): Declare variable.
+ (cur_f_s): Declare variable.
+ Add many accessor macros for previously global variables which now
+ live in struct function and its sub-structures.
+ (return_label): Delete declaration.
+ (stack_slot_list): Delete declaration.
+ (REGNO_POINTER_ALIGN): Define here, not in regs.h.
+ (REGNO_POINTER_FLAG): Likewise.
+ (get_func_frame_size): Declare new function.
+ (init_machine_status): Renamed from save_machine_status.
+ (save_eh_status, restore_eh_status, save_stmt_status,
+ restore_stmt_status, save_expr_status, restore_expr_status,
+ save_emit_status, save_storage_status, restore_storage_status):
+ Delete declarations.
+ (free_varasm_status): Declare new function.
+ (free_emit_status): Likewise.
+ (free_after_compilation): Likewise.
+
+ * stmt.c (emit_filename, emit_lineno, expr_stmts_for_value,
+ last_expr_type, last_expr_value, block_start_count, block_stack,
+ stack_block_stack, cond_stack, loop_stack, case_stack, nesting_stack,
+ nesting_depth, goto_fixup_chain): Delete global vars; now allocated
+ dynamically in stmt elt of struct function for each function.
+ (current_function_returns_pcc_struct, cleanup_label, return_label,
+ frame_offset, tail_recursion_label, tail_recursion_reentry,
+ arg_pointer_save_area, rtl_expr_chain): Delete extern declarations.
+ (struct nesting): Rename function_call_count elt to n_function_calls,
+ target_temp_slot_level to block_target_temp_slot_level. All users
+ changed.
+ (struct stmt_status): New structure definition.
+ Add many accessor macros for stmt_status elements which previously
+ were global variables.
+ (init_stmt): Don't set any roots.
+ (init_stmt_for_function): Allocate stmt elt for current_function.
+ (save_stmt_status, restore_stmt_status): Delete functions.
+ (mark_cond_nesting, mark_loop_nesting, mark_case_nesting,
+ mark_block_nesting): Now static.
+ (mark_stmt_state): New function.
+ (set_file_and_line_for_stmt): New function.
+ (expand_goto): Match changes in organization of struct function.
+ (preserve_subexpressions_p): Don't access loop_stack when outside
+ a function.
+ (expand_return): Use get_frame_size instead of testing frame_offset.
+ (expand_start_bindings): Reflect that block_start_count was renamed to
+ current_block_start_count.
+ (expand_end_bindings): Likewise.
+ (expand_decl): Don't access block_stack when outside a function.
+
+ * except.c (current_function_ehc, ehstack, catchstack, ehqueue,
+ catch_clauses, protect_list, caught_return_label_stack,
+ false_label_stack): Delete global vars; now allocated dynamically
+ in eh elt of struct function for each function.
+ (struct eh_status): New structure definition.
+ Add many accessor macros for eh_status elements which previously
+ were global variables.
+ (mark_eh_node, mark_eh_stack, mark_eh_queue, mark_tree_label_node,
+ mark_rtx_label_node): Now static.
+ (save_eh_status, restore_eh_status): Delete.
+ (mark_eh_state): Match changes in organization of struct function.
+ (init_eh): Don't set any roots.
+ (init_eh_for_function): Allocate eh elt for current_function.
+ * except.h (struct eh_function): Deleted; now defined in except.c
+ as struct eh_status.
+ (caught_return_label_stack, false_label_stack): Delete declarations.
+
+ * emit-rtl.c (reg_rtx_no, first_label_num, first_insn, last_insn,
+ sequence_rtl_expr, cur_insn_uid, last_linenum, last_filename,
+ regno_pointer_flag, regno_pointer_flag_length, regno_pointer_align,
+ regno_reg_rtx, sequence_stack): Delete global vars; now allocated
+ dynamically in emit elt of struct function for each function.
+ Add many accessor macros for emit_status elements which previously
+ were global variables.
+ (emit_filename, emit_lineno): Delete extern declarations.
+ (save_emit_status): Delete.
+ (restore_emit_status): Just clear last_label_num.
+ (free_emit_status): New function.
+ (set_new_last_label_num): New function.
+ (get_last_insn_anywhere): sequence_stack was renamed to seq_stack.
+ (add_insn_after): Likewise.
+ (add_insn_before): Likewise.
+ (start_sequence): Likewise.
+ (start_sequence_for_rtl_expr): Likewise.
+ (push_topmost_sequence): Likewise.
+ (end_sequence): Likewise.
+ (in_sequence_p): Likewise.
+ (emit_line_note): Don't set emit_filename/emit_lineno; call
+ set_file_and_line_for_stmt.
+ (init_emit): Allocate emit elt for current_function.
+ sequence_rtl_expr was renamed to seq_rtl_expr.
+ sequence_stack was renamed to seq_stack.
+ Allocate regno_pointer_flag, regno_pointer_align, regno_reg_rtx with
+ xcalloc.
+ (mark_sequence_stack): Now static.
+ (mark_regno_reg_rtx): Delete function.
+ (mark_emit_state): New function.
+ (init_emit_once): Don't clear sequence_stack; done in init_emit.
+ Don't add roots for first_insn, sequence_rtl_expr, sequence_stack,
+ regno_reg_rtx.
+
+ * varasm.c (free_varasm_status): New function.
+
+ * expr.c (pending_stack_adjust, inhibit_defer_pop, saveregs_value,
+ apply_args_value): Delete global vars; now allocated
+ dynamically in expr elt of struct function for each function.
+ Add many accessor macros for expr_status elements which previously
+ were global variables.
+ (arg_pointer_save_area): Delete extern declaration.
+ (init_expr): Allocate expr elt for current_function.
+ (save_expr_status, restore_expr_status): Delete functions.
+ (expand_expr): Match changes in organization of struct function.
+ Delete extern declaration for temp_slot_level.
+
+ * function.c: Include ggc.h.
+ (current_function_pops_args, current_function_returns_struct,
+ current_function_returns_pcc_struct, current_function_needs_context,
+ current_function_calls_setjmp, current_function_calls_longjmp,
+ current_function_has_nonlocal_label, current_function_is_thunk,
+ current_function_epilogue_delay_list, current_function_args_size,
+ current_function_returns_pointer, current_function_contains_functions,
+ current_function_calls_alloca, current_function_pretend_args_size,
+ current_function_outgoing_args_size, current_function_arg_offset_rtx,
+ current_function_return_rtx, current_function_uses_const_pool,
+ current_function_uses_pic_offset_table, current_function_stdarg,
+ current_function_internal_arg_pointer, current_function_varargs,
+ current_function_cannot_inline, current_function_args_info,
+ current_function_instrument_entry_exit, current_function_name,
+ function_call_count, nonlocal_labels, nonlocal_goto_handler_slot,
+ nonlocal_goto_stack_level, cleanup_label, return_label,
+ save_expr_regs, stack_slot_list, rtl_expr_chain, tail_recursion_label,
+ tail_recursion_reentry, arg_pointer_save_area, context_display,
+ trampoline_list, parm_birth_insn, invalid_stack_slot, last_parm_insn,
+ parm_reg_stack_loc, temp_slots, temp_slot_level, var_temp_slot_level,
+ target_temp_slot_level): Delete global vars; now allocated dynamically
+ in func elt of struct function for each function.
+ (sequence_rtl_expr): Delete extern declaration.
+ (current_function): New variable.
+ (cur_f_s): New variable.
+ (init_machine_status): Renamed from save_machine_status.
+ (struct var_refs_queue): Declare here.
+ (all_functions): New global variable.
+ (push_function_context_to): Don't allocate a struct function.
+ Don't copy around a million variables.
+ Don't call save_emit_status, save_expr_status, save_storage_status,
+ save_machine_status or save_stmt_status.
+ (pop_function_context_from): Lose test for inline_obstacks.
+ Don't copy around a million variables.
+ Set current_function and cur_f_s; don't free the struct function.
+ Don't call restore_expr_status, restore_storage_status,
+ restore_machine_status or restore_stmt_status.
+ Free elements found on the fixup_var_refs_queue.
+ (free_after_compilation): New function.
+ (get_func_frame_size): New function.
+ (assign_outer_stack_local): Accept a struct function_status arg
+ instead of struct function arg. All callers changed. Adjust the
+ code appropriately.
+ Delete obstack juggling code.
+ (assign_stack_temp): sequence_rtl_expr was renamed to seq_rtl_expr.
+ (put_reg_into_stack): Match changes in organization of struct
+ function. Allocate var_refs_queue with xmalloc. Delete obstack
+ juggling code.
+ (fixup_var_refs): sequence_stack was renamed to seq_stack.
+ Rename variable first_insn to first.
+ (assign_parms): Allocate parm_reg_stack_loc with xcalloc/xrealloc.
+ (fix_lexical_addr): Match changes in organization of struct function.
+ (trampoline_address): Likewise. Delete obstack juggling code.
+ (prepare_function_start): New function, mostly broken out of
+ init_function_start.
+ (init_function_start): Call it. Put current_function on the
+ chain of all functions ever seen.
+ (init_dummy_function_start): New function.
+ (expand_dummy_function_end): New function.
+ (mark_function_state): New function, mostly broken out of
+ mark_function_chain.
+ (mark_function_chain): Walk through the next_global elt of struct
+ function, not the next elt. Don't process functions which have the
+ can_garbage_collect flag set.
+ Call mark_function_state, mark_stmt_state, mark_eh_state,
+ mark_emit_state instead of doing the work here.
+ Mark the fields reserved for function inlining as roots.
+ (init_functino_once): Use all_functions instead of
+ outer_function_chain as root.
+ Delete temp_slots and parm_reg_stack_loc roots.
+
+ * integrate.c (initialize_for_inline): Lose all args except FNDECL.
+ Return the generated argvec. All callers changed.
+ Don't compute function_flags; lose the code for copying; don't
+ generate an INLINE_HEADER rtx.
+ (finish_inline, adjust_copied_decl_tree, save_for_inline_copying,
+ copy_decl_list, copy_decl_tree, copy_decl_rtls, copy_for_inline):
+ Delete unused functions.
+ (reg_map, label_map, insn_map, orig_asm_operands_vector,
+ copy_asm_operands_vector, copy_asm_constraints_vector,
+ in_nonparm_insn): Delete unused static vars.
+ (max_parm_reg, parm_reg_stack_loc): Delete extern declarations.
+ (save_for_inline_nocopy): in_nonparm_insns is now local to this
+ function.
+ Instead of calling finish_inline, put the necessary information
+ into current_function, and set DECL_SAVED_INSNS for the fndecl
+ to current_function.
+ Call free_varasm_status at the end.
+ (note_modified_parmregs): Don't test in_nonparm_insn.
+ (expand_inline_function): Get information from function structure,
+ not from an inline header rtx.
+ Adjust to match renamed fields in in struct inline_remap.
+ (copy_rtx_and_substitute): Likewise.
+ (output_inline_function): Lose code to extract the necessary
+ information from an inline header; simply put back the function
+ structure into current_function. Clear its inlinable elt.
+ Don't clear current_function_decl when done.
+ * integrate.h (struct inline_remap): Prefix regno_pointer_flag
+ and regno_pointer_align elts with "x_" to avoid name clashes
+ with global macros.
+
+ * toplev.c: Include function.h.
+ (compile_file): When calling initialization functions that need
+ to generate rtl, make sure we don't crash by calling
+ init_dummy_function_start/expand_dummy_function_end around those
+ calls to set up an initialized environment.
+ (rest_of_compilation): Lose code to save inline functions by
+ copying them.
+ Adjust for the fact that DECL_SAVED_INSNS points to a struct
+ function.
+ When done, but before calling ggc_collect, call
+ free_after_compilation and clear current_function and cur_f_s.
+
+ * calls.c: Include function.h.
+ (calls_function_1): Adjust for the fact that DECL_SAVED_INSNS points
+ to a struct function.
+ (expand_call): Likewise.
+
+ * ggc-simple.c (ggc_free_rtx): Delete INLINE_HEADER special case.
+ (ggc_mark_rtx): Likewise.
+ (ggc_mark_tree): Mark first operand of a SAVE_EXPR.
+ Lose special case for FUNCTION_DECL.
+ * ggc.h (mark_cond_nesting, mark_sequence_stack, mark_loop_nesting,
+ mark_block_nesting, mark_case_nesting, mark_goto_fixup,
+ mark_tree_label_node): Delete declarations.
+ (mark_stmt_state, mark_emit_state): Add declarations.
+
+ * tree.h (struct tree_decl): Add struct function pointer to
+ saved_insns union.
+ (DECL_SAVED_INSNS): Use it.
+ (current_function_calls_setjmp, current_function_calls_longjmp):
+ Delete delcarations.
+ * rtl.h (FIRST_FUNCTION_INSN, FIRST_PARM_INSN, FIRST_LABELNO,
+ LAST_LABELNO, MAX_PARMREG, MAX_REGNUM, FUNCTION_ARGS_SIZE,
+ POPS_ARGS, STACK_SLOT_LIST, FORCED_LABELS, FUNCTION_FLAGS,
+ OUTGOING_ARGS_SIZE, ORIGINAL_ARG_VECTOR, ORIGINAL_DECL_INITIAL,
+ INLINE_REGNO_REG_RTX, INLINE_REGNO_POINTER_FLAG,
+ INLINE_REGNO_POINTER_ALIGN, PARMREG_STACK_LOC,
+ FUNCTION_FLAGS_CALLS_ALLOCA, FUNCTION_FLAGS_CALLS_SETJMP,
+ FUNCTION_FLAGS_RETURNS_STRUCT, FUNCTION_FLAGS_RETURNS_PCC_STRUCT,
+ FUNCTION_FLAGS_NEEDS_CONTEXT, FUNCTION_FLAGS_HAS_NONLOCAL_LABEL,
+ FUNCTION_FLAGS_RETURNS_POINTER, FUNCTION_FLAGS_USES_CONST_POOL,
+ FUNCTION_FLAGS_CALLS_LONGJMP, FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE):
+ Delete macros.
+ (regno_reg_rtx, regno_pointer_align): Delete declarations.
+ (REGNO_POINTER_ALIGN): Delete macro.
+ (set_new_last_label_num, set_file_and_line_for_stmt): Declare
+ functions.
+
+ * expr.h (forced_labels, save_expr_regs, function_call_count,
+ current_function_outgoing_args_size, current_function_calls_alloca,
+ current_function_arg_offset_rtx, current_function_uses_const_pool,
+ current_function_uses_pic_offset_table,
+ current_function_internal_arg_pointer, inhibit_defer_pop,
+ nonlocal_goto_handler_slot, nonlocal_goto_stack_level,
+ nonlocal_labels, pending_stack_adjust, target_temp_slot_level,
+ temp_slot_level): Delete extern declarations.
+ (init_storage_once): Declare function.
+ * output.h (current_function_pops_args,
+ current_function_returns_struct, current_function_returns_pcc_struct,
+ current_function_needs_context, current_function_calls_setjmp,
+ current_function_calls_longjmp, current_function_calls_alloca,
+ current_function_has_nonlocal_label, current_function_returns_pointer,
+ current_function_contains_functions, current_function_args_size,
+ current_function_pretend_args_size, current_function_varargs,
+ current_function_outgoing_args_size, current_function_stdarg,
+ current_function_args_info, current_function_name,
+ current_function_return_rtx, current_function_epilogue_delay_list,
+ current_function_uses_pic_offset_table,
+ current_function_uses_const_pool, current_function_cannot_inline):
+ Delete extern declarations.
+ * flags.h (current_function_has_nonlocal_label,
+ current_function_has_nonlocal_gotom, current_function_is_thunk):
+ Delete extern declarations.
+
+
+ * i386.c (pic_label_rtx, pic_label_name, i386_stack_locals): Delete
+ global vars; now allocated dynamically in machine elt of struct
+ function for each function.
+ (struct machine_function): Prefix element names with "_x".
+ Add accessor macros for machine_function elements which previously
+ were global variables.
+ (clear_386_stack_locals): Move most of the code to
+ init_386_machine_status. Initialize init_machine_status, not
+ save_machine_status.
+ (init_386_machine_status): Renamed from save_386_machine_status.
+ Perform initialization of status previously done in
+ clear_386_stack_locals.
+ (restore_386_machine_status): Don't do anything.
+
+ * explow.c: Include function.h.
+ * alias.c: Include function.h.
+ * loop.c: Include function.h.
+ * global.c: Include function.h.
+ * final.c: Include function.h.
+ * gcse.c: Include function.h.
+ (current_function_name): Delete declaration.
+ (current_function_calls_setjmp): Likewise.
+ (current_function_calls_longjmp): Likewise.
+ * stupid.c: Include function.h.
+ * local-alloc.c: Include function.h.
+ * regmove.c: Include function.h.
+ * cse.c: Include function.h.
+ * combine.c: Include function.h.
+ * reload.c: Include function.h.
+ * reload1.c: Include function.h.
+ (forced_labels): Delete declaration.
+ * flow.c: Include function.h.
+ (forced_labels): Delete declaration.
+ * jump.c: Include function.h.
+ (forced_labels): Delete declaration.
+ * reg-stack.c: Include function.h.
+ (forced_labels): Delete declaration.
+ * haifa-sched.c: Include function.h.
+ (forced_labels): Delete declaration.
+ * optabs.c: Include function.h and ggc.h.
+
+ * genemit.c (main): Write include of function.h.
+
+ * unroll.c: Include function.h.
+ (unroll_loop): Adjust to match renamed fields in in struct
+ inline_remap.
+
+ * profile.c: Include function.h and ggc.h.
+ (init_arc_profiler): profiler_label is a root.
+ (output_func_start_profiler): Call start_sequence after
+ calling init_function_start.
+
+ * c-decl.c (duplicate_decls): Don't refer to DECL_FRAME_SIZE.
+ (pushdecl): Nor here.
+ (pop_c_function_context): Clear out language-specific elt in
+ struct function; data becomes invalid hereafter.
+ (mark_c_function_context): Don't crash if language-specific elt
+ is NULL.
+ * c-parse.in (c_parse_init): New function.
+ * c-tree.h: Declare it.
+ * c-lang.c (lang_init): Call it.
+
+ * stor-layout.c (save_storage_status, restore_storage_status):
+ Delete functions.
+ (init_storage_once): New function.
+
+ * print-tree.c (print_node): Don't refer to DECL_FRAME_SIZE.
+
+ * i386.h (FINALIZE_PIC): Delete extern declaration of
+ current_function_uses_pic_offset_table.
+
+ * Makefile.in (toplev.o, calls.o, explow.o, optabs.o, jump.o,
+ stupid.o, cse.o, gcse.o, profile.o, loop.o, flow.o, combine.o,
+ regclass.o, local-alloc.o, global.o, reload.o, reload1.o,
+ caller-save.o, alias.o, regmove.o, (haifa-)sched.o, final.o,
+ recog.o, reg-stack.o, insn-emit.o: Adjust dependencies.
+
Sun Nov 1 11:30:21 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
* tree.c (get_identifier): Use ggc_alloc_string, not obstack_copy0, to
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 3ab20cda509..61cff484c42 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1405,7 +1405,7 @@ stor-layout.o : stor-layout.c $(CONFIG_H) system.h $(TREE_H) flags.h \
function.h $(EXPR_H) $(RTL_H) toplev.h except.h
fold-const.o : fold-const.c $(CONFIG_H) system.h $(TREE_H) flags.h toplev.h \
$(RTL_H)
-toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) \
+toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) function.h \
flags.h input.h insn-attr.h xcoffout.h defaults.h output.h \
insn-codes.h insn-config.h $(RECOG_H) Makefile toplev.h dwarfout.h \
dwarf2out.h sdbout.h dbxout.h $(EXPR_H) \
@@ -1435,13 +1435,15 @@ expr.o : expr.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h function.h \
$(REGS_H) insn-flags.h insn-codes.h $(EXPR_H) insn-config.h $(RECOG_H) output.h \
typeclass.h hard-reg-set.h toplev.h hard-reg-set.h except.h
calls.o : calls.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h $(EXPR_H) \
- insn-flags.h $(REGS_H) toplev.h output.h
+ function.h insn-flags.h $(REGS_H) toplev.h output.h
expmed.o : expmed.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
insn-flags.h insn-config.h insn-codes.h $(EXPR_H) $(RECOG_H) real.h
explow.o : explow.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
- hard-reg-set.h insn-config.h $(EXPR_H) $(RECOG_H) insn-flags.h insn-codes.h
+ hard-reg-set.h insn-config.h $(EXPR_H) $(RECOG_H) insn-flags.h \
+ function.h insn-codes.h
optabs.o : optabs.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
- insn-flags.h insn-config.h insn-codes.h $(EXPR_H) $(RECOG_H) reload.h
+ insn-flags.h insn-config.h insn-codes.h $(EXPR_H) $(RECOG_H) reload.h \
+ function.h
dbxout.o : dbxout.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) flags.h $(REGS_H) \
insn-config.h reload.h gstab.h xcoffout.h defaults.h output.h dbxout.h \
toplev.h
@@ -1468,67 +1470,70 @@ integrate.o : integrate.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.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 \
- toplev.h
+ function.h toplev.h
stupid.o : stupid.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h \
- $(BASIC_BLOCK_H) insn-config.h reload.h flags.h toplev.h
+ $(BASIC_BLOCK_H) insn-config.h reload.h flags.h toplev.h function.h
cse.o : cse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
- real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h
+ real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h function.h
gcse.o : gcse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
- real.h insn-config.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) output.h
+ real.h insn-config.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) output.h \
+ function.h
profile.o : profile.c $(CONFIG_H) system.h $(RTL_H) flags.h insn-flags.h \
- gcov-io.h $(TREE_H) output.h $(REGS_H) toplev.h insn-config.h
+ gcov-io.h $(TREE_H) output.h $(REGS_H) toplev.h insn-config.h function.h
loop.o : loop.c $(CONFIG_H) system.h $(RTL_H) flags.h loop.h insn-config.h \
insn-flags.h $(REGS_H) hard-reg-set.h $(RECOG_H) $(EXPR_H) real.h \
- toplev.h
+ function.h toplev.h
unroll.o : unroll.c $(CONFIG_H) system.h $(RTL_H) insn-config.h \
integrate.h $(REGS_H) $(RECOG_H) flags.h $(EXPR_H) loop.h toplev.h
flow.o : flow.c $(CONFIG_H) system.h $(RTL_H) flags.h insn-config.h \
- $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h
+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h function.h
combine.o : combine.c $(CONFIG_H) system.h $(RTL_H) flags.h \
insn-config.h insn-flags.h insn-codes.h insn-attr.h $(REGS_H) $(EXPR_H) \
- $(BASIC_BLOCK_H) $(RECOG_H) real.h hard-reg-set.h toplev.h
+ $(BASIC_BLOCK_H) $(RECOG_H) real.h hard-reg-set.h toplev.h function.h
regclass.o : regclass.c $(CONFIG_H) system.h $(RTL_H) hard-reg-set.h flags.h \
$(BASIC_BLOCK_H) $(REGS_H) insn-config.h $(RECOG_H) reload.h real.h toplev.h \
- output.h
+ function.h output.h
local-alloc.o : local-alloc.c $(CONFIG_H) system.h $(RTL_H) flags.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) output.h \
- insn-attr.h toplev.h
+ insn-attr.h toplev.h function.h
bitmap.o : bitmap.c $(CONFIG_H) system.h $(RTL_H) flags.h $(BASIC_BLOCK_H) \
$(REGS_H)
global.o : global.c $(CONFIG_H) system.h $(RTL_H) flags.h reload.h \
- $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h toplev.h
+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h toplev.h \
+ function.h
varray.o : varray.c $(CONFIG_H) system.h varray.h $(RTL_H) $(TREE_H) bitmap.h
reload.o : reload.c $(CONFIG_H) system.h $(RTL_H) flags.h output.h $(EXPR_H) \
reload.h $(RECOG_H) hard-reg-set.h insn-config.h insn-codes.h $(REGS_H) \
- real.h toplev.h
+ real.h toplev.h function.h
reload1.o : reload1.c $(CONFIG_H) system.h $(RTL_H) real.h flags.h $(EXPR_H) \
reload.h $(REGS_H) hard-reg-set.h insn-config.h insn-flags.h insn-codes.h \
- $(BASIC_BLOCK_H) $(RECOG_H) output.h toplev.h
+ $(BASIC_BLOCK_H) $(RECOG_H) output.h toplev.h function.h
caller-save.o : caller-save.c $(CONFIG_H) system.h $(RTL_H) flags.h \
- $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) \
+ $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) function.h \
$(RECOG_H) reload.h $(EXPR_H) toplev.h
reorg.o : reorg.c $(CONFIG_H) system.h $(RTL_H) conditions.h hard-reg-set.h \
$(BASIC_BLOCK_H) $(REGS_H) insn-config.h insn-attr.h \
insn-flags.h $(RECOG_H) flags.h output.h $(EXPR_H)
alias.o : alias.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h \
- $(REGS_H) toplev.h output.h $(EXPR_H)
+ function.h $(REGS_H) toplev.h output.h $(EXPR_H)
regmove.o : regmove.c $(CONFIG_H) system.h $(RTL_H) insn-config.h \
$(RECOG_H) output.h reload.h $(REGS_H) hard-reg-set.h flags.h \
- $(EXPR_H) insn-flags.h $(BASIC_BLOCK_H) toplev.h
+ $(EXPR_H) insn-flags.h $(BASIC_BLOCK_H) toplev.h function.h
$(SCHED_PREFIX)sched.o : $(SCHED_PREFIX)sched.c $(CONFIG_H) system.h $(RTL_H) \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h insn-attr.h \
- toplev.h
+ function.h toplev.h
final.o : final.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h $(REGS_H) \
$(RECOG_H) conditions.h insn-config.h insn-attr.h except.h real.h output.h \
hard-reg-set.h insn-flags.h insn-codes.h gstab.h xcoffout.h defaults.h \
- toplev.h reload.h dwarfout.h dwarf2out.h sdbout.h dbxout.h
+ toplev.h reload.h dwarfout.h dwarf2out.h sdbout.h dbxout.h function.h
recog.o : recog.c $(CONFIG_H) system.h $(RTL_H) \
$(REGS_H) $(RECOG_H) hard-reg-set.h flags.h insn-config.h insn-attr.h \
insn-flags.h insn-codes.h real.h
reg-stack.o : reg-stack.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) \
- $(REGS_H) hard-reg-set.h flags.h insn-config.h insn-flags.h toplev.h
+ $(REGS_H) hard-reg-set.h flags.h insn-config.h insn-flags.h toplev.h \
+ function.h
dyn-string.o: dyn-string.c dyn-string.h $(CONFIG_H) system.h gansidecl.h
$(out_object_file): $(out_file) $(CONFIG_H) $(TREE_H) \
@@ -1605,7 +1610,7 @@ s-codes : $(md_file) gencodes $(srcdir)/move-if-change
touch s-codes
insn-emit.o : insn-emit.c $(CONFIG_H) $(RTL_H) $(EXPR_H) real.h output.h \
- insn-config.h insn-flags.h insn-codes.h system.h reload.h
+ insn-config.h insn-flags.h insn-codes.h system.h reload.h function.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-emit.c
insn-emit.c: s-emit ; @true
diff --git a/gcc/alias.c b/gcc/alias.c
index 7c6c75f1975..d26bacde8b1 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "rtl.h"
+#include "function.h"
#include "expr.h"
#include "regs.h"
#include "hard-reg-set.h"
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 10c6245502d..92ed23ec09e 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -2019,9 +2019,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
}
}
- /* Also preserve various other info from the definition. */
- else if (! new_is_definition)
- DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
+
if (! new_is_definition)
{
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
@@ -2393,7 +2391,6 @@ pushdecl (x)
DECL_INITIAL (x) = (current_function_decl == oldglobal
? 0 : DECL_INITIAL (oldglobal));
DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal);
- DECL_FRAME_SIZE (x) = DECL_FRAME_SIZE (oldglobal);
DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
DECL_RESULT (x) = DECL_RESULT (oldglobal);
TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
@@ -7388,6 +7385,7 @@ pop_c_function_context (f)
current_binding_level = p->binding_level;
free (p);
+ f->language = 0;
}
void
@@ -7395,6 +7393,10 @@ mark_c_function_context (f)
struct function *f;
{
struct language_function *p = f->language;
+
+ if (p == 0)
+ return;
+
ggc_mark_tree (p->shadowed_labels);
ggc_mark_tree (p->named_labels);
mark_binding_level (&p->binding_level);
diff --git a/gcc/c-lang.c b/gcc/c-lang.c
index 7dfa562c9b4..0bff5c1625e 100644
--- a/gcc/c-lang.c
+++ b/gcc/c-lang.c
@@ -58,6 +58,8 @@ lang_init ()
save_lang_status = &push_c_function_context;
restore_lang_status = &pop_c_function_context;
mark_lang_status = &mark_c_function_context;
+
+ c_parse_init ();
}
void
diff --git a/gcc/c-parse.c b/gcc/c-parse.c
index c20d2a00511..80ffe3d5de8 100644
--- a/gcc/c-parse.c
+++ b/gcc/c-parse.c
@@ -124,6 +124,15 @@ static int undeclared_variable_notice;
#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
extern void yyprint PROTO ((FILE *, int, YYSTYPE));
+
+void
+c_parse_init ()
+{
+ ggc_add_tree_root (&declspec_stack, 1);
+ ggc_add_tree_root (&current_declspecs, 1);
+ ggc_add_tree_root (&prefix_attributes, 1);
+}
+
#include <stdio.h>
#ifndef __cplusplus
@@ -356,47 +365,47 @@ static const short yyrhs[] = { -1,
#if YYDEBUG != 0
static const short yyrline[] = { 0,
- 233, 238, 252, 254, 254, 255, 257, 259, 260, 268,
- 272, 283, 288, 293, 295, 297, 298, 299, 304, 311,
- 313, 318, 323, 329, 331, 336, 341, 347, 349, 354,
- 361, 363, 366, 368, 370, 372, 374, 376, 378, 382,
- 386, 389, 392, 395, 399, 401, 404, 407, 411, 439,
- 445, 448, 451, 454, 456, 460, 464, 468, 470, 473,
- 477, 504, 506, 508, 510, 512, 514, 516, 518, 520,
- 522, 524, 526, 528, 530, 534, 536, 540, 542, 545,
- 549, 551, 558, 561, 564, 570, 669, 670, 672, 678,
- 680, 694, 717, 719, 721, 725, 731, 733, 738, 740,
- 745, 747, 748, 758, 763, 765, 766, 767, 774, 780,
- 785, 788, 796, 801, 803, 804, 805, 812, 823, 827,
- 833, 838, 843, 848, 850, 852, 861, 864, 868, 870,
- 872, 877, 881, 884, 888, 891, 893, 905, 908, 910,
- 912, 916, 920, 922, 925, 938, 941, 945, 947, 955,
- 956, 957, 961, 963, 969, 970, 971, 974, 976, 979,
- 981, 984, 987, 993, 1000, 1002, 1009, 1016, 1019, 1026,
- 1029, 1033, 1036, 1040, 1045, 1048, 1052, 1055, 1057, 1059,
- 1061, 1068, 1070, 1071, 1072, 1077, 1079, 1084, 1092, 1097,
- 1101, 1104, 1106, 1111, 1114, 1116, 1118, 1122, 1125, 1125,
- 1128, 1128, 1131, 1131, 1134, 1134, 1137, 1139, 1150, 1158,
- 1162, 1173, 1181, 1188, 1190, 1195, 1198, 1203, 1205, 1207,
- 1214, 1216, 1224, 1230, 1232, 1234, 1241, 1243, 1249, 1255,
- 1257, 1259, 1261, 1268, 1270, 1273, 1276, 1280, 1283, 1287,
- 1290, 1294, 1299, 1301, 1305, 1307, 1309, 1311, 1315, 1317,
- 1320, 1323, 1326, 1329, 1333, 1335, 1338, 1340, 1344, 1347,
- 1352, 1354, 1356, 1370, 1377, 1382, 1388, 1393, 1395, 1400,
- 1402, 1406, 1410, 1414, 1424, 1426, 1431, 1436, 1439, 1443,
- 1446, 1450, 1453, 1456, 1459, 1463, 1466, 1470, 1474, 1476,
- 1478, 1480, 1482, 1484, 1486, 1488, 1498, 1506, 1508, 1510,
- 1514, 1516, 1519, 1522, 1533, 1535, 1540, 1542, 1545, 1559,
- 1562, 1565, 1567, 1569, 1577, 1585, 1596, 1601, 1604, 1618,
- 1627, 1631, 1635, 1639, 1645, 1649, 1654, 1657, 1662, 1665,
- 1666, 1683, 1688, 1691, 1703, 1705, 1715, 1725, 1726, 1734,
- 1737, 1749, 1753, 1770, 1780, 1789, 1794, 1799, 1804, 1808,
- 1812, 1823, 1830, 1837, 1844, 1855, 1861, 1864, 1869, 1892,
- 1926, 1957, 1988, 2003, 2014, 2018, 2022, 2025, 2030, 2032,
- 2035, 2037, 2041, 2046, 2049, 2055, 2060, 2065, 2067, 2076,
- 2077, 2083, 2085, 2095, 2097, 2101, 2104, 2110, 2120, 2129,
- 2138, 2148, 2162, 2167, 2172, 2174, 2183, 2186, 2191, 2194,
- 2198
+ 242, 247, 261, 263, 263, 264, 266, 268, 269, 277,
+ 281, 292, 297, 302, 304, 306, 307, 308, 313, 320,
+ 322, 327, 332, 338, 340, 345, 350, 356, 358, 363,
+ 370, 372, 375, 377, 379, 381, 383, 385, 387, 391,
+ 395, 398, 401, 404, 408, 410, 413, 416, 420, 448,
+ 454, 457, 460, 463, 465, 469, 473, 477, 479, 482,
+ 486, 513, 515, 517, 519, 521, 523, 525, 527, 529,
+ 531, 533, 535, 537, 539, 543, 545, 549, 551, 554,
+ 558, 560, 567, 570, 573, 579, 678, 679, 681, 687,
+ 689, 703, 726, 728, 730, 734, 740, 742, 747, 749,
+ 754, 756, 757, 767, 772, 774, 775, 776, 783, 789,
+ 794, 797, 805, 810, 812, 813, 814, 821, 832, 836,
+ 842, 847, 852, 857, 859, 861, 870, 873, 877, 879,
+ 881, 886, 890, 893, 897, 900, 902, 914, 917, 919,
+ 921, 925, 929, 931, 934, 947, 950, 954, 956, 964,
+ 965, 966, 970, 972, 978, 979, 980, 983, 985, 988,
+ 990, 993, 996, 1002, 1009, 1011, 1018, 1025, 1028, 1035,
+ 1038, 1042, 1045, 1049, 1054, 1057, 1061, 1064, 1066, 1068,
+ 1070, 1077, 1079, 1080, 1081, 1086, 1088, 1093, 1101, 1106,
+ 1110, 1113, 1115, 1120, 1123, 1125, 1127, 1131, 1134, 1134,
+ 1137, 1137, 1140, 1140, 1143, 1143, 1146, 1148, 1162, 1170,
+ 1174, 1188, 1196, 1203, 1205, 1210, 1213, 1218, 1220, 1222,
+ 1229, 1231, 1239, 1245, 1247, 1249, 1256, 1258, 1264, 1270,
+ 1272, 1274, 1276, 1283, 1285, 1288, 1291, 1295, 1298, 1302,
+ 1305, 1309, 1314, 1316, 1320, 1322, 1324, 1326, 1330, 1332,
+ 1335, 1338, 1341, 1344, 1348, 1350, 1353, 1355, 1359, 1362,
+ 1367, 1369, 1371, 1385, 1392, 1397, 1403, 1408, 1410, 1415,
+ 1417, 1421, 1425, 1429, 1439, 1441, 1446, 1451, 1454, 1458,
+ 1461, 1465, 1468, 1471, 1474, 1478, 1481, 1485, 1489, 1491,
+ 1493, 1495, 1497, 1499, 1501, 1503, 1513, 1521, 1523, 1525,
+ 1529, 1531, 1534, 1537, 1548, 1550, 1555, 1557, 1560, 1574,
+ 1577, 1580, 1582, 1584, 1592, 1600, 1611, 1616, 1619, 1633,
+ 1642, 1646, 1650, 1654, 1660, 1664, 1669, 1672, 1677, 1680,
+ 1681, 1698, 1703, 1706, 1718, 1720, 1730, 1740, 1741, 1749,
+ 1752, 1764, 1768, 1785, 1795, 1804, 1809, 1814, 1819, 1823,
+ 1827, 1838, 1845, 1852, 1859, 1870, 1876, 1879, 1884, 1907,
+ 1941, 1972, 2003, 2018, 2029, 2033, 2037, 2040, 2045, 2047,
+ 2050, 2052, 2056, 2061, 2064, 2070, 2075, 2080, 2082, 2091,
+ 2092, 2098, 2100, 2110, 2112, 2116, 2119, 2125, 2135, 2144,
+ 2153, 2163, 2177, 2182, 2187, 2189, 2198, 2201, 2206, 2209,
+ 2213
};
#endif
@@ -1662,14 +1671,14 @@ yyreduce:
switch (yyn) {
case 1:
-#line 234 "c-parse.y"
+#line 243 "c-parse.y"
{ if (pedantic)
pedwarn ("ANSI C forbids an empty source file");
finish_file ();
;
break;}
case 2:
-#line 239 "c-parse.y"
+#line 248 "c-parse.y"
{
/* In case there were missing closebraces,
get us back to the global binding level. */
@@ -1679,15 +1688,15 @@ case 2:
;
break;}
case 3:
-#line 253 "c-parse.y"
+#line 262 "c-parse.y"
{yyval.ttype = NULL_TREE; ;
break;}
case 5:
-#line 254 "c-parse.y"
+#line 263 "c-parse.y"
{yyval.ttype = NULL_TREE; ;
break;}
case 9:
-#line 261 "c-parse.y"
+#line 270 "c-parse.y"
{ STRIP_NOPS (yyvsp[-2].ttype);
if ((TREE_CODE (yyvsp[-2].ttype) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (yyvsp[-2].ttype, 0)) == STRING_CST)
@@ -1697,11 +1706,11 @@ case 9:
error ("argument of `asm' is not a constant string"); ;
break;}
case 10:
-#line 269 "c-parse.y"
+#line 278 "c-parse.y"
{ pedantic = yyvsp[-1].itype; ;
break;}
case 11:
-#line 274 "c-parse.y"
+#line 283 "c-parse.y"
{ if (pedantic)
error ("ANSI C forbids data definition with no type or storage class");
else if (!flag_traditional)
@@ -1713,45 +1722,45 @@ case 11:
resume_momentary (yyvsp[-2].itype); ;
break;}
case 12:
-#line 284 "c-parse.y"
+#line 293 "c-parse.y"
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary (yyvsp[-2].itype); ;
break;}
case 13:
-#line 289 "c-parse.y"
+#line 298 "c-parse.y"
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary (yyvsp[-2].itype); ;
break;}
case 14:
-#line 294 "c-parse.y"
+#line 303 "c-parse.y"
{ pedwarn ("empty declaration"); ;
break;}
case 15:
-#line 296 "c-parse.y"
+#line 305 "c-parse.y"
{ shadow_tag (yyvsp[-1].ttype); ;
break;}
case 18:
-#line 300 "c-parse.y"
+#line 309 "c-parse.y"
{ if (pedantic)
pedwarn ("ANSI C does not allow extra `;' outside of a function"); ;
break;}
case 19:
-#line 306 "c-parse.y"
+#line 315 "c-parse.y"
{ if (! start_function (current_declspecs, yyvsp[0].ttype,
prefix_attributes, NULL_TREE, 0))
YYERROR1;
reinit_parse_for_function (); ;
break;}
case 20:
-#line 311 "c-parse.y"
+#line 320 "c-parse.y"
{ store_parm_decls (); ;
break;}
case 21:
-#line 313 "c-parse.y"
+#line 322 "c-parse.y"
{ finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
@@ -1759,25 +1768,25 @@ case 21:
resume_momentary (yyvsp[-5].itype); ;
break;}
case 22:
-#line 319 "c-parse.y"
+#line 328 "c-parse.y"
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary (yyvsp[-2].itype); ;
break;}
case 23:
-#line 324 "c-parse.y"
+#line 333 "c-parse.y"
{ if (! start_function (current_declspecs, yyvsp[0].ttype,
prefix_attributes, NULL_TREE, 0))
YYERROR1;
reinit_parse_for_function (); ;
break;}
case 24:
-#line 329 "c-parse.y"
+#line 338 "c-parse.y"
{ store_parm_decls (); ;
break;}
case 25:
-#line 331 "c-parse.y"
+#line 340 "c-parse.y"
{ finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
@@ -1785,25 +1794,25 @@ case 25:
resume_momentary (yyvsp[-5].itype); ;
break;}
case 26:
-#line 337 "c-parse.y"
+#line 346 "c-parse.y"
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary (yyvsp[-2].itype); ;
break;}
case 27:
-#line 342 "c-parse.y"
+#line 351 "c-parse.y"
{ if (! start_function (NULL_TREE, yyvsp[0].ttype,
prefix_attributes, NULL_TREE, 0))
YYERROR1;
reinit_parse_for_function (); ;
break;}
case 28:
-#line 347 "c-parse.y"
+#line 356 "c-parse.y"
{ store_parm_decls (); ;
break;}
case 29:
-#line 349 "c-parse.y"
+#line 358 "c-parse.y"
{ finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
@@ -1811,72 +1820,72 @@ case 29:
resume_momentary (yyvsp[-5].itype); ;
break;}
case 30:
-#line 355 "c-parse.y"
+#line 364 "c-parse.y"
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary (yyvsp[-2].itype); ;
break;}
case 33:
-#line 367 "c-parse.y"
+#line 376 "c-parse.y"
{ yyval.code = ADDR_EXPR; ;
break;}
case 34:
-#line 369 "c-parse.y"
+#line 378 "c-parse.y"
{ yyval.code = NEGATE_EXPR; ;
break;}
case 35:
-#line 371 "c-parse.y"
+#line 380 "c-parse.y"
{ yyval.code = CONVERT_EXPR; ;
break;}
case 36:
-#line 373 "c-parse.y"
+#line 382 "c-parse.y"
{ yyval.code = PREINCREMENT_EXPR; ;
break;}
case 37:
-#line 375 "c-parse.y"
+#line 384 "c-parse.y"
{ yyval.code = PREDECREMENT_EXPR; ;
break;}
case 38:
-#line 377 "c-parse.y"
+#line 386 "c-parse.y"
{ yyval.code = BIT_NOT_EXPR; ;
break;}
case 39:
-#line 379 "c-parse.y"
+#line 388 "c-parse.y"
{ yyval.code = TRUTH_NOT_EXPR; ;
break;}
case 40:
-#line 383 "c-parse.y"
+#line 392 "c-parse.y"
{ yyval.ttype = build_compound_expr (yyvsp[0].ttype); ;
break;}
case 41:
-#line 388 "c-parse.y"
+#line 397 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 43:
-#line 394 "c-parse.y"
+#line 403 "c-parse.y"
{ yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ;
break;}
case 44:
-#line 396 "c-parse.y"
+#line 405 "c-parse.y"
{ chainon (yyvsp[-2].ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ;
break;}
case 46:
-#line 402 "c-parse.y"
+#line 411 "c-parse.y"
{ yyval.ttype = build_indirect_ref (yyvsp[0].ttype, "unary *"); ;
break;}
case 47:
-#line 405 "c-parse.y"
+#line 414 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype;
pedantic = yyvsp[-1].itype; ;
break;}
case 48:
-#line 408 "c-parse.y"
+#line 417 "c-parse.y"
{ yyval.ttype = build_unary_op (yyvsp[-1].code, yyvsp[0].ttype, 0);
overflow_warning (yyval.ttype); ;
break;}
case 49:
-#line 412 "c-parse.y"
+#line 421 "c-parse.y"
{ tree label = lookup_label (yyvsp[0].ttype);
if (pedantic)
pedwarn ("ANSI C forbids `&&'");
@@ -1891,7 +1900,7 @@ case 49:
;
break;}
case 50:
-#line 440 "c-parse.y"
+#line 449 "c-parse.y"
{ skip_evaluation--;
if (TREE_CODE (yyvsp[0].ttype) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (yyvsp[0].ttype, 1)))
@@ -1899,49 +1908,49 @@ case 50:
yyval.ttype = c_sizeof (TREE_TYPE (yyvsp[0].ttype)); ;
break;}
case 51:
-#line 446 "c-parse.y"
+#line 455 "c-parse.y"
{ skip_evaluation--;
yyval.ttype = c_sizeof (groktypename (yyvsp[-1].ttype)); ;
break;}
case 52:
-#line 449 "c-parse.y"
+#line 458 "c-parse.y"
{ skip_evaluation--;
yyval.ttype = c_alignof_expr (yyvsp[0].ttype); ;
break;}
case 53:
-#line 452 "c-parse.y"
+#line 461 "c-parse.y"
{ skip_evaluation--;
yyval.ttype = c_alignof (groktypename (yyvsp[-1].ttype)); ;
break;}
case 54:
-#line 455 "c-parse.y"
+#line 464 "c-parse.y"
{ yyval.ttype = build_unary_op (REALPART_EXPR, yyvsp[0].ttype, 0); ;
break;}
case 55:
-#line 457 "c-parse.y"
+#line 466 "c-parse.y"
{ yyval.ttype = build_unary_op (IMAGPART_EXPR, yyvsp[0].ttype, 0); ;
break;}
case 56:
-#line 461 "c-parse.y"
+#line 470 "c-parse.y"
{ skip_evaluation++; ;
break;}
case 57:
-#line 465 "c-parse.y"
+#line 474 "c-parse.y"
{ skip_evaluation++; ;
break;}
case 59:
-#line 471 "c-parse.y"
+#line 480 "c-parse.y"
{ tree type = groktypename (yyvsp[-2].ttype);
yyval.ttype = build_c_cast (type, yyvsp[0].ttype); ;
break;}
case 60:
-#line 474 "c-parse.y"
+#line 483 "c-parse.y"
{ start_init (NULL_TREE, NULL, 0);
yyvsp[-2].ttype = groktypename (yyvsp[-2].ttype);
really_start_incremental_init (yyvsp[-2].ttype); ;
break;}
case 61:
-#line 478 "c-parse.y"
+#line 487 "c-parse.y"
{ char *name;
tree result = pop_init_level (0);
tree type = yyvsp[-5].ttype;
@@ -1968,90 +1977,90 @@ case 61:
;
break;}
case 63:
-#line 507 "c-parse.y"
+#line 516 "c-parse.y"
{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 64:
-#line 509 "c-parse.y"
+#line 518 "c-parse.y"
{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 65:
-#line 511 "c-parse.y"
+#line 520 "c-parse.y"
{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 66:
-#line 513 "c-parse.y"
+#line 522 "c-parse.y"
{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 67:
-#line 515 "c-parse.y"
+#line 524 "c-parse.y"
{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 68:
-#line 517 "c-parse.y"
+#line 526 "c-parse.y"
{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 69:
-#line 519 "c-parse.y"
+#line 528 "c-parse.y"
{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 70:
-#line 521 "c-parse.y"
+#line 530 "c-parse.y"
{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 71:
-#line 523 "c-parse.y"
+#line 532 "c-parse.y"
{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 72:
-#line 525 "c-parse.y"
+#line 534 "c-parse.y"
{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 73:
-#line 527 "c-parse.y"
+#line 536 "c-parse.y"
{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 74:
-#line 529 "c-parse.y"
+#line 538 "c-parse.y"
{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 75:
-#line 531 "c-parse.y"
+#line 540 "c-parse.y"
{ yyvsp[-1].ttype = truthvalue_conversion (default_conversion (yyvsp[-1].ttype));
skip_evaluation += yyvsp[-1].ttype == boolean_false_node; ;
break;}
case 76:
-#line 534 "c-parse.y"
+#line 543 "c-parse.y"
{ skip_evaluation -= yyvsp[-3].ttype == boolean_false_node;
yyval.ttype = parser_build_binary_op (TRUTH_ANDIF_EXPR, yyvsp[-3].ttype, yyvsp[0].ttype); ;
break;}
case 77:
-#line 537 "c-parse.y"
+#line 546 "c-parse.y"
{ yyvsp[-1].ttype = truthvalue_conversion (default_conversion (yyvsp[-1].ttype));
skip_evaluation += yyvsp[-1].ttype == boolean_true_node; ;
break;}
case 78:
-#line 540 "c-parse.y"
+#line 549 "c-parse.y"
{ skip_evaluation -= yyvsp[-3].ttype == boolean_true_node;
yyval.ttype = parser_build_binary_op (TRUTH_ORIF_EXPR, yyvsp[-3].ttype, yyvsp[0].ttype); ;
break;}
case 79:
-#line 543 "c-parse.y"
+#line 552 "c-parse.y"
{ yyvsp[-1].ttype = truthvalue_conversion (default_conversion (yyvsp[-1].ttype));
skip_evaluation += yyvsp[-1].ttype == boolean_false_node; ;
break;}
case 80:
-#line 546 "c-parse.y"
+#line 555 "c-parse.y"
{ skip_evaluation += ((yyvsp[-4].ttype == boolean_true_node)
- (yyvsp[-4].ttype == boolean_false_node)); ;
break;}
case 81:
-#line 549 "c-parse.y"
+#line 558 "c-parse.y"
{ skip_evaluation -= yyvsp[-6].ttype == boolean_true_node;
yyval.ttype = build_conditional_expr (yyvsp[-6].ttype, yyvsp[-3].ttype, yyvsp[0].ttype); ;
break;}
case 82:
-#line 552 "c-parse.y"
+#line 561 "c-parse.y"
{ if (pedantic)
pedwarn ("ANSI C forbids omitting the middle term of a ?: expression");
/* Make sure first operand is calculated only once. */
@@ -2060,23 +2069,23 @@ case 82:
skip_evaluation += yyvsp[-1].ttype == boolean_true_node; ;
break;}
case 83:
-#line 559 "c-parse.y"
+#line 568 "c-parse.y"
{ skip_evaluation -= yyvsp[-4].ttype == boolean_true_node;
yyval.ttype = build_conditional_expr (yyvsp[-4].ttype, yyvsp[-3].ttype, yyvsp[0].ttype); ;
break;}
case 84:
-#line 562 "c-parse.y"
+#line 571 "c-parse.y"
{ yyval.ttype = build_modify_expr (yyvsp[-2].ttype, NOP_EXPR, yyvsp[0].ttype);
C_SET_EXP_ORIGINAL_CODE (yyval.ttype, MODIFY_EXPR); ;
break;}
case 85:
-#line 565 "c-parse.y"
+#line 574 "c-parse.y"
{ yyval.ttype = build_modify_expr (yyvsp[-2].ttype, yyvsp[-1].code, yyvsp[0].ttype);
/* This inhibits warnings in truthvalue_conversion. */
C_SET_EXP_ORIGINAL_CODE (yyval.ttype, ERROR_MARK); ;
break;}
case 86:
-#line 572 "c-parse.y"
+#line 581 "c-parse.y"
{
yyval.ttype = lastiddecl;
if (!yyval.ttype || yyval.ttype == error_mark_node)
@@ -2176,11 +2185,11 @@ case 86:
;
break;}
case 88:
-#line 671 "c-parse.y"
+#line 680 "c-parse.y"
{ yyval.ttype = combine_strings (yyvsp[0].ttype); ;
break;}
case 89:
-#line 673 "c-parse.y"
+#line 682 "c-parse.y"
{ char class = TREE_CODE_CLASS (TREE_CODE (yyvsp[-1].ttype));
if (class == 'e' || class == '1'
|| class == '2' || class == '<')
@@ -2188,11 +2197,11 @@ case 89:
yyval.ttype = yyvsp[-1].ttype; ;
break;}
case 90:
-#line 679 "c-parse.y"
+#line 688 "c-parse.y"
{ yyval.ttype = error_mark_node; ;
break;}
case 91:
-#line 681 "c-parse.y"
+#line 690 "c-parse.y"
{ if (current_function_decl == 0)
{
error ("braced-group within expression allowed only inside a function");
@@ -2208,7 +2217,7 @@ case 91:
yyval.ttype = expand_start_stmt_expr (); ;
break;}
case 92:
-#line 695 "c-parse.y"
+#line 704 "c-parse.y"
{ tree rtl_exp;
if (pedantic)
pedwarn ("ANSI C forbids braced-groups within expressions");
@@ -2233,21 +2242,21 @@ case 92:
;
break;}
case 93:
-#line 718 "c-parse.y"
+#line 727 "c-parse.y"
{ yyval.ttype = build_function_call (yyvsp[-3].ttype, yyvsp[-1].ttype); ;
break;}
case 94:
-#line 720 "c-parse.y"
+#line 729 "c-parse.y"
{ yyval.ttype = build_array_ref (yyvsp[-3].ttype, yyvsp[-1].ttype); ;
break;}
case 95:
-#line 722 "c-parse.y"
+#line 731 "c-parse.y"
{
yyval.ttype = build_component_ref (yyvsp[-2].ttype, yyvsp[0].ttype);
;
break;}
case 96:
-#line 726 "c-parse.y"
+#line 735 "c-parse.y"
{
tree expr = build_indirect_ref (yyvsp[-2].ttype, "->");
@@ -2255,56 +2264,56 @@ case 96:
;
break;}
case 97:
-#line 732 "c-parse.y"
+#line 741 "c-parse.y"
{ yyval.ttype = build_unary_op (POSTINCREMENT_EXPR, yyvsp[-1].ttype, 0); ;
break;}
case 98:
-#line 734 "c-parse.y"
+#line 743 "c-parse.y"
{ yyval.ttype = build_unary_op (POSTDECREMENT_EXPR, yyvsp[-1].ttype, 0); ;
break;}
case 100:
-#line 741 "c-parse.y"
+#line 750 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 103:
-#line 750 "c-parse.y"
+#line 759 "c-parse.y"
{ c_mark_varargs ();
if (pedantic)
pedwarn ("ANSI C does not permit use of `varargs.h'"); ;
break;}
case 104:
-#line 760 "c-parse.y"
+#line 769 "c-parse.y"
{ ;
break;}
case 109:
-#line 776 "c-parse.y"
+#line 785 "c-parse.y"
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary (yyvsp[-2].itype); ;
break;}
case 110:
-#line 781 "c-parse.y"
+#line 790 "c-parse.y"
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary (yyvsp[-2].itype); ;
break;}
case 111:
-#line 786 "c-parse.y"
+#line 795 "c-parse.y"
{ shadow_tag_warned (yyvsp[-1].ttype, 1);
pedwarn ("empty declaration"); ;
break;}
case 112:
-#line 789 "c-parse.y"
+#line 798 "c-parse.y"
{ pedwarn ("empty declaration"); ;
break;}
case 113:
-#line 798 "c-parse.y"
+#line 807 "c-parse.y"
{ ;
break;}
case 118:
-#line 813 "c-parse.y"
+#line 822 "c-parse.y"
{ yyval.itype = suspend_momentary ();
pending_xref_error ();
declspec_stack = tree_cons (prefix_attributes,
@@ -2314,131 +2323,131 @@ case 118:
&current_declspecs, &prefix_attributes); ;
break;}
case 119:
-#line 824 "c-parse.y"
+#line 833 "c-parse.y"
{ prefix_attributes = chainon (prefix_attributes, yyvsp[0].ttype); ;
break;}
case 120:
-#line 829 "c-parse.y"
+#line 838 "c-parse.y"
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary (yyvsp[-2].itype); ;
break;}
case 121:
-#line 834 "c-parse.y"
+#line 843 "c-parse.y"
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary (yyvsp[-2].itype); ;
break;}
case 122:
-#line 839 "c-parse.y"
+#line 848 "c-parse.y"
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary (yyvsp[-1].itype); ;
break;}
case 123:
-#line 844 "c-parse.y"
+#line 853 "c-parse.y"
{ current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack);
resume_momentary (yyvsp[-1].itype); ;
break;}
case 124:
-#line 849 "c-parse.y"
+#line 858 "c-parse.y"
{ shadow_tag (yyvsp[-1].ttype); ;
break;}
case 125:
-#line 851 "c-parse.y"
+#line 860 "c-parse.y"
{ pedwarn ("empty declaration"); ;
break;}
case 126:
-#line 853 "c-parse.y"
+#line 862 "c-parse.y"
{ pedantic = yyvsp[-1].itype; ;
break;}
case 127:
-#line 863 "c-parse.y"
+#line 872 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 128:
-#line 865 "c-parse.y"
+#line 874 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[0].ttype, tree_cons (NULL_TREE, yyvsp[-1].ttype, yyvsp[-2].ttype)); ;
break;}
case 129:
-#line 869 "c-parse.y"
+#line 878 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 130:
-#line 871 "c-parse.y"
+#line 880 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ;
break;}
case 131:
-#line 873 "c-parse.y"
+#line 882 "c-parse.y"
{ if (extra_warnings)
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER (yyvsp[0].ttype));
yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ;
break;}
case 132:
-#line 878 "c-parse.y"
+#line 887 "c-parse.y"
{ yyval.ttype = tree_cons (yyvsp[0].ttype, NULL_TREE, yyvsp[-1].ttype); ;
break;}
case 133:
-#line 883 "c-parse.y"
+#line 892 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 134:
-#line 885 "c-parse.y"
+#line 894 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[0].ttype, tree_cons (NULL_TREE, yyvsp[-1].ttype, yyvsp[-2].ttype)); ;
break;}
case 135:
-#line 890 "c-parse.y"
+#line 899 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 136:
-#line 892 "c-parse.y"
+#line 901 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ;
break;}
case 137:
-#line 894 "c-parse.y"
+#line 903 "c-parse.y"
{ if (extra_warnings)
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER (yyvsp[0].ttype));
yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ;
break;}
case 138:
-#line 907 "c-parse.y"
+#line 916 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 139:
-#line 909 "c-parse.y"
+#line 918 "c-parse.y"
{ yyval.ttype = tree_cons (yyvsp[0].ttype, NULL_TREE, NULL_TREE); ;
break;}
case 140:
-#line 911 "c-parse.y"
+#line 920 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[0].ttype, yyvsp[-1].ttype); ;
break;}
case 141:
-#line 913 "c-parse.y"
+#line 922 "c-parse.y"
{ yyval.ttype = tree_cons (yyvsp[0].ttype, NULL_TREE, yyvsp[-1].ttype); ;
break;}
case 142:
-#line 918 "c-parse.y"
+#line 927 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, NULL_TREE);
TREE_STATIC (yyval.ttype) = 1; ;
break;}
case 143:
-#line 921 "c-parse.y"
+#line 930 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, NULL_TREE); ;
break;}
case 144:
-#line 923 "c-parse.y"
+#line 932 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype);
TREE_STATIC (yyval.ttype) = 1; ;
break;}
case 145:
-#line 926 "c-parse.y"
+#line 935 "c-parse.y"
{ if (extra_warnings && TREE_STATIC (yyvsp[-1].ttype))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER (yyvsp[0].ttype));
@@ -2446,138 +2455,138 @@ case 145:
TREE_STATIC (yyval.ttype) = TREE_STATIC (yyvsp[-1].ttype); ;
break;}
case 146:
-#line 940 "c-parse.y"
+#line 949 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 147:
-#line 942 "c-parse.y"
+#line 951 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[0].ttype, tree_cons (NULL_TREE, yyvsp[-1].ttype, yyvsp[-2].ttype)); ;
break;}
case 148:
-#line 946 "c-parse.y"
+#line 955 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 149:
-#line 948 "c-parse.y"
+#line 957 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ;
break;}
case 152:
-#line 958 "c-parse.y"
+#line 967 "c-parse.y"
{ /* For a typedef name, record the meaning, not the name.
In case of `foo foo, bar;'. */
yyval.ttype = lookup_name (yyvsp[0].ttype); ;
break;}
case 153:
-#line 962 "c-parse.y"
+#line 971 "c-parse.y"
{ yyval.ttype = TREE_TYPE (yyvsp[-1].ttype); ;
break;}
case 154:
-#line 964 "c-parse.y"
+#line 973 "c-parse.y"
{ yyval.ttype = groktypename (yyvsp[-1].ttype); ;
break;}
case 162:
-#line 986 "c-parse.y"
+#line 995 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 163:
-#line 988 "c-parse.y"
+#line 997 "c-parse.y"
{ if (TREE_CHAIN (yyvsp[-1].ttype)) yyvsp[-1].ttype = combine_strings (yyvsp[-1].ttype);
yyval.ttype = yyvsp[-1].ttype;
;
break;}
case 164:
-#line 995 "c-parse.y"
+#line 1004 "c-parse.y"
{ yyval.ttype = start_decl (yyvsp[-3].ttype, current_declspecs, 1,
yyvsp[-1].ttype, prefix_attributes);
start_init (yyval.ttype, yyvsp[-2].ttype, global_bindings_p ()); ;
break;}
case 165:
-#line 1000 "c-parse.y"
+#line 1009 "c-parse.y"
{ finish_init ();
finish_decl (yyvsp[-1].ttype, yyvsp[0].ttype, yyvsp[-4].ttype); ;
break;}
case 166:
-#line 1003 "c-parse.y"
+#line 1012 "c-parse.y"
{ tree d = start_decl (yyvsp[-2].ttype, current_declspecs, 0,
yyvsp[0].ttype, prefix_attributes);
finish_decl (d, NULL_TREE, yyvsp[-1].ttype);
;
break;}
case 167:
-#line 1011 "c-parse.y"
+#line 1020 "c-parse.y"
{ yyval.ttype = start_decl (yyvsp[-3].ttype, current_declspecs, 1,
yyvsp[-1].ttype, prefix_attributes);
start_init (yyval.ttype, yyvsp[-2].ttype, global_bindings_p ()); ;
break;}
case 168:
-#line 1016 "c-parse.y"
+#line 1025 "c-parse.y"
{ finish_init ();
decl_attributes (yyvsp[-1].ttype, yyvsp[-3].ttype, prefix_attributes);
finish_decl (yyvsp[-1].ttype, yyvsp[0].ttype, yyvsp[-4].ttype); ;
break;}
case 169:
-#line 1020 "c-parse.y"
+#line 1029 "c-parse.y"
{ tree d = start_decl (yyvsp[-2].ttype, current_declspecs, 0,
yyvsp[0].ttype, prefix_attributes);
finish_decl (d, NULL_TREE, yyvsp[-1].ttype); ;
break;}
case 170:
-#line 1028 "c-parse.y"
+#line 1037 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 171:
-#line 1030 "c-parse.y"
+#line 1039 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 172:
-#line 1035 "c-parse.y"
+#line 1044 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 173:
-#line 1037 "c-parse.y"
+#line 1046 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 174:
-#line 1042 "c-parse.y"
+#line 1051 "c-parse.y"
{ yyval.ttype = yyvsp[-2].ttype; ;
break;}
case 175:
-#line 1047 "c-parse.y"
+#line 1056 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 176:
-#line 1049 "c-parse.y"
+#line 1058 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 177:
-#line 1054 "c-parse.y"
+#line 1063 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 178:
-#line 1056 "c-parse.y"
+#line 1065 "c-parse.y"
{ yyval.ttype = build_tree_list (yyvsp[0].ttype, NULL_TREE); ;
break;}
case 179:
-#line 1058 "c-parse.y"
+#line 1067 "c-parse.y"
{ yyval.ttype = build_tree_list (yyvsp[-3].ttype, build_tree_list (NULL_TREE, yyvsp[-1].ttype)); ;
break;}
case 180:
-#line 1060 "c-parse.y"
+#line 1069 "c-parse.y"
{ yyval.ttype = build_tree_list (yyvsp[-5].ttype, tree_cons (NULL_TREE, yyvsp[-3].ttype, yyvsp[-1].ttype)); ;
break;}
case 181:
-#line 1062 "c-parse.y"
+#line 1071 "c-parse.y"
{ yyval.ttype = build_tree_list (yyvsp[-3].ttype, yyvsp[-1].ttype); ;
break;}
case 187:
-#line 1080 "c-parse.y"
+#line 1089 "c-parse.y"
{ really_start_incremental_init (NULL_TREE);
/* Note that the call to clear_momentary
is in process_init_element. */
push_momentary (); ;
break;}
case 188:
-#line 1085 "c-parse.y"
+#line 1094 "c-parse.y"
{ yyval.ttype = pop_init_level (0);
if (yyval.ttype == error_mark_node
&& ! (yychar == STRING || yychar == CONSTANT))
@@ -2586,268 +2595,274 @@ case 188:
pop_momentary_nofree (); ;
break;}
case 189:
-#line 1093 "c-parse.y"
+#line 1102 "c-parse.y"
{ yyval.ttype = error_mark_node; ;
break;}
case 190:
-#line 1099 "c-parse.y"
+#line 1108 "c-parse.y"
{ if (pedantic)
pedwarn ("ANSI C forbids empty initializer braces"); ;
break;}
case 194:
-#line 1113 "c-parse.y"
+#line 1122 "c-parse.y"
{ process_init_element (yyvsp[0].ttype); ;
break;}
case 195:
-#line 1115 "c-parse.y"
+#line 1124 "c-parse.y"
{ push_init_level (0); ;
break;}
case 196:
-#line 1117 "c-parse.y"
+#line 1126 "c-parse.y"
{ process_init_element (pop_init_level (0)); ;
break;}
case 198:
-#line 1123 "c-parse.y"
+#line 1132 "c-parse.y"
{ set_init_index (yyvsp[-4].ttype, yyvsp[-2].ttype); ;
break;}
case 200:
-#line 1126 "c-parse.y"
+#line 1135 "c-parse.y"
{ set_init_index (yyvsp[-2].ttype, NULL_TREE); ;
break;}
case 202:
-#line 1129 "c-parse.y"
+#line 1138 "c-parse.y"
{ set_init_index (yyvsp[-1].ttype, NULL_TREE); ;
break;}
case 204:
-#line 1132 "c-parse.y"
+#line 1141 "c-parse.y"
{ set_init_label (yyvsp[-1].ttype); ;
break;}
case 206:
-#line 1135 "c-parse.y"
+#line 1144 "c-parse.y"
{ set_init_label (yyvsp[-1].ttype); ;
break;}
case 208:
-#line 1141 "c-parse.y"
-{ push_c_function_context ();
+#line 1150 "c-parse.y"
+{ if (pedantic)
+ pedwarn ("ANSI C forbids nested functions");
+
+ push_function_context ();
if (! start_function (current_declspecs, yyvsp[0].ttype,
prefix_attributes, NULL_TREE, 1))
{
- pop_c_function_context ();
+ pop_function_context ();
YYERROR1;
}
reinit_parse_for_function (); ;
break;}
case 209:
-#line 1150 "c-parse.y"
+#line 1162 "c-parse.y"
{ store_parm_decls (); ;
break;}
case 210:
-#line 1158 "c-parse.y"
+#line 1170 "c-parse.y"
{ finish_function (1);
- pop_c_function_context (); ;
+ pop_function_context (); ;
break;}
case 211:
-#line 1164 "c-parse.y"
-{ push_c_function_context ();
+#line 1176 "c-parse.y"
+{ if (pedantic)
+ pedwarn ("ANSI C forbids nested functions");
+
+ push_function_context ();
if (! start_function (current_declspecs, yyvsp[0].ttype,
prefix_attributes, NULL_TREE, 1))
{
- pop_c_function_context ();
+ pop_function_context ();
YYERROR1;
}
reinit_parse_for_function (); ;
break;}
case 212:
-#line 1173 "c-parse.y"
+#line 1188 "c-parse.y"
{ store_parm_decls (); ;
break;}
case 213:
-#line 1181 "c-parse.y"
+#line 1196 "c-parse.y"
{ finish_function (1);
- pop_c_function_context (); ;
+ pop_function_context (); ;
break;}
case 216:
-#line 1197 "c-parse.y"
+#line 1212 "c-parse.y"
{ yyval.ttype = yyvsp[-1].ttype; ;
break;}
case 217:
-#line 1199 "c-parse.y"
+#line 1214 "c-parse.y"
{ yyval.ttype = build_nt (CALL_EXPR, yyvsp[-2].ttype, yyvsp[0].ttype, NULL_TREE); ;
break;}
case 218:
-#line 1204 "c-parse.y"
+#line 1219 "c-parse.y"
{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-3].ttype, yyvsp[-1].ttype); ;
break;}
case 219:
-#line 1206 "c-parse.y"
+#line 1221 "c-parse.y"
{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-2].ttype, NULL_TREE); ;
break;}
case 220:
-#line 1208 "c-parse.y"
+#line 1223 "c-parse.y"
{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 221:
-#line 1215 "c-parse.y"
+#line 1230 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 223:
-#line 1226 "c-parse.y"
+#line 1241 "c-parse.y"
{ yyval.ttype = build_nt (CALL_EXPR, yyvsp[-2].ttype, yyvsp[0].ttype, NULL_TREE); ;
break;}
case 224:
-#line 1231 "c-parse.y"
+#line 1246 "c-parse.y"
{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-3].ttype, yyvsp[-1].ttype); ;
break;}
case 225:
-#line 1233 "c-parse.y"
+#line 1248 "c-parse.y"
{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-2].ttype, NULL_TREE); ;
break;}
case 226:
-#line 1235 "c-parse.y"
+#line 1250 "c-parse.y"
{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 227:
-#line 1242 "c-parse.y"
+#line 1257 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 229:
-#line 1251 "c-parse.y"
+#line 1266 "c-parse.y"
{ yyval.ttype = build_nt (CALL_EXPR, yyvsp[-2].ttype, yyvsp[0].ttype, NULL_TREE); ;
break;}
case 230:
-#line 1256 "c-parse.y"
+#line 1271 "c-parse.y"
{ yyval.ttype = yyvsp[-1].ttype; ;
break;}
case 231:
-#line 1258 "c-parse.y"
+#line 1273 "c-parse.y"
{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 232:
-#line 1260 "c-parse.y"
+#line 1275 "c-parse.y"
{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-3].ttype, yyvsp[-1].ttype); ;
break;}
case 233:
-#line 1262 "c-parse.y"
+#line 1277 "c-parse.y"
{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-2].ttype, NULL_TREE); ;
break;}
case 234:
-#line 1269 "c-parse.y"
+#line 1284 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 236:
-#line 1275 "c-parse.y"
+#line 1290 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 237:
-#line 1277 "c-parse.y"
+#line 1292 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 238:
-#line 1282 "c-parse.y"
+#line 1297 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 239:
-#line 1284 "c-parse.y"
+#line 1299 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 240:
-#line 1289 "c-parse.y"
+#line 1304 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 241:
-#line 1291 "c-parse.y"
+#line 1306 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 242:
-#line 1296 "c-parse.y"
+#line 1311 "c-parse.y"
{ yyval.ttype = start_struct (RECORD_TYPE, yyvsp[-1].ttype);
/* Start scope of tag before parsing components. */
;
break;}
case 243:
-#line 1300 "c-parse.y"
+#line 1315 "c-parse.y"
{ yyval.ttype = finish_struct (yyvsp[-3].ttype, yyvsp[-2].ttype, chainon (yyvsp[-6].ttype, yyvsp[0].ttype)); ;
break;}
case 244:
-#line 1302 "c-parse.y"
+#line 1317 "c-parse.y"
{ yyval.ttype = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
yyvsp[-2].ttype, chainon (yyvsp[-4].ttype, yyvsp[0].ttype));
;
break;}
case 245:
-#line 1306 "c-parse.y"
+#line 1321 "c-parse.y"
{ yyval.ttype = xref_tag (RECORD_TYPE, yyvsp[0].ttype); ;
break;}
case 246:
-#line 1308 "c-parse.y"
+#line 1323 "c-parse.y"
{ yyval.ttype = start_struct (UNION_TYPE, yyvsp[-1].ttype); ;
break;}
case 247:
-#line 1310 "c-parse.y"
+#line 1325 "c-parse.y"
{ yyval.ttype = finish_struct (yyvsp[-3].ttype, yyvsp[-2].ttype, chainon (yyvsp[-6].ttype, yyvsp[0].ttype)); ;
break;}
case 248:
-#line 1312 "c-parse.y"
+#line 1327 "c-parse.y"
{ yyval.ttype = finish_struct (start_struct (UNION_TYPE, NULL_TREE),
yyvsp[-2].ttype, chainon (yyvsp[-4].ttype, yyvsp[0].ttype));
;
break;}
case 249:
-#line 1316 "c-parse.y"
+#line 1331 "c-parse.y"
{ yyval.ttype = xref_tag (UNION_TYPE, yyvsp[0].ttype); ;
break;}
case 250:
-#line 1318 "c-parse.y"
+#line 1333 "c-parse.y"
{ yyvsp[0].itype = suspend_momentary ();
yyval.ttype = start_enum (yyvsp[-1].ttype); ;
break;}
case 251:
-#line 1321 "c-parse.y"
+#line 1336 "c-parse.y"
{ yyval.ttype= finish_enum (yyvsp[-4].ttype, nreverse (yyvsp[-3].ttype), chainon (yyvsp[-7].ttype, yyvsp[0].ttype));
resume_momentary (yyvsp[-5].itype); ;
break;}
case 252:
-#line 1324 "c-parse.y"
+#line 1339 "c-parse.y"
{ yyvsp[0].itype = suspend_momentary ();
yyval.ttype = start_enum (NULL_TREE); ;
break;}
case 253:
-#line 1327 "c-parse.y"
+#line 1342 "c-parse.y"
{ yyval.ttype= finish_enum (yyvsp[-4].ttype, nreverse (yyvsp[-3].ttype), chainon (yyvsp[-6].ttype, yyvsp[0].ttype));
resume_momentary (yyvsp[-5].itype); ;
break;}
case 254:
-#line 1330 "c-parse.y"
+#line 1345 "c-parse.y"
{ yyval.ttype = xref_tag (ENUMERAL_TYPE, yyvsp[0].ttype); ;
break;}
case 258:
-#line 1341 "c-parse.y"
+#line 1356 "c-parse.y"
{ if (pedantic) pedwarn ("comma at end of enumerator list"); ;
break;}
case 259:
-#line 1346 "c-parse.y"
+#line 1361 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 260:
-#line 1348 "c-parse.y"
+#line 1363 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[-1].ttype, yyvsp[0].ttype);
pedwarn ("no semicolon at end of struct or union"); ;
break;}
case 261:
-#line 1353 "c-parse.y"
+#line 1368 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 262:
-#line 1355 "c-parse.y"
+#line 1370 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[-2].ttype, yyvsp[-1].ttype); ;
break;}
case 263:
-#line 1357 "c-parse.y"
+#line 1372 "c-parse.y"
{ if (pedantic)
pedwarn ("extra semicolon in struct or union specified"); ;
break;}
case 264:
-#line 1372 "c-parse.y"
+#line 1387 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype;
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
@@ -2855,14 +2870,14 @@ case 264:
resume_momentary (yyvsp[-1].itype); ;
break;}
case 265:
-#line 1378 "c-parse.y"
+#line 1393 "c-parse.y"
{ if (pedantic)
pedwarn ("ANSI C forbids member declarations with no members");
shadow_tag(yyvsp[0].ttype);
yyval.ttype = NULL_TREE; ;
break;}
case 266:
-#line 1383 "c-parse.y"
+#line 1398 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype;
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
@@ -2870,140 +2885,140 @@ case 266:
resume_momentary (yyvsp[-1].itype); ;
break;}
case 267:
-#line 1389 "c-parse.y"
+#line 1404 "c-parse.y"
{ if (pedantic)
pedwarn ("ANSI C forbids member declarations with no members");
shadow_tag(yyvsp[0].ttype);
yyval.ttype = NULL_TREE; ;
break;}
case 268:
-#line 1394 "c-parse.y"
+#line 1409 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 269:
-#line 1396 "c-parse.y"
+#line 1411 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype;
pedantic = yyvsp[-1].itype; ;
break;}
case 271:
-#line 1403 "c-parse.y"
+#line 1418 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 272:
-#line 1408 "c-parse.y"
+#line 1423 "c-parse.y"
{ yyval.ttype = grokfield (yyvsp[-3].filename, yyvsp[-2].lineno, yyvsp[-1].ttype, current_declspecs, NULL_TREE);
decl_attributes (yyval.ttype, yyvsp[0].ttype, prefix_attributes); ;
break;}
case 273:
-#line 1412 "c-parse.y"
+#line 1427 "c-parse.y"
{ yyval.ttype = grokfield (yyvsp[-5].filename, yyvsp[-4].lineno, yyvsp[-3].ttype, current_declspecs, yyvsp[-1].ttype);
decl_attributes (yyval.ttype, yyvsp[0].ttype, prefix_attributes); ;
break;}
case 274:
-#line 1415 "c-parse.y"
+#line 1430 "c-parse.y"
{ yyval.ttype = grokfield (yyvsp[-4].filename, yyvsp[-3].lineno, NULL_TREE, current_declspecs, yyvsp[-1].ttype);
decl_attributes (yyval.ttype, yyvsp[0].ttype, prefix_attributes); ;
break;}
case 276:
-#line 1427 "c-parse.y"
+#line 1442 "c-parse.y"
{ if (yyvsp[-2].ttype == error_mark_node)
yyval.ttype = yyvsp[-2].ttype;
else
yyval.ttype = chainon (yyvsp[0].ttype, yyvsp[-2].ttype); ;
break;}
case 277:
-#line 1432 "c-parse.y"
+#line 1447 "c-parse.y"
{ yyval.ttype = error_mark_node; ;
break;}
case 278:
-#line 1438 "c-parse.y"
+#line 1453 "c-parse.y"
{ yyval.ttype = build_enumerator (yyvsp[0].ttype, NULL_TREE); ;
break;}
case 279:
-#line 1440 "c-parse.y"
+#line 1455 "c-parse.y"
{ yyval.ttype = build_enumerator (yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 280:
-#line 1445 "c-parse.y"
+#line 1460 "c-parse.y"
{ yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 281:
-#line 1447 "c-parse.y"
+#line 1462 "c-parse.y"
{ yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 282:
-#line 1452 "c-parse.y"
+#line 1467 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 284:
-#line 1458 "c-parse.y"
+#line 1473 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, NULL_TREE); ;
break;}
case 285:
-#line 1460 "c-parse.y"
+#line 1475 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ;
break;}
case 286:
-#line 1465 "c-parse.y"
+#line 1480 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 287:
-#line 1467 "c-parse.y"
+#line 1482 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ;
break;}
case 288:
-#line 1472 "c-parse.y"
+#line 1487 "c-parse.y"
{ yyval.ttype = yyvsp[-1].ttype; ;
break;}
case 289:
-#line 1475 "c-parse.y"
+#line 1490 "c-parse.y"
{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
break;}
case 290:
-#line 1477 "c-parse.y"
+#line 1492 "c-parse.y"
{ yyval.ttype = make_pointer_declarator (yyvsp[0].ttype, NULL_TREE); ;
break;}
case 291:
-#line 1479 "c-parse.y"
+#line 1494 "c-parse.y"
{ yyval.ttype = build_nt (CALL_EXPR, yyvsp[-2].ttype, yyvsp[0].ttype, NULL_TREE); ;
break;}
case 292:
-#line 1481 "c-parse.y"
+#line 1496 "c-parse.y"
{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-3].ttype, yyvsp[-1].ttype); ;
break;}
case 293:
-#line 1483 "c-parse.y"
+#line 1498 "c-parse.y"
{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-2].ttype, NULL_TREE); ;
break;}
case 294:
-#line 1485 "c-parse.y"
+#line 1500 "c-parse.y"
{ yyval.ttype = build_nt (CALL_EXPR, NULL_TREE, yyvsp[0].ttype, NULL_TREE); ;
break;}
case 295:
-#line 1487 "c-parse.y"
+#line 1502 "c-parse.y"
{ yyval.ttype = build_nt (ARRAY_REF, NULL_TREE, yyvsp[-1].ttype); ;
break;}
case 296:
-#line 1489 "c-parse.y"
+#line 1504 "c-parse.y"
{ yyval.ttype = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); ;
break;}
case 297:
-#line 1500 "c-parse.y"
+#line 1515 "c-parse.y"
{
if (pedantic && yyvsp[0].ends_in_label)
pedwarn ("ANSI C forbids label at end of compound statement");
;
break;}
case 299:
-#line 1509 "c-parse.y"
+#line 1524 "c-parse.y"
{ yyval.ends_in_label = yyvsp[0].ends_in_label; ;
break;}
case 300:
-#line 1511 "c-parse.y"
+#line 1526 "c-parse.y"
{ yyval.ends_in_label = 0; ;
break;}
case 304:
-#line 1523 "c-parse.y"
+#line 1538 "c-parse.y"
{ emit_line_note (input_filename, lineno);
pushlevel (0);
clear_last_expr ();
@@ -3012,12 +3027,12 @@ case 304:
;
break;}
case 306:
-#line 1536 "c-parse.y"
+#line 1551 "c-parse.y"
{ if (pedantic)
pedwarn ("ANSI C forbids label declarations"); ;
break;}
case 309:
-#line 1547 "c-parse.y"
+#line 1562 "c-parse.y"
{ tree link;
for (link = yyvsp[-1].ttype; link; link = TREE_CHAIN (link))
{
@@ -3028,19 +3043,19 @@ case 309:
;
break;}
case 310:
-#line 1561 "c-parse.y"
+#line 1576 "c-parse.y"
{;
break;}
case 312:
-#line 1565 "c-parse.y"
+#line 1580 "c-parse.y"
{ compstmt_count++; ;
break;}
case 313:
-#line 1568 "c-parse.y"
+#line 1583 "c-parse.y"
{ yyval.ttype = convert (void_type_node, integer_zero_node); ;
break;}
case 314:
-#line 1570 "c-parse.y"
+#line 1585 "c-parse.y"
{ emit_line_note (input_filename, lineno);
expand_end_bindings (getdecls (), 1, 0);
yyval.ttype = poplevel (1, 1, 0);
@@ -3050,7 +3065,7 @@ case 314:
pop_momentary (); ;
break;}
case 315:
-#line 1578 "c-parse.y"
+#line 1593 "c-parse.y"
{ emit_line_note (input_filename, lineno);
expand_end_bindings (getdecls (), kept_level_p (), 0);
yyval.ttype = poplevel (kept_level_p (), 0, 0);
@@ -3060,7 +3075,7 @@ case 315:
pop_momentary (); ;
break;}
case 316:
-#line 1586 "c-parse.y"
+#line 1601 "c-parse.y"
{ emit_line_note (input_filename, lineno);
expand_end_bindings (getdecls (), kept_level_p (), 0);
yyval.ttype = poplevel (kept_level_p (), 0, 0);
@@ -3070,7 +3085,7 @@ case 316:
pop_momentary (); ;
break;}
case 319:
-#line 1606 "c-parse.y"
+#line 1621 "c-parse.y"
{ emit_line_note (yyvsp[-5].filename, yyvsp[-4].lineno);
c_expand_start_cond (truthvalue_conversion (yyvsp[-1].ttype), 0,
compstmt_count);
@@ -3080,7 +3095,7 @@ case 319:
position_after_white_space (); ;
break;}
case 320:
-#line 1620 "c-parse.y"
+#line 1635 "c-parse.y"
{ stmt_count++;
compstmt_count++;
emit_line_note (yyvsp[-2].filename, yyvsp[-1].lineno);
@@ -3090,43 +3105,43 @@ case 320:
position_after_white_space (); ;
break;}
case 321:
-#line 1628 "c-parse.y"
+#line 1643 "c-parse.y"
{ expand_loop_continue_here (); ;
break;}
case 322:
-#line 1632 "c-parse.y"
+#line 1647 "c-parse.y"
{ yyval.filename = input_filename; ;
break;}
case 323:
-#line 1636 "c-parse.y"
+#line 1651 "c-parse.y"
{ yyval.lineno = lineno; ;
break;}
case 324:
-#line 1641 "c-parse.y"
+#line 1656 "c-parse.y"
{ ;
break;}
case 325:
-#line 1646 "c-parse.y"
+#line 1661 "c-parse.y"
{ ;
break;}
case 326:
-#line 1651 "c-parse.y"
+#line 1666 "c-parse.y"
{ yyval.ends_in_label = yyvsp[0].ends_in_label; ;
break;}
case 327:
-#line 1656 "c-parse.y"
+#line 1671 "c-parse.y"
{ yyval.ends_in_label = 0; ;
break;}
case 328:
-#line 1658 "c-parse.y"
+#line 1673 "c-parse.y"
{ yyval.ends_in_label = 1; ;
break;}
case 329:
-#line 1664 "c-parse.y"
+#line 1679 "c-parse.y"
{ stmt_count++; ;
break;}
case 331:
-#line 1667 "c-parse.y"
+#line 1682 "c-parse.y"
{ stmt_count++;
emit_line_note (yyvsp[-3].filename, yyvsp[-2].lineno);
/* It appears that this should not be done--that a non-lvalue array
@@ -3145,19 +3160,19 @@ case 331:
clear_momentary (); ;
break;}
case 332:
-#line 1684 "c-parse.y"
+#line 1699 "c-parse.y"
{ c_expand_start_else ();
yyvsp[-1].itype = stmt_count;
position_after_white_space (); ;
break;}
case 333:
-#line 1688 "c-parse.y"
+#line 1703 "c-parse.y"
{ c_expand_end_cond ();
if (extra_warnings && stmt_count == yyvsp[-3].itype)
warning ("empty body in an else-statement"); ;
break;}
case 334:
-#line 1692 "c-parse.y"
+#line 1707 "c-parse.y"
{ c_expand_end_cond ();
/* This warning is here instead of in simple_if, because we
do not want a warning if an empty if is followed by an
@@ -3168,11 +3183,11 @@ case 334:
"empty body in an if-statement"); ;
break;}
case 335:
-#line 1704 "c-parse.y"
+#line 1719 "c-parse.y"
{ c_expand_end_cond (); ;
break;}
case 336:
-#line 1706 "c-parse.y"
+#line 1721 "c-parse.y"
{ stmt_count++;
emit_line_note (yyvsp[-2].filename, yyvsp[-1].lineno);
/* The emit_nop used to come before emit_line_note,
@@ -3184,7 +3199,7 @@ case 336:
emit_nop (); ;
break;}
case 337:
-#line 1716 "c-parse.y"
+#line 1731 "c-parse.y"
{ /* Don't start the loop till we have succeeded
in parsing the end test. This is to make sure
that we end every loop we start. */
@@ -3195,11 +3210,11 @@ case 337:
position_after_white_space (); ;
break;}
case 338:
-#line 1725 "c-parse.y"
+#line 1740 "c-parse.y"
{ expand_end_loop (); ;
break;}
case 339:
-#line 1728 "c-parse.y"
+#line 1743 "c-parse.y"
{ emit_line_note (input_filename, lineno);
expand_exit_loop_if_false (NULL_PTR,
truthvalue_conversion (yyvsp[-2].ttype));
@@ -3207,12 +3222,12 @@ case 339:
clear_momentary (); ;
break;}
case 340:
-#line 1735 "c-parse.y"
+#line 1750 "c-parse.y"
{ expand_end_loop ();
clear_momentary (); ;
break;}
case 341:
-#line 1739 "c-parse.y"
+#line 1754 "c-parse.y"
{ stmt_count++;
emit_line_note (yyvsp[-5].filename, yyvsp[-4].lineno);
/* See comment in `while' alternative, above. */
@@ -3225,12 +3240,12 @@ case 341:
;
break;}
case 342:
-#line 1751 "c-parse.y"
+#line 1766 "c-parse.y"
{ yyvsp[0].lineno = lineno;
yyval.filename = input_filename; ;
break;}
case 343:
-#line 1754 "c-parse.y"
+#line 1769 "c-parse.y"
{
/* Start the loop. Doing this after parsing
all the expressions ensures we will end the loop. */
@@ -3248,7 +3263,7 @@ case 343:
position_after_white_space (); ;
break;}
case 344:
-#line 1770 "c-parse.y"
+#line 1785 "c-parse.y"
{ /* Emit the increment expression, with a line number. */
emit_line_note (yyvsp[-4].filename, yyvsp[-5].lineno);
expand_loop_continue_here ();
@@ -3261,7 +3276,7 @@ case 344:
expand_end_loop (); ;
break;}
case 345:
-#line 1781 "c-parse.y"
+#line 1796 "c-parse.y"
{ stmt_count++;
emit_line_note (yyvsp[-5].filename, yyvsp[-4].lineno);
c_expand_start_case (yyvsp[-1].ttype);
@@ -3271,7 +3286,7 @@ case 345:
position_after_white_space (); ;
break;}
case 346:
-#line 1789 "c-parse.y"
+#line 1804 "c-parse.y"
{ expand_end_case (yyvsp[-3].ttype);
if (yychar == CONSTANT || yychar == STRING)
pop_momentary_nofree ();
@@ -3279,33 +3294,33 @@ case 346:
pop_momentary (); ;
break;}
case 347:
-#line 1795 "c-parse.y"
+#line 1810 "c-parse.y"
{ stmt_count++;
emit_line_note (yyvsp[-3].filename, yyvsp[-2].lineno);
if ( ! expand_exit_something ())
error ("break statement not within loop or switch"); ;
break;}
case 348:
-#line 1800 "c-parse.y"
+#line 1815 "c-parse.y"
{ stmt_count++;
emit_line_note (yyvsp[-3].filename, yyvsp[-2].lineno);
if (! expand_continue_loop (NULL_PTR))
error ("continue statement not within a loop"); ;
break;}
case 349:
-#line 1805 "c-parse.y"
+#line 1820 "c-parse.y"
{ stmt_count++;
emit_line_note (yyvsp[-3].filename, yyvsp[-2].lineno);
c_expand_return (NULL_TREE); ;
break;}
case 350:
-#line 1809 "c-parse.y"
+#line 1824 "c-parse.y"
{ stmt_count++;
emit_line_note (yyvsp[-4].filename, yyvsp[-3].lineno);
c_expand_return (yyvsp[-1].ttype); ;
break;}
case 351:
-#line 1813 "c-parse.y"
+#line 1828 "c-parse.y"
{ stmt_count++;
emit_line_note (yyvsp[-7].filename, yyvsp[-6].lineno);
STRIP_NOPS (yyvsp[-2].ttype);
@@ -3317,7 +3332,7 @@ case 351:
error ("argument of `asm' is not a constant string"); ;
break;}
case 352:
-#line 1824 "c-parse.y"
+#line 1839 "c-parse.y"
{ stmt_count++;
emit_line_note (yyvsp[-9].filename, yyvsp[-8].lineno);
c_expand_asm_operands (yyvsp[-4].ttype, yyvsp[-2].ttype, NULL_TREE, NULL_TREE,
@@ -3325,7 +3340,7 @@ case 352:
input_filename, lineno); ;
break;}
case 353:
-#line 1831 "c-parse.y"
+#line 1846 "c-parse.y"
{ stmt_count++;
emit_line_note (yyvsp[-11].filename, yyvsp[-10].lineno);
c_expand_asm_operands (yyvsp[-6].ttype, yyvsp[-4].ttype, yyvsp[-2].ttype, NULL_TREE,
@@ -3333,7 +3348,7 @@ case 353:
input_filename, lineno); ;
break;}
case 354:
-#line 1839 "c-parse.y"
+#line 1854 "c-parse.y"
{ stmt_count++;
emit_line_note (yyvsp[-13].filename, yyvsp[-12].lineno);
c_expand_asm_operands (yyvsp[-8].ttype, yyvsp[-6].ttype, yyvsp[-4].ttype, yyvsp[-2].ttype,
@@ -3341,7 +3356,7 @@ case 354:
input_filename, lineno); ;
break;}
case 355:
-#line 1845 "c-parse.y"
+#line 1860 "c-parse.y"
{ tree decl;
stmt_count++;
emit_line_note (yyvsp[-4].filename, yyvsp[-3].lineno);
@@ -3354,7 +3369,7 @@ case 355:
;
break;}
case 356:
-#line 1856 "c-parse.y"
+#line 1871 "c-parse.y"
{ if (pedantic)
pedwarn ("ANSI C forbids `goto *expr;'");
stmt_count++;
@@ -3362,7 +3377,7 @@ case 356:
expand_computed_goto (convert (ptr_type_node, yyvsp[-1].ttype)); ;
break;}
case 359:
-#line 1871 "c-parse.y"
+#line 1886 "c-parse.y"
{
/* The value returned by this action is */
/* 1 if everything is OK */
@@ -3385,14 +3400,14 @@ case 359:
;
break;}
case 360:
-#line 1892 "c-parse.y"
+#line 1907 "c-parse.y"
{
if (yyvsp[-1].itype)
iterator_for_loop_end (yyvsp[-3].ttype);
;
break;}
case 361:
-#line 1927 "c-parse.y"
+#line 1942 "c-parse.y"
{ register tree value = check_case_value (yyvsp[-1].ttype);
register tree label
= build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
@@ -3425,7 +3440,7 @@ case 361:
position_after_white_space (); ;
break;}
case 362:
-#line 1958 "c-parse.y"
+#line 1973 "c-parse.y"
{ register tree value1 = check_case_value (yyvsp[-3].ttype);
register tree value2 = check_case_value (yyvsp[-1].ttype);
register tree label
@@ -3458,7 +3473,7 @@ case 362:
position_after_white_space (); ;
break;}
case 363:
-#line 1989 "c-parse.y"
+#line 2004 "c-parse.y"
{
tree duplicate;
register tree label
@@ -3475,7 +3490,7 @@ case 363:
position_after_white_space (); ;
break;}
case 364:
-#line 2004 "c-parse.y"
+#line 2019 "c-parse.y"
{ tree label = define_label (input_filename, lineno, yyvsp[-1].ttype);
stmt_count++;
emit_nop ();
@@ -3484,52 +3499,52 @@ case 364:
position_after_white_space (); ;
break;}
case 365:
-#line 2016 "c-parse.y"
+#line 2031 "c-parse.y"
{ emit_line_note (input_filename, lineno);
yyval.ttype = NULL_TREE; ;
break;}
case 366:
-#line 2019 "c-parse.y"
+#line 2034 "c-parse.y"
{ emit_line_note (input_filename, lineno); ;
break;}
case 367:
-#line 2024 "c-parse.y"
+#line 2039 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 369:
-#line 2031 "c-parse.y"
+#line 2046 "c-parse.y"
{ yyval.ttype = NULL_TREE; ;
break;}
case 372:
-#line 2038 "c-parse.y"
+#line 2053 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[-2].ttype, yyvsp[0].ttype); ;
break;}
case 373:
-#line 2043 "c-parse.y"
+#line 2058 "c-parse.y"
{ yyval.ttype = build_tree_list (yyvsp[-3].ttype, yyvsp[-1].ttype); ;
break;}
case 374:
-#line 2048 "c-parse.y"
+#line 2063 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, combine_strings (yyvsp[0].ttype), NULL_TREE); ;
break;}
case 375:
-#line 2050 "c-parse.y"
+#line 2065 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, combine_strings (yyvsp[0].ttype), yyvsp[-2].ttype); ;
break;}
case 376:
-#line 2056 "c-parse.y"
+#line 2071 "c-parse.y"
{ pushlevel (0);
clear_parm_order ();
declare_parm_level (0); ;
break;}
case 377:
-#line 2060 "c-parse.y"
+#line 2075 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype;
parmlist_tags_warning ();
poplevel (0, 0, 0); ;
break;}
case 379:
-#line 2068 "c-parse.y"
+#line 2083 "c-parse.y"
{ tree parm;
if (pedantic)
pedwarn ("ANSI C forbids forward parameter declarations");
@@ -3539,19 +3554,19 @@ case 379:
clear_parm_order (); ;
break;}
case 380:
-#line 2076 "c-parse.y"
+#line 2091 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype; ;
break;}
case 381:
-#line 2078 "c-parse.y"
+#line 2093 "c-parse.y"
{ yyval.ttype = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); ;
break;}
case 382:
-#line 2084 "c-parse.y"
+#line 2099 "c-parse.y"
{ yyval.ttype = get_parm_info (0); ;
break;}
case 383:
-#line 2086 "c-parse.y"
+#line 2101 "c-parse.y"
{ yyval.ttype = get_parm_info (0);
/* Gcc used to allow this as an extension. However, it does
not work for all targets, and thus has been disabled.
@@ -3563,23 +3578,23 @@ case 383:
;
break;}
case 384:
-#line 2096 "c-parse.y"
+#line 2111 "c-parse.y"
{ yyval.ttype = get_parm_info (1); ;
break;}
case 385:
-#line 2098 "c-parse.y"
+#line 2113 "c-parse.y"
{ yyval.ttype = get_parm_info (0); ;
break;}
case 386:
-#line 2103 "c-parse.y"
+#line 2118 "c-parse.y"
{ push_parm_decl (yyvsp[0].ttype); ;
break;}
case 387:
-#line 2105 "c-parse.y"
+#line 2120 "c-parse.y"
{ push_parm_decl (yyvsp[0].ttype); ;
break;}
case 388:
-#line 2112 "c-parse.y"
+#line 2127 "c-parse.y"
{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs,
yyvsp[-1].ttype),
build_tree_list (prefix_attributes,
@@ -3590,7 +3605,7 @@ case 388:
resume_momentary (yyvsp[-2].itype); ;
break;}
case 389:
-#line 2121 "c-parse.y"
+#line 2136 "c-parse.y"
{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs,
yyvsp[-1].ttype),
build_tree_list (prefix_attributes,
@@ -3601,7 +3616,7 @@ case 389:
resume_momentary (yyvsp[-2].itype); ;
break;}
case 390:
-#line 2130 "c-parse.y"
+#line 2145 "c-parse.y"
{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs,
yyvsp[-1].ttype),
build_tree_list (prefix_attributes,
@@ -3612,7 +3627,7 @@ case 390:
resume_momentary (yyvsp[-2].itype); ;
break;}
case 391:
-#line 2139 "c-parse.y"
+#line 2154 "c-parse.y"
{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs,
yyvsp[-1].ttype),
build_tree_list (prefix_attributes,
@@ -3623,7 +3638,7 @@ case 391:
resume_momentary (yyvsp[-2].itype); ;
break;}
case 392:
-#line 2149 "c-parse.y"
+#line 2164 "c-parse.y"
{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs,
yyvsp[-1].ttype),
build_tree_list (prefix_attributes,
@@ -3634,19 +3649,19 @@ case 392:
resume_momentary (yyvsp[-2].itype); ;
break;}
case 393:
-#line 2163 "c-parse.y"
+#line 2178 "c-parse.y"
{ pushlevel (0);
clear_parm_order ();
declare_parm_level (1); ;
break;}
case 394:
-#line 2167 "c-parse.y"
+#line 2182 "c-parse.y"
{ yyval.ttype = yyvsp[0].ttype;
parmlist_tags_warning ();
poplevel (0, 0, 0); ;
break;}
case 396:
-#line 2175 "c-parse.y"
+#line 2190 "c-parse.y"
{ tree t;
for (t = yyvsp[-1].ttype; t; t = TREE_CHAIN (t))
if (TREE_VALUE (t) == NULL_TREE)
@@ -3654,23 +3669,23 @@ case 396:
yyval.ttype = tree_cons (NULL_TREE, NULL_TREE, yyvsp[-1].ttype); ;
break;}
case 397:
-#line 2185 "c-parse.y"
+#line 2200 "c-parse.y"
{ yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ;
break;}
case 398:
-#line 2187 "c-parse.y"
+#line 2202 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[-2].ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ;
break;}
case 399:
-#line 2193 "c-parse.y"
+#line 2208 "c-parse.y"
{ yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ;
break;}
case 400:
-#line 2195 "c-parse.y"
+#line 2210 "c-parse.y"
{ yyval.ttype = chainon (yyvsp[-2].ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ;
break;}
case 401:
-#line 2200 "c-parse.y"
+#line 2215 "c-parse.y"
{ yyval.itype = pedantic;
pedantic = 0; ;
break;}
@@ -3872,5 +3887,5 @@ yyerrhandle:
yystate = yyn;
goto yynewstate;
}
-#line 2204 "c-parse.y"
+#line 2219 "c-parse.y"
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index 8b2bf5b1ee1..3db5c1fd1d6 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -265,6 +265,15 @@ end ifobjc
#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
extern void yyprint PROTO ((FILE *, int, YYSTYPE));
+
+void
+c_parse_init ()
+{
+ ggc_add_tree_root (&declspec_stack, 1);
+ ggc_add_tree_root (&current_declspecs, 1);
+ ggc_add_tree_root (&prefix_attributes, 1);
+}
+
%}
%%
diff --git a/gcc/c-parse.y b/gcc/c-parse.y
index ab0d7d16b9d..693fd89cddc 100644
--- a/gcc/c-parse.y
+++ b/gcc/c-parse.y
@@ -227,6 +227,15 @@ static int undeclared_variable_notice;
#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
extern void yyprint PROTO ((FILE *, int, YYSTYPE));
+
+void
+c_parse_init ()
+{
+ ggc_add_tree_root (&declspec_stack, 1);
+ ggc_add_tree_root (&current_declspecs, 1);
+ ggc_add_tree_root (&prefix_attributes, 1);
+}
+
%}
%%
@@ -1138,11 +1147,14 @@ initelt:
nested_function:
declarator
- { push_c_function_context ();
+ { if (pedantic)
+ pedwarn ("ANSI C forbids nested functions");
+
+ push_function_context ();
if (! start_function (current_declspecs, $1,
prefix_attributes, NULL_TREE, 1))
{
- pop_c_function_context ();
+ pop_function_context ();
YYERROR1;
}
reinit_parse_for_function (); }
@@ -1156,16 +1168,19 @@ nested_function:
which called YYERROR1 again, and so on. */
compstmt
{ finish_function (1);
- pop_c_function_context (); }
+ pop_function_context (); }
;
notype_nested_function:
notype_declarator
- { push_c_function_context ();
+ { if (pedantic)
+ pedwarn ("ANSI C forbids nested functions");
+
+ push_function_context ();
if (! start_function (current_declspecs, $1,
prefix_attributes, NULL_TREE, 1))
{
- pop_c_function_context ();
+ pop_function_context ();
YYERROR1;
}
reinit_parse_for_function (); }
@@ -1179,7 +1194,7 @@ notype_nested_function:
which called YYERROR1 again, and so on. */
compstmt
{ finish_function (1);
- pop_c_function_context (); }
+ pop_function_context (); }
;
/* Any kind of declarator (thus, all declarators allowed
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 9dfca6a58d4..0bde0698949 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -158,6 +158,8 @@ extern tree maybe_objc_method_name PROTO((tree));
extern int recognize_objc_keyword PROTO((void));
extern tree build_objc_string PROTO((int, char *));
+/* in c-parse.in */
+extern void c_parse_init PROTO((void));
/* in c-aux-info.c */
extern void gen_aux_info_record PROTO((tree, int, int, int));
diff --git a/gcc/caller-save.c b/gcc/caller-save.c
index 03fceaebe65..086cdfc0a49 100644
--- a/gcc/caller-save.c
+++ b/gcc/caller-save.c
@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "rtl.h"
#include "insn-config.h"
+#include "function.h"
#include "flags.h"
#include "regs.h"
#include "hard-reg-set.h"
diff --git a/gcc/calls.c b/gcc/calls.c
index 2bddc2a32a1..337524e1709 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "rtl.h"
#include "tree.h"
+#include "function.h"
#include "flags.h"
#include "expr.h"
#include "regs.h"
@@ -183,8 +184,7 @@ calls_function_1 (exp, which)
if ((DECL_BUILT_IN (fndecl)
&& DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA)
|| (DECL_SAVED_INSNS (fndecl)
- && (FUNCTION_FLAGS (DECL_SAVED_INSNS (fndecl))
- & FUNCTION_FLAGS_CALLS_ALLOCA)))
+ && DECL_SAVED_INSNS (fndecl)->func->calls_alloca))
return 1;
}
@@ -613,7 +613,7 @@ expand_call (exp, target, ignore)
&& fndecl != current_function_decl
&& DECL_INLINE (fndecl)
&& DECL_SAVED_INSNS (fndecl)
- && RTX_INTEGRATED_P (DECL_SAVED_INSNS (fndecl)))
+ && DECL_SAVED_INSNS (fndecl)->inlinable)
is_integrable = 1;
else if (! TREE_ADDRESSABLE (fndecl))
{
@@ -754,7 +754,7 @@ expand_call (exp, target, ignore)
nonzero then there is a call and it is not necessary
to scan the insns. */
- if (OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl)) == 0)
+ if (DECL_SAVED_INSNS (fndecl)->func->outgoing_args_size == 0)
for (insn = first_insn; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == CALL_INSN)
break;
@@ -778,8 +778,9 @@ expand_call (exp, target, ignore)
value of reg_parm_stack_space is wrong, but gives
correct results on all supported machines. */
- int adjust = (OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl))
- + reg_parm_stack_space);
+ int adjust =
+ (DECL_SAVED_INSNS (fndecl)->func->outgoing_args_size
+ + reg_parm_stack_space);
start_sequence ();
emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
diff --git a/gcc/combine.c b/gcc/combine.c
index 420a60fca5f..8fc0d7640a6 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -76,7 +76,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
-#include "rtl.h" /* stdio.h must precede rtl.h for FFS. */
+#include "rtl.h"
+#include "function.h"
#include "flags.h"
#include "regs.h"
#include "hard-reg-set.h"
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index fc8edbd64d1..1d370657622 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1925,8 +1925,20 @@ ix86_unary_operator_ok (code, mode, operands)
return TRUE;
}
-static rtx pic_label_rtx;
-static char pic_label_name [256];
+#define MAX_386_STACK_LOCALS 2
+
+/* Define the structure for the machine field in struct function. */
+struct machine_function
+{
+ rtx x_i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
+ rtx x_pic_label_rtx;
+ char x_pic_label_name[256];
+};
+
+#define i386_stack_locals (current_function->machine->x_i386_stack_locals)
+#define pic_label_rtx (current_function->machine->x_pic_label_rtx)
+#define pic_label_name (current_function->machine->x_pic_label_name)
+
static int pic_label_no = 0;
/* This function generates code for -fpic that loads %ebx with
@@ -4521,44 +4533,33 @@ output_fp_cc0_set (insn)
return "";
}
-#define MAX_386_STACK_LOCALS 2
-
-static rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
-
-/* Define the structure for the machine field in struct function. */
-struct machine_function
-{
- rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
- rtx pic_label_rtx;
- char pic_label_name[256];
-};
-
/* Functions to save and restore i386_stack_locals.
These will be called, via pointer variables,
from push_function_context and pop_function_context. */
void
-save_386_machine_status (p)
+init_386_machine_status (p)
struct function *p;
{
+ enum machine_mode mode;
+ int n;
+
p->machine
= (struct machine_function *) xmalloc (sizeof (struct machine_function));
- bcopy ((char *) i386_stack_locals, (char *) p->machine->i386_stack_locals,
- sizeof i386_stack_locals);
- p->machine->pic_label_rtx = pic_label_rtx;
- bcopy (pic_label_name, p->machine->pic_label_name, 256);
+
+ for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
+ mode = (enum machine_mode) ((int) mode + 1))
+ for (n = 0; n < MAX_386_STACK_LOCALS; n++)
+ i386_stack_locals[(int) mode][n] = NULL_RTX;
+
+ pic_label_rtx = NULL_RTX;
+ bzero (pic_label_name, 256);
}
void
restore_386_machine_status (p)
struct function *p;
{
- bcopy ((char *) p->machine->i386_stack_locals, (char *) i386_stack_locals,
- sizeof i386_stack_locals);
- pic_label_rtx = p->machine->pic_label_rtx;
- bcopy (p->machine->pic_label_name, pic_label_name, 256);
- free (p->machine);
- p->machine = NULL;
}
/* Clear stack slot assignments remembered from previous functions.
@@ -4568,18 +4569,8 @@ restore_386_machine_status (p)
void
clear_386_stack_locals ()
{
- enum machine_mode mode;
- int n;
-
- for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
- mode = (enum machine_mode) ((int) mode + 1))
- for (n = 0; n < MAX_386_STACK_LOCALS; n++)
- i386_stack_locals[(int) mode][n] = NULL_RTX;
-
- pic_label_rtx = NULL_RTX;
- bzero (pic_label_name, 256);
/* Arrange to save and restore i386_stack_locals around nested functions. */
- save_machine_status = save_386_machine_status;
+ init_machine_status = init_386_machine_status;
restore_machine_status = restore_386_machine_status;
}
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 0bb72415367..8c3a877c645 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1825,8 +1825,6 @@ while (0)
#define FINALIZE_PIC \
do \
{ \
- extern int current_function_uses_pic_offset_table; \
- \
current_function_uses_pic_offset_table |= profile_flag | profile_block_flag; \
} \
while (0)
diff --git a/gcc/cse.c b/gcc/cse.c
index 8c0a6661364..06f859aa8a4 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA. */
#include <setjmp.h>
#include "rtl.h"
+#include "function.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "flags.h"
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 8b717649bb0..987bf979663 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -58,20 +58,11 @@ enum machine_mode word_mode; /* Mode whose width is BITS_PER_WORD. */
enum machine_mode double_mode; /* Mode whose width is DOUBLE_TYPE_SIZE. */
enum machine_mode ptr_mode; /* Mode whose width is POINTER_SIZE. */
-/* This is reset to LAST_VIRTUAL_REGISTER + 1 at the start of each function.
- After rtl generation, it is 1 plus the largest register number used. */
-
-int reg_rtx_no = LAST_VIRTUAL_REGISTER + 1;
-
/* This is *not* reset after each function. It gives each CODE_LABEL
in the entire compilation a unique label number. */
static int label_num = 1;
-/* Lowest label number in current function. */
-
-static int first_label_num;
-
/* Highest label number in current function.
Zero means use the value of label_num instead.
This is nonzero only when belatedly compiling an inline function. */
@@ -155,65 +146,15 @@ rtx return_address_pointer_rtx; /* (REG:Pmode RETURN_ADDRESS_POINTER_REGNUM) */
struct rtx_def const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
-/* The ends of the doubly-linked chain of rtl for the current function.
- Both are reset to null at the start of rtl generation for the function.
-
- start_sequence saves both of these on `sequence_stack' along with
- `sequence_rtl_expr' and then starts a new, nested sequence of insns. */
-
-static rtx first_insn = NULL;
-static rtx last_insn = NULL;
-
-/* RTL_EXPR within which the current sequence will be placed. Use to
- prevent reuse of any temporaries within the sequence until after the
- RTL_EXPR is emitted. */
-
-tree sequence_rtl_expr = NULL;
-
-/* INSN_UID for next insn emitted.
- Reset to 1 for each function compiled. */
-
-static int cur_insn_uid = 1;
-
-/* Line number and source file of the last line-number NOTE emitted.
- This is used to avoid generating duplicates. */
-
-static int last_linenum = 0;
-static char *last_filename = 0;
-
-/* A vector indexed by pseudo reg number. The allocated length
- of this vector is regno_pointer_flag_length. Since this
- vector is needed during the expansion phase when the total
- number of registers in the function is not yet known,
- it is copied and made bigger when necessary. */
-
-char *regno_pointer_flag;
-int regno_pointer_flag_length;
-
-/* Indexed by pseudo register number, if nonzero gives the known alignment
- for that pseudo (if regno_pointer_flag is set).
- Allocated in parallel with regno_pointer_flag. */
-char *regno_pointer_align;
-
-/* Indexed by pseudo register number, gives the rtx for that pseudo.
- Allocated in parallel with regno_pointer_flag. */
-
-rtx *regno_reg_rtx;
-
-/* Stack of pending (incomplete) sequences saved by `start_sequence'.
- Each element describes one pending sequence.
- The main insn-chain is saved in the last element of the chain,
- unless the chain is empty. */
-
-struct sequence_stack *sequence_stack;
+#define first_insn (current_function->emit->x_first_insn)
+#define last_insn (current_function->emit->x_last_insn)
+#define cur_insn_uid (current_function->emit->x_cur_insn_uid)
+#define last_linenum (current_function->emit->x_last_linenum)
+#define last_filename (current_function->emit->x_last_filename)
+#define first_label_num (current_function->emit->x_first_label_num)
extern int rtx_equal_function_value_matters;
-/* Filename and line number of last line-number note,
- whether we actually emitted it or not. */
-extern char *emit_filename;
-extern int emit_lineno;
-
static rtx make_jump_insn_raw PROTO((rtx));
static rtx make_call_insn_raw PROTO((rtx));
static rtx find_line_note PROTO((rtx));
@@ -508,25 +449,22 @@ gen_reg_rtx (mode)
if (reg_rtx_no == regno_pointer_flag_length)
{
+ int new_len = regno_pointer_flag_length * 2;
rtx *new1;
- char *new =
- (char *) savealloc (regno_pointer_flag_length * 2);
- bcopy (regno_pointer_flag, new, regno_pointer_flag_length);
+ char *new = (char *) xrealloc (regno_pointer_flag, new_len);
bzero (&new[regno_pointer_flag_length], regno_pointer_flag_length);
regno_pointer_flag = new;
- new = (char *) savealloc (regno_pointer_flag_length * 2);
- bcopy (regno_pointer_align, new, regno_pointer_flag_length);
+ new = (char *) xrealloc (regno_pointer_align, new_len);
bzero (&new[regno_pointer_flag_length], regno_pointer_flag_length);
regno_pointer_align = new;
- new1 = (rtx *) savealloc (regno_pointer_flag_length * 2 * sizeof (rtx));
- bcopy ((char *) regno_reg_rtx, (char *) new1,
- regno_pointer_flag_length * sizeof (rtx));
+ new1 = (rtx *) xrealloc (regno_reg_rtx, new_len * sizeof (rtx));
bzero ((char *) &new1[regno_pointer_flag_length],
regno_pointer_flag_length * sizeof (rtx));
regno_reg_rtx = new1;
- regno_pointer_flag_length *= 2;
+
+ regno_pointer_flag_length = new_len;
}
val = gen_rtx_raw_REG (mode, reg_rtx_no);
@@ -1495,49 +1433,6 @@ gen_label_rtx ()
return label;
}
-/* For procedure integration. */
-
-/* Return a newly created INLINE_HEADER rtx. Should allocate this
- from a permanent obstack when the opportunity arises. */
-
-rtx
-gen_inline_header_rtx (first_insn, first_parm_insn, first_labelno,
- last_labelno, max_parm_regnum, max_regnum, args_size,
- pops_args, stack_slots, forced_labels, function_flags,
- outgoing_args_size, original_arg_vector,
- original_decl_initial, regno_rtx, regno_flag,
- regno_align, parm_reg_stack_loc)
- rtx first_insn, first_parm_insn;
- int first_labelno, last_labelno, max_parm_regnum, max_regnum, args_size;
- int pops_args;
- rtx stack_slots;
- rtx forced_labels;
- int function_flags;
- int outgoing_args_size;
- rtvec original_arg_vector;
- tree original_decl_initial;
- rtx *regno_rtx;
- char *regno_flag;
- char *regno_align;
- rtx *parm_reg_stack_loc;
-{
- rtx header = gen_rtx_INLINE_HEADER (VOIDmode,
- cur_insn_uid++, NULL_RTX,
- first_insn, first_parm_insn,
- first_labelno, last_labelno,
- max_parm_regnum, max_regnum, args_size,
- pops_args, stack_slots, forced_labels,
- function_flags, outgoing_args_size,
- original_arg_vector);
- ORIGINAL_DECL_INITIAL (header) = original_decl_initial;
- INLINE_REGNO_REG_RTX (header) = regno_rtx;
- INLINE_REGNO_POINTER_FLAG (header) = regno_flag;
- INLINE_REGNO_POINTER_ALIGN (header) = regno_align;
- PARMREG_STACK_LOC (header) = parm_reg_stack_loc;
-
- return header;
-}
-
/* Install new pointers to the first and last insns in the chain.
Also, set cur_insn_uid to one higher than the last in use.
Used for an inline-procedure after copying the insn chain. */
@@ -1569,29 +1464,18 @@ set_new_first_and_last_label_num (first, last)
first_label_num = first;
last_label_num = last;
}
-
-/* Save all variables describing the current status into the structure *P.
- This is used before starting a nested function. */
+
+/* Set the last label number found in the current function.
+ This is used when belatedly compiling an inline function. */
void
-save_emit_status (p)
- struct function *p;
+set_new_last_label_num (last)
+ int last;
{
- p->reg_rtx_no = reg_rtx_no;
- p->first_label_num = first_label_num;
- p->first_insn = first_insn;
- p->last_insn = last_insn;
- p->sequence_rtl_expr = sequence_rtl_expr;
- p->sequence_stack = sequence_stack;
- p->cur_insn_uid = cur_insn_uid;
- p->last_linenum = last_linenum;
- p->last_filename = last_filename;
- p->regno_pointer_flag = regno_pointer_flag;
- p->regno_pointer_align = regno_pointer_align;
- p->regno_pointer_flag_length = regno_pointer_flag_length;
- p->regno_reg_rtx = regno_reg_rtx;
+ base_label_num = label_num;
+ last_label_num = last;
}
-
+
/* Restore all variables describing the current status from the structure *P.
This is used after a nested function. */
@@ -1599,22 +1483,20 @@ void
restore_emit_status (p)
struct function *p;
{
- int i;
-
- reg_rtx_no = p->reg_rtx_no;
- first_label_num = p->first_label_num;
last_label_num = 0;
- first_insn = p->first_insn;
- last_insn = p->last_insn;
- sequence_rtl_expr = p->sequence_rtl_expr;
- sequence_stack = p->sequence_stack;
- cur_insn_uid = p->cur_insn_uid;
- last_linenum = p->last_linenum;
- last_filename = p->last_filename;
- regno_pointer_flag = p->regno_pointer_flag;
- regno_pointer_align = p->regno_pointer_align;
- regno_pointer_flag_length = p->regno_pointer_flag_length;
- regno_reg_rtx = p->regno_reg_rtx;
+}
+
+/* Clear out all parts of our state in F that can safely be discarded
+ after the function has been compiled, to let garbage collection
+ reclaim the memory. */
+void
+free_emit_status (f)
+ struct function *f;
+{
+ free (f->emit->x_regno_reg_rtx);
+ free (f->emit->x_regno_pointer_flag);
+ free (f->emit->x_regno_pointer_align);
+ f->emit->x_regno_reg_rtx = 0;
}
/* Go through all the RTL insn bodies and copy any invalid shared structure.
@@ -1908,7 +1790,7 @@ get_last_insn_anywhere ()
struct sequence_stack *stack;
if (last_insn)
return last_insn;
- for (stack = sequence_stack; stack; stack = stack->next)
+ for (stack = seq_stack; stack; stack = stack->next)
if (stack->last != 0)
return stack->last;
return 0;
@@ -2364,7 +2246,7 @@ add_insn_after (insn, after)
last_insn = insn;
else
{
- struct sequence_stack *stack = sequence_stack;
+ struct sequence_stack *stack = seq_stack;
/* Scan all pending sequences too. */
for (; stack; stack = stack->next)
if (after == stack->last)
@@ -2415,7 +2297,7 @@ add_insn_before (insn, before)
first_insn = insn;
else
{
- struct sequence_stack *stack = sequence_stack;
+ struct sequence_stack *stack = seq_stack;
/* Scan all pending sequences too. */
for (; stack; stack = stack->next)
if (before == stack->first)
@@ -2951,8 +2833,7 @@ emit_line_note (file, line)
char *file;
int line;
{
- emit_filename = file;
- emit_lineno = line;
+ set_file_and_line_for_stmt (file, line);
#if 0
if (no_line_numbers)
@@ -3090,12 +2971,12 @@ start_sequence ()
tem = (struct sequence_stack *) xmalloc (sizeof (struct sequence_stack));
- tem->next = sequence_stack;
+ tem->next = seq_stack;
tem->first = first_insn;
tem->last = last_insn;
- tem->sequence_rtl_expr = sequence_rtl_expr;
+ tem->sequence_rtl_expr = seq_rtl_expr;
- sequence_stack = tem;
+ seq_stack = tem;
first_insn = 0;
last_insn = 0;
@@ -3110,7 +2991,7 @@ start_sequence_for_rtl_expr (t)
{
start_sequence ();
- sequence_rtl_expr = t;
+ seq_rtl_expr = t;
}
/* Set up the insn chain starting with FIRST
@@ -3140,12 +3021,12 @@ push_topmost_sequence ()
start_sequence ();
- for (stack = sequence_stack; stack; stack = stack->next)
+ for (stack = seq_stack; stack; stack = stack->next)
top = stack;
first_insn = top->first;
last_insn = top->last;
- sequence_rtl_expr = top->sequence_rtl_expr;
+ seq_rtl_expr = top->sequence_rtl_expr;
}
/* After emitting to the outer-level insn chain, update the outer-level
@@ -3156,7 +3037,7 @@ pop_topmost_sequence ()
{
struct sequence_stack *stack, *top = NULL;
- for (stack = sequence_stack; stack; stack = stack->next)
+ for (stack = seq_stack; stack; stack = stack->next)
top = stack;
top->first = first_insn;
@@ -3174,12 +3055,12 @@ pop_topmost_sequence ()
void
end_sequence ()
{
- struct sequence_stack *tem = sequence_stack;
+ struct sequence_stack *tem = seq_stack;
first_insn = tem->first;
last_insn = tem->last;
- sequence_rtl_expr = tem->sequence_rtl_expr;
- sequence_stack = tem->next;
+ seq_rtl_expr = tem->sequence_rtl_expr;
+ seq_stack = tem->next;
free (tem);
}
@@ -3189,7 +3070,7 @@ end_sequence ()
int
in_sequence_p ()
{
- return sequence_stack != 0;
+ return seq_stack != 0;
}
/* Generate a SEQUENCE rtx containing the insns already emitted
@@ -3253,32 +3134,26 @@ init_emit ()
{
int i;
+ current_function->emit = (struct emit_status *) xmalloc (sizeof (struct emit_status));
+
first_insn = NULL;
last_insn = NULL;
- sequence_rtl_expr = NULL;
+ seq_rtl_expr = NULL;
cur_insn_uid = 1;
reg_rtx_no = LAST_VIRTUAL_REGISTER + 1;
last_linenum = 0;
last_filename = 0;
first_label_num = label_num;
last_label_num = 0;
- sequence_stack = NULL;
+ seq_stack = NULL;
/* Init the tables that describe all the pseudo regs. */
regno_pointer_flag_length = LAST_VIRTUAL_REGISTER + 101;
- regno_pointer_flag
- = (char *) savealloc (regno_pointer_flag_length);
- bzero (regno_pointer_flag, regno_pointer_flag_length);
-
- regno_pointer_align
- = (char *) savealloc (regno_pointer_flag_length);
- bzero (regno_pointer_align, regno_pointer_flag_length);
-
- regno_reg_rtx
- = (rtx *) savealloc (regno_pointer_flag_length * sizeof (rtx));
- bzero ((char *) regno_reg_rtx, regno_pointer_flag_length * sizeof (rtx));
+ regno_pointer_flag = (char *) xcalloc (regno_pointer_flag_length, 1);
+ regno_pointer_align = (char *) xcalloc (regno_pointer_flag_length, 1);
+ regno_reg_rtx = (rtx *) xcalloc (regno_pointer_flag_length, sizeof (rtx));
/* Put copies of all the virtual register rtx into regno_reg_rtx. */
init_virtual_regs ();
@@ -3321,7 +3196,7 @@ init_emit ()
/* Mark the sequence stack for GC. */
-void
+static void
mark_sequence_stack (arg)
void *arg;
{
@@ -3334,16 +3209,24 @@ mark_sequence_stack (arg)
}
}
-/* A special mark function for regno_reg_rtx, since we don't want to
- keep swapping out its root. */
-
-static void
-mark_regno_reg_rtx (dummy)
- void *dummy;
+void
+mark_emit_state (arg)
+ void *arg;
{
+ struct emit_status *es = *(struct emit_status **)arg;
+ rtx *r;
int i;
- for (i = 0; i < regno_pointer_flag_length; ++i)
- ggc_mark_rtx (regno_reg_rtx[i]);
+
+ if (es == 0)
+ return;
+
+ for (i = es->x_regno_pointer_flag_length, r = es->x_regno_reg_rtx;
+ i > 0; --i, ++r)
+ ggc_mark_rtx (*r);
+
+ mark_sequence_stack (&es->sequence_stack);
+ ggc_mark_tree (es->sequence_rtl_expr);
+ ggc_mark_rtx (es->x_first_insn);
}
/* Create some permanent unique rtl objects shared between all functions.
@@ -3359,8 +3242,6 @@ init_emit_once (line_numbers)
no_line_numbers = ! line_numbers;
- sequence_stack = NULL;
-
/* Compute the word and byte modes. */
byte_mode = VOIDmode;
@@ -3530,13 +3411,6 @@ init_emit_once (line_numbers)
ggc_add_rtx_root (&static_chain_rtx, 1);
ggc_add_rtx_root (&static_chain_incoming_rtx, 1);
ggc_add_rtx_root (&return_address_pointer_rtx, 1);
-
- ggc_add_rtx_root (&first_insn, 1);
- ggc_add_tree_root (&sequence_rtl_expr, 1);
- ggc_add_root (&sequence_stack, 1, sizeof(sequence_stack),
- mark_sequence_stack);
- ggc_add_root (&regno_reg_rtx, 1, sizeof(regno_reg_rtx),
- mark_regno_reg_rtx);
}
/* Query and clear/ restore no_line_numbers. This is used by the
diff --git a/gcc/except.c b/gcc/except.c
index 01bda61ba09..755cc9425dd 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -427,70 +427,13 @@ int protect_cleanup_actions_with_terminate;
rtx exception_handler_labels;
-/* The EH context. Nonzero if the function has already
- fetched a pointer to the EH context for exception handling. */
-
-rtx current_function_ehc;
-
-/* A stack used for keeping track of the currently active exception
- handling region. As each exception region is started, an entry
- describing the region is pushed onto this stack. The current
- region can be found by looking at the top of the stack, and as we
- exit regions, the corresponding entries are popped.
-
- Entries cannot overlap; they can be nested. So there is only one
- entry at most that corresponds to the current instruction, and that
- is the entry on the top of the stack. */
-
-static struct eh_stack ehstack;
-
-
-/* This stack is used to represent what the current eh region is
- for the catch blocks beings processed */
-
-static struct eh_stack catchstack;
-
-/* A queue used for tracking which exception regions have closed but
- whose handlers have not yet been expanded. Regions are emitted in
- groups in an attempt to improve paging performance.
-
- As we exit a region, we enqueue a new entry. The entries are then
- dequeued during expand_leftover_cleanups and expand_start_all_catch,
-
- We should redo things so that we either take RTL for the handler,
- or we expand the handler expressed as a tree immediately at region
- end time. */
-
-static struct eh_queue ehqueue;
-
-/* Insns for all of the exception handlers for the current function.
- They are currently emitted by the frontend code. */
-
-rtx catch_clauses;
-
-/* A TREE_CHAINed list of handlers for regions that are not yet
- closed. The TREE_VALUE of each entry contains the handler for the
- corresponding entry on the ehstack. */
-
-static tree protect_list;
-
/* Stacks to keep track of various labels. */
-/* Keeps track of the label to resume to should one want to resume
- normal control flow out of a handler (instead of, say, returning to
- the caller of the current function or exiting the program). */
-
-struct label_node *caught_return_label_stack = NULL;
-
/* Keeps track of the label used as the context of a throw to rethrow an
exception to the outer exception region. */
struct label_node *outer_context_label_stack = NULL;
-/* A random data area for the front end's own use. */
-
-struct label_node *false_label_stack = NULL;
-
/* Pseudos used to hold exception return data in the interim between
__builtin_eh_return and the end of the function. */
@@ -503,26 +446,94 @@ static rtx eh_return_handler;
rtx eh_return_stub_label;
+/* Used to save exception handling status for nested functions. */
+struct eh_status
+{
+ /* A stack used for keeping track of the currently active exception
+ handling region. As each exception region is started, an entry
+ describing the region is pushed onto this stack. The current
+ region can be found by looking at the top of the stack, and as we
+ exit regions, the corresponding entries are popped.
+
+ Entries cannot overlap; they can be nested. So there is only one
+ entry at most that corresponds to the current instruction, and that
+ is the entry on the top of the stack. */
+ struct eh_stack x_ehstack;
+
+ /* This stack is used to represent what the current eh region is
+ for the catch blocks beings processed */
+ struct eh_stack x_catchstack;
+
+ /* A queue used for tracking which exception regions have closed but
+ whose handlers have not yet been expanded. Regions are emitted in
+ groups in an attempt to improve paging performance.
+
+ As we exit a region, we enqueue a new entry. The entries are then
+ dequeued during expand_leftover_cleanups and expand_start_all_catch,
+
+ We should redo things so that we either take RTL for the handler,
+ or we expand the handler expressed as a tree immediately at region
+ end time. */
+ struct eh_queue x_ehqueue;
+ /* Insns for all of the exception handlers for the current function.
+ They are currently emitted by the frontend code. */
+ rtx x_catch_clauses;
+
+ /* A random data area for the front end's own use. */
+ struct label_node *x_false_label_stack;
+
+ /* Keeps track of the label to resume to should one want to resume
+ normal control flow out of a handler (instead of, say, returning to
+ the caller of the current function or exiting the program). */
+ struct label_node *x_caught_return_label_stack;
+
+ /* A TREE_CHAINed list of handlers for regions that are not yet
+ closed. The TREE_VALUE of each entry contains the handler for the
+ corresponding entry on the ehstack. */
+ tree x_protect_list;
+
+ /* The EH context. Nonzero if the function has already
+ fetched a pointer to the EH context for exception handling. */
+ rtx ehc;
+};
+
+#define ehstack (current_function->eh->x_ehstack)
+#define catchstack (current_function->eh->x_catchstack)
+#define ehqueue (current_function->eh->x_ehqueue)
+#define catch_clauses (current_function->eh->x_catch_clauses)
+#define false_label_stack (current_function->eh->x_false_label_stack)
+#define caught_return_label_stack (current_function->eh->x_caught_return_label_stack)
+#define protect_list (current_function->eh->x_protect_list)
+#define current_function_ehc (current_function->eh->ehc)
+
/* Prototypes for local functions. */
-static void push_eh_entry PROTO((struct eh_stack *));
+static void mark_eh_node PROTO((struct eh_node *));
+static void mark_eh_stack PROTO((void *));
+static void mark_eh_queue PROTO((void *));
+static void mark_tree_label_node PROTO((void *));
+static void mark_rtx_label_node PROTO((void *));
+static void push_eh_entry PROTO((struct eh_stack *));
static struct eh_entry * pop_eh_entry PROTO((struct eh_stack *));
-static void enqueue_eh_entry PROTO((struct eh_queue *, struct eh_entry *));
+static void enqueue_eh_entry PROTO((struct eh_queue *,
+ struct eh_entry *));
static struct eh_entry * dequeue_eh_entry PROTO((struct eh_queue *));
-static rtx call_get_eh_context PROTO((void));
+static rtx call_get_eh_context PROTO((void));
static void start_dynamic_cleanup PROTO((tree, tree));
static void start_dynamic_handler PROTO((void));
-static void expand_rethrow PROTO((rtx));
+static void expand_rethrow PROTO((rtx));
static void output_exception_table_entry PROTO((FILE *, int));
-static int can_throw PROTO((rtx));
-static rtx scan_region PROTO((rtx, int, int *));
-static void eh_regs PROTO((rtx *, rtx *, rtx *, int));
-static void set_insn_eh_region PROTO((rtx *, int));
+static int can_throw PROTO((rtx));
+static rtx scan_region PROTO((rtx, int, int *));
+static void eh_regs PROTO((rtx *, rtx *, rtx *,
+ int));
+static void set_insn_eh_region PROTO((rtx *, int));
#ifdef DONT_USE_BUILTIN_SETJMP
-static void jumpif_rtx PROTO((rtx, rtx));
+static void jumpif_rtx PROTO((rtx, rtx));
#endif
-rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
+rtx expand_builtin_return_addr PROTO((enum built_in_function,
+ int, rtx));
/* Various support routines to manipulate the various data structures
used by the exception handling code. */
@@ -2185,59 +2196,8 @@ check_exception_handler_labels ()
}
/* This group of functions initializes the exception handling data
- structures at the start of the compilation, initializes the data
- structures at the start of a function, and saves and restores the
- exception handling data structures for the start/end of a nested
- function. */
-
-/* Save some of the per-function EH info into the save area denoted by
- P.
-
- This is currently called from save_stmt_status. */
-
-void
-save_eh_status (f)
- struct function *f;
-{
- struct eh_function *p;
-
- p = (struct eh_function *) xmalloc (sizeof (struct eh_function));
- f->eh = p;
-
- p->ehstack = ehstack;
- p->catchstack = catchstack;
- p->ehqueue = ehqueue;
- p->catch_clauses = catch_clauses;
- p->false_label_stack = false_label_stack;
- p->caught_return_label_stack = caught_return_label_stack;
- p->protect_list = protect_list;
- p->ehc = current_function_ehc;
-
- init_eh_for_function ();
-}
-
-/* Restore the per-function EH info saved into the area denoted by P.
-
- This is currently called from restore_stmt_status. */
-
-void
-restore_eh_status (f)
- struct function *f;
-{
- struct eh_function *p = f->eh;
-
- protect_list = p->protect_list;
- caught_return_label_stack = p->caught_return_label_stack;
- false_label_stack = p->false_label_stack;
- catch_clauses = p->catch_clauses;
- ehqueue = p->ehqueue;
- ehstack = p->ehstack;
- catchstack = p->catchstack;
- current_function_ehc = p->ehc;
-
- free (p);
-}
-
+ structures at the start of the compilation and at the start of
+ each function. */
static void
mark_eh_node (node)
struct eh_node *node;
@@ -2254,7 +2214,7 @@ mark_eh_node (node)
}
}
-void
+static void
mark_eh_stack (arg)
void *arg;
{
@@ -2263,7 +2223,7 @@ mark_eh_stack (arg)
mark_eh_node (s->top);
}
-void
+static void
mark_eh_queue (arg)
void *arg;
{
@@ -2272,7 +2232,7 @@ mark_eh_queue (arg)
mark_eh_node (q->head);
}
-void
+static void
mark_tree_label_node (arg)
void *arg;
{
@@ -2285,7 +2245,7 @@ mark_tree_label_node (arg)
}
}
-void
+static void
mark_rtx_label_node (arg)
void *arg;
{
@@ -2302,16 +2262,16 @@ void
mark_eh_state (arg)
void *arg;
{
- struct eh_function *eh = *(struct eh_function **) arg;
+ struct eh_status *eh = *(struct eh_status **) arg;
- mark_eh_stack (&eh->ehstack);
- mark_eh_queue (&eh->ehqueue);
- ggc_mark_rtx (eh->catch_clauses);
+ mark_eh_stack (&eh->x_ehstack);
+ mark_eh_queue (&eh->x_ehqueue);
+ ggc_mark_rtx (eh->x_catch_clauses);
- lang_mark_false_label_stack (&eh->false_label_stack);
- mark_tree_label_node (&eh->caught_return_label_stack);
+ lang_mark_false_label_stack (&eh->x_false_label_stack);
+ mark_tree_label_node (&eh->x_caught_return_label_stack);
- ggc_mark_tree (eh->protect_list);
+ ggc_mark_tree (eh->x_protect_list);
ggc_mark_rtx (eh->ehc);
}
@@ -2320,12 +2280,6 @@ mark_eh_state (arg)
void
init_eh ()
{
- ggc_add_root (&caught_return_label_stack, 1,
- sizeof(caught_return_label_stack), mark_tree_label_node);
- ggc_add_root (&ehstack, 1, sizeof(ehstack), mark_eh_stack);
- ggc_add_root (&ehqueue, 1, sizeof(ehqueue), mark_eh_queue);
- ggc_add_rtx_root (&catch_clauses, 1);
- ggc_add_tree_root (&protect_list, 1);
}
/* Initialize the per-function EH information. */
@@ -2333,6 +2287,8 @@ init_eh ()
void
init_eh_for_function ()
{
+ current_function->eh = (struct eh_status *) xmalloc (sizeof (struct eh_status));
+
ehstack.top = 0;
catchstack.top = 0;
ehqueue.head = ehqueue.tail = 0;
diff --git a/gcc/except.h b/gcc/except.h
index a90b8d2c6a0..35fb73ad53d 100644
--- a/gcc/except.h
+++ b/gcc/except.h
@@ -91,19 +91,6 @@ struct eh_queue {
struct eh_node *tail;
};
-/* Used to save exception handling status for nested functions. */
-struct eh_function
-{
- struct eh_stack ehstack;
- struct eh_stack catchstack;
- struct eh_queue ehqueue;
- rtx catch_clauses;
- struct label_node *false_label_stack;
- struct label_node *caught_return_label_stack;
- tree protect_list;
- rtx ehc;
-};
-
/* Start an exception handling region. All instructions emitted after
this point are considered to be part of the region until
expand_eh_region_end () is invoked. */
@@ -325,20 +312,11 @@ extern int is_exception_handler_label PROTO((int));
extern void check_exception_handler_labels PROTO((void));
-/* A stack used to keep track of the label used to resume normal program
- flow out of the current exception handler region. */
-
-extern struct label_node *caught_return_label_stack;
-
/* Keeps track of the label used as the context of a throw to rethrow an
exception to the outer exception region. */
extern struct label_node *outer_context_label_stack;
-/* A random area used for purposes elsewhere. */
-
-extern struct label_node *false_label_stack;
-
/* A list of labels used for exception handlers. It is created by
find_exception_handler_labels for the optimization passes. */
diff --git a/gcc/explow.c b/gcc/explow.c
index 58d4ebd9757..a15afade550 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "flags.h"
#include "expr.h"
+#include "function.h"
#include "hard-reg-set.h"
#include "insn-config.h"
#include "recog.h"
diff --git a/gcc/expr.c b/gcc/expr.c
index d2dcdf8c592..e951f141975 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -86,24 +86,6 @@ int cse_not_expected;
Nowadays this is never zero. */
int do_preexpand_calls = 1;
-/* Number of units that we should eventually pop off the stack.
- These are the arguments to function calls that have already returned. */
-int pending_stack_adjust;
-
-/* Nonzero means stack pops must not be deferred, and deferred stack
- pops must not be output. It is nonzero inside a function call,
- inside a conditional expression, inside a statement expression,
- and in other cases as well. */
-int inhibit_defer_pop;
-
-/* Nonzero means __builtin_saveregs has already been done in this function.
- The value is the pseudoreg containing the value __builtin_saveregs
- returned. */
-static rtx saveregs_value;
-
-/* Similarly for __builtin_apply_args. */
-static rtx apply_args_value;
-
/* Nonzero if the machine description has been fixed to accept
CONSTANT_P_RTX patterns. We will emit a warning and continue
if we find we must actually use such a beast. */
@@ -149,7 +131,6 @@ struct clear_by_pieces
};
extern struct obstack permanent_obstack;
-extern rtx arg_pointer_save_area;
static rtx get_push_address PROTO ((int));
@@ -326,30 +307,9 @@ init_expr_once ()
void
init_expr ()
{
- init_queue ();
-
- pending_stack_adjust = 0;
- inhibit_defer_pop = 0;
- saveregs_value = 0;
- apply_args_value = 0;
- forced_labels = 0;
-}
+ current_function->expr = (struct expr_status *) xmalloc (sizeof (struct expr_status));
-/* Save all variables describing the current status into the structure *P.
- This is used before starting a nested function. */
-
-void
-save_expr_status (p)
- struct function *p;
-{
- /* Instead of saving the postincrement queue, empty it. */
- emit_queue ();
-
- p->pending_stack_adjust = pending_stack_adjust;
- p->inhibit_defer_pop = inhibit_defer_pop;
- p->saveregs_value = saveregs_value;
- p->apply_args_value = apply_args_value;
- p->forced_labels = forced_labels;
+ init_queue ();
pending_stack_adjust = 0;
inhibit_defer_pop = 0;
@@ -357,20 +317,6 @@ save_expr_status (p)
apply_args_value = 0;
forced_labels = 0;
}
-
-/* Restore all variables describing the current status from the structure *P.
- This is used after a nested function. */
-
-void
-restore_expr_status (p)
- struct function *p;
-{
- pending_stack_adjust = p->pending_stack_adjust;
- inhibit_defer_pop = p->inhibit_defer_pop;
- saveregs_value = p->saveregs_value;
- apply_args_value = p->apply_args_value;
- forced_labels = p->forced_labels;
-}
/* Manage the queue of increment instructions to be output
for POSTINCREMENT_EXPR expressions, etc. */
@@ -5546,9 +5492,9 @@ expand_expr (exp, target, tmode, modifier)
push_obstacks (p->function_obstack,
p->function_maybepermanent_obstack);
- p->forced_labels = gen_rtx_EXPR_LIST (VOIDmode,
- label_rtx (exp),
- p->forced_labels);
+ p->expr->x_forced_labels = gen_rtx_EXPR_LIST (VOIDmode,
+ label_rtx (exp),
+ p->expr->x_forced_labels);
pop_obstacks ();
}
else if (modifier == EXPAND_INITIALIZER)
@@ -6682,7 +6628,6 @@ expand_expr (exp, target, tmode, modifier)
case CLEANUP_POINT_EXPR:
{
- extern int temp_slot_level;
/* Start a new binding layer that will keep track of all cleanup
actions to be performed. */
expand_start_bindings (0);
diff --git a/gcc/expr.h b/gcc/expr.h
index bf623211043..e992bd52711 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -68,74 +68,8 @@ enum memory_use_mode {MEMORY_USE_BAD = 0, MEMORY_USE_RO = 1,
MEMORY_USE_WO = 2, MEMORY_USE_RW = 3,
MEMORY_USE_TW = 6, MEMORY_USE_DONT = 99};
-/* List of labels that must never be deleted. */
-extern rtx forced_labels;
-
-/* List (chain of EXPR_LISTs) of pseudo-regs of SAVE_EXPRs.
- So we can mark them all live at the end of the function, if stupid. */
-extern rtx save_expr_regs;
-
-extern int current_function_calls_alloca;
-extern int current_function_outgoing_args_size;
-
-/* This is the offset from the arg pointer to the place where the first
- anonymous arg can be found, if there is one. */
-extern rtx current_function_arg_offset_rtx;
-
-/* This is nonzero if the current function uses the constant pool. */
-extern int current_function_uses_const_pool;
-
-/* This is nonzero if the current function uses pic_offset_table_rtx. */
-extern int current_function_uses_pic_offset_table;
-
-/* The arg pointer hard register, or the pseudo into which it was copied. */
-extern rtx current_function_internal_arg_pointer;
-
-/* Nonzero means stack pops must not be deferred, and deferred stack
- pops must not be output. It is nonzero inside a function call,
- inside a conditional expression, inside a statement expression,
- and in other cases as well. */
-extern int inhibit_defer_pop;
-
-/* Number of function calls seen so far in current function. */
-
-extern int function_call_count;
-
-/* RTX for stack slot that holds the current handler for nonlocal gotos.
- Zero when function does not have nonlocal labels. */
-
-extern rtx nonlocal_goto_handler_slot;
-
-/* RTX for stack slot that holds the stack pointer value to restore
- for a nonlocal goto.
- Zero when function does not have nonlocal labels. */
-
-extern rtx nonlocal_goto_stack_level;
-
-/* 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. */
-
-#ifdef TREE_CODE /* Don't lose if tree.h not included. */
-extern tree nonlocal_labels;
-#endif
-
#define NO_DEFER_POP (inhibit_defer_pop += 1)
#define OK_DEFER_POP (inhibit_defer_pop -= 1)
-
-/* Number of units that we should eventually pop off the stack.
- These are the arguments to function calls that have already returned. */
-extern int pending_stack_adjust;
-
-/* When temporaries are created by TARGET_EXPRs, they are created at
- this level of temp_slot_level, so that they can remain allocated
- until no longer needed. CLEANUP_POINT_EXPRs define the lifetime
- of TARGET_EXPRs. */
-extern int target_temp_slot_level;
-
-/* Current level for normal temporaries. */
-
-extern int temp_slot_level;
#ifdef TREE_CODE /* Don't lose if tree.h not included. */
/* Structure to record the size of a sequence of arguments
@@ -710,6 +644,9 @@ extern void init_expr_once PROTO((void));
/* This is run at the start of compiling a function. */
extern void init_expr PROTO((void));
+/* This is run once per compilation to set GC roots in stor-layout.c. */
+extern void init_storage_once PROTO((void));
+
/* Use protect_from_queue to convert a QUEUED expression
into something that you can put immediately into an instruction. */
extern rtx protect_from_queue PROTO((rtx, int));
diff --git a/gcc/final.c b/gcc/final.c
index 04f72cd422c..29c0db5b9db 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -49,6 +49,7 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "rtl.h"
+#include "function.h"
#include "regs.h"
#include "insn-config.h"
#include "insn-flags.h"
diff --git a/gcc/flags.h b/gcc/flags.h
index 3b7dd5ee3b8..c37f5925a44 100644
--- a/gcc/flags.h
+++ b/gcc/flags.h
@@ -470,16 +470,6 @@ extern int frame_pointer_needed;
extern int can_reach_end;
-/* Nonzero if function being compiled receives nonlocal gotos
- from nested functions. */
-
-extern int current_function_has_nonlocal_label;
-
-/* Nonzero if function being compiled has nonlocal gotos to parent
- function. */
-
-extern int current_function_has_nonlocal_goto;
-
/* Nonzero if this function has a computed goto.
It is computed during find_basic_blocks or during stupid life
@@ -495,9 +485,6 @@ extern int flag_check_memory_usage;
flag_check_memory_usage). */
extern int flag_prefix_function_name;
-/* Nonzero if the current function is a thunk, so we should try to cut
- corners where we can. */
-extern int current_function_is_thunk;
/* Value of the -G xx switch, and whether it was passed or not. */
extern int g_switch_value;
diff --git a/gcc/flow.c b/gcc/flow.c
index 3aa26ef0281..bf875bb2708 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -111,6 +111,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "rtl.h"
+#include "function.h"
#include "basic-block.h"
#include "insn-config.h"
#include "regs.h"
@@ -131,9 +132,6 @@ Boston, MA 02111-1307, USA. */
extern struct obstack *function_obstack;
-/* List of labels that must never be deleted. */
-extern rtx forced_labels;
-
/* Get the basic block number of an insn.
This info should not be expected to remain available
after the end of life_analysis. */
diff --git a/gcc/function.c b/gcc/function.c
index 77a533c888b..a0bdd5e73b7 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -56,6 +56,7 @@ Boston, MA 02111-1307, USA. */
#include "basic-block.h"
#include "obstack.h"
#include "toplev.h"
+#include "ggc.h"
#ifndef TRAMPOLINE_ALIGNMENT
#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
@@ -89,43 +90,11 @@ Boston, MA 02111-1307, USA. */
#define NEED_SEPARATE_AP
#endif
-/* Number of bytes of args popped by function being compiled on its return.
- Zero if no bytes are to be popped.
- May affect compilation of return insn or of function epilogue. */
+/* The function structure for the currently being compiled function. */
+struct function *current_function;
-int current_function_pops_args;
-
-/* Nonzero if function being compiled needs to be given an address
- where the value should be stored. */
-
-int current_function_returns_struct;
-
-/* Nonzero if function being compiled needs to
- return the address of where it has put a structure value. */
-
-int current_function_returns_pcc_struct;
-
-/* Nonzero if function being compiled needs to be passed a static chain. */
-
-int current_function_needs_context;
-
-/* Nonzero if function being compiled can call setjmp. */
-
-int current_function_calls_setjmp;
-
-/* Nonzero if function being compiled can call longjmp. */
-
-int current_function_calls_longjmp;
-
-/* Nonzero if function being compiled receives nonlocal gotos
- from nested functions. */
-
-int current_function_has_nonlocal_label;
-
-/* Nonzero if function being compiled has nonlocal gotos to parent
- function. */
-
-int current_function_has_nonlocal_goto;
+/* Current function status. */
+struct function_status *cur_f_s;
/* Nonzero if this function has a computed goto.
@@ -134,195 +103,9 @@ int current_function_has_nonlocal_goto;
int current_function_has_computed_jump;
-/* Nonzero if function being compiled contains nested functions. */
-
-int current_function_contains_functions;
-
-/* Nonzero if the current function is a thunk (a lightweight function that
- just adjusts one of its arguments and forwards to another function), so
- we should try to cut corners where we can. */
-int current_function_is_thunk;
-
-/* Nonzero if function being compiled can call alloca,
- either as a subroutine or builtin. */
-
-int current_function_calls_alloca;
-
-/* Nonzero if the current function returns a pointer type */
-
-int current_function_returns_pointer;
-
-/* If some insns can be deferred to the delay slots of the epilogue, the
- delay list for them is recorded here. */
-
-rtx current_function_epilogue_delay_list;
-
-/* If function's args have a fixed size, this is that size, in bytes.
- Otherwise, it is -1.
- May affect compilation of return insn or of function epilogue. */
-
-int current_function_args_size;
-
-/* # bytes the prologue should push and pretend that the caller pushed them.
- The prologue must do this, but only if parms can be passed in registers. */
-
-int current_function_pretend_args_size;
-
-/* # of bytes of outgoing arguments. If ACCUMULATE_OUTGOING_ARGS is
- defined, the needed space is pushed by the prologue. */
-
-int current_function_outgoing_args_size;
-
-/* This is the offset from the arg pointer to the place where the first
- anonymous arg can be found, if there is one. */
-
-rtx current_function_arg_offset_rtx;
-
-/* Nonzero if current function uses varargs.h or equivalent.
- Zero for functions that use stdarg.h. */
-
-int current_function_varargs;
-
-/* Nonzero if current function uses stdarg.h or equivalent.
- Zero for functions that use varargs.h. */
-
-int current_function_stdarg;
-
-/* Quantities of various kinds of registers
- used for the current function's args. */
-
-CUMULATIVE_ARGS current_function_args_info;
-
-/* Name of function now being compiled. */
-
-char *current_function_name;
-
-/* If non-zero, an RTL expression for the location at which the current
- function returns its result. If the current function returns its
- result in a register, current_function_return_rtx will always be
- the hard register containing the result. */
-
-rtx current_function_return_rtx;
-
-/* Nonzero if the current function uses the constant pool. */
-
-int current_function_uses_const_pool;
-
-/* Nonzero if the current function uses pic_offset_table_rtx. */
-int current_function_uses_pic_offset_table;
-
-/* The arg pointer hard register, or the pseudo into which it was copied. */
-rtx current_function_internal_arg_pointer;
-
-/* Language-specific reason why the current function cannot be made inline. */
-char *current_function_cannot_inline;
-
-/* Nonzero if instrumentation calls for function entry and exit should be
- generated. */
-int current_function_instrument_entry_exit;
-
/* The FUNCTION_DECL for an inline function currently being expanded. */
tree inline_function_decl;
-/* Number of function calls seen so far in current function. */
-
-int function_call_count;
-
-/* 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. */
-
-tree nonlocal_labels;
-
-/* RTX for stack slot that holds the current handler for nonlocal gotos.
- Zero when function does not have nonlocal labels. */
-
-rtx nonlocal_goto_handler_slot;
-
-/* RTX for stack slot that holds the stack pointer value to restore
- for a nonlocal goto.
- Zero when function does not have nonlocal labels. */
-
-rtx nonlocal_goto_stack_level;
-
-/* Label that will go on parm cleanup code, if any.
- Jumping to this label runs cleanup code for parameters, if
- such code must be run. Following this code is the logical return label. */
-
-rtx cleanup_label;
-
-/* Label that will go on function epilogue.
- Jumping to this label serves as a "return" instruction
- on machines which require execution of the epilogue on all returns. */
-
-rtx return_label;
-
-/* List (chain of EXPR_LISTs) of pseudo-regs of SAVE_EXPRs.
- So we can mark them all live at the end of the function, if nonopt. */
-rtx save_expr_regs;
-
-/* List (chain of EXPR_LISTs) of all stack slots in this function.
- Made for the sake of unshare_all_rtl. */
-rtx stack_slot_list;
-
-/* Chain of all RTL_EXPRs that have insns in them. */
-tree rtl_expr_chain;
-
-/* Label to jump back to for tail recursion, or 0 if we have
- not yet needed one for this function. */
-rtx tail_recursion_label;
-
-/* Place after which to insert the tail_recursion_label if we need one. */
-rtx tail_recursion_reentry;
-
-/* Location at which to save the argument pointer if it will need to be
- referenced. There are two cases where this is done: if nonlocal gotos
- exist, or if vars stored at an offset from the argument pointer will be
- needed by inner routines. */
-
-rtx arg_pointer_save_area;
-
-/* Offset to end of allocated area of stack frame.
- If stack grows down, this is the address of the last stack slot allocated.
- If stack grows up, this is the address for the next slot. */
-HOST_WIDE_INT frame_offset;
-
-/* List (chain of TREE_LISTs) of static chains for containing functions.
- Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx
- in an RTL_EXPR in the TREE_VALUE. */
-static tree context_display;
-
-/* List (chain of TREE_LISTs) of trampolines for nested functions.
- The trampoline sets up the static chain and jumps to the function.
- We supply the trampoline's address when the function's address is requested.
-
- Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx
- in an RTL_EXPR in the TREE_VALUE. */
-static tree trampoline_list;
-
-/* Insn after which register parms and SAVE_EXPRs are born, if nonopt. */
-static rtx parm_birth_insn;
-
-#if 0
-/* Nonzero if a stack slot has been generated whose address is not
- actually valid. It means that the generated rtl must all be scanned
- to detect and correct the invalid addresses where they occur. */
-static int invalid_stack_slot;
-#endif
-
-/* Last insn of those whose job was to put parms into their nominal homes. */
-static rtx last_parm_insn;
-
-/* 1 + last pseudo register number possibly used for loading a copy
- of a parameter of this function. */
-int max_parm_reg;
-
-/* Vector indexed by REGNO, containing location on stack in which
- to put the parm which is nominally in pseudo register REGNO,
- if we discover that that parm must go in the stack. The highest
- element in this vector is one less than MAX_PARM_REG, above. */
-rtx *parm_reg_stack_loc;
-
/* Nonzero once virtual register instantiation has been done.
assign_stack_local uses frame_pointer_rtx when this is nonzero. */
static int virtuals_instantiated;
@@ -330,7 +113,7 @@ static int virtuals_instantiated;
/* These variables hold pointers to functions to save and restore
machine-specific data, in push_function_context and pop_function_context.
We also need to mark machine-specific data we may have tucked away. */
-void (*save_machine_status) PROTO((struct function *));
+void (*init_machine_status) PROTO((struct function *));
void (*restore_machine_status) PROTO((struct function *));
void (*mark_machine_status) PROTO((struct function *));
@@ -344,7 +127,6 @@ void (*mark_lang_status) PROTO((struct function *));
integrate.c */
extern int rtx_equal_function_value_matters;
-extern tree sequence_rtl_expr;
/* In order to evaluate some expressions, such as function calls returning
structures in memory, we need to temporarily allocate stack locations.
@@ -375,7 +157,7 @@ struct temp_slot
rtx address;
/* The size, in units, of the slot. */
HOST_WIDE_INT size;
- /* The value of `sequence_rtl_expr' when this temporary is allocated. */
+ /* The value of `seq_rtl_expr' when this temporary is allocated. */
tree rtl_expr;
/* Non-zero if this temporary is currently in use. */
char in_use;
@@ -392,24 +174,6 @@ struct temp_slot
info is for combine_temp_slots. */
HOST_WIDE_INT full_size;
};
-
-/* List of all temporaries allocated, both available and in use. */
-
-struct temp_slot *temp_slots;
-
-/* Current nesting level for temporaries. */
-
-int temp_slot_level;
-
-/* Current nesting level for variables in a block. */
-
-int var_temp_slot_level;
-
-/* When temporaries are created by TARGET_EXPRs, they are created at
- this level of temp_slot_level, so that they can remain allocated
- until no longer needed. CLEANUP_POINT_EXPRs define the lifetime
- of TARGET_EXPRs. */
-int target_temp_slot_level;
/* This structure is used to record MEMs or pseudos used to replace VAR, any
SUBREGs of VAR, and any MEMs containing VAR as an address. We need to
@@ -422,11 +186,19 @@ struct fixup_replacement
rtx new;
struct fixup_replacement *next;
};
-
+
+struct var_refs_queue
+{
+ rtx modified;
+ enum machine_mode promoted_mode;
+ int unsignedp;
+ struct var_refs_queue *next;
+};
+
/* Forward declarations. */
static rtx assign_outer_stack_local PROTO ((enum machine_mode, HOST_WIDE_INT,
- int, struct function *));
+ int, struct function_status *));
static struct temp_slot *find_temp_slot_from_address PROTO((rtx));
static void put_reg_into_stack PROTO((struct function *, rtx, tree,
enum machine_mode, enum machine_mode,
@@ -465,6 +237,9 @@ static int contains PROTO((rtx, int *));
static void put_addressof_into_stack PROTO((rtx));
static void purge_addressof_1 PROTO((rtx *, rtx, int, int));
+/* Global list of all compiled functions. */
+struct function *all_functions = 0;
+
/* Pointer to chain of `struct function' for containing functions. */
struct function *outer_function_chain;
@@ -493,74 +268,15 @@ void
push_function_context_to (context)
tree context;
{
- struct function *p = (struct function *) xmalloc (sizeof (struct function));
-
- p->next = outer_function_chain;
- outer_function_chain = p;
-
- p->name = current_function_name;
- p->decl = current_function_decl;
- p->pops_args = current_function_pops_args;
- p->returns_struct = current_function_returns_struct;
- p->returns_pcc_struct = current_function_returns_pcc_struct;
- p->returns_pointer = current_function_returns_pointer;
- p->needs_context = current_function_needs_context;
- p->calls_setjmp = current_function_calls_setjmp;
- p->calls_longjmp = current_function_calls_longjmp;
- p->calls_alloca = current_function_calls_alloca;
- p->has_nonlocal_label = current_function_has_nonlocal_label;
- p->has_nonlocal_goto = current_function_has_nonlocal_goto;
- p->contains_functions = current_function_contains_functions;
- p->is_thunk = current_function_is_thunk;
- p->args_size = current_function_args_size;
- p->pretend_args_size = current_function_pretend_args_size;
- p->arg_offset_rtx = current_function_arg_offset_rtx;
- p->varargs = current_function_varargs;
- p->stdarg = current_function_stdarg;
- p->uses_const_pool = current_function_uses_const_pool;
- p->uses_pic_offset_table = current_function_uses_pic_offset_table;
- p->internal_arg_pointer = current_function_internal_arg_pointer;
- p->cannot_inline = current_function_cannot_inline;
- p->max_parm_reg = max_parm_reg;
- p->parm_reg_stack_loc = parm_reg_stack_loc;
- p->outgoing_args_size = current_function_outgoing_args_size;
- p->return_rtx = current_function_return_rtx;
- p->nonlocal_goto_handler_slot = nonlocal_goto_handler_slot;
- p->nonlocal_goto_stack_level = nonlocal_goto_stack_level;
- p->nonlocal_labels = nonlocal_labels;
- p->cleanup_label = cleanup_label;
- p->return_label = return_label;
- p->save_expr_regs = save_expr_regs;
- p->stack_slot_list = stack_slot_list;
- p->parm_birth_insn = parm_birth_insn;
- p->frame_offset = frame_offset;
- p->tail_recursion_label = tail_recursion_label;
- p->tail_recursion_reentry = tail_recursion_reentry;
- p->arg_pointer_save_area = arg_pointer_save_area;
- p->rtl_expr_chain = rtl_expr_chain;
- p->last_parm_insn = last_parm_insn;
- p->context_display = context_display;
- p->trampoline_list = trampoline_list;
- p->function_call_count = function_call_count;
- p->temp_slots = temp_slots;
- p->temp_slot_level = temp_slot_level;
- p->target_temp_slot_level = target_temp_slot_level;
- p->var_temp_slot_level = var_temp_slot_level;
- p->fixup_var_refs_queue = 0;
- p->epilogue_delay_list = current_function_epilogue_delay_list;
- p->args_info = current_function_args_info;
- p->instrument_entry_exit = current_function_instrument_entry_exit;
-
- save_tree_status (p, context);
- save_storage_status (p);
- save_emit_status (p);
- save_expr_status (p);
- save_stmt_status (p);
- save_varasm_status (p, context);
- if (save_machine_status)
- (*save_machine_status) (p);
+ struct function *f = current_function;
+
+ f->next = outer_function_chain;
+ outer_function_chain = f;
+
+ save_tree_status (f, context);
+ save_varasm_status (f, context);
if (save_lang_status)
- (*save_lang_status) (p);
+ (*save_lang_status) (f);
}
void
@@ -576,111 +292,89 @@ void
pop_function_context_from (context)
tree context;
{
- struct function *p = outer_function_chain;
- struct var_refs_queue *queue;
-
- outer_function_chain = p->next;
-
- current_function_contains_functions
- = p->contains_functions || p->inline_obstacks
- || context == current_function_decl;
- current_function_name = p->name;
- current_function_decl = p->decl;
- current_function_pops_args = p->pops_args;
- current_function_returns_struct = p->returns_struct;
- current_function_returns_pcc_struct = p->returns_pcc_struct;
- current_function_returns_pointer = p->returns_pointer;
- current_function_needs_context = p->needs_context;
- current_function_calls_setjmp = p->calls_setjmp;
- current_function_calls_longjmp = p->calls_longjmp;
- current_function_calls_alloca = p->calls_alloca;
- current_function_has_nonlocal_label = p->has_nonlocal_label;
- current_function_has_nonlocal_goto = p->has_nonlocal_goto;
- current_function_is_thunk = p->is_thunk;
- current_function_args_size = p->args_size;
- current_function_pretend_args_size = p->pretend_args_size;
- current_function_arg_offset_rtx = p->arg_offset_rtx;
- current_function_varargs = p->varargs;
- current_function_stdarg = p->stdarg;
- current_function_uses_const_pool = p->uses_const_pool;
- current_function_uses_pic_offset_table = p->uses_pic_offset_table;
- current_function_internal_arg_pointer = p->internal_arg_pointer;
- current_function_cannot_inline = p->cannot_inline;
- max_parm_reg = p->max_parm_reg;
- parm_reg_stack_loc = p->parm_reg_stack_loc;
- current_function_outgoing_args_size = p->outgoing_args_size;
- current_function_return_rtx = p->return_rtx;
- nonlocal_goto_handler_slot = p->nonlocal_goto_handler_slot;
- nonlocal_goto_stack_level = p->nonlocal_goto_stack_level;
- nonlocal_labels = p->nonlocal_labels;
- cleanup_label = p->cleanup_label;
- return_label = p->return_label;
- save_expr_regs = p->save_expr_regs;
- stack_slot_list = p->stack_slot_list;
- parm_birth_insn = p->parm_birth_insn;
- frame_offset = p->frame_offset;
- tail_recursion_label = p->tail_recursion_label;
- tail_recursion_reentry = p->tail_recursion_reentry;
- arg_pointer_save_area = p->arg_pointer_save_area;
- rtl_expr_chain = p->rtl_expr_chain;
- last_parm_insn = p->last_parm_insn;
- context_display = p->context_display;
- trampoline_list = p->trampoline_list;
- function_call_count = p->function_call_count;
- temp_slots = p->temp_slots;
- temp_slot_level = p->temp_slot_level;
- target_temp_slot_level = p->target_temp_slot_level;
- var_temp_slot_level = p->var_temp_slot_level;
- current_function_epilogue_delay_list = p->epilogue_delay_list;
- reg_renumber = 0;
- current_function_args_info = p->args_info;
- current_function_instrument_entry_exit = p->instrument_entry_exit;
+ /* @@@ This used to test inline_obstacks, which is no longer meaningful. */
+ int was_nested = context == current_function_decl;
+ struct function *f = outer_function_chain;
+ struct var_refs_queue *queue, *next;
+
+ outer_function_chain = f->next;
- restore_tree_status (p, context);
- restore_storage_status (p);
- restore_expr_status (p);
- restore_emit_status (p);
- restore_stmt_status (p);
- restore_varasm_status (p);
+ cur_f_s = f->func;
+
+ restore_tree_status (f, context);
+ restore_emit_status (f);
+ restore_varasm_status (f);
if (restore_machine_status)
- (*restore_machine_status) (p);
+ (*restore_machine_status) (f);
if (restore_lang_status)
- (*restore_lang_status) (p);
+ (*restore_lang_status) (f);
+
+ current_function = f;
+ current_function_decl = f->decl;
+
+ reg_renumber = 0;
+ current_function_contains_functions |= was_nested;
/* Finish doing put_var_into_stack for any of our variables
which became addressable during the nested function. */
- for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
- fixup_var_refs (queue->modified, queue->promoted_mode, queue->unsignedp);
-
- free (p);
+ for (queue = f->func->saved_fixup_var_refs_queue; queue; queue = next)
+ {
+ next = queue->next;
+ fixup_var_refs (queue->modified, queue->promoted_mode, queue->unsignedp);
+ free (queue);
+ }
+ f->func->saved_fixup_var_refs_queue = 0;
/* Reset variables that have known state during rtx generation. */
rtx_equal_function_value_matters = 1;
virtuals_instantiated = 0;
}
-void pop_function_context ()
+void
+pop_function_context ()
{
pop_function_context_from (current_function_decl);
}
+
+/* Clear out all parts of the state in F that can safely be discarded
+ after the function has been compiled, to let garbage collection
+ reclaim the memory. */
+void
+free_after_compilation (f)
+ struct function *f;
+{
+ free_emit_status (f);
+ free_varasm_status (f);
+
+ f->can_garbage_collect = 1;
+}
/* Allocate fixed slots in the stack frame of the current function. */
-/* Return size needed for stack frame based on slots so far allocated.
- This size counts from zero. It is not rounded to STACK_BOUNDARY;
- the caller may have to do that. */
+/* Return size needed for stack frame based on slots so far allocated in
+ function F. This size counts from zero. It is not rounded to
+ STACK_BOUNDARY; the caller may have to do that. */
HOST_WIDE_INT
-get_frame_size ()
+get_func_frame_size (f)
+ struct function *f;
{
#ifdef FRAME_GROWS_DOWNWARD
- return -frame_offset;
+ return -f->func->saved_frame_offset;
#else
- return frame_offset;
+ return f->func->saved_frame_offset;
#endif
}
+/* For backward compatibiliy, an abbreviation of get_func_frame_size. */
+HOST_WIDE_INT
+get_frame_size ()
+{
+ return get_func_frame_size (current_function);
+}
+
+
/* Allocate a stack slot of SIZE bytes and return a MEM rtx for it
with machine mode MODE.
@@ -761,21 +455,16 @@ assign_stack_local (mode, size, align)
The last argument specifies the function to allocate in. */
static rtx
-assign_outer_stack_local (mode, size, align, function)
+assign_outer_stack_local (mode, size, align, f)
enum machine_mode mode;
HOST_WIDE_INT size;
int align;
- struct function *function;
+ struct function_status *f;
{
register rtx x, addr;
int bigend_correction = 0;
int alignment;
- /* Allocate in the memory associated with the function in whose frame
- we are assigning. */
- push_obstacks (function->function_obstack,
- function->function_maybepermanent_obstack);
-
if (align == 0)
{
alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
@@ -792,9 +481,9 @@ assign_outer_stack_local (mode, size, align, function)
/* Round frame offset to that alignment. */
#ifdef FRAME_GROWS_DOWNWARD
- function->frame_offset = FLOOR_ROUND (function->frame_offset, alignment);
+ f->saved_frame_offset = FLOOR_ROUND (f->saved_frame_offset, alignment);
#else
- function->frame_offset = CEIL_ROUND (function->frame_offset, alignment);
+ f->saved_frame_offset = CEIL_ROUND (f->saved_frame_offset, alignment);
#endif
/* On a big-endian machine, if we are allocating more space than we will use,
@@ -803,20 +492,18 @@ assign_outer_stack_local (mode, size, align, function)
bigend_correction = size - GET_MODE_SIZE (mode);
#ifdef FRAME_GROWS_DOWNWARD
- function->frame_offset -= size;
+ f->saved_frame_offset -= size;
#endif
addr = plus_constant (virtual_stack_vars_rtx,
- function->frame_offset + bigend_correction);
+ f->saved_frame_offset + bigend_correction);
#ifndef FRAME_GROWS_DOWNWARD
- function->frame_offset += size;
+ f->saved_frame_offset += size;
#endif
x = gen_rtx_MEM (mode, addr);
- function->stack_slot_list
- = gen_rtx_EXPR_LIST (VOIDmode, x, function->stack_slot_list);
-
- pop_obstacks ();
+ f->saved_stack_slot_list = gen_rtx_EXPR_LIST (VOIDmode, x,
+ f->saved_stack_slot_list);
return x;
}
@@ -939,7 +626,7 @@ assign_stack_temp (mode, size, keep)
p->in_use = 1;
p->addr_taken = 0;
- p->rtl_expr = sequence_rtl_expr;
+ p->rtl_expr = seq_rtl_expr;
if (keep == 2)
{
@@ -1529,11 +1216,11 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
if (function)
{
- if (regno < function->max_parm_reg)
- new = function->parm_reg_stack_loc[regno];
+ if (regno < function->func->saved_max_parm_reg)
+ new = function->func->saved_parm_reg_stack_loc[regno];
if (new == 0)
new = assign_outer_stack_local (decl_mode, GET_MODE_SIZE (decl_mode),
- 0, function);
+ 0, function->func);
}
else
{
@@ -1564,20 +1251,12 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
{
struct var_refs_queue *temp;
- /* Variable is inherited; fix it up when we get back to its function. */
- push_obstacks (function->function_obstack,
- function->function_maybepermanent_obstack);
-
- /* See comment in restore_tree_status in tree.c for why this needs to be
- on saveable obstack. */
- temp
- = (struct var_refs_queue *) savealloc (sizeof (struct var_refs_queue));
+ temp = (struct var_refs_queue *) xmalloc (sizeof (struct var_refs_queue));
temp->modified = reg;
temp->promoted_mode = promoted_mode;
temp->unsignedp = TREE_UNSIGNED (type);
- temp->next = function->fixup_var_refs_queue;
- function->fixup_var_refs_queue = temp;
- pop_obstacks ();
+ temp->next = function->func->saved_fixup_var_refs_queue;
+ function->func->saved_fixup_var_refs_queue = temp;
}
else if (used_p)
/* Variable is local; fix it up now. */
@@ -1591,12 +1270,12 @@ fixup_var_refs (var, promoted_mode, unsignedp)
int unsignedp;
{
tree pending;
- rtx first_insn = get_insns ();
- struct sequence_stack *stack = sequence_stack;
+ rtx first = get_insns ();
+ struct sequence_stack *stack = seq_stack;
tree rtl_exps = rtl_expr_chain;
/* Must scan all insns for stack-refs that exceed the limit. */
- fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn, stack == 0);
+ fixup_var_refs_insns (var, promoted_mode, unsignedp, first, stack == 0);
/* Scan all pending sequences too. */
for (; stack; stack = stack->next)
@@ -3587,11 +3266,11 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
/* Optimization: assuming this function does not receive nonlocal gotos,
delete the handlers for such, as well as the insns to establish
and disestablish them. */
-
static void
delete_handlers ()
{
rtx insn;
+
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
/* Delete the handler by turning off the flag that would
@@ -3849,8 +3528,7 @@ assign_parms (fndecl, second_time)
}
max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
- parm_reg_stack_loc = (rtx *) savealloc (max_parm_reg * sizeof (rtx));
- bzero ((char *) parm_reg_stack_loc, max_parm_reg * sizeof (rtx));
+ parm_reg_stack_loc = (rtx *) xcalloc (max_parm_reg, sizeof (rtx));
#ifdef INIT_CUMULATIVE_INCOMING_ARGS
INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_RTX);
@@ -4417,9 +4095,8 @@ assign_parms (fndecl, second_time)
but it's also rare and we need max_parm_reg to be
precisely correct. */
max_parm_reg = regno + 1;
- new = (rtx *) savealloc (max_parm_reg * sizeof (rtx));
- bcopy ((char *) parm_reg_stack_loc, (char *) new,
- old_max_parm_reg * sizeof (rtx));
+ new = (rtx *) xrealloc (parm_reg_stack_loc,
+ max_parm_reg * sizeof (rtx));
bzero ((char *) (new + old_max_parm_reg),
(max_parm_reg - old_max_parm_reg) * sizeof (rtx));
parm_reg_stack_loc = new;
@@ -5039,6 +4716,7 @@ fix_lexical_addr (addr, var)
HOST_WIDE_INT displacement;
tree context = decl_function_context (var);
struct function *fp;
+ struct function_status *fps;
rtx base = 0;
/* If this is the present function, we need not do anything. */
@@ -5051,6 +4729,7 @@ fix_lexical_addr (addr, var)
if (fp == 0)
abort ();
+ fps = fp->func;
if (GET_CODE (addr) == ADDRESSOF && GET_CODE (XEXP (addr, 0)) == MEM)
addr = XEXP (XEXP (addr, 0), 0);
@@ -5065,7 +4744,7 @@ fix_lexical_addr (addr, var)
/* We accept vars reached via the containing function's
incoming arg pointer and via its stack variables pointer. */
- if (basereg == fp->internal_arg_pointer)
+ if (basereg == fps->internal_arg_pointer)
{
/* If reached via arg pointer, get the arg pointer value
out of that function's stack frame.
@@ -5079,11 +4758,11 @@ fix_lexical_addr (addr, var)
#ifdef NEED_SEPARATE_AP
rtx addr;
- if (fp->arg_pointer_save_area == 0)
- fp->arg_pointer_save_area
- = assign_outer_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0, fp);
+ if (fps->saved_arg_pointer_save_area == 0)
+ fps->saved_arg_pointer_save_area
+ = assign_outer_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0, fps);
- addr = fix_lexical_addr (XEXP (fp->arg_pointer_save_area, 0), var);
+ addr = fix_lexical_addr (XEXP (fps->saved_arg_pointer_save_area, 0), var);
addr = memory_address (Pmode, addr);
base = copy_to_reg (gen_rtx_MEM (Pmode, addr));
@@ -5136,7 +4815,7 @@ trampoline_address (function)
round_trampoline_addr (XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0));
for (fp = outer_function_chain; fp; fp = fp->next)
- for (link = fp->trampoline_list; link; link = TREE_CHAIN (link))
+ for (link = fp->func->saved_trampoline_list; link; link = TREE_CHAIN (link))
if (TREE_PURPOSE (link) == function)
{
tramp = fix_lexical_addr (XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0),
@@ -5169,33 +4848,20 @@ trampoline_address (function)
#define TRAMPOLINE_REAL_SIZE (TRAMPOLINE_SIZE)
#endif
if (fp != 0)
- tramp = assign_outer_stack_local (BLKmode, TRAMPOLINE_REAL_SIZE, 0, fp);
+ tramp = assign_outer_stack_local (BLKmode, TRAMPOLINE_REAL_SIZE, 0, fp->func);
else
tramp = assign_stack_local (BLKmode, TRAMPOLINE_REAL_SIZE, 0);
#endif
/* Record the trampoline for reuse and note it for later initialization
by expand_function_end. */
+ rtlexp = make_node (RTL_EXPR);
+ RTL_EXPR_RTL (rtlexp) = tramp;
if (fp != 0)
- {
- push_obstacks (fp->function_maybepermanent_obstack,
- fp->function_maybepermanent_obstack);
- rtlexp = make_node (RTL_EXPR);
- RTL_EXPR_RTL (rtlexp) = tramp;
- fp->trampoline_list = tree_cons (function, rtlexp, fp->trampoline_list);
- pop_obstacks ();
- }
+ fp->func->saved_trampoline_list = tree_cons (function, rtlexp,
+ fp->func->saved_trampoline_list);
else
- {
- /* Make the RTL_EXPR node temporary, not momentary, so that the
- trampoline_list doesn't become garbage. */
- int momentary = suspend_momentary ();
- rtlexp = make_node (RTL_EXPR);
- resume_momentary (momentary);
-
- RTL_EXPR_RTL (rtlexp) = tramp;
- trampoline_list = tree_cons (function, rtlexp, trampoline_list);
- }
+ trampoline_list = tree_cons (function, rtlexp, trampoline_list);
tramp = fix_lexical_addr (XEXP (tramp, 0), function);
return round_trampoline_addr (tramp);
@@ -5377,16 +5043,16 @@ all_blocks (block, vector)
return n_blocks;
}
-/* Generate RTL for the start of the function SUBR (a FUNCTION_DECL tree node)
- and initialize static variables for generating RTL for the statements
- of the function. */
-
-void
-init_function_start (subr, filename, line)
- tree subr;
- char *filename;
- int line;
+/* Allocate a function structure and reset its contents to the defaults. */
+static void
+prepare_function_start ()
{
+ current_function = (struct function *) xcalloc (1, sizeof (struct function));
+
+ cur_f_s = (struct function_status *) xcalloc (1, sizeof (struct function_status));
+
+ current_function->func = cur_f_s;
+
init_stmt_for_function ();
cse_not_expected = ! optimize;
@@ -5397,6 +5063,9 @@ init_function_start (subr, filename, line)
/* No stack slots have been made yet. */
stack_slot_list = 0;
+ current_function_has_nonlocal_label = 0;
+ current_function_has_nonlocal_goto = 0;
+
/* There is no stack slot for handling nonlocal gotos. */
nonlocal_goto_handler_slot = 0;
nonlocal_goto_stack_level = 0;
@@ -5418,18 +5087,18 @@ init_function_start (subr, filename, line)
and some other info in expr.c. */
init_expr ();
+ if (init_machine_status)
+ (*init_machine_status) (current_function);
+
/* We haven't done register allocation yet. */
reg_renumber = 0;
init_const_rtx_hash_table ();
- current_function_name = (*decl_printable_name) (subr, 2);
-
- /* Nonzero if this is a nested function that uses a static chain. */
-
- current_function_needs_context
- = (decl_function_context (current_function_decl) != 0
- && ! DECL_NO_STATIC_CHAIN (current_function_decl));
+ /* Clear out data used for inlining. */
+ current_function->inlinable = 0;
+ current_function->original_decl_initial = 0;
+ current_function->original_arg_vector = 0;
/* Set if a call to setjmp is seen. */
current_function_calls_setjmp = 0;
@@ -5438,8 +5107,6 @@ init_function_start (subr, filename, line)
current_function_calls_longjmp = 0;
current_function_calls_alloca = 0;
- current_function_has_nonlocal_label = 0;
- current_function_has_nonlocal_goto = 0;
current_function_contains_functions = 0;
current_function_is_thunk = 0;
@@ -5450,11 +5117,12 @@ init_function_start (subr, filename, line)
current_function_uses_pic_offset_table = 0;
current_function_cannot_inline = 0;
+ fixup_var_refs_queue = 0;
+
/* We have not yet needed to make a label to jump to for tail-recursion. */
tail_recursion_label = 0;
/* We haven't had a need to make a save area for ap yet. */
-
arg_pointer_save_area = 0;
/* No stack slots allocated yet. */
@@ -5469,8 +5137,19 @@ init_function_start (subr, filename, line)
/* Set up to allocate temporaries. */
init_temp_slots ();
- /* Within function body, compute a type's size as soon it is laid out. */
- immediate_size_expand++;
+ /* Indicate that we need to distinguish between the return value of the
+ present function and the return value of a function being called. */
+ rtx_equal_function_value_matters = 1;
+
+ /* Indicate that we have not instantiated virtual registers yet. */
+ virtuals_instantiated = 0;
+
+ /* Indicate we have no need of a frame pointer yet. */
+ frame_pointer_needed = 0;
+
+ /* By default assume not varargs or stdarg. */
+ current_function_varargs = 0;
+ current_function_stdarg = 0;
/* We haven't made any trampolines for this function yet. */
trampoline_list = 0;
@@ -5479,6 +5158,45 @@ init_function_start (subr, filename, line)
inhibit_defer_pop = 0;
current_function_outgoing_args_size = 0;
+}
+
+/* Initialize the rtl expansion mechanism so that we can do simple things
+ like generate sequences. This is used to provide a context during global
+ initialization of some passes. */
+void
+init_dummy_function_start ()
+{
+ prepare_function_start ();
+}
+
+/* Generate RTL for the start of the function SUBR (a FUNCTION_DECL tree node)
+ and initialize static variables for generating RTL for the statements
+ of the function. */
+
+void
+init_function_start (subr, filename, line)
+ tree subr;
+ char *filename;
+ int line;
+{
+ prepare_function_start ();
+
+ /* Remember this function for later. */
+ current_function->next_global = all_functions;
+ all_functions = current_function;
+ current_function->can_garbage_collect = 0;
+
+ current_function->decl = current_function_decl;
+ current_function_name = (*decl_printable_name) (subr, 2);
+
+ /* Nonzero if this is a nested function that uses a static chain. */
+
+ current_function_needs_context
+ = (decl_function_context (current_function_decl) != 0
+ && ! DECL_NO_STATIC_CHAIN (current_function_decl));
+
+ /* Within function body, compute a type's size as soon it is laid out. */
+ immediate_size_expand++;
/* Prevent ever trying to delete the first instruction of a function.
Also tell final how to output a linenum before the function prologue.
@@ -5508,20 +5226,6 @@ init_function_start (subr, filename, line)
current_function_returns_pointer
= POINTER_TYPE_P (TREE_TYPE (DECL_RESULT (subr)));
-
- /* Indicate that we need to distinguish between the return value of the
- present function and the return value of a function being called. */
- rtx_equal_function_value_matters = 1;
-
- /* Indicate that we have not instantiated virtual registers yet. */
- virtuals_instantiated = 0;
-
- /* Indicate we have no need of a frame pointer yet. */
- frame_pointer_needed = 0;
-
- /* By default assume not varargs or stdarg. */
- current_function_varargs = 0;
- current_function_stdarg = 0;
}
/* Indicate that the current function uses extra args
@@ -5801,6 +5505,18 @@ expand_function_start (subr, parms_have_cleanups)
force_next_line_note ();
}
+/* Undo the effects of init_dummy_function_start. */
+void
+expand_dummy_function_end ()
+{
+ /* End any sequences that failed to be closed due to syntax errors. */
+ while (in_sequence_p ())
+ end_sequence ();
+
+ /* Outside function body, can't compute type's actual size
+ until next function's body starts. */
+ current_function = 0;
+}
/* Generate RTL for the end of the current function.
FILENAME and LINE are the current position in the source file.
@@ -6412,95 +6128,94 @@ mark_parm_reg_stack_loc (dummy)
}
void
-mark_function_chain (arg)
+mark_function_state (arg)
void *arg;
{
- struct function *f = *(struct function **) arg;
+ struct function_status *p = *(struct function_status **) arg;
+ int i;
+ rtx *r;
- while (f)
- {
- rtx *r;
- int i;
+ if (p == 0)
+ return;
- ggc_mark_tree (f->decl);
- ggc_mark_rtx (f->nonlocal_goto_handler_slot);
- ggc_mark_rtx (f->nonlocal_goto_stack_level);
- ggc_mark_tree (f->nonlocal_labels);
- ggc_mark_rtx (f->arg_offset_rtx);
+ ggc_mark_rtx (p->arg_offset_rtx);
- for (i = f->max_parm_reg, r = f->parm_reg_stack_loc; i > 0; --i, ++r)
- ggc_mark_rtx (*r);
-
- ggc_mark_rtx (f->return_rtx);
- ggc_mark_rtx (f->cleanup_label);
- ggc_mark_rtx (f->return_label);
- ggc_mark_rtx (f->save_expr_regs);
- ggc_mark_rtx (f->stack_slot_list);
- ggc_mark_rtx (f->parm_birth_insn);
- ggc_mark_rtx (f->tail_recursion_label);
- ggc_mark_rtx (f->tail_recursion_reentry);
- ggc_mark_rtx (f->internal_arg_pointer);
- ggc_mark_rtx (f->arg_pointer_save_area);
- ggc_mark_tree (f->rtl_expr_chain);
- ggc_mark_rtx (f->last_parm_insn);
- ggc_mark_tree (f->context_display);
- ggc_mark_tree (f->trampoline_list);
-
- mark_temp_slot (&f->temp_slots);
+ for (i = p->saved_max_parm_reg, r = p->saved_parm_reg_stack_loc;
+ i > 0; --i, ++r)
+ ggc_mark_rtx (*r);
+
+ ggc_mark_rtx (p->return_rtx);
+ ggc_mark_rtx (p->saved_cleanup_label);
+ ggc_mark_rtx (p->saved_return_label);
+ ggc_mark_rtx (p->saved_save_expr_regs);
+ ggc_mark_rtx (p->saved_stack_slot_list);
+ ggc_mark_rtx (p->saved_parm_birth_insn);
+ ggc_mark_rtx (p->saved_tail_recursion_label);
+ ggc_mark_rtx (p->saved_tail_recursion_reentry);
+ ggc_mark_rtx (p->internal_arg_pointer);
+ ggc_mark_rtx (p->saved_arg_pointer_save_area);
+ ggc_mark_tree (p->saved_rtl_expr_chain);
+ ggc_mark_rtx (p->saved_last_parm_insn);
+ ggc_mark_tree (p->saved_context_display);
+ ggc_mark_tree (p->saved_trampoline_list);
+ ggc_mark_rtx (p->epilogue_delay_list);
+
+ mark_temp_slot (&p->saved_temp_slots);
+ {
+ struct var_refs_queue *q = p->saved_fixup_var_refs_queue;
+ while (q)
{
- struct var_refs_queue *q = f->fixup_var_refs_queue;
- while (q)
- {
- ggc_mark_rtx (q->modified);
- q = q->next;
- }
+ ggc_mark_rtx (q->modified);
+ q = q->next;
}
+ }
- mark_block_nesting (&f->block_stack);
- mark_cond_nesting (&f->cond_stack);
- mark_loop_nesting (&f->loop_stack);
- mark_case_nesting (&f->case_stack);
-
- ggc_mark_tree (f->last_expr_type);
- ggc_mark_rtx (f->last_expr_value);
+ ggc_mark_rtx (p->saved_nonlocal_goto_handler_slot);
+ ggc_mark_rtx (p->saved_nonlocal_goto_stack_level);
+ ggc_mark_tree (p->saved_nonlocal_labels);
+}
- mark_goto_fixup (&f->goto_fixup_chain);
+void
+mark_function_chain (arg)
+ void *arg;
+{
+ struct function *f = *(struct function **) arg;
- mark_eh_state (&f->eh);
+ for (; f; f = f->next_global)
+ {
+ if (f->can_garbage_collect)
+ continue;
- ggc_mark_rtx (f->saveregs_value);
- ggc_mark_rtx (f->apply_args_value);
- ggc_mark_rtx (f->forced_labels);
- ggc_mark_rtx (f->first_insn);
- ggc_mark_tree (f->sequence_rtl_expr);
+ ggc_mark_tree (f->decl);
- mark_sequence_stack (&f->sequence_stack);
+ mark_function_state (&f->func);
+ mark_stmt_state (&f->stmt);
+ mark_eh_state (&f->eh);
+ mark_emit_state (&f->emit);
- for (i = f->regno_pointer_flag_length, r = f->regno_reg_rtx;
- i > 0; --i, ++r)
- ggc_mark_rtx (*r);
+ ggc_mark_rtx (f->expr->x_saveregs_value);
+ ggc_mark_rtx (f->expr->x_apply_args_value);
+ ggc_mark_rtx (f->expr->x_forced_labels);
if (mark_machine_status)
(*mark_machine_status) (f);
if (mark_lang_status)
(*mark_lang_status) (f);
- ggc_mark_rtx (f->epilogue_delay_list);
mark_pool_constant (&f->first_pool);
ggc_mark_rtx (f->const_double_chain);
- f = f->next;
+ if (f->original_arg_vector)
+ ggc_mark_rtvec ((rtvec) f->original_arg_vector);
+ if (f->original_decl_initial)
+ ggc_mark_tree (f->original_decl_initial);
}
}
void
init_function_once ()
{
- ggc_add_root (&outer_function_chain, 1, sizeof(outer_function_chain),
+ ggc_add_root (&all_functions, 1, sizeof all_functions,
mark_function_chain);
- ggc_add_root (&temp_slots, 1, sizeof(temp_slots),
- mark_temp_slot);
- ggc_add_root (&parm_reg_stack_loc, 1, sizeof parm_reg_stack_loc,
- mark_parm_reg_stack_loc);
}
diff --git a/gcc/function.h b/gcc/function.h
index e096ea15b87..6f78e728794 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -28,14 +28,6 @@ typedef struct rtx_def *_function_rtx;
#define rtx _function_rtx
#endif
-struct var_refs_queue
-{
- rtx modified;
- enum machine_mode promoted_mode;
- int unsignedp;
- struct var_refs_queue *next;
-};
-
/* Stack of pending (incomplete) sequences saved by `start_sequence'.
Each element describes one pending sequence.
The main insn-chain is saved in the last element of the chain,
@@ -59,106 +51,389 @@ struct simple_obstack_stack
struct simple_obstack_stack *next;
};
-/* This structure can save all the important global and static variables
- describing the status of the current function. */
-
-struct function
+struct function_status
{
- struct function *next;
-
- /* For function.c. */
+ /* Name of function now being compiled. */
char *name;
- tree decl;
+
+ /* Number of bytes of args popped by function being compiled on its return.
+ Zero if no bytes are to be popped.
+ May affect compilation of return insn or of function epilogue. */
int pops_args;
+
+ /* Nonzero if function being compiled needs to be given an address
+ where the value should be stored. */
int returns_struct;
+
+ /* Nonzero if function being compiled needs to
+ return the address of where it has put a structure value. */
int returns_pcc_struct;
+
+ /* Nonzero if the current function returns a pointer type */
int returns_pointer;
+
+ /* Nonzero if function being compiled needs to be passed a static chain. */
int needs_context;
+
+ /* Nonzero if function being compiled can call setjmp. */
int calls_setjmp;
+
+ /* Nonzero if function being compiled can call longjmp. */
int calls_longjmp;
+
+ /* Nonzero if function being compiled can call alloca,
+ either as a subroutine or builtin. */
int calls_alloca;
- int has_nonlocal_label;
- int has_nonlocal_goto;
+
+ /* Nonzero if function being compiled contains nested functions. */
int contains_functions;
+
+ /* Nonzero if the current function is a thunk (a lightweight function that
+ just adjusts one of its arguments and forwards to another function), so
+ we should try to cut corners where we can. */
int is_thunk;
- rtx nonlocal_goto_handler_slot;
- rtx nonlocal_goto_stack_level;
- tree nonlocal_labels;
+
+ /* If function's args have a fixed size, this is that size, in bytes.
+ Otherwise, it is -1.
+ May affect compilation of return insn or of function epilogue. */
int args_size;
+
+ /* # bytes the prologue should push and pretend that the caller pushed them.
+ The prologue must do this, but only if parms can be passed in registers. */
int pretend_args_size;
+
+ /* This is the offset from the arg pointer to the place where the first
+ anonymous arg can be found, if there is one. */
rtx arg_offset_rtx;
+
+ /* Nonzero if current function uses varargs.h or equivalent.
+ Zero for functions that use stdarg.h. */
int varargs;
+
+ /* Nonzero if current function uses stdarg.h or equivalent.
+ Zero for functions that use varargs.h. */
int stdarg;
- int max_parm_reg;
- rtx *parm_reg_stack_loc;
- int outgoing_args_size;
- rtx return_rtx;
- rtx cleanup_label;
- rtx return_label;
- rtx save_expr_regs;
- rtx stack_slot_list;
- rtx parm_birth_insn;
- HOST_WIDE_INT frame_offset;
- rtx tail_recursion_label;
- rtx tail_recursion_reentry;
+
+ /* The arg pointer hard register, or the pseudo into which it was copied. */
rtx internal_arg_pointer;
+
+ /* Language-specific reason why the current function cannot be made inline. */
char *cannot_inline;
- rtx arg_pointer_save_area;
- tree rtl_expr_chain;
- rtx last_parm_insn;
- tree context_display;
- tree trampoline_list;
- int function_call_count;
- struct temp_slot *temp_slots;
- int temp_slot_level;
- int target_temp_slot_level;
- int var_temp_slot_level;
+
+ /* # of bytes of outgoing arguments. If ACCUMULATE_OUTGOING_ARGS is
+ defined, the needed space is pushed by the prologue. */
+ int outgoing_args_size;
+
+ /* If non-zero, an RTL expression for the location at which the current
+ function returns its result. If the current function returns its
+ result in a register, current_function_return_rtx will always be
+ the hard register containing the result. */
+ rtx return_rtx;
+
+ /* Nonzero if the current function uses pic_offset_table_rtx. */
+ int uses_pic_offset_table;
+
+ /* Nonzero if the current function uses the constant pool. */
+ int uses_const_pool;
+
+ /* If some insns can be deferred to the delay slots of the epilogue, the
+ delay list for them is recorded here. */
+ rtx epilogue_delay_list;
+
+ /* Quantities of various kinds of registers
+ used for the current function's args. */
+ CUMULATIVE_ARGS args_info;
+
+ /* Nonzero if instrumentation calls for function entry and exit should be
+ generated. */
int instrument_entry_exit;
+
+ /* 1 + last pseudo register number possibly used for loading a copy
+ of a parameter of this function. */
+ int saved_max_parm_reg;
+
+ /* Vector indexed by REGNO, containing location on stack in which
+ to put the parm which is nominally in pseudo register REGNO,
+ if we discover that that parm must go in the stack. The highest
+ element in this vector is one less than MAX_PARM_REG, above. */
+ rtx *saved_parm_reg_stack_loc;
+
+ /* Label that will go on parm cleanup code, if any.
+ Jumping to this label runs cleanup code for parameters, if
+ such code must be run. Following this code is the logical return label. */
+ rtx saved_cleanup_label;
+
+ /* Label that will go on function epilogue.
+ Jumping to this label serves as a "return" instruction
+ on machines which require execution of the epilogue on all returns. */
+ rtx saved_return_label;
+
+ /* List (chain of EXPR_LISTs) of pseudo-regs of SAVE_EXPRs.
+ So we can mark them all live at the end of the function, if nonopt. */
+ rtx saved_save_expr_regs;
+
+ /* List (chain of EXPR_LISTs) of all stack slots in this function.
+ Made for the sake of unshare_all_rtl. */
+ rtx saved_stack_slot_list;
+
+ /* Insn after which register parms and SAVE_EXPRs are born, if nonopt. */
+ rtx saved_parm_birth_insn;
+
+ /* Offset to end of allocated area of stack frame.
+ If stack grows down, this is the address of the last stack slot allocated.
+ If stack grows up, this is the address for the next slot. */
+ HOST_WIDE_INT saved_frame_offset;
+
+ /* Label to jump back to for tail recursion, or 0 if we have
+ not yet needed one for this function. */
+ rtx saved_tail_recursion_label;
+
+ /* Place after which to insert the tail_recursion_label if we need one. */
+ rtx saved_tail_recursion_reentry;
+
+ /* Location at which to save the argument pointer if it will need to be
+ referenced. There are two cases where this is done: if nonlocal gotos
+ exist, or if vars stored at an offset from the argument pointer will be
+ needed by inner routines. */
+ rtx saved_arg_pointer_save_area;
+
+ /* Chain of all RTL_EXPRs that have insns in them. */
+ tree saved_rtl_expr_chain;
+
+ /* Last insn of those whose job was to put parms into their nominal homes. */
+ rtx saved_last_parm_insn;
+
+ /* List (chain of TREE_LISTs) of static chains for containing functions.
+ Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx
+ in an RTL_EXPR in the TREE_VALUE. */
+ tree saved_context_display;
+
+ /* List (chain of TREE_LISTs) of trampolines for nested functions.
+ The trampoline sets up the static chain and jumps to the function.
+ We supply the trampoline's address when the function's address is requested.
+
+ Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx
+ in an RTL_EXPR in the TREE_VALUE. */
+ tree saved_trampoline_list;
+
+ /* Number of function calls seen so far in current function. */
+ int saved_function_call_count;
+
+ /* List of all temporaries allocated, both available and in use. */
+ struct temp_slot *saved_temp_slots;
+
+ /* Current nesting level for temporaries. */
+ int saved_temp_slot_level;
+
+ /* When temporaries are created by TARGET_EXPRs, they are created at
+ this level of temp_slot_level, so that they can remain allocated
+ until no longer needed. CLEANUP_POINT_EXPRs define the lifetime
+ of TARGET_EXPRs. */
+ int saved_target_temp_slot_level;
+
+ /* Current nesting level for variables in a block. */
+ int saved_var_temp_slot_level;
+
/* This slot is initialized as 0 and is added to
during the nested function. */
- struct var_refs_queue *fixup_var_refs_queue;
- CUMULATIVE_ARGS args_info;
+ struct var_refs_queue *saved_fixup_var_refs_queue;
+
+ /* RTX for stack slot that holds the current handler for nonlocal gotos.
+ Zero when function does not have nonlocal labels. */
+ rtx saved_nonlocal_goto_handler_slot;
- /* For stmt.c */
- struct nesting *block_stack;
- struct nesting *stack_block_stack;
- struct nesting *cond_stack;
- struct nesting *loop_stack;
- struct nesting *case_stack;
- struct nesting *nesting_stack;
- int nesting_depth;
- int block_start_count;
- tree last_expr_type;
- rtx last_expr_value;
- int expr_stmts_for_value;
- char *emit_filename;
- int emit_lineno;
- struct goto_fixup *goto_fixup_chain;
-
- /* For exception handling information. */
- struct eh_function *eh;
-
- /* For expr.c. */
- int pending_stack_adjust;
- int inhibit_defer_pop;
- rtx saveregs_value;
- rtx apply_args_value;
- rtx forced_labels;
-
- /* For emit-rtl.c. */
- int reg_rtx_no;
- int first_label_num;
- rtx first_insn;
- rtx last_insn;
+ /* RTX for stack slot that holds the stack pointer value to restore
+ for a nonlocal goto.
+ Zero when function does not have nonlocal labels. */
+ rtx saved_nonlocal_goto_stack_level;
+
+ /* 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. */
+ tree saved_nonlocal_labels;
+
+ /* Nonzero if function being compiled receives nonlocal gotos
+ from nested functions. */
+ int has_nonlocal_label;
+
+ /* Nonzero if function being compiled has nonlocal gotos to parent
+ function. */
+ int has_nonlocal_goto;
+};
+
+/* Current function status. */
+extern struct function_status *cur_f_s;
+
+/* For backward compatibility... eventually these should all go away. */
+#define current_function_name (cur_f_s->name)
+#define current_function_pops_args (cur_f_s->pops_args)
+#define current_function_returns_struct (cur_f_s->returns_struct)
+#define current_function_returns_pcc_struct (cur_f_s->returns_pcc_struct)
+#define current_function_needs_context (cur_f_s->needs_context)
+#define current_function_calls_setjmp (cur_f_s->calls_setjmp)
+#define current_function_calls_longjmp (cur_f_s->calls_longjmp)
+#define current_function_contains_functions (cur_f_s->contains_functions)
+#define current_function_is_thunk (cur_f_s->is_thunk)
+#define current_function_calls_alloca (cur_f_s->calls_alloca)
+#define current_function_returns_pointer (cur_f_s->returns_pointer)
+#define current_function_args_info (cur_f_s->args_info)
+#define current_function_args_size (cur_f_s->args_size)
+#define current_function_pretend_args_size (cur_f_s->pretend_args_size)
+#define current_function_outgoing_args_size (cur_f_s->outgoing_args_size)
+#define current_function_arg_offset_rtx (cur_f_s->arg_offset_rtx)
+#define current_function_varargs (cur_f_s->varargs)
+#define current_function_stdarg (cur_f_s->stdarg)
+#define current_function_internal_arg_pointer (cur_f_s->internal_arg_pointer)
+#define current_function_return_rtx (cur_f_s->return_rtx)
+#define current_function_instrument_entry_exit (cur_f_s->instrument_entry_exit)
+#define current_function_uses_pic_offset_table (cur_f_s->uses_pic_offset_table)
+#define current_function_uses_const_pool (cur_f_s->uses_const_pool)
+#define current_function_cannot_inline (cur_f_s->cannot_inline)
+#define current_function_epilogue_delay_list (cur_f_s->epilogue_delay_list)
+#define current_function_has_nonlocal_label (cur_f_s->has_nonlocal_label)
+#define current_function_has_nonlocal_goto (cur_f_s->has_nonlocal_goto)
+
+#define max_parm_reg (cur_f_s->saved_max_parm_reg)
+#define parm_reg_stack_loc (cur_f_s->saved_parm_reg_stack_loc)
+#define cleanup_label (cur_f_s->saved_cleanup_label)
+#define return_label (cur_f_s->saved_return_label)
+#define save_expr_regs (cur_f_s->saved_save_expr_regs)
+#define stack_slot_list (cur_f_s->saved_stack_slot_list)
+#define parm_birth_insn (cur_f_s->saved_parm_birth_insn)
+#define frame_offset (cur_f_s->saved_frame_offset)
+#define tail_recursion_label (cur_f_s->saved_tail_recursion_label)
+#define tail_recursion_reentry (cur_f_s->saved_tail_recursion_reentry)
+#define arg_pointer_save_area (cur_f_s->saved_arg_pointer_save_area)
+#define rtl_expr_chain (cur_f_s->saved_rtl_expr_chain)
+#define last_parm_insn (cur_f_s->saved_last_parm_insn)
+#define context_display (cur_f_s->saved_context_display)
+#define trampoline_list (cur_f_s->saved_trampoline_list)
+#define function_call_count (cur_f_s->saved_function_call_count)
+#define temp_slots (cur_f_s->saved_temp_slots)
+#define temp_slot_level (cur_f_s->saved_temp_slot_level)
+#define target_temp_slot_level (cur_f_s->saved_target_temp_slot_level)
+#define var_temp_slot_level (cur_f_s->saved_var_temp_slot_level)
+#define fixup_var_refs_queue (cur_f_s->saved_fixup_var_refs_queue)
+#define nonlocal_labels (cur_f_s->saved_nonlocal_labels)
+#define nonlocal_goto_handler_slot (cur_f_s->saved_nonlocal_goto_handler_slot)
+#define nonlocal_goto_stack_level (cur_f_s->saved_nonlocal_goto_stack_level)
+
+struct emit_status
+{
+ /* This is reset to LAST_VIRTUAL_REGISTER + 1 at the start of each function.
+ After rtl generation, it is 1 plus the largest register number used. */
+ int x_reg_rtx_no;
+
+ /* Lowest label number in current function. */
+ int x_first_label_num;
+
+ /* The ends of the doubly-linked chain of rtl for the current function.
+ Both are reset to null at the start of rtl generation for the function.
+
+ start_sequence saves both of these on `sequence_stack' along with
+ `sequence_rtl_expr' and then starts a new, nested sequence of insns. */
+ rtx x_first_insn;
+ rtx x_last_insn;
+
+ /* RTL_EXPR within which the current sequence will be placed. Use to
+ prevent reuse of any temporaries within the sequence until after the
+ RTL_EXPR is emitted. */
tree sequence_rtl_expr;
+
+ /* Stack of pending (incomplete) sequences saved by `start_sequence'.
+ Each element describes one pending sequence.
+ The main insn-chain is saved in the last element of the chain,
+ unless the chain is empty. */
struct sequence_stack *sequence_stack;
- int cur_insn_uid;
- int last_linenum;
- char *last_filename;
- char *regno_pointer_flag;
- char *regno_pointer_align;
- int regno_pointer_flag_length;
- rtx *regno_reg_rtx;
+
+ /* INSN_UID for next insn emitted.
+ Reset to 1 for each function compiled. */
+ int x_cur_insn_uid;
+
+ /* Line number and source file of the last line-number NOTE emitted.
+ This is used to avoid generating duplicates. */
+ int x_last_linenum;
+ char *x_last_filename;
+
+ /* A vector indexed by pseudo reg number. The allocated length
+ of this vector is regno_pointer_flag_length. Since this
+ vector is needed during the expansion phase when the total
+ number of registers in the function is not yet known,
+ it is copied and made bigger when necessary. */
+ char *x_regno_pointer_flag;
+ int x_regno_pointer_flag_length;
+
+ /* Indexed by pseudo register number, if nonzero gives the known alignment
+ for that pseudo (if regno_pointer_flag is set).
+ Allocated in parallel with regno_pointer_flag. */
+ char *x_regno_pointer_align;
+
+ /* Indexed by pseudo register number, gives the rtx for that pseudo.
+ Allocated in parallel with regno_pointer_flag. */
+ rtx *x_regno_reg_rtx;
+};
+
+/* For backward compatibility... eventually these should all go away. */
+#define reg_rtx_no (current_function->emit->x_reg_rtx_no)
+#define seq_rtl_expr (current_function->emit->sequence_rtl_expr)
+#define regno_pointer_flag (current_function->emit->x_regno_pointer_flag)
+#define regno_pointer_flag_length (current_function->emit->x_regno_pointer_flag_length)
+#define regno_pointer_align (current_function->emit->x_regno_pointer_align)
+#define regno_reg_rtx (current_function->emit->x_regno_reg_rtx)
+#define seq_stack (current_function->emit->sequence_stack)
+
+#define REGNO_POINTER_ALIGN(REGNO) regno_pointer_align[REGNO]
+#define REGNO_POINTER_FLAG(REGNO) regno_pointer_flag[REGNO]
+
+struct expr_status
+{
+ /* Number of units that we should eventually pop off the stack.
+ These are the arguments to function calls that have already returned. */
+ int x_pending_stack_adjust;
+
+ /* Nonzero means stack pops must not be deferred, and deferred stack
+ pops must not be output. It is nonzero inside a function call,
+ inside a conditional expression, inside a statement expression,
+ and in other cases as well. */
+ int x_inhibit_defer_pop;
+
+ /* Nonzero means __builtin_saveregs has already been done in this function.
+ The value is the pseudoreg containing the value __builtin_saveregs
+ returned. */
+ rtx x_saveregs_value;
+
+ /* Similarly for __builtin_apply_args. */
+ rtx x_apply_args_value;
+
+ /* List of labels that must never be deleted. */
+ rtx x_forced_labels;
+};
+
+#define pending_stack_adjust (current_function->expr->x_pending_stack_adjust)
+#define inhibit_defer_pop (current_function->expr->x_inhibit_defer_pop)
+#define saveregs_value (current_function->expr->x_saveregs_value)
+#define apply_args_value (current_function->expr->x_apply_args_value)
+#define forced_labels (current_function->expr->x_forced_labels)
+
+/* This structure can save all the important global and static variables
+ describing the status of the current function. */
+
+struct function
+{
+ /* Global list of all functions. */
+ struct function *next_global;
+
+ /* Chain of nested functions. */
+ struct function *next;
+
+ /* The FUNCTION_DECL for this function. */
+ tree decl;
+
+ struct function_status *func;
+ struct stmt_status *stmt;
+ struct eh_status *eh;
+ struct emit_status *emit;
+ struct expr_status *expr;
/* For tree.c. */
int all_types_permanent;
@@ -175,40 +450,38 @@ struct function
struct obstack *rtl_obstack;
struct simple_obstack_stack *inline_obstacks;
- /* For integrate.c. */
- int uses_const_pool;
-
- /* For md files. */
- int uses_pic_offset_table;
/* tm.h can use this to store whatever it likes. */
struct machine_function *machine;
/* Language-specific code can use this to store whatever it likes. */
struct language_function *language;
- /* For reorg. */
- rtx epilogue_delay_list;
-
/* For varasm. */
struct constant_descriptor **const_rtx_hash_table;
struct pool_sym **const_rtx_sym_hash_table;
struct pool_constant *first_pool, *last_pool;
int pool_offset;
rtx const_double_chain;
+
+ /* For inlinable functions. */
+ int inlinable;
+ /* This is in fact an rtvec. */
+ void *original_arg_vector;
+ tree original_decl_initial;
+ /* Highest label number in current function. */
+ int max_label_num;
+
+ /* This is nonzero once this function has been compiled and its data is
+ no longer required to be kept around. */
+ int can_garbage_collect;
};
+/* The function structure for the currently being compiled function. */
+extern struct function *current_function;
+
/* The FUNCTION_DECL for an inline function currently being expanded. */
extern tree inline_function_decl;
-/* Label that will go on function epilogue.
- Jumping to this label serves as a "return" instruction
- on machines which require execution of the epilogue on all returns. */
-extern rtx return_label;
-
-/* List (chain of EXPR_LISTs) of all stack slots in this function.
- Made for the sake of unshare_all_rtl. */
-extern rtx stack_slot_list;
-
/* Given a function decl for a containing function,
return the `struct function' for it. */
struct function *find_function_data PROTO((tree));
@@ -225,11 +498,12 @@ extern tree *identify_blocks PROTO((tree, rtx));
This size counts from zero. It is not rounded to STACK_BOUNDARY;
the caller may have to do that. */
extern HOST_WIDE_INT get_frame_size PROTO((void));
+extern HOST_WIDE_INT get_func_frame_size PROTO((struct function *));
/* These variables hold pointers to functions to
save and restore machine-specific data,
in push_function_context and pop_function_context. */
-extern void (*save_machine_status) PROTO((struct function *));
+extern void (*init_machine_status) PROTO((struct function *));
extern void (*restore_machine_status) PROTO((struct function *));
extern void (*mark_machine_status) PROTO((struct function *));
@@ -238,22 +512,15 @@ extern void (*save_lang_status) PROTO((struct function *));
extern void (*restore_lang_status) PROTO((struct function *));
extern void (*mark_lang_status) PROTO((struct function *));
-
/* Save and restore status information for a nested function. */
extern void save_tree_status PROTO((struct function *, tree));
extern void restore_tree_status PROTO((struct function *, tree));
extern void save_varasm_status PROTO((struct function *, tree));
extern void restore_varasm_status PROTO((struct function *));
-extern void save_eh_status PROTO((struct function *));
-extern void restore_eh_status PROTO((struct function *));
-extern void save_stmt_status PROTO((struct function *));
-extern void restore_stmt_status PROTO((struct function *));
-extern void save_expr_status PROTO((struct function *));
-extern void restore_expr_status PROTO((struct function *));
-extern void save_emit_status PROTO((struct function *));
extern void restore_emit_status PROTO((struct function *));
-extern void save_storage_status PROTO((struct function *));
-extern void restore_storage_status PROTO((struct function *));
+extern void free_varasm_status PROTO((struct function *));
+extern void free_emit_status PROTO((struct function *));
+extern void free_after_compilation PROTO((struct function *));
extern rtx get_first_block_beg PROTO((void));
diff --git a/gcc/gcse.c b/gcc/gcse.c
index 0732cb4cadd..bf5b66d7735 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -144,6 +144,7 @@ yyy
#include "system.h"
#include "rtl.h"
+#include "function.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "flags.h"
@@ -502,10 +503,6 @@ static int gcse_create_count;
static int const_prop_count;
/* Number of copys propagated. */
static int copy_prop_count;
-
-extern char *current_function_name;
-extern int current_function_calls_setjmp;
-extern int current_function_calls_longjmp;
/* These variables are used by classic GCSE.
Normally they'd be defined a bit later, but `rd_gen' needs to
diff --git a/gcc/genemit.c b/gcc/genemit.c
index d13ff5e35b2..692f02831e4 100644
--- a/gcc/genemit.c
+++ b/gcc/genemit.c
@@ -766,6 +766,7 @@ from the machine description file `md'. */\n\n");
printf ("#include \"config.h\"\n");
printf ("#include \"system.h\"\n");
printf ("#include \"rtl.h\"\n");
+ printf ("#include \"function.h\"\n");
printf ("#include \"expr.h\"\n");
printf ("#include \"real.h\"\n");
printf ("#include \"flags.h\"\n");
diff --git a/gcc/ggc-simple.c b/gcc/ggc-simple.c
index 1b837d0575e..3dd8670eb4e 100644
--- a/gcc/ggc-simple.c
+++ b/gcc/ggc-simple.c
@@ -205,22 +205,6 @@ static void
ggc_free_rtx (r)
struct ggc_rtx *r;
{
- switch (GET_CODE (&r->rtx))
- {
- case INLINE_HEADER:
-#if 0
- /* These are currently allocated off an obstack. This will change. */
- free (INLINE_REGNO_REG_RTX (&r->rtx));
- free (INLINE_REGNO_POINTER_FLAG (&r->rtx));
- free (INLINE_REGNO_POINTER_ALIGN (&r->rtx));
- free (PARMREG_STACK_LOC (&r->rtx));
-#endif
- break;
-
- default:
- break;
- }
-
#ifdef GGC_DUMP
fprintf (dump, "collect rtx %p\n", &r->rtx);
#endif
@@ -321,26 +305,6 @@ ggc_mark_rtx (r)
ggc_mark_tree (ADDRESSOF_DECL (r));
break;
- case INLINE_HEADER:
- {
- rtx *tmp;
- int i;
-
- ggc_mark_tree (ORIGINAL_DECL_INITIAL (r));
-
- tmp = INLINE_REGNO_REG_RTX (r);
- i = MAX_REGNUM (r);
- while (--i >= 0)
- ggc_mark_rtx (*tmp++);
-
- tmp = PARMREG_STACK_LOC (r);
- i = MAX_PARMREG (r);
- while (--i >= 0)
- ggc_mark_rtx (*tmp++);
-
- break;
- }
-
default:
break;
}
@@ -406,6 +370,7 @@ ggc_mark_tree (t)
}
case SAVE_EXPR:
+ ggc_mark_tree (TREE_OPERAND (t, 0));
ggc_mark_tree (SAVE_EXPR_CONTEXT (t));
ggc_mark_rtx (SAVE_EXPR_RTL (t));
return;
@@ -434,10 +399,6 @@ ggc_mark_tree (t)
ggc_mark_rtx (DECL_INCOMING_RTL (t));
break;
- case FUNCTION_DECL:
- ggc_mark_rtx (DECL_SAVED_INSNS (t));
- break;
-
case IDENTIFIER_NODE:
ggc_mark_string (IDENTIFIER_POINTER (t));
lang_mark_tree (t);
diff --git a/gcc/ggc.h b/gcc/ggc.h
index ac510cd7bef..43bff9c2c61 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -23,6 +23,10 @@
/* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with
an external gc library that might be linked in. */
+/* Startup */
+
+extern void init_ggc PROTO ((void));
+
/* Allocation. */
struct rtx_def *ggc_alloc_rtx PROTO ((int nslots));
@@ -60,16 +64,10 @@ void lang_cleanup_tree PROTO ((union tree_node *));
/* Mark functions for various structs scattered about. */
void mark_binding_level PROTO ((void *));
-void mark_sequence_stack PROTO ((void *));
void mark_temp_slot PROTO ((void *));
void mark_function_chain PROTO ((void *));
-void mark_cond_nesting PROTO ((void *));
-void mark_loop_nesting PROTO ((void *));
-void mark_block_nesting PROTO ((void *));
-void mark_case_nesting PROTO ((void *));
-void mark_goto_fixup PROTO ((void *));
-void mark_tree_label_node PROTO ((void *));
-void mark_rtx_label_node PROTO ((void *));
void mark_eh_state PROTO ((void *));
+void mark_stmt_state PROTO ((void *));
+void mark_emit_state PROTO ((void *));
void mark_pool_constant PROTO ((void *));
void mark_optab PROTO ((void *));
diff --git a/gcc/global.c b/gcc/global.c
index b133b893a97..af0fb3eb445 100644
--- a/gcc/global.c
+++ b/gcc/global.c
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA. */
#include "machmode.h"
#include "hard-reg-set.h"
#include "rtl.h"
+#include "function.h"
#include "flags.h"
#include "basic-block.h"
#include "regs.h"
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 5274f01be66..8e1538c58e0 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -158,6 +158,7 @@
#include "config.h"
#include "system.h"
#include "rtl.h"
+#include "function.h"
#include "basic-block.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -492,11 +493,6 @@ static int *out_edges;
#define IN_EDGES(block) (in_edges[block])
#define OUT_EDGES(block) (out_edges[block])
-/* List of labels which cannot be deleted, needed for control
- flow graph construction. */
-extern rtx forced_labels;
-
-
static int is_cfg_nonregular PROTO ((void));
static int build_control_flow PROTO ((int_list_ptr *, int_list_ptr *,
int *, int *));
diff --git a/gcc/integrate.c b/gcc/integrate.c
index d374543dc26..fad09c13d59 100644
--- a/gcc/integrate.c
+++ b/gcc/integrate.c
@@ -59,15 +59,9 @@ extern struct obstack *function_maybepermanent_obstack;
: (8 * (8 + list_length (DECL_ARGUMENTS (DECL)))))
#endif
-static rtx initialize_for_inline PROTO((tree, int, int, int, int));
-static void finish_inline PROTO((tree, rtx));
-static void adjust_copied_decl_tree PROTO((tree));
-static tree copy_decl_list PROTO((tree));
-static tree copy_decl_tree PROTO((tree));
-static void copy_decl_rtls PROTO((tree));
+static rtvec initialize_for_inline PROTO((tree));
static void save_constants PROTO((rtx *));
static void note_modified_parmregs PROTO((rtx, rtx));
-static rtx copy_for_inline PROTO((rtx));
static void integrate_parm_decls PROTO((tree, struct inline_remap *,
rtvec));
static void integrate_decl_tree PROTO((tree, int,
@@ -223,77 +217,23 @@ function_cannot_inline_p (fndecl)
/* Variables used within save_for_inline. */
-/* Mapping from old pseudo-register to new pseudo-registers.
- The first element of this map is reg_map[FIRST_PSEUDO_REGISTER].
- It is allocated in `save_for_inline' and `expand_inline_function',
- and deallocated on exit from each of those routines. */
-static rtx *reg_map;
-
-/* Mapping from old code-labels to new code-labels.
- The first element of this map is label_map[min_labelno].
- It is allocated in `save_for_inline' and `expand_inline_function',
- and deallocated on exit from each of those routines. */
-static rtx *label_map;
-
-/* Mapping from old insn uid's to copied insns.
- It is allocated in `save_for_inline' and `expand_inline_function',
- and deallocated on exit from each of those routines. */
-static rtx *insn_map;
-
/* Map pseudo reg number into the PARM_DECL for the parm living in the reg.
Zero for a reg that isn't a parm's home.
Only reg numbers less than max_parm_reg are mapped here. */
static tree *parmdecl_map;
-/* Keep track of first pseudo-register beyond those that are parms. */
-extern int max_parm_reg;
-extern rtx *parm_reg_stack_loc;
-
-/* When an insn is being copied by copy_for_inline,
- this is nonzero if we have copied an ASM_OPERANDS.
- In that case, it is the original input-operand vector. */
-static rtvec orig_asm_operands_vector;
-
-/* When an insn is being copied by copy_for_inline,
- this is nonzero if we have copied an ASM_OPERANDS.
- In that case, it is the copied input-operand vector. */
-static rtvec copy_asm_operands_vector;
-
-/* Likewise, this is the copied constraints vector. */
-static rtvec copy_asm_constraints_vector;
-
-/* In save_for_inline, nonzero if past the parm-initialization insns. */
-static int in_nonparm_insns;
-/* Subroutine for `save_for_inline{copying,nocopy}'. Performs initialization
+/* Subroutine for `save_for_inline_nocopy. Performs initialization
needed to save FNDECL's insns and info for future inline expansion. */
-static rtx
-initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
+static rtvec
+initialize_for_inline (fndecl)
tree fndecl;
- int min_labelno;
- int max_labelno;
- int max_reg;
- int copy;
{
- int function_flags, i;
+ int i;
rtvec arg_vector;
tree parms;
- /* Compute the values of any flags we must restore when inlining this. */
-
- function_flags
- = (current_function_calls_alloca * FUNCTION_FLAGS_CALLS_ALLOCA
- + current_function_calls_setjmp * FUNCTION_FLAGS_CALLS_SETJMP
- + current_function_calls_longjmp * FUNCTION_FLAGS_CALLS_LONGJMP
- + current_function_returns_struct * FUNCTION_FLAGS_RETURNS_STRUCT
- + current_function_returns_pcc_struct * FUNCTION_FLAGS_RETURNS_PCC_STRUCT
- + current_function_needs_context * FUNCTION_FLAGS_NEEDS_CONTEXT
- + current_function_has_nonlocal_label * FUNCTION_FLAGS_HAS_NONLOCAL_LABEL
- + current_function_returns_pointer * FUNCTION_FLAGS_RETURNS_POINTER
- + current_function_uses_const_pool * FUNCTION_FLAGS_USES_CONST_POOL
- + current_function_uses_pic_offset_table * FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE);
-
/* Clear out PARMDECL_MAP. It was allocated in the caller's frame. */
bzero ((char *) parmdecl_map, max_parm_reg * sizeof (tree));
arg_vector = rtvec_alloc (list_length (DECL_ARGUMENTS (fndecl)));
@@ -303,7 +243,6 @@ initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
parms = TREE_CHAIN (parms), i++)
{
rtx p = DECL_RTL (parms);
- int copied_incoming = 0;
/* If we have (mem (addressof (mem ...))), use the inner MEM since
otherwise the copy_rtx call below will not unshare the MEM since
@@ -312,25 +251,6 @@ initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
&& GET_CODE (XEXP (XEXP (p, 0), 0)) == MEM)
p = XEXP (XEXP (p, 0), 0);
- if (GET_CODE (p) == MEM && copy)
- {
- /* Copy the rtl so that modifications of the addresses
- later in compilation won't affect this arg_vector.
- Virtual register instantiation can screw the address
- of the rtl. */
- rtx new = copy_rtx (p);
-
- /* Don't leave the old copy anywhere in this decl. */
- if (DECL_RTL (parms) == DECL_INCOMING_RTL (parms)
- || (GET_CODE (DECL_RTL (parms)) == MEM
- && GET_CODE (DECL_INCOMING_RTL (parms)) == MEM
- && (XEXP (DECL_RTL (parms), 0)
- == XEXP (DECL_INCOMING_RTL (parms), 0))))
- DECL_INCOMING_RTL (parms) = new, copied_incoming = 1;
-
- DECL_RTL (parms) = new;
- }
-
RTVEC_ELT (arg_vector, i) = p;
if (GET_CODE (p) == REG)
@@ -349,405 +269,9 @@ initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
/* This flag is cleared later
if the function ever modifies the value of the parm. */
TREE_READONLY (parms) = 1;
-
- /* Copy DECL_INCOMING_RTL if not done already. This can
- happen if DECL_RTL is a reg. */
- if (copy && ! copied_incoming)
- {
- p = DECL_INCOMING_RTL (parms);
-
- /* If we have (mem (addressof (mem ...))), use the inner MEM since
- otherwise the copy_rtx call below will not unshare the MEM since
- it shares ADDRESSOF. */
- if (GET_CODE (p) == MEM && GET_CODE (XEXP (p, 0)) == ADDRESSOF
- && GET_CODE (XEXP (XEXP (p, 0), 0)) == MEM)
- p = XEXP (XEXP (p, 0), 0);
-
- if (GET_CODE (p) == MEM)
- DECL_INCOMING_RTL (parms) = copy_rtx (p);
- }
- }
-
- /* Assume we start out in the insns that set up the parameters. */
- in_nonparm_insns = 0;
-
- /* The list of DECL_SAVED_INSNS, starts off with a header which
- contains the following information:
-
- the first insn of the function (not including the insns that copy
- parameters into registers).
- the first parameter insn of the function,
- the first label used by that function,
- the last label used by that function,
- the highest register number used for parameters,
- the total number of registers used,
- the size of the incoming stack area for parameters,
- the number of bytes popped on return,
- the stack slot list,
- the labels that are forced to exist,
- some flags that are used to restore compiler globals,
- the value of current_function_outgoing_args_size,
- the original argument vector,
- the original DECL_INITIAL,
- and pointers to the table of pseudo regs, pointer flags, and alignment. */
-
- return gen_inline_header_rtx (NULL_RTX, NULL_RTX, min_labelno, max_labelno,
- max_parm_reg, max_reg,
- current_function_args_size,
- current_function_pops_args,
- stack_slot_list, forced_labels, function_flags,
- current_function_outgoing_args_size,
- arg_vector, DECL_INITIAL (fndecl),
- regno_reg_rtx, regno_pointer_flag,
- regno_pointer_align, parm_reg_stack_loc);
-}
-
-/* Subroutine for `save_for_inline{copying,nocopy}'. Finishes up the
- things that must be done to make FNDECL expandable as an inline function.
- HEAD contains the chain of insns to which FNDECL will expand. */
-
-static void
-finish_inline (fndecl, head)
- tree fndecl;
- rtx head;
-{
- FIRST_FUNCTION_INSN (head) = get_first_nonparm_insn ();
- FIRST_PARM_INSN (head) = get_insns ();
- DECL_SAVED_INSNS (fndecl) = head;
- DECL_FRAME_SIZE (fndecl) = get_frame_size ();
-}
-
-/* Adjust the BLOCK_END_NOTE pointers in a given copied DECL tree so that
- they all point to the new (copied) rtxs. */
-
-static void
-adjust_copied_decl_tree (block)
- register tree block;
-{
- register tree subblock;
- register rtx original_end;
-
- original_end = BLOCK_END_NOTE (block);
- if (original_end)
- {
- BLOCK_END_NOTE (block) = (rtx) NOTE_SOURCE_FILE (original_end);
- NOTE_SOURCE_FILE (original_end) = 0;
- }
-
- /* Process all subblocks. */
- for (subblock = BLOCK_SUBBLOCKS (block);
- subblock;
- subblock = TREE_CHAIN (subblock))
- adjust_copied_decl_tree (subblock);
-}
-
-/* Make the insns and PARM_DECLs of the current function permanent
- and record other information in DECL_SAVED_INSNS to allow inlining
- of this function in subsequent calls.
-
- This function is called when we are going to immediately compile
- the insns for FNDECL. The insns in maybepermanent_obstack cannot be
- modified by the compilation process, so we copy all of them to
- new storage and consider the new insns to be the insn chain to be
- compiled. Our caller (rest_of_compilation) saves the original
- DECL_INITIAL and DECL_ARGUMENTS; here we copy them. */
-
-/* ??? The nonlocal_label list should be adjusted also. However, since
- a function that contains a nested function never gets inlined currently,
- the nonlocal_label list will always be empty, so we don't worry about
- it for now. */
-
-void
-save_for_inline_copying (fndecl)
- tree fndecl;
-{
- rtx first_insn, last_insn, insn;
- rtx head, copy;
- int max_labelno, min_labelno, i, len;
- int max_reg;
- int max_uid;
- rtx first_nonparm_insn;
- char *new, *new1;
- rtx *new_parm_reg_stack_loc;
- rtx *new2;
-
- /* Make and emit a return-label if we have not already done so.
- Do this before recording the bounds on label numbers. */
-
- if (return_label == 0)
- {
- return_label = gen_label_rtx ();
- emit_label (return_label);
- }
-
- /* Get some bounds on the labels and registers used. */
-
- max_labelno = max_label_num ();
- min_labelno = get_first_label_num ();
- max_reg = max_reg_num ();
-
- /* Set up PARMDECL_MAP which maps pseudo-reg number to its PARM_DECL.
- Later we set TREE_READONLY to 0 if the parm is modified inside the fn.
- Also set up ARG_VECTOR, which holds the unmodified DECL_RTX values
- for the parms, prior to elimination of virtual registers.
- These values are needed for substituting parms properly. */
-
- parmdecl_map = (tree *) alloca (max_parm_reg * sizeof (tree));
-
- head = initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, 1);
-
- if (current_function_uses_const_pool)
- {
- /* Replace any constant pool references with the actual constant. We
- will put the constants back in the copy made below. */
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- {
- save_constants (&PATTERN (insn));
- if (REG_NOTES (insn))
- save_constants (&REG_NOTES (insn));
- }
-
- /* Also scan all decls, and replace any constant pool references with the
- actual constant. */
- save_constants_in_decl_trees (DECL_INITIAL (fndecl));
-
- /* Clear out the constant pool so that we can recreate it with the
- copied constants below. */
- init_const_rtx_hash_table ();
- clear_const_double_mem ();
- }
-
- max_uid = INSN_UID (head);
-
- /* We have now allocated all that needs to be allocated permanently
- on the rtx obstack. Set our high-water mark, so that we
- can free the rest of this when the time comes. */
-
- preserve_data ();
-
- /* Copy the chain insns of this function.
- Install the copied chain as the insns of this function,
- for continued compilation;
- the original chain is recorded as the DECL_SAVED_INSNS
- for inlining future calls. */
-
- /* If there are insns that copy parms from the stack into pseudo registers,
- those insns are not copied. `expand_inline_function' must
- emit the correct code to handle such things. */
-
- insn = get_insns ();
- if (GET_CODE (insn) != NOTE)
- abort ();
- first_insn = rtx_alloc (NOTE);
- NOTE_SOURCE_FILE (first_insn) = NOTE_SOURCE_FILE (insn);
- NOTE_LINE_NUMBER (first_insn) = NOTE_LINE_NUMBER (insn);
- INSN_UID (first_insn) = INSN_UID (insn);
- PREV_INSN (first_insn) = NULL;
- NEXT_INSN (first_insn) = NULL;
- last_insn = first_insn;
-
- /* Each pseudo-reg in the old insn chain must have a unique rtx in the copy.
- Make these new rtx's now, and install them in regno_reg_rtx, so they
- will be the official pseudo-reg rtx's for the rest of compilation. */
-
- reg_map = (rtx *) savealloc (regno_pointer_flag_length * sizeof (rtx));
-
- len = sizeof (struct rtx_def) + (GET_RTX_LENGTH (REG) - 1) * sizeof (rtunion);
- for (i = max_reg - 1; i > LAST_VIRTUAL_REGISTER; i--)
- reg_map[i] = (rtx)obstack_copy (function_maybepermanent_obstack,
- regno_reg_rtx[i], len);
-
- regno_reg_rtx = reg_map;
-
- /* Put copies of all the virtual register rtx into the new regno_reg_rtx. */
- init_virtual_regs ();
-
- /* Likewise each label rtx must have a unique rtx as its copy. */
-
- /* We used to use alloca here, but the size of what it would try to
- allocate would occasionally cause it to exceed the stack limit and
- cause unpredictable core dumps. Some examples were > 2Mb in size. */
- label_map = (rtx *) xmalloc ((max_labelno) * sizeof (rtx));
-
- for (i = min_labelno; i < max_labelno; i++)
- label_map[i] = gen_label_rtx ();
-
- /* Likewise for parm_reg_stack_slot. */
- new_parm_reg_stack_loc = (rtx *) savealloc (max_parm_reg * sizeof (rtx));
- for (i = 0; i < max_parm_reg; i++)
- new_parm_reg_stack_loc[i] = copy_for_inline (parm_reg_stack_loc[i]);
-
- parm_reg_stack_loc = new_parm_reg_stack_loc;
-
- /* Record the mapping of old insns to copied insns. */
-
- insn_map = (rtx *) alloca (max_uid * sizeof (rtx));
- bzero ((char *) insn_map, max_uid * sizeof (rtx));
-
- /* Get the insn which signals the end of parameter setup code. */
- first_nonparm_insn = get_first_nonparm_insn ();
-
- /* Copy any entries in regno_reg_rtx or DECL_RTLs that reference MEM
- (the former occurs when a variable has its address taken)
- since these may be shared and can be changed by virtual
- register instantiation. DECL_RTL values for our arguments
- have already been copied by initialize_for_inline. */
- for (i = LAST_VIRTUAL_REGISTER + 1; i < max_reg; i++)
- if (GET_CODE (regno_reg_rtx[i]) == MEM)
- XEXP (regno_reg_rtx[i], 0)
- = copy_for_inline (XEXP (regno_reg_rtx[i], 0));
-
- /* Copy the parm_reg_stack_loc array, and substitute for all of the rtx
- contained in it. */
- new2 = (rtx *) savealloc (max_parm_reg * sizeof (rtx));
- bcopy ((char *) parm_reg_stack_loc, (char *) new2,
- max_parm_reg * sizeof (rtx));
- parm_reg_stack_loc = new2;
- for (i = LAST_VIRTUAL_REGISTER + 1; i < max_parm_reg; ++i)
- if (parm_reg_stack_loc[i])
- parm_reg_stack_loc[i] = copy_for_inline (parm_reg_stack_loc[i]);
-
- /* Copy the tree of subblocks of the function, and the decls in them.
- We will use the copy for compiling this function, then restore the original
- subblocks and decls for use when inlining this function.
-
- Several parts of the compiler modify BLOCK trees. In particular,
- instantiate_virtual_regs will instantiate any virtual regs
- mentioned in the DECL_RTLs of the decls, and loop
- unrolling will replicate any BLOCK trees inside an unrolled loop.
-
- The modified subblocks or DECL_RTLs would be incorrect for the original rtl
- which we will use for inlining. The rtl might even contain pseudoregs
- whose space has been freed. */
-
- DECL_INITIAL (fndecl) = copy_decl_tree (DECL_INITIAL (fndecl));
- DECL_ARGUMENTS (fndecl) = copy_decl_list (DECL_ARGUMENTS (fndecl));
-
- /* Now copy each DECL_RTL which is a MEM,
- so it is safe to modify their addresses. */
- copy_decl_rtls (DECL_INITIAL (fndecl));
-
- /* The fndecl node acts as its own progenitor, so mark it as such. */
- DECL_ABSTRACT_ORIGIN (fndecl) = fndecl;
-
- /* Now copy the chain of insns. Do this twice. The first copy the insn
- itself and its body. The second time copy of REG_NOTES. This is because
- a REG_NOTE may have a forward pointer to another insn. */
-
- for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
- {
- orig_asm_operands_vector = 0;
-
- if (insn == first_nonparm_insn)
- in_nonparm_insns = 1;
-
- switch (GET_CODE (insn))
- {
- case NOTE:
- /* No need to keep these. */
- if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
- continue;
-
- copy = rtx_alloc (NOTE);
- NOTE_LINE_NUMBER (copy) = NOTE_LINE_NUMBER (insn);
- if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END)
- NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn);
- else
- {
- NOTE_SOURCE_FILE (insn) = (char *) copy;
- NOTE_SOURCE_FILE (copy) = 0;
- }
- if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG
- || NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_END)
- {
- int new_region = CODE_LABEL_NUMBER
- (label_map[NOTE_BLOCK_NUMBER (copy)]);
-
- /* we have to duplicate the handlers for the original */
- if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG)
- {
- handler_info *ptr, *temp;
- int nr;
- nr = new_eh_region_entry (new_region);
- ptr = get_first_handler (NOTE_BLOCK_NUMBER (copy));
- for ( ; ptr; ptr = ptr->next)
- {
- temp = get_new_handler (
- label_map[CODE_LABEL_NUMBER (ptr->handler_label)],
- ptr->type_info);
- add_new_handler (nr, temp);
- }
- }
-
- /* We have to forward these both to match the new exception
- region. */
- NOTE_BLOCK_NUMBER (copy) = new_region;
-
- }
- RTX_INTEGRATED_P (copy) = RTX_INTEGRATED_P (insn);
- break;
-
- case INSN:
- case JUMP_INSN:
- case CALL_INSN:
- copy = rtx_alloc (GET_CODE (insn));
-
- if (GET_CODE (insn) == CALL_INSN)
- CALL_INSN_FUNCTION_USAGE (copy)
- = copy_for_inline (CALL_INSN_FUNCTION_USAGE (insn));
-
- PATTERN (copy) = copy_for_inline (PATTERN (insn));
- INSN_CODE (copy) = -1;
- LOG_LINKS (copy) = NULL_RTX;
- RTX_INTEGRATED_P (copy) = RTX_INTEGRATED_P (insn);
- break;
-
- case CODE_LABEL:
- copy = label_map[CODE_LABEL_NUMBER (insn)];
- LABEL_NAME (copy) = LABEL_NAME (insn);
- break;
-
- case BARRIER:
- copy = rtx_alloc (BARRIER);
- break;
-
- default:
- abort ();
- }
- INSN_UID (copy) = INSN_UID (insn);
- insn_map[INSN_UID (insn)] = copy;
- NEXT_INSN (last_insn) = copy;
- PREV_INSN (copy) = last_insn;
- last_insn = copy;
}
- adjust_copied_decl_tree (DECL_INITIAL (fndecl));
-
- /* Now copy the REG_NOTES. */
- for (insn = NEXT_INSN (get_insns ()); insn; insn = NEXT_INSN (insn))
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
- && insn_map[INSN_UID(insn)])
- REG_NOTES (insn_map[INSN_UID (insn)])
- = copy_for_inline (REG_NOTES (insn));
-
- NEXT_INSN (last_insn) = NULL;
-
- finish_inline (fndecl, head);
-
- /* Make new versions of the register tables. */
- new = (char *) savealloc (regno_pointer_flag_length);
- bcopy (regno_pointer_flag, new, regno_pointer_flag_length);
- new1 = (char *) savealloc (regno_pointer_flag_length);
- bcopy (regno_pointer_align, new1, regno_pointer_flag_length);
-
- regno_pointer_flag = new;
- regno_pointer_align = new1;
-
- set_new_first_and_last_insn (first_insn, last_insn);
-
- if (label_map)
- free (label_map);
+ return arg_vector;
}
/* Copy NODE (as with copy_node). NODE must be a DECL. Set the
@@ -771,81 +295,6 @@ copy_and_set_decl_abstract_origin (node)
return copy;
}
-/* Return a copy of a chain of nodes, chained through the TREE_CHAIN field.
- For example, this can copy a list made of TREE_LIST nodes. While copying,
- set DECL_ABSTRACT_ORIGIN appropriately. */
-
-static tree
-copy_decl_list (list)
- tree list;
-{
- tree head;
- register tree prev, next;
-
- if (list == 0)
- return 0;
-
- head = prev = copy_and_set_decl_abstract_origin (list);
- next = TREE_CHAIN (list);
- while (next)
- {
- register tree copy;
-
- copy = copy_and_set_decl_abstract_origin (next);
- TREE_CHAIN (prev) = copy;
- prev = copy;
- next = TREE_CHAIN (next);
- }
- return head;
-}
-
-/* Make a copy of the entire tree of blocks BLOCK, and return it. */
-
-static tree
-copy_decl_tree (block)
- tree block;
-{
- tree t, vars, subblocks;
-
- vars = copy_decl_list (BLOCK_VARS (block));
- subblocks = 0;
-
- /* Process all subblocks. */
- for (t = BLOCK_SUBBLOCKS (block); t; t = TREE_CHAIN (t))
- {
- tree copy = copy_decl_tree (t);
- TREE_CHAIN (copy) = subblocks;
- subblocks = copy;
- }
-
- t = copy_node (block);
- BLOCK_VARS (t) = vars;
- BLOCK_SUBBLOCKS (t) = nreverse (subblocks);
- /* If the BLOCK being cloned is already marked as having been instantiated
- from something else, then leave that `origin' marking alone. Otherwise,
- mark the clone as having originated from the BLOCK we are cloning. */
- if (BLOCK_ABSTRACT_ORIGIN (t) == NULL_TREE)
- BLOCK_ABSTRACT_ORIGIN (t) = block;
- return t;
-}
-
-/* Copy DECL_RTLs in all decls in the given BLOCK node. */
-
-static void
-copy_decl_rtls (block)
- tree block;
-{
- tree t;
-
- for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
- if (DECL_RTL (t) && GET_CODE (DECL_RTL (t)) == MEM)
- DECL_RTL (t) = copy_for_inline (DECL_RTL (t));
-
- /* Process all subblocks. */
- for (t = BLOCK_SUBBLOCKS (block); t; t = TREE_CHAIN (t))
- copy_decl_rtls (t);
-}
-
/* Make the insns and PARM_DECLs of the current function permanent
and record other information in DECL_SAVED_INSNS to allow inlining
of this function in subsequent calls.
@@ -870,8 +319,11 @@ save_for_inline_nocopy (fndecl)
tree fndecl;
{
rtx insn;
- rtx head;
rtx first_nonparm_insn;
+ rtvec argvec;
+
+ /* Nonzero if past the parm-initialization insns. */
+ int in_nonparm_insns;
/* Set up PARMDECL_MAP which maps pseudo-reg number to its PARM_DECL.
Later we set TREE_READONLY to 0 if the parm is modified inside the fn.
@@ -889,8 +341,7 @@ save_for_inline_nocopy (fndecl)
emit_label (return_label);
}
- head = initialize_for_inline (fndecl, get_first_label_num (),
- max_label_num (), max_reg_num (), 0);
+ argvec = initialize_for_inline (fndecl);
/* If there are insns that copy parms from the stack into pseudo registers,
those insns are not copied. `expand_inline_function' must
@@ -903,6 +354,9 @@ save_for_inline_nocopy (fndecl)
/* Get the insn which signals the end of parameter setup code. */
first_nonparm_insn = get_first_nonparm_insn ();
+ /* Assume we start out in the insns that set up the parameters. */
+ in_nonparm_insns = 0;
+
/* Now just scan the chain of insns to see what happens to our
PARM_DECLs. If a PARM_DECL is used but never modified, we
can substitute its rtl directly when expanding inline (and
@@ -928,7 +382,8 @@ save_for_inline_nocopy (fndecl)
}
/* Record what interesting things happen to our parameters. */
- note_stores (PATTERN (insn), note_modified_parmregs);
+ if (in_nonparm_insns)
+ note_stores (PATTERN (insn), note_modified_parmregs);
}
}
@@ -942,7 +397,13 @@ save_for_inline_nocopy (fndecl)
preserve_data ();
- finish_inline (fndecl, head);
+ /* We'll regenerate the constant pool later; for now delete it. */
+ free_varasm_status (current_function);
+
+ current_function->max_label_num = max_label_num ();
+ current_function->original_arg_vector = argvec;
+ current_function->original_decl_initial = DECL_INITIAL (fndecl);
+ DECL_SAVED_INSNS (fndecl) = current_function;
}
/* Given PX, a pointer into an insn, search for references to the constant
@@ -1033,265 +494,13 @@ note_modified_parmregs (reg, x)
rtx reg;
rtx x ATTRIBUTE_UNUSED;
{
- if (GET_CODE (reg) == REG && in_nonparm_insns
+ if (GET_CODE (reg) == REG
&& REGNO (reg) < max_parm_reg
&& REGNO (reg) >= FIRST_PSEUDO_REGISTER
&& parmdecl_map[REGNO (reg)] != 0)
TREE_READONLY (parmdecl_map[REGNO (reg)]) = 0;
}
-/* Copy the rtx ORIG recursively, replacing pseudo-regs and labels
- according to `reg_map' and `label_map'. The original rtl insns
- will be saved for inlining; this is used to make a copy
- which is used to finish compiling the inline function itself.
-
- If we find a "saved" constant pool entry, one which was replaced with
- the value of the constant, convert it back to a constant pool entry.
- Since the pool wasn't touched, this should simply restore the old
- address.
-
- All other kinds of rtx are copied except those that can never be
- changed during compilation. */
-
-static rtx
-copy_for_inline (orig)
- rtx orig;
-{
- register rtx x = orig;
- register rtx new;
- register int i;
- register enum rtx_code code;
- register char *format_ptr;
-
- if (x == 0)
- return x;
-
- code = GET_CODE (x);
-
- /* These types may be freely shared. */
-
- switch (code)
- {
- case QUEUED:
- case CONST_INT:
- case SYMBOL_REF:
- case PC:
- case CC0:
- return x;
-
- case CONST_DOUBLE:
- /* We have to make a new CONST_DOUBLE to ensure that we account for
- it correctly. Using the old CONST_DOUBLE_MEM data is wrong. */
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
- {
- REAL_VALUE_TYPE d;
-
- REAL_VALUE_FROM_CONST_DOUBLE (d, x);
- return CONST_DOUBLE_FROM_REAL_VALUE (d, GET_MODE (x));
- }
- else
- return immed_double_const (CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x),
- VOIDmode);
-
- case CONST:
- /* Get constant pool entry for constant in the pool. */
- if (RTX_INTEGRATED_P (x))
- return validize_mem (force_const_mem (GET_MODE (x),
- copy_for_inline (XEXP (x, 0))));
- break;
-
- case SUBREG:
- /* Get constant pool entry, but access in different mode. */
- if (RTX_INTEGRATED_P (x))
- {
- new = force_const_mem (GET_MODE (SUBREG_REG (x)),
- copy_for_inline (XEXP (SUBREG_REG (x), 0)));
-
- PUT_MODE (new, GET_MODE (x));
- return validize_mem (new);
- }
- break;
-
- case ADDRESS:
- /* If not special for constant pool error. Else get constant pool
- address. */
- if (! RTX_INTEGRATED_P (x))
- abort ();
-
- new = force_const_mem (GET_MODE (XEXP (x, 0)),
- copy_for_inline (XEXP (XEXP (x, 0), 0)));
- new = XEXP (new, 0);
-
-#ifdef POINTERS_EXTEND_UNSIGNED
- if (GET_MODE (new) != GET_MODE (x))
- new = convert_memory_address (GET_MODE (x), new);
-#endif
-
- return new;
-
- case ASM_OPERANDS:
- /* If a single asm insn contains multiple output operands
- then it contains multiple ASM_OPERANDS rtx's that share operand 3.
- We must make sure that the copied insn continues to share it. */
- if (orig_asm_operands_vector == XVEC (orig, 3))
- {
- x = rtx_alloc (ASM_OPERANDS);
- x->volatil = orig->volatil;
- XSTR (x, 0) = XSTR (orig, 0);
- XSTR (x, 1) = XSTR (orig, 1);
- XINT (x, 2) = XINT (orig, 2);
- XVEC (x, 3) = copy_asm_operands_vector;
- XVEC (x, 4) = copy_asm_constraints_vector;
- XSTR (x, 5) = XSTR (orig, 5);
- XINT (x, 6) = XINT (orig, 6);
- return x;
- }
- break;
-
- case MEM:
- /* A MEM is usually allowed to be shared if its address is constant
- or is a constant plus one of the special registers.
-
- We do not allow sharing of addresses that are either a special
- register or the sum of a constant and a special register because
- it is possible for unshare_all_rtl to copy the address, into memory
- that won't be saved. Although the MEM can safely be shared, and
- won't be copied there, the address itself cannot be shared, and may
- need to be copied.
-
- There are also two exceptions with constants: The first is if the
- constant is a LABEL_REF or the sum of the LABEL_REF
- and an integer. This case can happen if we have an inline
- function that supplies a constant operand to the call of another
- inline function that uses it in a switch statement. In this case,
- we will be replacing the LABEL_REF, so we have to replace this MEM
- as well.
-
- The second case is if we have a (const (plus (address ..) ...)).
- In that case we need to put back the address of the constant pool
- entry. */
-
- if (CONSTANT_ADDRESS_P (XEXP (x, 0))
- && GET_CODE (XEXP (x, 0)) != LABEL_REF
- && ! (GET_CODE (XEXP (x, 0)) == CONST
- && (GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
- && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
- == LABEL_REF)
- || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
- == ADDRESS)))))
- return x;
- break;
-
- case LABEL_REF:
- /* If this is a non-local label, just make a new LABEL_REF.
- Otherwise, use the new label as well. */
- x = gen_rtx_LABEL_REF (GET_MODE (orig),
- LABEL_REF_NONLOCAL_P (orig) ? XEXP (orig, 0)
- : label_map[CODE_LABEL_NUMBER (XEXP (orig, 0))]);
- LABEL_REF_NONLOCAL_P (x) = LABEL_REF_NONLOCAL_P (orig);
- LABEL_OUTSIDE_LOOP_P (x) = LABEL_OUTSIDE_LOOP_P (orig);
- return x;
-
- case REG:
- if (REGNO (x) > LAST_VIRTUAL_REGISTER)
- return reg_map [REGNO (x)];
- else
- return x;
-
- case SET:
- /* If a parm that gets modified lives in a pseudo-reg,
- clear its TREE_READONLY to prevent certain optimizations. */
- {
- rtx dest = SET_DEST (x);
-
- while (GET_CODE (dest) == STRICT_LOW_PART
- || GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SUBREG)
- dest = XEXP (dest, 0);
-
- if (GET_CODE (dest) == REG
- && REGNO (dest) < max_parm_reg
- && REGNO (dest) >= FIRST_PSEUDO_REGISTER
- && parmdecl_map[REGNO (dest)] != 0
- /* The insn to load an arg pseudo from a stack slot
- does not count as modifying it. */
- && in_nonparm_insns)
- TREE_READONLY (parmdecl_map[REGNO (dest)]) = 0;
- }
- break;
-
-#if 0 /* This is a good idea, but here is the wrong place for it. */
- /* Arrange that CONST_INTs always appear as the second operand
- if they appear, and that `frame_pointer_rtx' or `arg_pointer_rtx'
- always appear as the first. */
- case PLUS:
- if (GET_CODE (XEXP (x, 0)) == CONST_INT
- || (XEXP (x, 1) == frame_pointer_rtx
- || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
- && XEXP (x, 1) == arg_pointer_rtx)))
- {
- rtx t = XEXP (x, 0);
- XEXP (x, 0) = XEXP (x, 1);
- XEXP (x, 1) = t;
- }
- break;
-#endif
- default:
- break;
- }
-
- /* Replace this rtx with a copy of itself. */
-
- x = rtx_alloc (code);
- bcopy ((char *) orig, (char *) x,
- (sizeof (*x) - sizeof (x->fld)
- + sizeof (x->fld[0]) * GET_RTX_LENGTH (code)));
-
- /* Now scan the subexpressions recursively.
- We can store any replaced subexpressions directly into X
- since we know X is not shared! Any vectors in X
- must be copied if X was copied. */
-
- format_ptr = GET_RTX_FORMAT (code);
-
- for (i = 0; i < GET_RTX_LENGTH (code); i++)
- {
- switch (*format_ptr++)
- {
- case 'e':
- XEXP (x, i) = copy_for_inline (XEXP (x, i));
- break;
-
- case 'u':
- /* Change any references to old-insns to point to the
- corresponding copied insns. */
- XEXP (x, i) = insn_map[INSN_UID (XEXP (x, i))];
- break;
-
- case 'E':
- if (XVEC (x, i) != NULL && XVECLEN (x, i) != 0)
- {
- register int j;
-
- XVEC (x, i) = gen_rtvec_vv (XVECLEN (x, i), XVEC (x, i)->elem);
- for (j = 0; j < XVECLEN (x, i); j++)
- XVECEXP (x, i, j)
- = copy_for_inline (XVECEXP (x, i, j));
- }
- break;
- }
- }
-
- if (code == ASM_OPERANDS && orig_asm_operands_vector == 0)
- {
- orig_asm_operands_vector = XVEC (orig, 3);
- copy_asm_operands_vector = XVEC (x, 3);
- copy_asm_constraints_vector = XVEC (x, 4);
- }
-
- return x;
-}
-
/* Unfortunately, we need a global copy of const_equiv map for communication
with a function called from note_stores. Be *very* careful that this
is used properly in the presence of recursion. */
@@ -1359,17 +568,19 @@ expand_inline_function (fndecl, parms, target, ignore, type,
tree type;
rtx structure_value_addr;
{
+ struct function *inl_f = DECL_SAVED_INSNS (fndecl);
tree formal, actual, block;
- rtx header = DECL_SAVED_INSNS (fndecl);
- rtx insns = FIRST_FUNCTION_INSN (header);
- rtx parm_insns = FIRST_PARM_INSN (header);
+ rtx parm_insns = inl_f->emit->x_first_insn;
+ rtx insns = (inl_f->func->saved_last_parm_insn
+ ? NEXT_INSN (inl_f->func->saved_last_parm_insn)
+ : parm_insns);
tree *arg_trees;
rtx *arg_vals;
rtx insn;
int max_regno;
register int i;
- int min_labelno = FIRST_LABELNO (header);
- int max_labelno = LAST_LABELNO (header);
+ int min_labelno = inl_f->emit->x_first_label_num;
+ int max_labelno = inl_f->max_label_num;
int nargs;
rtx local_return_label = 0;
rtx loc;
@@ -1379,15 +590,16 @@ expand_inline_function (fndecl, parms, target, ignore, type,
#ifdef HAVE_cc0
rtx cc0_insn = 0;
#endif
- rtvec arg_vector = ORIGINAL_ARG_VECTOR (header);
+ rtvec arg_vector = (rtvec) inl_f->original_arg_vector;
rtx static_chain_value = 0;
+ int inl_max_uid;
/* The pointer used to track the true location of the memory used
for MAP->LABEL_MAP. */
rtx *real_label_map = 0;
/* Allow for equivalences of the pseudos we make for virtual fp and ap. */
- max_regno = MAX_REGNUM (header) + 3;
+ max_regno = inl_f->emit->x_reg_rtx_no + 3;
if (max_regno < FIRST_PSEUDO_REGISTER)
abort ();
@@ -1529,10 +741,11 @@ expand_inline_function (fndecl, parms, target, ignore, type,
= (rtx *) xmalloc ((max_labelno) * sizeof (rtx));
map->label_map = real_label_map;
- map->insn_map = (rtx *) alloca (INSN_UID (header) * sizeof (rtx));
- bzero ((char *) map->insn_map, INSN_UID (header) * sizeof (rtx));
+ inl_max_uid = (inl_f->emit->x_cur_insn_uid + 1);
+ map->insn_map = (rtx *) alloca (inl_max_uid * sizeof (rtx));
+ bzero ((char *) map->insn_map, inl_max_uid * sizeof (rtx));
map->min_insnno = 0;
- map->max_insnno = INSN_UID (header);
+ map->max_insnno = inl_max_uid;
map->integrating = 1;
@@ -1569,21 +782,21 @@ expand_inline_function (fndecl, parms, target, ignore, type,
if (map->insns_at_start == 0)
map->insns_at_start = emit_note (NULL_PTR, NOTE_INSN_DELETED);
- map->regno_pointer_flag = INLINE_REGNO_POINTER_FLAG (header);
- map->regno_pointer_align = INLINE_REGNO_POINTER_ALIGN (header);
+ map->x_regno_pointer_flag = inl_f->emit->x_regno_pointer_flag;
+ map->x_regno_pointer_align = inl_f->emit->x_regno_pointer_align;
/* Update the outgoing argument size to allow for those in the inlined
function. */
- if (OUTGOING_ARGS_SIZE (header) > current_function_outgoing_args_size)
- current_function_outgoing_args_size = OUTGOING_ARGS_SIZE (header);
+ if (inl_f->func->outgoing_args_size > current_function_outgoing_args_size)
+ current_function_outgoing_args_size = inl_f->func->outgoing_args_size;
/* If the inline function needs to make PIC references, that means
that this function's PIC offset table must be used. */
- if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE)
+ if (inl_f->func->uses_pic_offset_table)
current_function_uses_pic_offset_table = 1;
/* If this function needs a context, set it up. */
- if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_NEEDS_CONTEXT)
+ if (inl_f->func->needs_context)
static_chain_value = lookup_static_chain (fndecl);
if (GET_CODE (parm_insns) == NOTE
@@ -1840,7 +1053,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
stack pointer around the call. This saves stack space, but
also is required if this inline is being done between two
pushes. */
- if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_CALLS_ALLOCA)
+ if (inl_f->func->calls_alloca)
emit_stack_save (SAVE_BLOCK, &stack_save, NULL_RTX);
/* Now copy the insns one by one. Do this in two passes, first the insns and
@@ -2108,7 +1321,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
emit_label (local_return_label);
/* Restore the stack pointer if we saved it above. */
- if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_CALLS_ALLOCA)
+ if (inl_f->func->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
@@ -2118,7 +1331,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
inline_function_decl = fndecl;
integrate_parm_decls (DECL_ARGUMENTS (fndecl), map, arg_vector);
- integrate_decl_tree ((tree) ORIGINAL_DECL_INITIAL (header), 0, map);
+ integrate_decl_tree (inl_f->original_decl_initial, 0, map);
inline_function_decl = 0;
/* End the scope containing the copied formal parameter variables
@@ -2335,7 +1548,7 @@ copy_rtx_and_substitute (orig, map)
if (regno == VIRTUAL_STACK_VARS_REGNUM)
{
rtx loc, seq;
- int size = DECL_FRAME_SIZE (map->fndecl);
+ int size = get_func_frame_size (DECL_SAVED_INSNS (map->fndecl));
#ifdef FRAME_GROWS_DOWNWARD
/* In this case, virtual_stack_vars_rtx points to one byte
@@ -2377,7 +1590,7 @@ copy_rtx_and_substitute (orig, map)
/* Do the same for a block to contain any arguments referenced
in memory. */
rtx loc, seq;
- int size = FUNCTION_ARGS_SIZE (DECL_SAVED_INSNS (map->fndecl));
+ int size = DECL_SAVED_INSNS (map->fndecl)->func->args_size;
start_sequence ();
loc = assign_stack_temp (BLKmode, size, 1);
@@ -2432,9 +1645,9 @@ copy_rtx_and_substitute (orig, map)
RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (orig);
/* A reg with REG_FUNCTION_VALUE_P true will never reach here. */
- if (map->regno_pointer_flag[regno])
+ if (map->x_regno_pointer_flag[regno])
mark_reg_pointer (map->reg_map[regno],
- map->regno_pointer_align[regno]);
+ map->x_regno_pointer_align[regno]);
}
return map->reg_map[regno];
@@ -2466,9 +1679,9 @@ copy_rtx_and_substitute (orig, map)
RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (temp);
/* A reg with REG_FUNCTION_VALUE_P true will never reach here. */
- if (map->regno_pointer_flag[regno])
+ if (map->x_regno_pointer_flag[regno])
mark_reg_pointer (map->reg_map[regno],
- map->regno_pointer_align[regno]);
+ map->x_regno_pointer_align[regno]);
regno = REGNO (map->reg_map[regno]);
}
ADDRESSOF_REGNO (copy) = regno;
@@ -3333,78 +2546,16 @@ void
output_inline_function (fndecl)
tree fndecl;
{
- rtx head;
+ struct function *f = DECL_SAVED_INSNS (fndecl);
rtx last;
- /* Things we allocate from here on are part of this function, not
- permanent. */
- temporary_allocation ();
-
- head = DECL_SAVED_INSNS (fndecl);
+ current_function = f;
current_function_decl = fndecl;
-
- /* This call is only used to initialize global variables. */
- init_function_start (fndecl, "lossage", 1);
-
- /* Redo parameter determinations in case the FUNCTION_...
- macros took machine-specific actions that need to be redone. */
- assign_parms (fndecl, 1);
-
- /* Set stack frame size. */
- assign_stack_local (BLKmode, DECL_FRAME_SIZE (fndecl), 0);
-
- /* The first is a bit of a lie (the array may be larger), but doesn't
- matter too much and it isn't worth saving the actual bound. */
- reg_rtx_no = regno_pointer_flag_length = MAX_REGNUM (head);
- regno_reg_rtx = (rtx *) INLINE_REGNO_REG_RTX (head);
- regno_pointer_flag = INLINE_REGNO_POINTER_FLAG (head);
- regno_pointer_align = INLINE_REGNO_POINTER_ALIGN (head);
- max_parm_reg = MAX_PARMREG (head);
- parm_reg_stack_loc = (rtx *) PARMREG_STACK_LOC (head);
-
- stack_slot_list = STACK_SLOT_LIST (head);
- forced_labels = FORCED_LABELS (head);
-
- if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_ALLOCA)
- current_function_calls_alloca = 1;
-
- if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_SETJMP)
- current_function_calls_setjmp = 1;
-
- if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_LONGJMP)
- current_function_calls_longjmp = 1;
-
- if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_RETURNS_STRUCT)
- current_function_returns_struct = 1;
-
- if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_RETURNS_PCC_STRUCT)
- current_function_returns_pcc_struct = 1;
-
- if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_NEEDS_CONTEXT)
- current_function_needs_context = 1;
-
- if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_HAS_NONLOCAL_LABEL)
- current_function_has_nonlocal_label = 1;
-
- if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_RETURNS_POINTER)
- current_function_returns_pointer = 1;
-
- if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_USES_CONST_POOL)
- current_function_uses_const_pool = 1;
-
- if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE)
- current_function_uses_pic_offset_table = 1;
-
- current_function_outgoing_args_size = OUTGOING_ARGS_SIZE (head);
- current_function_pops_args = POPS_ARGS (head);
-
- /* This is the only thing the expand_function_end call that uses to be here
- actually does and that call can cause problems. */
- immediate_size_expand--;
+ cur_f_s = f->func;
/* Find last insn and rebuild the constant pool. */
- for (last = FIRST_PARM_INSN (head);
- NEXT_INSN (last); last = NEXT_INSN (last))
+ init_const_rtx_hash_table ();
+ for (last = get_insns (); NEXT_INSN (last); last = NEXT_INSN (last))
{
if (GET_RTX_CLASS (GET_CODE (last)) == 'i')
{
@@ -3413,8 +2564,7 @@ output_inline_function (fndecl)
}
}
- set_new_first_and_last_insn (FIRST_PARM_INSN (head), last);
- set_new_first_and_last_label_num (FIRST_LABELNO (head), LAST_LABELNO (head));
+ set_new_last_label_num (f->max_label_num);
/* We must have already output DWARF debugging information for the
original (abstract) inline function declaration/definition, so
@@ -3431,10 +2581,9 @@ output_inline_function (fndecl)
DECL_DEFER_OUTPUT (fndecl) = 0;
/* We can't inline this anymore. */
+ f->inlinable = 0;
DECL_INLINE (fndecl) = 0;
/* Compile this function all the way down to assembly code. */
rest_of_compilation (fndecl);
-
- current_function_decl = 0;
}
diff --git a/gcc/integrate.h b/gcc/integrate.h
index 23e2e561d94..ce766e96c77 100644
--- a/gcc/integrate.h
+++ b/gcc/integrate.h
@@ -94,8 +94,8 @@ struct inline_remap
rtvec copy_asm_constraints_vector;
/* Indications for regs being pointers and their alignment. */
- char *regno_pointer_flag;
- char *regno_pointer_align;
+ char *x_regno_pointer_flag;
+ char *x_regno_pointer_align;
/* The next few fields are used for subst_constants to record the SETs
that it saw. */
diff --git a/gcc/jump.c b/gcc/jump.c
index 967981aef44..5eebbac2452 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -54,6 +54,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "rtl.h"
+#include "function.h"
#include "flags.h"
#include "hard-reg-set.h"
#include "regs.h"
@@ -88,10 +89,6 @@ Boston, MA 02111-1307, USA. */
static rtx *jump_chain;
-/* List of labels referred to from initializers.
- These can never be deleted. */
-rtx forced_labels;
-
/* Maximum index in jump_chain. */
static int max_jump_chain;
diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c
index 3bcd4f8e1b1..e3b1667b403 100644
--- a/gcc/local-alloc.c
+++ b/gcc/local-alloc.c
@@ -62,6 +62,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "rtl.h"
+#include "function.h"
#include "flags.h"
#include "basic-block.h"
#include "regs.h"
diff --git a/gcc/loop.c b/gcc/loop.c
index 4529946d1a9..fdf6d28723a 100644
--- a/gcc/loop.c
+++ b/gcc/loop.c
@@ -37,6 +37,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "rtl.h"
+#include "function.h"
#include "obstack.h"
#include "expr.h"
#include "insn-config.h"
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 878a2eaee38..c11a16dff25 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "rtl.h"
#include "tree.h"
+#include "function.h"
#include "flags.h"
#include "insn-flags.h"
#include "insn-codes.h"
@@ -30,6 +31,7 @@ Boston, MA 02111-1307, USA. */
#include "insn-config.h"
#include "recog.h"
#include "reload.h"
+#include "ggc.h"
/* Each optab contains info on how this target machine
can perform a particular operation
diff --git a/gcc/output.h b/gcc/output.h
index 1d1a2afd8cd..8e6ce63b961 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -338,115 +338,9 @@ extern int which_alternative;
extern rtx final_sequence;
#endif
-/* Number of bytes of args popped by function being compiled on its return.
- Zero if no bytes are to be popped.
- May affect compilation of return insn or of function epilogue. */
-
-extern int current_function_pops_args;
-
-/* Nonzero if function being compiled needs to be given an address
- where the value should be stored. */
-
-extern int current_function_returns_struct;
-
-/* Nonzero if function being compiled needs to
- return the address of where it has put a structure value. */
-
-extern int current_function_returns_pcc_struct;
-
-/* Nonzero if function being compiled needs to be passed a static chain. */
-
-extern int current_function_needs_context;
-
-/* Nonzero if function being compiled can call setjmp. */
-
-extern int current_function_calls_setjmp;
-
-/* Nonzero if function being compiled can call longjmp. */
-
-extern int current_function_calls_longjmp;
-
-/* Nonzero if function being compiled can call alloca,
- either as a subroutine or builtin. */
-
-extern int current_function_calls_alloca;
-
-/* Nonzero if function being compiled receives nonlocal gotos
- from nested functions. */
-
-extern int current_function_has_nonlocal_label;
-
-/* Nonzero if function being compiled contains nested functions. */
-
-extern int current_function_contains_functions;
-
-/* Nonzero if the current function returns a pointer type */
-
-extern int current_function_returns_pointer;
-
-/* If function's args have a fixed size, this is that size, in bytes.
- Otherwise, it is -1.
- May affect compilation of return insn or of function epilogue. */
-
-extern int current_function_args_size;
-
-/* # bytes the prologue should push and pretend that the caller pushed them.
- The prologue must do this, but only if parms can be passed in registers. */
-
-extern int current_function_pretend_args_size;
-
-/* # of bytes of outgoing arguments required to be pushed by the prologue.
- If this is non-zero, it means that ACCUMULATE_OUTGOING_ARGS was defined
- and no stack adjusts will be done on function calls. */
-
-extern int current_function_outgoing_args_size;
-
-/* Nonzero if current function uses varargs.h or equivalent.
- Zero for functions that use stdarg.h. */
-
-extern int current_function_varargs;
-
-/* Nonzero if current function uses stdarg.h or equivalent.
- Zero for functions that use varargs.h. */
-
-extern int current_function_stdarg;
-
-/* Quantities of various kinds of registers
- used for the current function's args. */
-
-extern CUMULATIVE_ARGS current_function_args_info;
-
-/* Name of function now being compiled. */
-
-extern char *current_function_name;
-
-#ifdef RTX_CODE
-/* If non-zero, an RTL expression for that location at which the current
- function returns its result. Usually equal to
- DECL_RTL (DECL_RESULT (current_function_decl)). */
-
-extern rtx current_function_return_rtx;
-
-/* If some insns can be deferred to the delay slots of the epilogue, the
- delay list for them is recorded here. */
-
-extern rtx current_function_epilogue_delay_list;
-#endif
-
-/* Nonzero means generate position-independent code.
- This is not fully implemented yet. */
-
+/* Nonzero means generate position-independent code. */
extern int flag_pic;
-/* This is nonzero if the current function uses pic_offset_table_rtx. */
-extern int current_function_uses_pic_offset_table;
-
-/* This is nonzero if the current function uses the constant pool. */
-extern int current_function_uses_const_pool;
-
-/* Language-specific reason why the current function cannot be made inline. */
-extern char *current_function_cannot_inline;
-
/* The line number of the beginning of the current function.
sdbout.c needs this so that it can output relative linenumbers. */
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index 096218fac1d..851b06636e7 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -401,7 +401,9 @@ print_node (file, prefix, node, indent)
if (TREE_CODE (node) != FUNCTION_DECL)
fprintf (file, " align %d", DECL_ALIGN (node));
else if (DECL_INLINE (node))
- fprintf (file, " frame_size %d", DECL_FRAME_SIZE (node));
+ {
+ /* print various information here... */
+ }
else if (DECL_BUILT_IN (node))
fprintf (file, " built-in code %d", DECL_FUNCTION_CODE (node));
if (TREE_CODE (node) == FIELD_DECL)
diff --git a/gcc/profile.c b/gcc/profile.c
index b06f91bb4fc..b0f2c1e1de5 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -43,15 +43,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "system.h"
#include "rtl.h"
+#include "tree.h"
+#include "function.h"
#include "flags.h"
#include "insn-flags.h"
#include "insn-config.h"
#include "output.h"
#include "regs.h"
-#include "tree.h"
#include "output.h"
#include "gcov-io.h"
#include "toplev.h"
+#include "ggc.h"
extern char * xmalloc ();
@@ -1544,6 +1546,7 @@ init_arc_profiler ()
char *name = xmalloc (20);
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
profiler_label = gen_rtx_SYMBOL_REF (Pmode, name);
+ ggc_add_rtx_root (&profiler_label, 1);
}
/* Output instructions as RTL to increment the arc execution count. */
@@ -1647,10 +1650,6 @@ output_func_start_profiler ()
need_func_profiler = 0;
- /* Synthesize a constructor function to invoke __bb_init_func with a
- pointer to this object file's profile block. */
- start_sequence ();
-
/* Try and make a unique name given the "file function name".
And no, I don't like this either. */
@@ -1674,6 +1673,10 @@ output_func_start_profiler ()
init_function_start (fndecl, input_filename, lineno);
expand_function_start (fndecl, 0);
+ /* Synthesize a constructor function to invoke __bb_init_func with a
+ pointer to this object file's profile block. */
+ start_sequence ();
+
/* Actually generate the code to call __bb_init_func. */
name = xmalloc (20);
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index a7a5fb7cd90..387ae8c6829 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -161,6 +161,7 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "tree.h"
#include "rtl.h"
+#include "function.h"
#include "insn-config.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -232,8 +233,6 @@ static rtx
((INSN_UID (INSN) > max_uid) \
? (abort() , -1) : block_number[INSN_UID (INSN)])
-extern rtx forced_labels;
-
/* Forward declarations */
static void mark_regs_pat PROTO((rtx, HARD_REG_SET *));
diff --git a/gcc/regclass.c b/gcc/regclass.c
index cd882df5cd1..03872ac4dba 100644
--- a/gcc/regclass.c
+++ b/gcc/regclass.c
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "rtl.h"
#include "hard-reg-set.h"
+#include "function.h"
#include "flags.h"
#include "basic-block.h"
#include "regs.h"
diff --git a/gcc/regmove.c b/gcc/regmove.c
index 41235f13704..e0af189e422 100644
--- a/gcc/regmove.c
+++ b/gcc/regmove.c
@@ -25,7 +25,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "system.h"
-#include "rtl.h" /* stdio.h must precede rtl.h for FFS. */
+#include "rtl.h"
+#include "function.h"
#include "insn-config.h"
#include "recog.h"
#include "output.h"
diff --git a/gcc/regs.h b/gcc/regs.h
index 1ececb3c6a7..c12f7f996fc 100644
--- a/gcc/regs.h
+++ b/gcc/regs.h
@@ -170,28 +170,10 @@ extern enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
#define REGNO_LAST_NOTE_UID(N) (VARRAY_REG (reg_n_info, N)->last_note_uid)
-/* This is reset to LAST_VIRTUAL_REGISTER + 1 at the start of each function.
- After rtl generation, it is 1 plus the largest register number used. */
-
-extern int reg_rtx_no;
-
-/* Vector indexed by regno; contains 1 for a register is considered a pointer.
- Reloading, etc. will use a pointer register rather than a non-pointer
- as the base register in an address, when there is a choice of two regs. */
-
-extern char *regno_pointer_flag;
-#define REGNO_POINTER_FLAG(REGNO) regno_pointer_flag[REGNO]
-extern int regno_pointer_flag_length;
-
/* List made of EXPR_LIST rtx's which gives pairs of pseudo registers
that have to go in the same hard reg. */
extern rtx regs_may_share;
-/* Vector mapping pseudo regno into the REG rtx for that register.
- This is computed by reg_scan. */
-
-extern rtx *regno_reg_rtx;
-
/* Flag set by local-alloc or global-alloc if they decide to allocate
something in a call-clobbered register. */
diff --git a/gcc/reload.c b/gcc/reload.c
index 428ce879894..eea1a0b9f3b 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -90,6 +90,7 @@ a register with any other reload. */
#include "config.h"
#include "system.h"
#include "rtl.h"
+#include "function.h"
#include "insn-config.h"
#include "insn-codes.h"
#include "recog.h"
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 15a43eeca41..7caa58f6e85 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA. */
#include "machmode.h"
#include "hard-reg-set.h"
#include "rtl.h"
+#include "function.h"
#include "obstack.h"
#include "insn-config.h"
#include "insn-flags.h"
@@ -291,9 +292,6 @@ char *reload_firstobj;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-/* List of labels that must never be deleted. */
-extern rtx forced_labels;
-
/* List of insn_chain instructions, one for every insn that reload needs to
examine. */
struct insn_chain *reload_insn_chain;
diff --git a/gcc/rtl.h b/gcc/rtl.h
index ec78c66ad17..f06a0c6781a 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -627,67 +627,6 @@ extern char *note_insn_name[];
/* 1 means a SYMBOL_REF has been the library function in emit_library_call. */
#define SYMBOL_REF_USED(RTX) ((RTX)->used)
-/* For an INLINE_HEADER rtx, FIRST_FUNCTION_INSN is the first insn
- of the function that is not involved in copying parameters to
- pseudo-registers. FIRST_PARM_INSN is the very first insn of
- the function, including the parameter copying.
- We keep this around in case we must splice
- this function into the assembly code at the end of the file.
- FIRST_LABELNO is the first label number used by the function (inclusive).
- LAST_LABELNO is the last label used by the function (exclusive).
- MAX_REGNUM is the largest pseudo-register used by that function.
- FUNCTION_ARGS_SIZE is the size of the argument block in the stack.
- POPS_ARGS is the number of bytes of input arguments popped by the function
- STACK_SLOT_LIST is the list of stack slots.
- FORCED_LABELS is the list of labels whose address was taken.
- FUNCTION_FLAGS are where single-bit flags are saved.
- OUTGOING_ARGS_SIZE is the size of the largest outgoing stack parameter list.
- ORIGINAL_ARG_VECTOR is a vector of the original DECL_RTX values
- for the function arguments.
- ORIGINAL_DECL_INITIAL is a pointer to the original DECL_INITIAL for the
- function.
- INLINE_REGNO_REG_RTX, INLINE_REGNO_POINTER_FLAG, and
- INLINE_REGNO_POINTER_ALIGN are pointers to the corresponding arrays.
-
- We want this to lay down like an INSN. The PREV_INSN field
- is always NULL. The NEXT_INSN field always points to the
- first function insn of the function being squirreled away. */
-
-#define FIRST_FUNCTION_INSN(RTX) ((RTX)->fld[2].rtx)
-#define FIRST_PARM_INSN(RTX) ((RTX)->fld[3].rtx)
-#define FIRST_LABELNO(RTX) ((RTX)->fld[4].rtint)
-#define LAST_LABELNO(RTX) ((RTX)->fld[5].rtint)
-#define MAX_PARMREG(RTX) ((RTX)->fld[6].rtint)
-#define MAX_REGNUM(RTX) ((RTX)->fld[7].rtint)
-#define FUNCTION_ARGS_SIZE(RTX) ((RTX)->fld[8].rtint)
-#define POPS_ARGS(RTX) ((RTX)->fld[9].rtint)
-#define STACK_SLOT_LIST(RTX) ((RTX)->fld[10].rtx)
-#define FORCED_LABELS(RTX) ((RTX)->fld[11].rtx)
-#define FUNCTION_FLAGS(RTX) ((RTX)->fld[12].rtint)
-#define OUTGOING_ARGS_SIZE(RTX) ((RTX)->fld[13].rtint)
-#define ORIGINAL_ARG_VECTOR(RTX) ((RTX)->fld[14].rtvec)
-#define ORIGINAL_DECL_INITIAL(RTX) (*(tree *) &(RTX)->fld[15].rtx)
-#define INLINE_REGNO_REG_RTX(RTX) (*(rtx **) &(RTX)->fld[16].rtx)
-#define INLINE_REGNO_POINTER_FLAG(RTX) ((RTX)->fld[17].rtstr)
-#define INLINE_REGNO_POINTER_ALIGN(RTX) ((RTX)->fld[18].rtstr)
-#define PARMREG_STACK_LOC(RTX) (*(rtx **) &(RTX)->fld[19].rtx)
-
-/* In FUNCTION_FLAGS we save some variables computed when emitting the code
- for the function and which must be `or'ed into the current flag values when
- insns from that function are being inlined. */
-
-/* These ought to be an enum, but non-ANSI compilers don't like that. */
-#define FUNCTION_FLAGS_CALLS_ALLOCA 01
-#define FUNCTION_FLAGS_CALLS_SETJMP 02
-#define FUNCTION_FLAGS_RETURNS_STRUCT 04
-#define FUNCTION_FLAGS_RETURNS_PCC_STRUCT 010
-#define FUNCTION_FLAGS_NEEDS_CONTEXT 020
-#define FUNCTION_FLAGS_HAS_NONLOCAL_LABEL 040
-#define FUNCTION_FLAGS_RETURNS_POINTER 0100
-#define FUNCTION_FLAGS_USES_CONST_POOL 0200
-#define FUNCTION_FLAGS_CALLS_LONGJMP 0400
-#define FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE 01000
-
/* Define a macro to look for REG_INC notes,
but save time on machines where they never exist. */
@@ -1208,15 +1147,6 @@ extern int reload_in_progress;
the same indirect address eventually. */
extern int cse_not_expected;
-/* Indexed by pseudo register number, gives the rtx for that pseudo.
- Allocated in parallel with regno_pointer_flag. */
-extern rtx *regno_reg_rtx;
-
-/* Vector indexed by regno; contain the alignment in bytes and type
- pointed to for a register that contains a pointer, if known. */
-extern char *regno_pointer_align;
-#define REGNO_POINTER_ALIGN(REGNO) regno_pointer_align[REGNO]
-
/* Translates rtx code to tree code, for those codes needed by
REAL_ARITHMETIC. The function returns an int because the caller may not
know what `enum tree_code' means. */
@@ -1306,6 +1236,7 @@ extern int subreg_realpart_p PROTO ((rtx));
extern void reverse_comparison PROTO ((rtx));
extern void set_new_first_and_last_insn PROTO ((rtx, rtx));
extern void set_new_first_and_last_label_num PROTO ((int, int));
+extern void set_new_last_label_num PROTO ((int));
extern void unshare_all_rtl PROTO ((rtx));
extern void set_last_insn PROTO ((rtx));
extern void link_cc0_insns PROTO ((rtx));
@@ -1379,7 +1310,8 @@ extern int safe_from_earlyclobber PROTO ((rtx, rtx));
extern int recog PROTO ((rtx, rtx, int *));
/* In stmt.c */
-extern void expand_null_return PROTO((void));
+extern void set_file_and_line_for_stmt PROTO ((char *, int));
+extern void expand_null_return PROTO ((void));
extern void emit_jump PROTO ((rtx));
extern int preserve_subexpressions_p PROTO ((void));
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 450ae34eed9..2af97d03c5a 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -63,71 +63,12 @@ struct obstack stmt_obstack;
#define CASE_VECTOR_PC_RELATIVE 0
#endif
-/* Filename and line number of last line-number note,
- whether we actually emitted it or not. */
-char *emit_filename;
-int emit_lineno;
-
-/* Nonzero if within a ({...}) grouping, in which case we must
- always compute a value for each expr-stmt in case it is the last one. */
-
-int expr_stmts_for_value;
-
-/* Each time we expand an expression-statement,
- record the expr's type and its RTL value here. */
-
-static tree last_expr_type;
-static rtx last_expr_value;
-
/* Each time we expand the end of a binding contour (in `expand_end_bindings')
and we emit a new NOTE_INSN_BLOCK_END note, we save a pointer to it here.
This is used by the `remember_end_note' function to record the endpoint
of each generated block in its associated BLOCK node. */
static rtx last_block_end_note;
-
-/* Number of binding contours started so far in this function. */
-
-int block_start_count;
-
-/* Nonzero if function being compiled needs to
- return the address of where it has put a structure value. */
-
-extern int current_function_returns_pcc_struct;
-
-/* Label that will go on parm cleanup code, if any.
- Jumping to this label runs cleanup code for parameters, if
- such code must be run. Following this code is the logical return label. */
-
-extern rtx cleanup_label;
-
-/* Label that will go on function epilogue.
- Jumping to this label serves as a "return" instruction
- on machines which require execution of the epilogue on all returns. */
-
-extern rtx return_label;
-
-/* Offset to end of allocated area of stack frame.
- If stack grows down, this is the address of the last stack slot allocated.
- If stack grows up, this is the address for the next slot. */
-extern int frame_offset;
-
-/* Label to jump back to for tail recursion, or 0 if we have
- not yet needed one for this function. */
-extern rtx tail_recursion_label;
-
-/* Place after which to insert the tail_recursion_label if we need one. */
-extern rtx tail_recursion_reentry;
-
-/* Location at which to save the argument pointer if it will need to be
- referenced. There are two cases where this is done: if nonlocal gotos
- exist, or if vars whose is an offset from the argument pointer will be
- needed by inner routines. */
-
-extern rtx arg_pointer_save_area;
-
-/* Chain of all RTL_EXPRs that have insns in them. */
-extern tree rtl_expr_chain;
/* Functions and data structures for expanding case statements. */
@@ -263,7 +204,7 @@ struct nesting
For contours that have stack levels or cleanups. */
struct label_chain *label_chain;
/* Number of function calls seen, as of start of this block. */
- int function_call_count;
+ int n_function_calls;
/* Nonzero if this is associated with a EH region. */
int exception_region;
/* The saved target_temp_slot_level from our outer block.
@@ -271,7 +212,7 @@ struct nesting
this block, if that is done, target_temp_slot_level
reverts to the saved target_temp_slot_level at the very
end of the block. */
- int target_temp_slot_level;
+ int block_target_temp_slot_level;
/* True if we are currently emitting insns in an area of
output code that is controlled by a conditional
expression. This is used by the cleanup handling code to
@@ -316,31 +257,6 @@ struct nesting
} data;
};
-/* Chain of all pending binding contours. */
-struct nesting *block_stack;
-
-/* If any new stacks are added here, add them to POPSTACKS too. */
-
-/* Chain of all pending binding contours that restore stack levels
- or have cleanups. */
-struct nesting *stack_block_stack;
-
-/* Chain of all pending conditional statements. */
-struct nesting *cond_stack;
-
-/* Chain of all pending loops. */
-struct nesting *loop_stack;
-
-/* Chain of all pending case or switch statements. */
-struct nesting *case_stack;
-
-/* Separate chain including all of the above,
- chained through the `all' field. */
-struct nesting *nesting_stack;
-
-/* Number of entries on nesting_stack now. */
-int nesting_depth;
-
/* Allocate and return a new `struct nesting'. */
#define ALLOC_NESTING() \
@@ -409,8 +325,6 @@ struct goto_fixup
tree cleanup_list_list;
};
-static struct goto_fixup *goto_fixup_chain;
-
/* Within any binding contour that must restore a stack level,
all labels are recorded with a chain of these structures. */
@@ -421,6 +335,68 @@ struct label_chain
tree label;
};
+struct stmt_status
+{
+ /* Chain of all pending binding contours. */
+ struct nesting *x_block_stack;
+
+ /* If any new stacks are added here, add them to POPSTACKS too. */
+
+ /* Chain of all pending binding contours that restore stack levels
+ or have cleanups. */
+ struct nesting *x_stack_block_stack;
+
+ /* Chain of all pending conditional statements. */
+ struct nesting *x_cond_stack;
+
+ /* Chain of all pending loops. */
+ struct nesting *x_loop_stack;
+
+ /* Chain of all pending case or switch statements. */
+ struct nesting *x_case_stack;
+
+ /* Separate chain including all of the above,
+ chained through the `all' field. */
+ struct nesting *x_nesting_stack;
+
+ /* Number of entries on nesting_stack now. */
+ int x_nesting_depth;
+
+ /* Number of binding contours started so far in this function. */
+ int x_block_start_count;
+
+ /* Each time we expand an expression-statement,
+ record the expr's type and its RTL value here. */
+ tree x_last_expr_type;
+ rtx x_last_expr_value;
+
+ /* Nonzero if within a ({...}) grouping, in which case we must
+ always compute a value for each expr-stmt in case it is the last one. */
+ int x_expr_stmts_for_value;
+
+ /* Filename and line number of last line-number note,
+ whether we actually emitted it or not. */
+ char *x_emit_filename;
+ int x_emit_lineno;
+
+ struct goto_fixup *x_goto_fixup_chain;
+};
+
+#define block_stack (current_function->stmt->x_block_stack)
+#define stack_block_stack (current_function->stmt->x_stack_block_stack)
+#define cond_stack (current_function->stmt->x_cond_stack)
+#define loop_stack (current_function->stmt->x_loop_stack)
+#define case_stack (current_function->stmt->x_case_stack)
+#define nesting_stack (current_function->stmt->x_nesting_stack)
+#define nesting_depth (current_function->stmt->x_nesting_depth)
+#define current_block_start_count (current_function->stmt->x_block_start_count)
+#define last_expr_type (current_function->stmt->x_last_expr_type)
+#define last_expr_value (current_function->stmt->x_last_expr_value)
+#define expr_stmts_for_value (current_function->stmt->x_expr_stmts_for_value)
+#define emit_filename (current_function->stmt->x_emit_filename)
+#define emit_lineno (current_function->stmt->x_emit_lineno)
+#define goto_fixup_chain (current_function->stmt->x_goto_fixup_chain)
+
/* Non-zero if we are using EH to handle cleanus. */
static int using_eh_for_cleanups_p = 0;
@@ -454,91 +430,7 @@ using_eh_for_cleanups ()
using_eh_for_cleanups_p = 1;
}
-void
-init_stmt ()
-{
- gcc_obstack_init (&stmt_obstack);
- init_eh ();
-
- ggc_add_root (&cond_stack, 1, sizeof(cond_stack), mark_cond_nesting);
- ggc_add_root (&loop_stack, 1, sizeof(loop_stack), mark_loop_nesting);
- ggc_add_root (&block_stack, 1, sizeof(block_stack), mark_block_nesting);
- ggc_add_root (&case_stack, 1, sizeof(case_stack), mark_case_nesting);
- ggc_add_root (&goto_fixup_chain, 1, sizeof(goto_fixup_chain),
- mark_goto_fixup);
-
- ggc_add_tree_root (&nonlocal_labels, 1);
- ggc_add_rtx_root (&nonlocal_goto_handler_slot, 1);
- ggc_add_rtx_root (&nonlocal_goto_stack_level, 1);
-}
-
-void
-init_stmt_for_function ()
-{
- /* We are not currently within any block, conditional, loop or case. */
- block_stack = 0;
- stack_block_stack = 0;
- loop_stack = 0;
- case_stack = 0;
- cond_stack = 0;
- nesting_stack = 0;
- nesting_depth = 0;
-
- block_start_count = 0;
-
- /* No gotos have been expanded yet. */
- goto_fixup_chain = 0;
-
- /* We are not processing a ({...}) grouping. */
- expr_stmts_for_value = 0;
- last_expr_type = 0;
-
- init_eh_for_function ();
-}
-
-void
-save_stmt_status (p)
- struct function *p;
-{
- p->block_stack = block_stack;
- p->stack_block_stack = stack_block_stack;
- p->cond_stack = cond_stack;
- p->loop_stack = loop_stack;
- p->case_stack = case_stack;
- p->nesting_stack = nesting_stack;
- p->nesting_depth = nesting_depth;
- p->block_start_count = block_start_count;
- p->last_expr_type = last_expr_type;
- p->last_expr_value = last_expr_value;
- p->expr_stmts_for_value = expr_stmts_for_value;
- p->emit_filename = emit_filename;
- p->emit_lineno = emit_lineno;
- p->goto_fixup_chain = goto_fixup_chain;
- save_eh_status (p);
-}
-
-void
-restore_stmt_status (p)
- struct function *p;
-{
- block_stack = p->block_stack;
- stack_block_stack = p->stack_block_stack;
- cond_stack = p->cond_stack;
- loop_stack = p->loop_stack;
- case_stack = p->case_stack;
- nesting_stack = p->nesting_stack;
- nesting_depth = p->nesting_depth;
- block_start_count = p->block_start_count;
- last_expr_type = p->last_expr_type;
- last_expr_value = p->last_expr_value;
- expr_stmts_for_value = p->expr_stmts_for_value;
- emit_filename = p->emit_filename;
- emit_lineno = p->emit_lineno;
- goto_fixup_chain = p->goto_fixup_chain;
- restore_eh_status (p);
-}
-
-void
+static void
mark_cond_nesting (arg)
void *arg;
{
@@ -554,7 +446,7 @@ mark_cond_nesting (arg)
}
}
-void
+static void
mark_loop_nesting (arg)
void *arg;
{
@@ -572,7 +464,7 @@ mark_loop_nesting (arg)
}
}
-void
+static void
mark_block_nesting (arg)
void *arg;
{
@@ -599,7 +491,7 @@ mark_block_nesting (arg)
}
}
-void
+static void
mark_case_nesting (arg)
void *arg;
{
@@ -629,7 +521,7 @@ mark_case_nesting (arg)
}
}
-void
+static void
mark_goto_fixup (arg)
void *arg;
{
@@ -647,7 +539,71 @@ mark_goto_fixup (arg)
g = g->next;
}
}
+
+void
+mark_stmt_state (arg)
+ void *arg;
+{
+ struct stmt_status *p = *(struct stmt_status **)arg;
+
+ if (p == 0)
+ return;
+
+ mark_block_nesting (&p->x_block_stack);
+ mark_cond_nesting (&p->x_cond_stack);
+ mark_loop_nesting (&p->x_loop_stack);
+ mark_case_nesting (&p->x_case_stack);
+
+ ggc_mark_tree (p->x_last_expr_type);
+ /* last_epxr_value is only valid if last_expr_type is nonzero. */
+ if (p->x_last_expr_type)
+ ggc_mark_rtx (p->x_last_expr_value);
+
+ mark_goto_fixup (&p->x_goto_fixup_chain);
+}
+
+void
+init_stmt ()
+{
+ gcc_obstack_init (&stmt_obstack);
+ init_eh ();
+}
+
+void
+init_stmt_for_function ()
+{
+ current_function->stmt = (struct stmt_status *) xmalloc (sizeof (struct stmt_status));
+
+ /* We are not currently within any block, conditional, loop or case. */
+ block_stack = 0;
+ stack_block_stack = 0;
+ loop_stack = 0;
+ case_stack = 0;
+ cond_stack = 0;
+ nesting_stack = 0;
+ nesting_depth = 0;
+
+ current_block_start_count = 0;
+
+ /* No gotos have been expanded yet. */
+ goto_fixup_chain = 0;
+
+ /* We are not processing a ({...}) grouping. */
+ expr_stmts_for_value = 0;
+ last_expr_type = 0;
+
+ init_eh_for_function ();
+}
+void
+set_file_and_line_for_stmt (file, line)
+ char *file;
+ int line;
+{
+ emit_filename = file;
+ emit_lineno = line;
+}
+
/* Emit a no-op instruction. */
void
@@ -783,7 +739,7 @@ expand_goto (label)
rtx label_ref = gen_rtx_LABEL_REF (Pmode, label_rtx (label));
rtx temp;
- p->has_nonlocal_label = 1;
+ p->func->has_nonlocal_label = 1;
current_function_has_nonlocal_goto = 1;
LABEL_REF_NONLOCAL_P (label_ref) = 1;
@@ -794,8 +750,8 @@ expand_goto (label)
#if HAVE_nonlocal_goto
if (HAVE_nonlocal_goto)
emit_insn (gen_nonlocal_goto (lookup_static_chain (label),
- copy_rtx (p->nonlocal_goto_handler_slot),
- copy_rtx (p->nonlocal_goto_stack_level),
+ copy_rtx (p->func->saved_nonlocal_goto_handler_slot),
+ copy_rtx (p->func->saved_nonlocal_goto_stack_level),
label_ref));
else
#endif
@@ -816,12 +772,12 @@ expand_goto (label)
/* Get addr of containing function's current nonlocal goto handler,
which will do any cleanups and then jump to the label. */
- addr = copy_rtx (p->nonlocal_goto_handler_slot);
+ addr = copy_rtx (p->func->saved_nonlocal_goto_handler_slot);
temp = copy_to_reg (replace_rtx (addr, virtual_stack_vars_rtx,
hard_frame_pointer_rtx));
/* Restore the stack pointer. Note this uses fp just restored. */
- addr = p->nonlocal_goto_stack_level;
+ addr = p->func->saved_nonlocal_goto_stack_level;
if (addr)
addr = replace_rtx (copy_rtx (addr),
virtual_stack_vars_rtx,
@@ -1022,7 +978,7 @@ expand_fixup (tree_label, rtl_label, last_insn)
emit_insns_after (fixup->before_jump, original_before_jump);
}
- fixup->block_start_count = block_start_count;
+ fixup->block_start_count = current_block_start_count;
fixup->stack_level = 0;
fixup->cleanup_list_list
= ((block->data.block.outer_cleanups
@@ -2315,11 +2271,11 @@ expand_exit_loop_if_false (whichloop, cond)
whichloop = loop_stack;
if (whichloop == 0)
return 0;
+
/* In order to handle fixups, we actually create a conditional jump
around a unconditional branch to exit the loop. If fixups are
necessary, they go before the unconditional branch. */
-
do_jump (cond, NULL_RTX, label);
last_insn = get_last_insn ();
if (GET_CODE (last_insn) == CODE_LABEL)
@@ -2346,7 +2302,7 @@ preserve_subexpressions_p ()
if (flag_expensive_optimizations)
return 1;
- if (optimize == 0 || loop_stack == 0)
+ if (optimize == 0 || current_function == 0 || loop_stack == 0)
return 0;
insn = get_last_insn_anywhere ();
@@ -2562,7 +2518,7 @@ expand_return (retval)
conditional expressions when it would help. */
if (optimize && retval_rhs != 0
- && frame_offset == 0
+ && get_frame_size () == 0
&& TREE_CODE (retval_rhs) == COND_EXPR
&& (TREE_CODE (TREE_OPERAND (retval_rhs, 1)) == CALL_EXPR
|| TREE_CODE (TREE_OPERAND (retval_rhs, 2)) == CALL_EXPR))
@@ -2592,7 +2548,7 @@ expand_return (retval)
has its address taken; for simplicity,
require stack frame to be empty. */
if (optimize && retval_rhs != 0
- && frame_offset == 0
+ && get_frame_size () == 0
&& TREE_CODE (retval_rhs) == CALL_EXPR
&& TREE_CODE (TREE_OPERAND (retval_rhs, 0)) == ADDR_EXPR
&& TREE_OPERAND (TREE_OPERAND (retval_rhs, 0), 0) == current_function_decl
@@ -2904,9 +2860,9 @@ expand_start_bindings (exit_flag)
thisblock->depth = ++nesting_depth;
thisblock->data.block.stack_level = 0;
thisblock->data.block.cleanups = 0;
- thisblock->data.block.function_call_count = 0;
+ thisblock->data.block.n_function_calls = 0;
thisblock->data.block.exception_region = 0;
- thisblock->data.block.target_temp_slot_level = target_temp_slot_level;
+ thisblock->data.block.block_target_temp_slot_level = target_temp_slot_level;
thisblock->data.block.conditional_code = 0;
thisblock->data.block.last_unconditional_cleanup = note;
@@ -2923,7 +2879,7 @@ expand_start_bindings (exit_flag)
thisblock->data.block.label_chain = 0;
thisblock->data.block.innermost_stack_block = stack_block_stack;
thisblock->data.block.first_insn = note;
- thisblock->data.block.block_start_count = ++block_start_count;
+ thisblock->data.block.block_start_count = ++current_block_start_count;
thisblock->exit_label = exit_flag ? gen_label_rtx () : 0;
block_stack = thisblock;
nesting_stack = thisblock;
@@ -3081,7 +3037,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
/* If necessary, make a handler for nonlocal gotos taking
place in the function calls in this block. */
- if (function_call_count != thisblock->data.block.function_call_count
+ if (function_call_count != thisblock->data.block.n_function_calls
&& nonlocal_labels
/* Make handler for outermost block
if there were any nonlocal gotos to this function. */
@@ -3293,7 +3249,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
}
/* Restore the temporary level of TARGET_EXPRs. */
- target_temp_slot_level = thisblock->data.block.target_temp_slot_level;
+ target_temp_slot_level = thisblock->data.block.block_target_temp_slot_level;
/* Restore block_stack level for containing block. */
@@ -3303,8 +3259,6 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
/* Pop the stack slot nesting and free any slots at this level. */
pop_temp_slots ();
}
-
-
/* Generate RTL for the automatic variable declaration DECL.
(Other kinds of declarations are simply ignored if seen here.) */
@@ -3313,7 +3267,7 @@ void
expand_decl (decl)
register tree decl;
{
- struct nesting *thisblock = block_stack;
+ struct nesting *thisblock;
tree type;
type = TREE_TYPE (decl);
@@ -3329,6 +3283,8 @@ expand_decl (decl)
if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
return;
+ thisblock = block_stack;
+
/* Create the RTL representation for the variable. */
if (type == error_mark_node)
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index d918496dbda..c88375b622c 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -1349,28 +1349,9 @@ get_best_mode (bitsize, bitpos, align, largest_mode, volatilep)
return mode;
}
-/* Save all variables describing the current status into the structure *P.
- This is used before starting a nested function. */
-
-void
-save_storage_status (p)
- struct function *p;
-{
-#if 0 /* Need not save, since always 0 and non0 (resp.) within a function. */
- p->pending_sizes = pending_sizes;
- p->immediate_size_expand = immediate_size_expand;
-#endif /* 0 */
-}
-
-/* Restore all variables describing the current status from the structure *P.
- This is used after a nested function. */
-
+/* This is run once per compilation to set GC roots for this file. */
void
-restore_storage_status (p)
- struct function *p;
+init_storage_once ()
{
-#if 0
- pending_sizes = p->pending_sizes;
- immediate_size_expand = p->immediate_size_expand;
-#endif /* 0 */
+ ggc_add_tree_root (&pending_sizes, 1);
}
diff --git a/gcc/stupid.c b/gcc/stupid.c
index cd1329f83d7..34c9f034507 100644
--- a/gcc/stupid.c
+++ b/gcc/stupid.c
@@ -46,6 +46,7 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "rtl.h"
+#include "function.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "regs.h"
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 1e036c6b5d3..c96dfc32a4d 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -42,6 +42,7 @@ Boston, MA 02111-1307, USA. */
#include "input.h"
#include "tree.h"
#include "rtl.h"
+#include "function.h"
#include "flags.h"
#include "insn-attr.h"
#include "insn-codes.h"
@@ -2568,17 +2569,21 @@ compile_file (name)
init_decl_processing ();
init_optabs ();
init_stmt ();
- init_expmed ();
- init_expr_once ();
init_loop ();
init_reload ();
init_alias_once ();
init_function_once ();
init_const_rtx_hash_table_once ();
+ init_storage_once ();
+ init_dummy_function_start ();
+ init_expmed ();
+ init_expr_once ();
if (flag_caller_saves)
init_caller_save ();
+ expand_dummy_function_end ();
+
/* If auxiliary info generation is desired, open the output file.
This goes in the same directory as the source file--unlike
all the other output files. */
@@ -3282,49 +3287,17 @@ rest_of_compilation (decl)
close_dump_file (print_rtl, insns);
}
- /* If we can, defer compiling inlines until EOF.
- save_for_inline_copying can be extremely expensive. */
- if (inlinable && ! decl_function_context (decl))
- DECL_DEFER_OUTPUT (decl) = 1;
-
- /* If function is inline, and we don't yet know whether to
- compile it by itself, defer decision till end of compilation.
- finish_compilation will call rest_of_compilation again
- for those functions that need to be output. Also defer those
- functions that we are supposed to defer. We cannot defer
- functions containing nested functions since the nested function
- data is in our non-saved obstack. We cannot defer nested
- functions for the same reason. */
-
- /* If this is a nested inline, remove ADDRESSOF now so we can
- finish compiling ourselves. Otherwise, wait until EOF.
- We have to do this because the purge_addressof transformation
- changes the DECL_RTL for many variables, which confuses integrate. */
- if (inlinable)
- {
- if (decl_function_context (decl))
- purge_addressof (insns);
- else
- DECL_DEFER_OUTPUT (decl) = 1;
- }
-
- if (! current_function_contains_functions
- && (DECL_DEFER_OUTPUT (decl)
- || (DECL_INLINE (decl)
- && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
- && ! flag_keep_inline_functions)
- || DECL_EXTERNAL (decl)))))
+ /* Defer compiling inlines until they go out of scope (the current
+ block for nested functions, EOF for toplevel functions). */
+ if (inlinable || DECL_DEFER_OUTPUT (decl))
{
DECL_DEFER_OUTPUT (decl) = 1;
/* If -Wreturn-type, we have to do a bit of compilation.
- However, if we just fall through we will call
- save_for_inline_copying() which results in excessive
- memory use. Instead, we just want to call
- jump_optimize() to figure out whether or not we can fall
- off the end of the function; we do the minimum amount of
- work necessary to make that safe. And, we set optimize
- to zero to keep jump_optimize from working too hard. */
+ Just want to call jump_optimize() to figure out whether or not
+ we can fall off the end of the function; we do the minimum
+ amount of work necessary to make that safe. And, we set
+ optimize to zero to keep jump_optimize from working too hard. */
if (warn_return_type)
{
int saved_optimize = optimize;
@@ -3358,44 +3331,10 @@ rest_of_compilation (decl)
}
#endif
TIMEVAR (integration_time, save_for_inline_nocopy (decl));
- RTX_INTEGRATED_P (DECL_SAVED_INSNS (decl)) = inlinable;
+ DECL_SAVED_INSNS (decl)->inlinable = inlinable;
goto exit_rest_of_compilation;
}
- /* If we have to compile the function now, save its rtl and subdecls
- so that its compilation will not affect what others get. */
- if (inlinable || DECL_DEFER_OUTPUT (decl))
- {
-#ifdef DWARF_DEBUGGING_INFO
- /* Generate the DWARF info for the "abstract" instance of
- a function which we will generate an out-of-line instance
- of almost immediately (and which we may also later generate
- various inlined instances of). */
- if (write_symbols == DWARF_DEBUG)
- {
- set_decl_abstract_flags (decl, 1);
- TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 0));
- set_decl_abstract_flags (decl, 0);
- }
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
- /* Generate the DWARF2 info for the "abstract" instance of
- a function which we will generate an out-of-line instance
- of almost immediately (and which we may also later generate
- various inlined instances of). */
- if (write_symbols == DWARF2_DEBUG)
- {
- set_decl_abstract_flags (decl, 1);
- TIMEVAR (symout_time, dwarf2out_decl (decl));
- set_decl_abstract_flags (decl, 0);
- }
-#endif
- saved_block_tree = DECL_INITIAL (decl);
- saved_arguments = DECL_ARGUMENTS (decl);
- TIMEVAR (integration_time, save_for_inline_copying (decl));
- RTX_INTEGRATED_P (DECL_SAVED_INSNS (decl)) = inlinable;
- }
-
/* If specified extern inline but we aren't inlining it, we are
done. This goes for anything that gets here with DECL_EXTERNAL
set, not just things with DECL_INLINE. */
@@ -3963,12 +3902,20 @@ rest_of_compilation (decl)
init_recog_no_volatile ();
+ /* We're done with this function. */
+ if (! DECL_DEFER_OUTPUT (decl))
+ free_after_compilation (current_function);
+
+ current_function = 0;
+ cur_f_s = 0;
+
ggc_collect (0);
/* The parsing time is all the time spent in yyparse
*except* what is spent in this function. */
parse_time -= get_run_time () - start_time;
+
}
static void
diff --git a/gcc/tree.h b/gcc/tree.h
index 9b0d57fafc5..48422f03fd4 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1070,10 +1070,7 @@ struct tree_type
where the data was actually passed. */
#define DECL_INCOMING_RTL(NODE) (DECL_CHECK (NODE)->decl.saved_insns.r)
/* For FUNCTION_DECL, if it is inline, holds the saved insn chain. */
-#define DECL_SAVED_INSNS(NODE) (DECL_CHECK (NODE)->decl.saved_insns.r)
-/* For FUNCTION_DECL, if it is inline,
- holds the size of the stack frame, as an integer. */
-#define DECL_FRAME_SIZE(NODE) (DECL_CHECK (NODE)->decl.frame_size.i)
+#define DECL_SAVED_INSNS(NODE) (DECL_CHECK (NODE)->decl.saved_insns.f)
/* For FUNCTION_DECL, if it is built-in,
this identifies which built-in operation it is. */
#define DECL_FUNCTION_CODE(NODE) (DECL_CHECK (NODE)->decl.frame_size.f)
@@ -1312,6 +1309,7 @@ struct tree_decl
union {
struct rtx_def *r;
HOST_WIDE_INT i;
+ struct function *f;
} saved_insns;
union tree_node *vindex;
/* Points to a structure whose details depend on the language in use. */
@@ -1837,14 +1835,6 @@ extern int immediate_size_expand;
extern tree current_function_decl;
-/* Nonzero if function being compiled can call setjmp. */
-
-extern int current_function_calls_setjmp;
-
-/* Nonzero if function being compiled can call longjmp. */
-
-extern int current_function_calls_longjmp;
-
/* Nonzero means all ..._TYPE nodes should be allocated permanently. */
extern int all_types_permanent;
diff --git a/gcc/unroll.c b/gcc/unroll.c
index 3222e207890..f6ebc37bd2c 100644
--- a/gcc/unroll.c
+++ b/gcc/unroll.c
@@ -149,6 +149,7 @@ enum unroll_types { UNROLL_COMPLETELY, UNROLL_MODULO, UNROLL_NAIVE };
#include "config.h"
#include "system.h"
#include "rtl.h"
+#include "function.h"
#include "insn-config.h"
#include "integrate.h"
#include "regs.h"
@@ -1201,8 +1202,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
}
/* Use our current register alignment and pointer flags. */
- map->regno_pointer_flag = regno_pointer_flag;
- map->regno_pointer_align = regno_pointer_align;
+ map->x_regno_pointer_flag = regno_pointer_flag;
+ map->x_regno_pointer_align = regno_pointer_align;
/* If the loop is being partially unrolled, and the iteration variables
are being split, and are being renamed for the split, then must fix up
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 4b96685ab93..cdf5743d045 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -3168,6 +3168,19 @@ restore_varasm_status (p)
const_double_chain = p->const_double_chain;
}
+/* Clear out all parts of our state in F that can safely be discarded
+ after the function has been compiled, or after it has been saved for
+ inlining, to let garbage collection reclaim the memory. */
+void
+free_varasm_status (f)
+ struct function *f;
+{
+ f->first_pool = f->last_pool = 0;
+ f->const_rtx_hash_table = 0;
+ f->const_rtx_sym_hash_table = 0;
+ f->const_double_chain = 0;
+}
+
void
mark_pool_constant (arg)
void *arg;