summaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c456
1 files changed, 60 insertions, 396 deletions
diff --git a/gcc/function.c b/gcc/function.c
index e25d676e579..c30c0d113c6 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -94,266 +94,22 @@ 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. */
-
-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;
-
-/* Nonzero if function being compiled contains nested functions. */
-
-int current_function_contains_functions;
-
/* Nonzero if function being compiled doesn't contain any calls
(ignoring the prologue and epilogue). This is set prior to
local register allocation and is valid for the remaining
compiler passes. */
-
int current_function_is_leaf;
/* Nonzero if function being compiled doesn't modify the stack pointer
(ignoring the prologue and epilogue). This is only valid after
life_analysis has run. */
-
int current_function_sp_is_unchanging;
/* Nonzero if the function being compiled is a leaf function which only
uses leaf registers. This is valid after reload (specifically after
sched2) and is useful only if the port defines LEAF_REGISTERS. */
-
int current_function_uses_only_leaf_regs;
-/* Nonzero if the function being compiled issues a computed jump. */
-
-int current_function_has_computed_jump;
-
-/* 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;
-
-/* Nonzero if memory access checking be enabled in the current function. */
-int current_function_check_memory_usage;
-
-/* 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;
-
-/* List (chain of EXPR_LIST) of stack slots that hold the current handlers
- for nonlocal gotos. There is one for every nonlocal label in the function;
- this list matches the one in nonlocal_labels.
- Zero when function does not have nonlocal labels. */
-
-rtx nonlocal_goto_handler_slots;
-
-/* List (chain of EXPR_LIST) of labels heading the current handlers for
- nonlocal gotos. */
-
-rtx nonlocal_goto_handler_labels;
-
-/* 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;
@@ -369,7 +125,9 @@ void (*restore_machine_status) PROTO((struct function *));
integrate.c */
extern int rtx_equal_function_value_matters;
-extern tree sequence_rtl_expr;
+
+/* The FUNCTION_DECL for an inline function currently being expanded. */
+tree inline_function_decl;
/* The currently compiled function. */
struct function *current_function = 0;
@@ -440,24 +198,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
@@ -569,67 +309,10 @@ push_function_context_to (context)
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->has_computed_jump = current_function_has_computed_jump;
- 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_slots = nonlocal_goto_handler_slots;
- p->nonlocal_goto_handler_labels = nonlocal_goto_handler_labels;
- 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->check_memory_usage = current_function_check_memory_usage;
- 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_varasm_status (p, context);
if (save_machine_status)
(*save_machine_status) (p);
@@ -657,66 +340,11 @@ pop_function_context_from (context)
outer_function_chain = p->next;
current_function_contains_functions
- = p->contains_functions || p->inline_obstacks
- || context == current_function_decl;
- current_function_has_computed_jump = p->has_computed_jump;
- current_function_name = p->name;
+ |= p->inline_obstacks || context == current_function_decl;
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_slots = p->nonlocal_goto_handler_slots;
- nonlocal_goto_handler_labels = p->nonlocal_goto_handler_labels;
- 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_check_memory_usage = p->check_memory_usage;
- current_function_instrument_entry_exit = p->instrument_entry_exit;
restore_tree_status (p, context);
- restore_storage_status (p);
- restore_expr_status (p);
restore_emit_status (p);
restore_varasm_status (p);
@@ -741,20 +369,31 @@ void pop_function_context ()
/* Allocate fixed slots in the stack frame of the current function. */
-/* Return size needed for stack frame based on slots so far allocated.
+/* 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 PREFERRED_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->x_frame_offset;
#else
- return frame_offset;
+ return f->x_frame_offset;
#endif
}
+/* Return size needed for stack frame based on slots so far allocated.
+ This size counts from zero. It is not rounded to PREFERRED_STACK_BOUNDARY;
+ the caller may have to do that. */
+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.
@@ -885,14 +524,14 @@ assign_outer_stack_local (mode, size, align, function)
alignment = align / BITS_PER_UNIT;
#ifdef FRAME_GROWS_DOWNWARD
- function->frame_offset -= size;
+ function->x_frame_offset -= size;
#endif
/* Round frame offset to that alignment. */
#ifdef FRAME_GROWS_DOWNWARD
- function->frame_offset = FLOOR_ROUND (function->frame_offset, alignment);
+ function->x_frame_offset = FLOOR_ROUND (function->x_frame_offset, alignment);
#else
- function->frame_offset = CEIL_ROUND (function->frame_offset, alignment);
+ function->x_frame_offset = CEIL_ROUND (function->x_frame_offset, alignment);
#endif
/* On a big-endian machine, if we are allocating more space than we will use,
@@ -901,15 +540,15 @@ assign_outer_stack_local (mode, size, align, function)
bigend_correction = size - GET_MODE_SIZE (mode);
addr = plus_constant (virtual_stack_vars_rtx,
- function->frame_offset + bigend_correction);
+ function->x_frame_offset + bigend_correction);
#ifndef FRAME_GROWS_DOWNWARD
- function->frame_offset += size;
+ function->x_frame_offset += size;
#endif
x = gen_rtx_MEM (mode, addr);
- function->stack_slot_list
- = gen_rtx_EXPR_LIST (VOIDmode, x, function->stack_slot_list);
+ function->x_stack_slot_list
+ = gen_rtx_EXPR_LIST (VOIDmode, x, function->x_stack_slot_list);
pop_obstacks ();
@@ -1079,7 +718,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
p->in_use = 1;
p->addr_taken = 0;
- p->rtl_expr = sequence_rtl_expr;
+ p->rtl_expr = seq_rtl_expr;
if (keep == 2)
{
@@ -1693,8 +1332,8 @@ 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->x_max_parm_reg)
+ new = function->x_parm_reg_stack_loc[regno];
if (new == 0)
new = assign_outer_stack_local (decl_mode, GET_MODE_SIZE (decl_mode),
0, function);
@@ -1758,7 +1397,7 @@ fixup_var_refs (var, promoted_mode, unsignedp, ht)
{
tree pending;
rtx first_insn = get_insns ();
- struct sequence_stack *stack = sequence_stack;
+ struct sequence_stack *stack = seq_stack;
tree rtl_exps = rtl_expr_chain;
/* Must scan all insns for stack-refs that exceed the limit. */
@@ -5584,11 +5223,11 @@ fix_lexical_addr (addr, var)
#ifdef NEED_SEPARATE_AP
rtx addr;
- if (fp->arg_pointer_save_area == 0)
- fp->arg_pointer_save_area
+ if (fp->x_arg_pointer_save_area == 0)
+ fp->x_arg_pointer_save_area
= assign_outer_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0, fp);
- addr = fix_lexical_addr (XEXP (fp->arg_pointer_save_area, 0), var);
+ addr = fix_lexical_addr (XEXP (fp->x_arg_pointer_save_area, 0), var);
addr = memory_address (Pmode, addr);
base = copy_to_reg (gen_rtx_MEM (Pmode, addr));
@@ -5641,7 +5280,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->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),
@@ -5687,7 +5326,8 @@ trampoline_address (function)
fp->function_maybepermanent_obstack);
rtlexp = make_node (RTL_EXPR);
RTL_EXPR_RTL (rtlexp) = tramp;
- fp->trampoline_list = tree_cons (function, rtlexp, fp->trampoline_list);
+ fp->x_trampoline_list = tree_cons (function, rtlexp,
+ fp->x_trampoline_list);
pop_obstacks ();
}
else
@@ -5949,6 +5589,8 @@ prepare_function_start ()
current_function_uses_pic_offset_table = 0;
current_function_cannot_inline = 0;
+ current_function->inlinable = 0;
+
/* We have not yet needed to make a label to jump to for tail-recursion. */
tail_recursion_label = 0;
@@ -6054,7 +5696,14 @@ init_function_start (subr, filename, line)
current_function_returns_pointer
= POINTER_TYPE_P (TREE_TYPE (DECL_RESULT (subr)));
+}
+/* Make sure all values used by the optimization passes have sane
+ defaults. */
+void
+init_function_for_compilation ()
+{
+ reg_renumber = 0;
/* No prologue/epilogue insns yet. */
prologue = epilogue = 0;
}
@@ -6343,6 +5992,19 @@ 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.
@@ -6362,6 +6024,8 @@ expand_function_end (filename, line, end_bindings)
static rtx initial_trampoline;
#endif
+ finish_expr_for_function ();
+
#ifdef NON_SAVING_SETJMP
/* Don't put any variables in registers if we call setjmp
on a machine that fails to restore the registers. */