aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c171
1 files changed, 63 insertions, 108 deletions
diff --git a/gcc/function.c b/gcc/function.c
index 6d07ff3..cb474b2 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -120,10 +120,12 @@ static int virtuals_instantiated;
void (*init_machine_status) PROTO((struct function *));
void (*save_machine_status) PROTO((struct function *));
void (*restore_machine_status) PROTO((struct function *));
+void (*mark_machine_status) PROTO((struct function *));
/* Likewise, but for language-specific data. */
void (*save_lang_status) PROTO((struct function *));
void (*restore_lang_status) PROTO((struct function *));
+void (*mark_lang_status) PROTO((struct function *));
/* The FUNCTION_DECL for an inline function currently being expanded. */
tree inline_function_decl;
@@ -219,7 +221,7 @@ struct insns_for_mem_entry {
/* Forward declarations. */
-static rtx assign_outer_stack_local PROTO ((enum machine_mode, HOST_WIDE_INT,
+static rtx assign_stack_local_1 PROTO ((enum machine_mode, HOST_WIDE_INT,
int, struct function *));
static rtx assign_stack_temp_for_type PROTO ((enum machine_mode, HOST_WIDE_INT,
int, tree));
@@ -375,6 +377,21 @@ 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);
+
+ free (f->x_parm_reg_stack_loc);
+
+ f->can_garbage_collect = 1;
+}
/* Allocate fixed slots in the stack frame of the current function. */
@@ -411,18 +428,27 @@ get_frame_size ()
-1 means use BIGGEST_ALIGNMENT and round size to multiple of that,
positive specifies alignment boundary in bits.
- We do not round to stack_boundary here. */
+ We do not round to stack_boundary here.
-rtx
-assign_stack_local (mode, size, align)
+ FUNCTION specifies the function to allocate in. */
+
+static rtx
+assign_stack_local_1 (mode, size, align, function)
enum machine_mode mode;
HOST_WIDE_INT size;
int align;
+ struct function *function;
{
register rtx x, addr;
int bigend_correction = 0;
int alignment;
+ /* Allocate in the memory associated with the function in whose frame
+ we are assigning. */
+ if (function != current_function)
+ push_obstacks (function->function_obstack,
+ function->function_maybepermanent_obstack);
+
if (align == 0)
{
tree type;
@@ -448,7 +474,7 @@ assign_stack_local (mode, size, align)
alignment = align / BITS_PER_UNIT;
#ifdef FRAME_GROWS_DOWNWARD
- frame_offset -= size;
+ function->x_frame_offset -= size;
#endif
/* Round frame offset to that alignment.
@@ -457,9 +483,9 @@ assign_stack_local (mode, size, align)
like. So we instead assume that ALIGNMENT is a power of two and
use logical operations which are unambiguous. */
#ifdef FRAME_GROWS_DOWNWARD
- frame_offset = FLOOR_ROUND (frame_offset, alignment);
+ function->x_frame_offset = FLOOR_ROUND (function->x_frame_offset, alignment);
#else
- frame_offset = CEIL_ROUND (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,
@@ -469,7 +495,7 @@ assign_stack_local (mode, size, align)
/* If we have already instantiated virtual registers, return the actual
address relative to the frame pointer. */
- if (virtuals_instantiated)
+ if (function == current_function && virtuals_instantiated)
addr = plus_constant (frame_pointer_rtx,
(frame_offset + bigend_correction
+ STARTING_FRAME_OFFSET));
@@ -478,90 +504,29 @@ assign_stack_local (mode, size, align)
frame_offset + bigend_correction);
#ifndef FRAME_GROWS_DOWNWARD
- frame_offset += size;
+ function->x_frame_offset += size;
#endif
x = gen_rtx_MEM (mode, addr);
- stack_slot_list = gen_rtx_EXPR_LIST (VOIDmode, x, stack_slot_list);
+ function->x_stack_slot_list
+ = gen_rtx_EXPR_LIST (VOIDmode, x, function->x_stack_slot_list);
+
+ if (function != current_function)
+ pop_obstacks ();
return x;
}
-/* Assign a stack slot in a containing function.
- First three arguments are same as in preceding function.
- The last argument specifies the function to allocate in. */
-
-static rtx
-assign_outer_stack_local (mode, size, align, function)
+/* Wrapper around assign_stack_local_1; assign a local stack slot for the
+ current function. */
+rtx
+assign_stack_local (mode, size, align)
enum machine_mode mode;
HOST_WIDE_INT size;
int align;
- struct function *function;
{
- 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)
- {
- tree type;
-
- alignment = GET_MODE_ALIGNMENT (mode);
- if (mode == BLKmode)
- alignment = BIGGEST_ALIGNMENT;
-
- /* Allow the target to (possibly) increase the alignment of this
- stack slot. */
- type = type_for_mode (mode, 0);
- if (type)
- alignment = LOCAL_ALIGNMENT (type, alignment);
-
- alignment /= BITS_PER_UNIT;
- }
- else if (align == -1)
- {
- alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
- size = CEIL_ROUND (size, alignment);
- }
- else
- alignment = align / BITS_PER_UNIT;
-
-#ifdef FRAME_GROWS_DOWNWARD
- function->x_frame_offset -= size;
-#endif
-
- /* Round frame offset to that alignment. */
-#ifdef FRAME_GROWS_DOWNWARD
- function->x_frame_offset = FLOOR_ROUND (function->x_frame_offset, alignment);
-#else
- 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,
- use the least significant bytes of those that are allocated. */
- if (BYTES_BIG_ENDIAN && mode != BLKmode)
- bigend_correction = size - GET_MODE_SIZE (mode);
-
- addr = plus_constant (virtual_stack_vars_rtx,
- function->x_frame_offset + bigend_correction);
-#ifndef FRAME_GROWS_DOWNWARD
- function->x_frame_offset += size;
-#endif
-
- x = gen_rtx_MEM (mode, addr);
-
- function->x_stack_slot_list
- = gen_rtx_EXPR_LIST (VOIDmode, x, function->x_stack_slot_list);
-
- pop_obstacks ();
-
- return x;
+ return assign_stack_local_1 (mode, size, align, current_function);
}
/* Allocate a temporary stack slot and record it for possible later
@@ -1334,27 +1299,17 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
int used_p;
struct hash_table *ht;
{
+ struct function *func = function ? function : current_function;
rtx new = 0;
int regno = original_regno;
if (regno == 0)
regno = REGNO (reg);
- if (function)
- {
- 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);
- }
- else
- {
- if (regno < max_parm_reg)
- new = parm_reg_stack_loc[regno];
- if (new == 0)
- new = assign_stack_local (decl_mode, GET_MODE_SIZE (decl_mode), 0);
- }
+ if (regno < func->x_max_parm_reg)
+ new = func->x_parm_reg_stack_loc[regno];
+ if (new == 0)
+ new = assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode), 0, func);
PUT_CODE (reg, MEM);
PUT_MODE (reg, decl_mode);
@@ -3993,8 +3948,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);
@@ -4568,9 +4522,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;
@@ -5241,7 +5194,7 @@ fix_lexical_addr (addr, var)
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);
+ = assign_stack_local_1 (Pmode, GET_MODE_SIZE (Pmode), 0, fp);
addr = fix_lexical_addr (XEXP (fp->x_arg_pointer_save_area, 0), var);
addr = memory_address (Pmode, addr);
@@ -5328,10 +5281,8 @@ trampoline_address (function)
#else
#define TRAMPOLINE_REAL_SIZE (TRAMPOLINE_SIZE)
#endif
- if (fp != 0)
- tramp = assign_outer_stack_local (BLKmode, TRAMPOLINE_REAL_SIZE, 0, fp);
- else
- tramp = assign_stack_local (BLKmode, TRAMPOLINE_REAL_SIZE, 0);
+ tramp = assign_stack_local_1 (BLKmode, TRAMPOLINE_REAL_SIZE, 0,
+ fp ? fp : current_function);
#endif
/* Record the trampoline for reuse and note it for later initialization
@@ -5543,7 +5494,8 @@ static void
prepare_function_start ()
{
current_function = (struct function *) xcalloc (1, sizeof (struct function));
-
+ current_function->can_garbage_collect = 0;
+
init_stmt_for_function ();
cse_not_expected = ! optimize;
@@ -5584,6 +5536,11 @@ prepare_function_start ()
init_varasm_status (current_function);
+ /* 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;
@@ -5605,8 +5562,6 @@ 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;