diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-11-03 20:24:34 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-11-03 20:24:34 +0000 |
commit | 5106338e8c59391943a1ad51e61527d2ab957889 (patch) | |
tree | 3eacc26ce046eaa6379b125c284a8e98e76e7ef5 | |
parent | cf7b0b09a6bb4735f1670573b3316d4b6f1b89d8 (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
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 (¤t_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: ¤t_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 (¤t_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 (¤t_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 (®no_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 (®_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; |