/* Expands front end tree to back end RTL for GNU C-Compiler
Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "rtl.h"
#include "tree.h"
#include "flags.h"
int virtuals_instantiated;
/* Assign unique numbers to labels generated for profiling, debugging, etc. */
-static int funcdef_no;
+static GTY(()) int funcdef_no;
/* These variables hold pointers to functions to create and destroy
target specific, per-function data structures. */
f->x_nonlocal_goto_stack_level = NULL;
f->x_cleanup_label = NULL;
f->x_return_label = NULL;
+ f->computed_goto_common_label = NULL;
+ f->computed_goto_common_reg = NULL;
f->x_save_expr_regs = NULL;
f->x_stack_slot_list = NULL;
f->x_rtl_expr_chain = NULL;
address relative to the frame pointer. */
if (function == cfun && virtuals_instantiated)
addr = plus_constant (frame_pointer_rtx,
+ trunc_int_for_mode
(frame_offset + bigend_correction
- + STARTING_FRAME_OFFSET));
+ + STARTING_FRAME_OFFSET, Pmode));
else
addr = plus_constant (virtual_stack_vars_rtx,
- function->x_frame_offset + bigend_correction);
+ trunc_int_for_mode
+ (function->x_frame_offset + bigend_correction,
+ Pmode));
#ifndef FRAME_GROWS_DOWNWARD
function->x_frame_offset += size;
abort ();
p->slot = assign_stack_local (mode,
(mode == BLKmode
- ? CEIL_ROUND (size, align / BITS_PER_UNIT)
+ ? CEIL_ROUND (size, (int) align / BITS_PER_UNIT)
: size),
align);
/* If a type is specified, set the relevant flags. */
if (type != 0)
{
- RTX_UNCHANGING_P (slot) = TYPE_READONLY (type);
+ RTX_UNCHANGING_P (slot) = (lang_hooks.honor_readonly
+ && TYPE_READONLY (type));
MEM_VOLATILE_P (slot) = TYPE_VOLATILE (type);
MEM_SET_IN_STRUCT_P (slot, AGGREGATE_TYPE_P (type));
}
temp_slot_level++;
}
-/* Likewise, but save the new level as the place to allocate variables
- for blocks. */
-
-#if 0
-void
-push_temp_slots_for_block ()
-{
- push_temp_slots ();
-
- var_temp_slot_level = temp_slot_level;
-}
-
-/* Likewise, but save the new level as the place to allocate temporaries
- for TARGET_EXPRs. */
-
-void
-push_temp_slots_for_target ()
-{
- push_temp_slots ();
-
- target_temp_slot_level = temp_slot_level;
-}
-
-/* Set and get the value of target_temp_slot_level. The only
- permitted use of these functions is to save and restore this value. */
-
-int
-get_target_temp_slot_level ()
-{
- return target_temp_slot_level;
-}
-
-void
-set_target_temp_slot_level (level)
- int level;
-{
- target_temp_slot_level = level;
-}
-#endif
-
/* Pop a temporary nesting level. All slots in use in the current level
are freed. */
copy SET_SRC (x) to SET_DEST (x) in some way. So
we generate the move and see whether it requires more
than one insn. If it does, we emit those insns and
- delete INSN. Otherwise, we an just replace the pattern
+ delete INSN. Otherwise, we can just replace the pattern
of INSN; we have already verified above that INSN has
no other function that to do X. */
rtx sub, insns;
if (GET_CODE (XEXP (x, 0)) != MEM)
- {
- put_addressof_into_stack (x, ht);
- return true;
- }
+ put_addressof_into_stack (x, ht);
/* We must create a copy of the rtx because it was created by
overwriting a REG rtx which is always shared. */
compute_insns_for_mem (insns, NULL_RTX, ht);
for (insn = insns; insn; insn = NEXT_INSN (insn))
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
- || GET_CODE (insn) == CALL_INSN)
+ if (INSN_P (insn))
{
if (! purge_addressof_1 (&PATTERN (insn), insn,
asm_noperands (PATTERN (insn)) > 0, 0, ht))
case ABS:
case SQRT:
case FFS:
+ case CLZ: case CTZ:
+ case POPCOUNT: case PARITY:
/* These case either have just one operand or we know that we need not
check the rest of the operands. */
loc = &XEXP (x, 0);
}
}
\f
-int
-max_parm_reg_num ()
-{
- return max_parm_reg;
-}
-
/* Return the first insn following those generated by `assign_parms'. */
rtx
return get_insns ();
}
-/* Return the first NOTE_INSN_BLOCK_BEG note in the function.
- Crash if there is none. */
-
-rtx
-get_first_block_beg ()
-{
- rtx searcher;
- rtx insn = get_first_nonparm_insn ();
-
- for (searcher = insn; searcher; searcher = NEXT_INSN (searcher))
- if (GET_CODE (searcher) == NOTE
- && NOTE_LINE_NUMBER (searcher) == NOTE_INSN_BLOCK_BEG)
- return searcher;
-
- abort (); /* Invalid call to this function. (See comments above.) */
- return NULL_RTX;
-}
-
/* Return 1 if EXP is an aggregate type (or a value with aggregate type).
This means a type for which function calls must pass an address to the
function or get an address back from the function.
#ifdef INIT_CUMULATIVE_INCOMING_ARGS
INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_RTX);
#else
- INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0);
+ INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, fndecl);
#endif
/* We haven't yet found an argument that we must push and pretend the
offset_rtx));
set_mem_attributes (stack_parm, parm, 1);
+
+ /* Set also REG_ATTRS if parameter was passed in a register. */
+ if (entry_parm)
+ set_reg_attrs_for_parm (entry_parm, stack_parm);
}
/* If this parameter was passed both in registers and in the stack,
if (nregs > 0)
{
+#if defined (REG_PARM_STACK_SPACE) && !defined (MAYBE_REG_PARM_STACK_SPACE)
+ /* When REG_PARM_STACK_SPACE is nonzero, stack space for
+ split parameters was allocated by our caller, so we
+ won't be pushing it in the prolog. */
+ if (REG_PARM_STACK_SPACE (fndecl) == 0)
+#endif
current_function_pretend_args_size
= (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
/ (PARM_BOUNDARY / BITS_PER_UNIT)
set_mem_attributes (x, result, 1);
SET_DECL_RTL (result, x);
}
-
- if (GET_CODE (DECL_RTL (parm)) == REG)
- REGNO_DECL (REGNO (DECL_RTL (parm))) = parm;
- else if (GET_CODE (DECL_RTL (parm)) == CONCAT)
- {
- REGNO_DECL (REGNO (XEXP (DECL_RTL (parm), 0))) = parm;
- REGNO_DECL (REGNO (XEXP (DECL_RTL (parm), 1))) = parm;
- }
-
}
/* Output all parameter conversion instructions (possibly including calls)
current_function_calls_longjmp = 0;
current_function_calls_alloca = 0;
+ current_function_calls_eh_return = 0;
+ current_function_calls_constant_p = 0;
current_function_contains_functions = 0;
current_function_is_leaf = 0;
current_function_nothrow = 0;
cfun->arc_profile = profile_arc_flag || flag_test_coverage;
- cfun->arc_profile = profile_arc_flag || flag_test_coverage;
-
cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL;
cfun->max_jumptable_ents = 0;
subr, 1);
/* Structures that are returned in registers are not aggregate_value_p,
- so we may see a PARALLEL. Don't play pseudo games with this. */
- if (! REG_P (hard_reg))
- SET_DECL_RTL (DECL_RESULT (subr), hard_reg);
+ so we may see a PARALLEL or a REG. */
+ if (REG_P (hard_reg))
+ SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg)));
+ else if (GET_CODE (hard_reg) == PARALLEL)
+ SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg));
else
- {
- /* Create the pseudo. */
- SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg)));
+ abort ();
- /* Needed because we may need to move this to memory
- in case it's a named return value whose address is taken. */
- DECL_REGISTER (DECL_RESULT (subr)) = 1;
- }
+ /* Set DECL_REGISTER flag so that expand_function_end will copy the
+ result to the real return register(s). */
+ DECL_REGISTER (DECL_RESULT (subr)) = 1;
}
/* Initialize rtx for parameters and local variables.
}
/* Warn about unused parms if extra warnings were specified. */
- /* Either ``-W -Wunused'' or ``-Wunused-parameter'' enables this
+ /* Either ``-Wextra -Wunused'' or ``-Wunused-parameter'' enables this
warning. WARN_UNUSED_PARAMETER is negative when set by
- -Wunused. */
+ -Wunused. Note that -Wall implies -Wunused, so ``-Wall -Wextra'' will
+ also give these warnings. */
if (warn_unused_parameter > 0
|| (warn_unused_parameter < 0 && extra_warnings))
{
convert_move (real_decl_rtl, decl_rtl, unsignedp);
}
else if (GET_CODE (real_decl_rtl) == PARALLEL)
- emit_group_load (real_decl_rtl, decl_rtl,
- int_size_in_bytes (TREE_TYPE (decl_result)));
+ {
+ /* If expand_function_start has created a PARALLEL for decl_rtl,
+ move the result to the real return registers. Otherwise, do
+ a group load from decl_rtl for a named return. */
+ if (GET_CODE (decl_rtl) == PARALLEL)
+ emit_group_move (real_decl_rtl, decl_rtl);
+ else
+ emit_group_load (real_decl_rtl, decl_rtl,
+ int_size_in_bytes (TREE_TYPE (decl_result)));
+ }
else
emit_move_insn (real_decl_rtl, decl_rtl);
}
basic_block bb;
rtx line_note;
{
- rtx p, end;
-
- p = NEXT_INSN (bb->end);
- end = emit_jump_insn_after (gen_return (), bb->end);
+ emit_jump_insn_after (gen_return (), bb->end);
if (line_note)
emit_line_note_after (NOTE_SOURCE_FILE (line_note),
NOTE_LINE_NUMBER (line_note), PREV_INSN (bb->end));
if (last)
{
- rtx next;
-
/* Find the prologue-end note if we haven't already, and
move it to just after the last prologue insn. */
if (note == 0)
break;
}
- next = NEXT_INSN (note);
-
/* Avoid placing note between CODE_LABEL and BASIC_BLOCK note. */
if (GET_CODE (last) == CODE_LABEL)
last = NEXT_INSN (last);