diff options
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 538 |
1 files changed, 102 insertions, 436 deletions
diff --git a/gcc/function.c b/gcc/function.c index 8ce5ef5ef79..322227bc495 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -64,10 +64,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "langhooks.h" #include "target.h" -#ifndef TRAMPOLINE_ALIGNMENT -#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY -#endif - #ifndef LOCAL_ALIGNMENT #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT #endif @@ -132,9 +128,6 @@ int current_function_uses_only_leaf_regs; post-instantiation libcalls. */ int virtuals_instantiated; -/* Nonzero if at least one trampoline has been created. */ -int trampolines_created; - /* Assign unique numbers to labels generated for profiling, debugging, etc. */ static GTY(()) int funcdef_no; @@ -142,9 +135,6 @@ static GTY(()) int funcdef_no; target specific, per-function data structures. */ struct machine_function * (*init_machine_status) (void); -/* The FUNCTION_DECL for an inline function currently being expanded. */ -tree inline_function_decl; - /* The currently compiled function. */ struct function *cfun = 0; @@ -256,16 +246,11 @@ static void instantiate_decls_1 (tree, int); static void instantiate_decl (rtx, HOST_WIDE_INT, int); static rtx instantiate_new_reg (rtx, HOST_WIDE_INT *); static int instantiate_virtual_regs_1 (rtx *, rtx, int); -static void delete_handlers (void); static void pad_to_arg_alignment (struct args_size *, int, struct args_size *); static void pad_below (struct args_size *, enum machine_mode, tree); -static rtx round_trampoline_addr (rtx); -static rtx adjust_trampoline_addr (rtx); static tree *identify_blocks_1 (rtx, tree *, tree *, tree *); -static void reorder_blocks_0 (tree); static void reorder_blocks_1 (rtx, tree, varray_type *); static void reorder_fix_fragments (tree); -static tree blocks_nreverse (tree); static int all_blocks (tree, tree *); static tree *get_block_vector (tree, int *); extern tree debug_find_var_in_block_tree (tree, tree); @@ -446,10 +431,7 @@ free_after_compilation (struct function *f) f->arg_offset_rtx = NULL; f->return_rtx = NULL; f->internal_arg_pointer = NULL; - f->x_nonlocal_labels = NULL; - f->x_nonlocal_goto_handler_slots = NULL; f->x_nonlocal_goto_handler_labels = NULL; - f->x_nonlocal_goto_stack_level = NULL; f->x_cleanup_label = NULL; f->x_return_label = NULL; f->x_naked_return_label = NULL; @@ -461,9 +443,6 @@ free_after_compilation (struct function *f) f->x_tail_recursion_label = NULL; f->x_tail_recursion_reentry = NULL; f->x_arg_pointer_save_area = NULL; - f->x_clobber_return_insn = NULL; - f->x_context_display = NULL; - f->x_trampoline_list = NULL; f->x_parm_birth_insn = NULL; f->x_last_parm_insn = NULL; f->x_parm_reg_stack_loc = NULL; @@ -1323,7 +1302,7 @@ put_var_into_stack (tree decl, int rescan) because it might not be in any active function. FIXME: Is that really supposed to happen? It does in ObjC at least. */ - if (context != current_function_decl && context != inline_function_decl) + if (context != current_function_decl) for (function = outer_function_chain; function; function = function->outer) if (function->decl == context) break; @@ -4168,59 +4147,6 @@ instantiate_virtual_regs_1 (rtx *loc, rtx object, int extra_insns) return 1; } -/* 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 (void) -{ - rtx insn; - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - { - /* Delete the handler by turning off the flag that would - prevent jump_optimize from deleting it. - Also permit deletion of the nonlocal labels themselves - if nothing local refers to them. */ - if (GET_CODE (insn) == CODE_LABEL) - { - tree t, last_t; - - LABEL_PRESERVE_P (insn) = 0; - - /* Remove it from the nonlocal_label list, to avoid confusing - flow. */ - for (t = nonlocal_labels, last_t = 0; t; - last_t = t, t = TREE_CHAIN (t)) - if (DECL_RTL (TREE_VALUE (t)) == insn) - break; - if (t) - { - if (! last_t) - nonlocal_labels = TREE_CHAIN (nonlocal_labels); - else - TREE_CHAIN (last_t) = TREE_CHAIN (t); - } - } - if (GET_CODE (insn) == INSN) - { - int can_delete = 0; - rtx t; - for (t = nonlocal_goto_handler_slots; t != 0; t = XEXP (t, 1)) - if (reg_mentioned_p (t, PATTERN (insn))) - { - can_delete = 1; - break; - } - if (can_delete - || (nonlocal_goto_stack_level != 0 - && reg_mentioned_p (nonlocal_goto_stack_level, - PATTERN (insn)))) - delete_related_insns (insn); - } - } -} - /* Return the first insn following those generated by `assign_parms'. */ rtx @@ -4319,12 +4245,7 @@ assign_parms (tree fndecl) /* Nonzero if function takes extra anonymous args. This means the last named arg must be on the stack right before the anonymous ones. */ - int stdarg - = (TYPE_ARG_TYPES (fntype) != 0 - && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) - != void_type_node)); - - current_function_stdarg = stdarg; + int stdarg = current_function_stdarg; /* If the reg that the virtual arg pointer will be translated into is not a fixed reg or is the stack pointer, make a copy of the virtual @@ -5714,49 +5635,30 @@ pad_below (struct args_size *offset_ptr, enum machine_mode passed_mode, tree siz } /* Walk the tree of blocks describing the binding levels within a function - and warn about uninitialized variables. + and warn about variables the might be killed by setjmp or vfork. This is done after calling flow_analysis and before global_alloc clobbers the pseudo-regs to hard regs. */ void -uninitialized_vars_warning (tree block) +setjmp_vars_warning (tree block) { tree decl, sub; + for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl)) { - if (warn_uninitialized - && TREE_CODE (decl) == VAR_DECL - /* These warnings are unreliable for and aggregates - because assigning the fields one by one can fail to convince - flow.c that the entire aggregate was initialized. - Unions are troublesome because members may be shorter. */ - && ! AGGREGATE_TYPE_P (TREE_TYPE (decl)) - && DECL_RTL_SET_P (decl) - && GET_CODE (DECL_RTL (decl)) == REG - /* Global optimizations can make it difficult to determine if a - particular variable has been initialized. However, a VAR_DECL - with a nonzero DECL_INITIAL had an initializer, so do not - claim it is potentially uninitialized. - - When the DECL_INITIAL is NULL call the language hook to tell us - if we want to warn. */ - && (DECL_INITIAL (decl) == NULL_TREE || lang_hooks.decl_uninit (decl)) - && regno_uninitialized (REGNO (DECL_RTL (decl)))) - warning ("%J'%D' might be used uninitialized in this function", - decl, decl); - if (extra_warnings - && TREE_CODE (decl) == VAR_DECL + if (TREE_CODE (decl) == VAR_DECL && DECL_RTL_SET_P (decl) && GET_CODE (DECL_RTL (decl)) == REG && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl)))) warning ("%Jvariable '%D' might be clobbered by `longjmp' or `vfork'", decl, decl); } + for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub)) - uninitialized_vars_warning (sub); + setjmp_vars_warning (sub); } -/* Do the appropriate part of uninitialized_vars_warning +/* Do the appropriate part of setjmp_vars_warning but for arguments instead of local variables. */ void @@ -5830,33 +5732,6 @@ setjmp_protect_args (void) put_var_into_stack (decl, /*rescan=*/true); } -/* Return the context-pointer register corresponding to DECL, - or 0 if it does not need one. */ - -rtx -lookup_static_chain (tree decl) -{ - tree context = decl_function_context (decl); - tree link; - - if (context == 0 - || (TREE_CODE (decl) == FUNCTION_DECL && DECL_NO_STATIC_CHAIN (decl))) - return 0; - - /* We treat inline_function_decl as an alias for the current function - because that is the inline function whose vars, types, etc. - are being merged into the current function. - See expand_inline_function. */ - if (context == current_function_decl || context == inline_function_decl) - return virtual_stack_vars_rtx; - - for (link = context_display; link; link = TREE_CHAIN (link)) - if (TREE_PURPOSE (link) == context) - return RTL_EXPR_RTL (TREE_VALUE (link)); - - abort (); -} - /* Convert a stack slot address ADDR for variable VAR (from a containing function) into an address valid in this function (using a static chain). */ @@ -5871,7 +5746,7 @@ fix_lexical_addr (rtx addr, tree var) rtx base = 0; /* If this is the present function, we need not do anything. */ - if (context == current_function_decl || context == inline_function_decl) + if (context == current_function_decl) return addr; fp = find_function_data (context); @@ -5887,49 +5762,6 @@ fix_lexical_addr (rtx addr, tree var) else abort (); - /* 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 reached via arg pointer, get the arg pointer value - out of that function's stack frame. - - There are two cases: If a separate ap is needed, allocate a - slot in the outer function for it and dereference it that way. - This is correct even if the real ap is actually a pseudo. - Otherwise, just adjust the offset from the frame pointer to - compensate. */ - -#ifdef NEED_SEPARATE_AP - rtx addr; - - addr = get_arg_pointer_save_area (fp); - addr = fix_lexical_addr (XEXP (addr, 0), var); - addr = memory_address (Pmode, addr); - - base = gen_rtx_MEM (Pmode, addr); - set_mem_alias_set (base, get_frame_alias_set ()); - base = copy_to_reg (base); -#else - displacement += (FIRST_PARM_OFFSET (context) - STARTING_FRAME_OFFSET); - base = lookup_static_chain (var); -#endif - } - - else if (basereg == virtual_stack_vars_rtx) - { - /* This is the same code as lookup_static_chain, duplicated here to - avoid an extra call to decl_function_context. */ - tree link; - - for (link = context_display; link; link = TREE_CHAIN (link)) - if (TREE_PURPOSE (link) == context) - { - base = RTL_EXPR_RTL (TREE_VALUE (link)); - break; - } - } - if (base == 0) abort (); @@ -5938,106 +5770,6 @@ fix_lexical_addr (rtx addr, tree var) return plus_constant (base, displacement); } -/* Return the address of the trampoline for entering nested fn FUNCTION. - If necessary, allocate a trampoline (in the stack frame) - and emit rtl to initialize its contents (at entry to this function). */ - -rtx -trampoline_address (tree function) -{ - tree link; - tree rtlexp; - rtx tramp; - struct function *fp; - tree fn_context; - - /* Find an existing trampoline and return it. */ - for (link = trampoline_list; link; link = TREE_CHAIN (link)) - if (TREE_PURPOSE (link) == function) - return - adjust_trampoline_addr (XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0)); - - for (fp = outer_function_chain; fp; fp = fp->outer) - for (link = fp->x_trampoline_list; link; link = TREE_CHAIN (link)) - if (TREE_PURPOSE (link) == function) - { - tramp = fix_lexical_addr (XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0), - function); - return adjust_trampoline_addr (tramp); - } - - /* None exists; we must make one. */ - - /* Find the `struct function' for the function containing FUNCTION. */ - fp = 0; - fn_context = decl_function_context (function); - if (fn_context != current_function_decl - && fn_context != inline_function_decl) - fp = find_function_data (fn_context); - - /* Allocate run-time space for this trampoline. */ - /* If rounding needed, allocate extra space - to ensure we have TRAMPOLINE_SIZE bytes left after rounding up. */ -#define TRAMPOLINE_REAL_SIZE \ - (TRAMPOLINE_SIZE + (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT) - 1) - tramp = assign_stack_local_1 (BLKmode, TRAMPOLINE_REAL_SIZE, 0, - fp ? fp : cfun); - /* Record the trampoline for reuse and note it for later initialization - by expand_function_end. */ - if (fp != 0) - { - rtlexp = make_node (RTL_EXPR); - RTL_EXPR_RTL (rtlexp) = tramp; - fp->x_trampoline_list = tree_cons (function, rtlexp, - fp->x_trampoline_list); - } - else - { - /* Make the RTL_EXPR node temporary, not momentary, so that the - trampoline_list doesn't become garbage. */ - rtlexp = make_node (RTL_EXPR); - - RTL_EXPR_RTL (rtlexp) = tramp; - trampoline_list = tree_cons (function, rtlexp, trampoline_list); - } - - tramp = fix_lexical_addr (XEXP (tramp, 0), function); - return adjust_trampoline_addr (tramp); -} - -/* Given a trampoline address, - round it to multiple of TRAMPOLINE_ALIGNMENT. */ - -static rtx -round_trampoline_addr (rtx tramp) -{ - /* Round address up to desired boundary. */ - rtx temp = gen_reg_rtx (Pmode); - rtx addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1); - rtx mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT); - - temp = expand_simple_binop (Pmode, PLUS, tramp, addend, - temp, 0, OPTAB_LIB_WIDEN); - tramp = expand_simple_binop (Pmode, AND, temp, mask, - temp, 0, OPTAB_LIB_WIDEN); - - return tramp; -} - -/* Given a trampoline address, round it then apply any - platform-specific adjustments so that the result can be used for a - function call . */ - -static rtx -adjust_trampoline_addr (rtx tramp) -{ - tramp = round_trampoline_addr (tramp); -#ifdef TRAMPOLINE_ADJUST_ADDRESS - TRAMPOLINE_ADJUST_ADDRESS (tramp); -#endif - return tramp; -} - /* Put all this function's BLOCK nodes including those that are chained onto the first block into a vector, and return it. Also store in each NOTE for the beginning or end of a block @@ -6157,7 +5889,7 @@ reorder_blocks (void) VARRAY_TREE_INIT (block_stack, 10, "block_stack"); /* Reset the TREE_ASM_WRITTEN bit for all blocks. */ - reorder_blocks_0 (block); + clear_block_marks (block); /* Prune the old trees away, so that they don't get in the way. */ BLOCK_SUBBLOCKS (block) = NULL_TREE; @@ -6173,13 +5905,13 @@ reorder_blocks (void) /* Helper function for reorder_blocks. Reset TREE_ASM_WRITTEN. */ -static void -reorder_blocks_0 (tree block) +void +clear_block_marks (tree block) { while (block) { TREE_ASM_WRITTEN (block) = 0; - reorder_blocks_0 (BLOCK_SUBBLOCKS (block)); + clear_block_marks (BLOCK_SUBBLOCKS (block)); block = BLOCK_CHAIN (block); } } @@ -6310,7 +6042,7 @@ reorder_fix_fragments (tree block) /* Reverse the order of elements in the chain T of blocks, and return the new head of the chain (old last element). */ -static tree +tree blocks_nreverse (tree t) { tree prev = 0, decl, next; @@ -6428,6 +6160,7 @@ void allocate_struct_function (tree fndecl) { tree result; + tree fntype = fndecl ? TREE_TYPE (fndecl) : NULL_TREE; cfun = ggc_alloc_cleared (sizeof (struct function)); @@ -6464,9 +6197,11 @@ allocate_struct_function (tree fndecl) current_function_returns_pointer = POINTER_TYPE_P (TREE_TYPE (result)); - current_function_needs_context - = (decl_function_context (current_function_decl) != 0 - && ! DECL_NO_STATIC_CHAIN (current_function_decl)); + current_function_stdarg + = (fntype + && TYPE_ARG_TYPES (fntype) != 0 + && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) + != void_type_node)); } /* Reset cfun, and other non-struct-function variables to defaults as @@ -6639,17 +6374,10 @@ expand_pending_sizes (tree pending_sizes) void expand_function_start (tree subr, int parms_have_cleanups) { - tree tem; - rtx last_ptr = NULL_RTX; - /* Make sure volatile mem refs aren't considered valid operands of arithmetic insns. */ init_recog_no_volatile (); - current_function_instrument_entry_exit - = (flag_instrument_function_entry_exit - && ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr)); - current_function_profile = (profile_flag && ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr)); @@ -6657,19 +6385,6 @@ expand_function_start (tree subr, int parms_have_cleanups) current_function_limit_stack = (stack_limit_rtx != NULL_RTX && ! DECL_NO_LIMIT_STACK (subr)); - /* If function gets a static chain arg, store it in the stack frame. - Do this first, so it gets the first stack slot offset. */ - if (current_function_needs_context) - { - last_ptr = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0); - - /* Delay copying static chain if it is not a register to avoid - conflicts with regs used for parameters. */ - if (! SMALL_REGISTER_CLASSES - || GET_CODE (static_chain_incoming_rtx) == REG) - emit_move_insn (last_ptr, static_chain_incoming_rtx); - } - /* If the parameters of this function need cleaning up, get a label for the beginning of the code which executes those cleanups. This must be done before doing anything with return_label. */ @@ -6750,15 +6465,37 @@ expand_function_start (tree subr, int parms_have_cleanups) /* Initialize rtx for parameters and local variables. In some cases this requires emitting insns. */ - assign_parms (subr); - /* Copy the static chain now if it wasn't a register. The delay is to - avoid conflicts with the parameter passing registers. */ + /* If function gets a static chain arg, store it. */ + if (cfun->static_chain_decl) + { + rtx x; + + expand_var (cfun->static_chain_decl); + x = expand_expr (cfun->static_chain_decl, NULL_RTX, + VOIDmode, EXPAND_WRITE); + emit_move_insn (x, static_chain_incoming_rtx); + } + + /* If the function receives a non-local goto, then store the + bits we need to restore the frame pointer. */ + if (cfun->nonlocal_goto_save_area) + { + tree t_save; + rtx r_save; + + /* ??? We need to do this save early. Unfortunately here is + before the frame variable gets declared. Help out... */ + expand_var (TREE_OPERAND (cfun->nonlocal_goto_save_area, 0)); + + t_save = build (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area, + integer_zero_node); + r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE); - if (SMALL_REGISTER_CLASSES && current_function_needs_context) - if (GET_CODE (static_chain_incoming_rtx) != REG) - emit_move_insn (last_ptr, static_chain_incoming_rtx); + emit_move_insn (r_save, virtual_stack_vars_rtx); + update_nonlocal_goto_save_area (); + } /* The following was moved from init_function_start. The move is supposed to make sdb output more accurate. */ @@ -6770,67 +6507,6 @@ expand_function_start (tree subr, int parms_have_cleanups) emit_note (NOTE_INSN_DELETED); parm_birth_insn = get_last_insn (); - context_display = 0; - if (current_function_needs_context) - { - /* Fetch static chain values for containing functions. */ - tem = decl_function_context (current_function_decl); - /* Copy the static chain pointer into a pseudo. If we have - small register classes, copy the value from memory if - static_chain_incoming_rtx is a REG. */ - if (tem) - { - /* If the static chain originally came in a register, put it back - there, then move it out in the next insn. The reason for - this peculiar code is to satisfy function integration. */ - if (SMALL_REGISTER_CLASSES - && GET_CODE (static_chain_incoming_rtx) == REG) - emit_move_insn (static_chain_incoming_rtx, last_ptr); - last_ptr = copy_to_reg (static_chain_incoming_rtx); - } - - while (tem) - { - tree rtlexp = make_node (RTL_EXPR); - - RTL_EXPR_RTL (rtlexp) = last_ptr; - context_display = tree_cons (tem, rtlexp, context_display); - tem = decl_function_context (tem); - if (tem == 0) - break; - /* Chain through stack frames, assuming pointer to next lexical frame - is found at the place we always store it. */ -#ifdef FRAME_GROWS_DOWNWARD - last_ptr = plus_constant (last_ptr, - -(HOST_WIDE_INT) GET_MODE_SIZE (Pmode)); -#endif - last_ptr = gen_rtx_MEM (Pmode, memory_address (Pmode, last_ptr)); - set_mem_alias_set (last_ptr, get_frame_alias_set ()); - last_ptr = copy_to_reg (last_ptr); - - /* If we are not optimizing, ensure that we know that this - piece of context is live over the entire function. */ - if (! optimize) - save_expr_regs = gen_rtx_EXPR_LIST (VOIDmode, last_ptr, - save_expr_regs); - } - } - - if (current_function_instrument_entry_exit) - { - rtx fun = DECL_RTL (current_function_decl); - if (GET_CODE (fun) == MEM) - fun = XEXP (fun, 0); - else - abort (); - emit_library_call (profile_function_entry_libfunc, LCT_NORMAL, VOIDmode, - 2, fun, Pmode, - expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS, - 0, - hard_frame_pointer_rtx), - Pmode); - } - if (current_function_profile) { #ifdef PROFILE_HOOK @@ -6948,7 +6624,6 @@ static GTY(()) rtx initial_trampoline; void expand_function_end (void) { - tree link; rtx clobber_after; finish_expr_for_function (); @@ -6970,45 +6645,6 @@ expand_function_end (void) } #endif - /* Initialize any trampolines required by this function. */ - for (link = trampoline_list; link; link = TREE_CHAIN (link)) - { - tree function = TREE_PURPOSE (link); - rtx context ATTRIBUTE_UNUSED = lookup_static_chain (function); - rtx tramp = RTL_EXPR_RTL (TREE_VALUE (link)); -#ifdef TRAMPOLINE_TEMPLATE - rtx blktramp; -#endif - rtx seq; - -#ifdef TRAMPOLINE_TEMPLATE - /* First make sure this compilation has a template for - initializing trampolines. */ - if (initial_trampoline == 0) - { - initial_trampoline - = gen_rtx_MEM (BLKmode, assemble_trampoline_template ()); - set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT); - } -#endif - - /* Generate insns to initialize the trampoline. */ - start_sequence (); - tramp = round_trampoline_addr (XEXP (tramp, 0)); -#ifdef TRAMPOLINE_TEMPLATE - blktramp = replace_equiv_address (initial_trampoline, tramp); - emit_block_move (blktramp, initial_trampoline, - GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); -#endif - trampolines_created = 1; - INITIALIZE_TRAMPOLINE (tramp, XEXP (DECL_RTL (function), 0), context); - seq = get_insns (); - end_sequence (); - - /* Put those insns at entry to the containing function (this one). */ - emit_insn_before (seq, tail_recursion_reentry); - } - /* If we are doing stack checking and this function makes calls, do a stack probe at the start of the function to ensure we have enough space for another stack frame. */ @@ -7036,11 +6672,6 @@ expand_function_end (void) && !lang_hooks.callgraph.expand_function) do_warn_unused_parameter (current_function_decl); - /* Delete handlers for nonlocal gotos if nothing uses them. */ - if (nonlocal_goto_handler_slots != 0 - && ! current_function_has_nonlocal_label) - delete_handlers (); - /* End any sequences that failed to be closed due to syntax errors. */ while (in_sequence_p ()) end_sequence (); @@ -7096,21 +6727,6 @@ expand_function_end (void) if (return_label) emit_label (return_label); - if (current_function_instrument_entry_exit) - { - rtx fun = DECL_RTL (current_function_decl); - if (GET_CODE (fun) == MEM) - fun = XEXP (fun, 0); - else - abort (); - emit_library_call (profile_function_exit_libfunc, LCT_NORMAL, VOIDmode, - 2, fun, Pmode, - expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS, - 0, - hard_frame_pointer_rtx), - Pmode); - } - /* Let except.c know where it should emit the call to unregister the function context for sjlj exceptions. */ if (flag_exceptions && USING_SJLJ_EXCEPTIONS) @@ -7233,9 +6849,6 @@ expand_function_end (void) end_sequence (); after = emit_insn_after (seq, clobber_after); - - if (clobber_after != after) - cfun->x_clobber_return_insn = after; } /* Output the label for the naked return from the function, if one is @@ -8161,6 +7774,59 @@ init_function_once (void) VARRAY_INT_INIT (sibcall_epilogue, 0, "sibcall_epilogue"); } +/* Resets insn_block_boundaries array. */ + +void +reset_block_changes (void) +{ + VARRAY_TREE_INIT (cfun->ib_boundaries_block, 100, "ib_boundaries_block"); + VARRAY_PUSH_TREE (cfun->ib_boundaries_block, NULL_TREE); +} + +/* Record the boundary for BLOCK. */ +void +record_block_change (tree block) +{ + int i, n; + tree last_block; + + if (!block) + return; + + last_block = VARRAY_TOP_TREE (cfun->ib_boundaries_block); + VARRAY_POP (cfun->ib_boundaries_block); + n = get_max_uid (); + for (i = VARRAY_ACTIVE_SIZE (cfun->ib_boundaries_block); i < n; i++) + VARRAY_PUSH_TREE (cfun->ib_boundaries_block, last_block); + + VARRAY_PUSH_TREE (cfun->ib_boundaries_block, block); +} + +/* Finishes record of boundaries. */ +void finalize_block_changes (void) +{ + record_block_change (DECL_INITIAL (current_function_decl)); +} + +/* For INSN return the BLOCK it belongs to. */ +void +check_block_change (rtx insn, tree *block) +{ + unsigned uid = INSN_UID (insn); + + if (uid >= VARRAY_ACTIVE_SIZE (cfun->ib_boundaries_block)) + return; + + *block = VARRAY_TREE (cfun->ib_boundaries_block, uid); +} + +/* Releases the ib_boundaries_block records. */ +void +free_block_changes (void) +{ + cfun->ib_boundaries_block = NULL; +} + /* Returns the name of the current function. */ const char * current_function_name (void) |