GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "tree-flow.h"
#include "tree-stdarg.h"
#include "tm-constrs.h"
-
+#include "df.h"
/* Specify which cpu to schedule for. */
enum processor_type alpha_tune;
/* The alias set for prologue/epilogue register save/restore. */
-static GTY(()) int alpha_sr_alias_set;
+static GTY(()) alias_set_type alpha_sr_alias_set;
/* The assembler name of the current function. */
}
#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
-/* Implement TARGET_MANGLE_FUNDAMENTAL_TYPE. */
+/* Implement TARGET_MANGLE_TYPE. */
static const char *
-alpha_mangle_fundamental_type (tree type)
+alpha_mangle_type (const_tree type)
{
if (TYPE_MAIN_VARIANT (type) == long_double_type_node
&& TARGET_LONG_DOUBLE_128)
if (!(target_flags_explicit & MASK_LONG_DOUBLE_128))
target_flags |= MASK_LONG_DOUBLE_128;
#endif
+
+ /* If using typedef char *va_list, signal that __builtin_va_start (&ap, 0)
+ can be optimized to ap = __builtin_next_arg (0). */
+ if (TARGET_ABI_UNICOSMK)
+ targetm.expand_builtin_va_start = NULL;
}
\f
/* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */
function in the current unit of translation. */
static bool
-decl_has_samegp (tree decl)
+decl_has_samegp (const_tree decl)
{
/* Functions that are not local can be overridden, and thus may
not share the same gp. */
/* Return true if EXP should be placed in the small data section. */
static bool
-alpha_in_small_data_p (tree exp)
+alpha_in_small_data_p (const_tree exp)
{
/* We want to merge strings, so we never consider them small data. */
if (TREE_CODE (exp) == STRING_CST)
part of the CONST_INT. Then load FOO plus any high-order part of the
CONST_INT into a register. Our address is (plus reg low-part-const).
This is done to reduce the number of GOT entries. */
- if (!no_new_pseudos
+ if (can_create_pseudo_p ()
&& GET_CODE (x) == CONST
&& GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
/* If we have a (plus reg const), emit the load as in (2), then add
the two registers, and finally generate (plus reg low-part-const) as
our address. */
- if (!no_new_pseudos
+ if (can_create_pseudo_p ()
&& GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 0)) == REG
&& GET_CODE (XEXP (x, 1)) == CONST
return x;
else
{
- if (!no_new_pseudos)
+ if (can_create_pseudo_p ())
scratch = gen_reg_rtx (Pmode);
emit_insn (gen_rtx_SET (VOIDmode, scratch,
gen_rtx_HIGH (Pmode, x)));
if (addend)
x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (addend),
- (no_new_pseudos ? scratch : NULL_RTX),
+ (!can_create_pseudo_p () ? scratch : NULL_RTX),
1, OPTAB_LIB_WIDEN);
if (high)
x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (high),
- (no_new_pseudos ? scratch : NULL_RTX),
+ (!can_create_pseudo_p () ? scratch : NULL_RTX),
1, OPTAB_LIB_WIDEN);
return plus_constant (x, low);
int i, bits;
/* Use a pseudo if highly optimizing and still generating RTL. */
rtx subtarget
- = (flag_expensive_optimizations && !no_new_pseudos ? 0 : target);
+ = (flag_expensive_optimizations && can_create_pseudo_p () ? 0 : target);
rtx temp, insn;
/* If this is a sign-extended 32-bit constant, we can do this in at most
{
if (no_output)
return pc_rtx;
- if (no_new_pseudos)
+ if (!can_create_pseudo_p ())
{
emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (high << 16)));
temp = target;
we can't make pseudos, we can't do anything since the expand_binop
and expand_unop calls will widen and try to make pseudos. */
- if (n == 1 || (mode == SImode && no_new_pseudos))
+ if (n == 1 || (mode == SImode && !can_create_pseudo_p ()))
return 0;
/* Next, see if we can load a related constant and then shift and possibly
/* If we can't make any pseudos, TARGET is an SImode hard register, we
can't load this constant in one insn, do this in DImode. */
- if (no_new_pseudos && mode == SImode
+ if (!can_create_pseudo_p () && mode == SImode
&& GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER)
{
result = alpha_emit_set_const_1 (target, mode, c, 1, no_output);
conditional move. Make sure we emit only comparisons we have;
swap or reverse as necessary. */
- if (no_new_pseudos)
+ if (!can_create_pseudo_p ())
return NULL_RTX;
switch (code)
if (mode != DImode)
{
target = gen_lowpart (DImode, dest);
- if (! no_new_pseudos)
+ if (can_create_pseudo_p ())
subtarget = gen_reg_rtx (DImode);
else
subtarget = target;
alpha_emit_xfloating_compare (enum rtx_code *pcode, rtx op0, rtx op1)
{
enum rtx_code cmp_code, res_code;
- rtx func, out, operands[2];
+ rtx func, out, operands[2], note;
/* X_floating library comparison functions return
-1 unordered
operands[1] = op1;
out = gen_reg_rtx (DImode);
- /* ??? Strange mode for equiv because what's actually returned
- is -1,0,1, not a proper boolean value. */
- alpha_emit_xfloating_libcall (func, out, operands, 2,
- gen_rtx_fmt_ee (cmp_code, CCmode, op0, op1));
+ /* What's actually returned is -1,0,1, not a proper boolean value,
+ so use an EXPR_LIST as with a generic libcall instead of a
+ comparison type expression. */
+ note = gen_rtx_EXPR_LIST (VOIDmode, op1, NULL_RTX);
+ note = gen_rtx_EXPR_LIST (VOIDmode, op0, note);
+ note = gen_rtx_EXPR_LIST (VOIDmode, func, note);
+ alpha_emit_xfloating_libcall (func, out, operands, 2, note);
return out;
}
seq = get_insns ();
end_sequence ();
- emit_insn_at_entry (seq);
+
+ /* We used to simply emit the sequence after entry_of_function.
+ However this breaks the CFG if the first instruction in the
+ first block is not the NOTE_INSN_BASIC_BLOCK, for example a
+ label. Emit the sequence properly on the edge. We are only
+ invoked from dw2_build_landing_pads and finish_eh_generation
+ will call commit_edge_insertions thanks to a kludge. */
+ insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR));
cfun->machine->gp_save_rtx = m;
}
rtx top;
if (!has_hard_reg_initial_val (Pmode, REG_RA))
- return regs_ever_live[REG_RA];
+ return (int)df_regs_ever_live_p (REG_RA);
push_topmost_sequence ();
top = get_insns ();
addr = memory_address (mode, plus_constant (tramp, cxtofs));
emit_move_insn (gen_rtx_MEM (mode, addr), cxt);
- /* This has been disabled since the hint only has a 32k range, and in
- no existing OS is the stack within 32k of the text segment. */
- if (0 && jmpofs >= 0)
- {
- /* Compute hint value. */
- temp = force_operand (plus_constant (tramp, jmpofs+4), NULL_RTX);
- temp = expand_binop (DImode, sub_optab, fnaddr, temp, temp, 1,
- OPTAB_WIDEN);
- temp = expand_shift (RSHIFT_EXPR, Pmode, temp,
- build_int_cst (NULL_TREE, 2), NULL_RTX, 1);
- temp = expand_and (SImode, gen_lowpart (SImode, temp),
- GEN_INT (0x3fff), 0);
-
- /* Merge in the hint. */
- addr = memory_address (SImode, plus_constant (tramp, jmpofs));
- temp1 = force_reg (SImode, gen_rtx_MEM (SImode, addr));
- temp1 = expand_and (SImode, temp1, GEN_INT (0xffffc000), NULL_RTX);
- temp1 = expand_binop (SImode, ior_optab, temp1, temp, temp1, 1,
- OPTAB_WIDEN);
- emit_move_insn (gen_rtx_MEM (SImode, addr), temp1);
- }
-
#ifdef ENABLE_EXECUTE_STACK
emit_library_call (init_one_libfunc ("__enable_execute_stack"),
0, VOIDmode, 1, tramp, Pmode);
/* Return true if TYPE must be returned in memory, instead of in registers. */
static bool
-alpha_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED)
+alpha_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED)
{
enum machine_mode mode = VOIDmode;
int size;
static bool
alpha_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
enum machine_mode mode,
- tree type ATTRIBUTE_UNUSED,
+ const_tree type ATTRIBUTE_UNUSED,
bool named ATTRIBUTE_UNUSED)
{
return mode == TFmode || mode == TCmode;
$f0 for floating-point functions. */
rtx
-function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
+function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED,
enum machine_mode mode)
{
unsigned int regnum, dummy;
should not split these values. */
static bool
-alpha_split_complex_arg (tree type)
+alpha_split_complex_arg (const_tree type)
{
return TYPE_MODE (type) != TCmode;
}
if ((TREE_CODE (rhs) != NOP_EXPR
&& TREE_CODE (rhs) != CONVERT_EXPR
- && (TREE_CODE (rhs) != PLUS_EXPR
+ && ((TREE_CODE (rhs) != PLUS_EXPR
+ && TREE_CODE (rhs) != POINTER_PLUS_EXPR)
|| TREE_CODE (TREE_OPERAND (rhs, 1)) != INTEGER_CST
|| !host_integerp (TREE_OPERAND (rhs, 1), 1)))
|| TREE_CODE (TREE_OPERAND (rhs, 0)) != SSA_NAME)
current statement. */
static bool
-alpha_stdarg_optimize_hook (struct stdarg_info *si, tree lhs, tree rhs)
+alpha_stdarg_optimize_hook (struct stdarg_info *si, const_tree lhs, const_tree rhs)
{
tree base, offset, arg1, arg2;
int offset_arg = 1;
lhs = va_list_skip_additions (TREE_OPERAND (rhs, 0));
if (lhs == NULL_TREE
- || TREE_CODE (lhs) != PLUS_EXPR)
+ || TREE_CODE (lhs) != POINTER_PLUS_EXPR)
return false;
base = TREE_OPERAND (lhs, 0);
if (!no_rtl)
{
- int count, set = get_varargs_alias_set ();
+ int count;
+ alias_set_type set = get_varargs_alias_set ();
rtx tmp;
count = cfun->va_list_gpr_size / UNITS_PER_WORD;
#endif
}
-void
+static void
alpha_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
{
HOST_WIDE_INT offset;
valist, offset_field, NULL_TREE);
t = make_tree (ptr_type_node, virtual_incoming_args_rtx);
- t = build2 (PLUS_EXPR, ptr_type_node, t,
- build_int_cst (NULL_TREE, offset));
+ t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t,
+ size_int (offset));
t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (base_field), base_field, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
/* Build the final address and force that value into a temporary. */
- addr = build2 (PLUS_EXPR, ptr_type, fold_convert (ptr_type, base),
- fold_convert (ptr_type, addend));
+ addr = build2 (POINTER_PLUS_EXPR, ptr_type, fold_convert (ptr_type, base),
+ fold_convert (sizetype, addend));
internal_post = NULL;
gimplify_expr (&addr, pre_p, &internal_post, is_gimple_val, fb_rvalue);
append_to_statement_list (internal_post, pre_p);
/* One for every register we have to save. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (! fixed_regs[i] && ! call_used_regs[i]
- && regs_ever_live[i] && i != REG_RA
+ && df_regs_ever_live_p (i) && i != REG_RA
&& (!TARGET_ABI_UNICOSMK || i != HARD_FRAME_POINTER_REGNUM))
{
if (i < 32)
vms_save_fp_regno = -1;
if (vms_base_regno == HARD_FRAME_POINTER_REGNUM)
for (i = 0; i < 32; i++)
- if (! fixed_regs[i] && call_used_regs[i] && ! regs_ever_live[i])
+ if (! fixed_regs[i] && call_used_regs[i] && ! df_regs_ever_live_p (i))
vms_save_fp_regno = i;
if (vms_save_fp_regno == -1 && alpha_procedure_type == PT_REGISTER)
HOST_WIDE_INT hi, lo;
rtx this, insn, funexp;
- reset_block_changes ();
-
/* We always require a valid GP. */
emit_insn (gen_prologue_ldgp ());
emit_note (NOTE_INSN_PROLOGUE_END);
instruction scheduling worth while. Note that use_thunk calls
assemble_start_function and assemble_end_function. */
insn = get_insns ();
- insn_locators_initialize ();
+ insn_locators_alloc ();
shorten_branches (insn);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ free_after_compilation (cfun);
}
#endif /* TARGET_ABI_OSF */
\f
{
if (GET_CODE (i) == NOTE)
{
- switch (NOTE_LINE_NUMBER (i))
+ switch (NOTE_KIND (i))
{
case NOTE_INSN_EH_REGION_BEG:
exception_nesting++;
registers. */
static bool
-unicosmk_must_pass_in_stack (enum machine_mode mode, tree type)
+unicosmk_must_pass_in_stack (enum machine_mode mode, const_tree type)
{
if (type == NULL)
return false;
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK alpha_output_mi_thunk_osf
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
-#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
#undef TARGET_STDARG_OPTIMIZE_HOOK
#define TARGET_STDARG_OPTIMIZE_HOOK alpha_stdarg_optimize_hook
#endif
#define TARGET_MACHINE_DEPENDENT_REORG alpha_reorg
#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
#undef TARGET_PROMOTE_PROTOTYPES
-#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_false
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY alpha_return_in_memory
#undef TARGET_PASS_BY_REFERENCE
#undef TARGET_BUILD_BUILTIN_VA_LIST
#define TARGET_BUILD_BUILTIN_VA_LIST alpha_build_builtin_va_list
+#undef TARGET_EXPAND_BUILTIN_VA_START
+#define TARGET_EXPAND_BUILTIN_VA_START alpha_va_start
+
/* The Alpha architecture does not require sequential consistency. See
http://www.cs.umd.edu/~pugh/java/memoryModel/AlphaReordering.html
for an example of how it can be violated in practice. */
#define TARGET_HANDLE_OPTION alpha_handle_option
#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
-#undef TARGET_MANGLE_FUNDAMENTAL_TYPE
-#define TARGET_MANGLE_FUNDAMENTAL_TYPE alpha_mangle_fundamental_type
+#undef TARGET_MANGLE_TYPE
+#define TARGET_MANGLE_TYPE alpha_mangle_type
#endif
struct gcc_target targetm = TARGET_INITIALIZER;