/* Subroutines for manipulating rtx's in semantically interesting ways.
- Copyright (C) 1987-2015 Free Software Foundation, Inc.
+ Copyright (C) 1987-2016 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "diagnostic-core.h"
+#include "target.h"
+#include "function.h"
#include "rtl.h"
-#include "alias.h"
-#include "symtab.h"
#include "tree.h"
-#include "stor-layout.h"
#include "tm_p.h"
-#include "flags.h"
-#include "except.h"
-#include "hard-reg-set.h"
-#include "function.h"
-#include "insn-config.h"
#include "expmed.h"
+#include "optabs.h"
+#include "emit-rtl.h"
+#include "recog.h"
+#include "diagnostic-core.h"
+#include "stor-layout.h"
+#include "except.h"
#include "dojump.h"
#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
#include "expr.h"
-#include "insn-codes.h"
-#include "optabs.h"
-#include "libfuncs.h"
-#include "recog.h"
-#include "langhooks.h"
-#include "target.h"
#include "common/common-target.h"
#include "output.h"
machine_mode mode = DECL_MODE (decl);
machine_mode pmode;
- if (TREE_CODE (decl) == RESULT_DECL
- || TREE_CODE (decl) == PARM_DECL)
+ if (TREE_CODE (decl) == RESULT_DECL && !DECL_BY_REFERENCE (decl))
+ pmode = promote_function_mode (type, mode, &unsignedp,
+ TREE_TYPE (current_function_decl), 1);
+ else if (TREE_CODE (decl) == RESULT_DECL || TREE_CODE (decl) == PARM_DECL)
pmode = promote_function_mode (type, mode, &unsignedp,
TREE_TYPE (current_function_decl), 2);
else
return pmode;
}
+/* Return the promoted mode for name. If it is a named SSA_NAME, it
+ is the same as promote_decl_mode. Otherwise, it is the promoted
+ mode of a temp decl of same type as the SSA_NAME, if we had created
+ one. */
+
+machine_mode
+promote_ssa_mode (const_tree name, int *punsignedp)
+{
+ gcc_assert (TREE_CODE (name) == SSA_NAME);
+
+ /* Partitions holding parms and results must be promoted as expected
+ by function.c. */
+ if (SSA_NAME_VAR (name)
+ && (TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL
+ || TREE_CODE (SSA_NAME_VAR (name)) == RESULT_DECL))
+ {
+ machine_mode mode = promote_decl_mode (SSA_NAME_VAR (name), punsignedp);
+ if (mode != BLKmode)
+ return mode;
+ }
+
+ tree type = TREE_TYPE (name);
+ int unsignedp = TYPE_UNSIGNED (type);
+ machine_mode mode = TYPE_MODE (type);
+
+ /* Bypass TYPE_MODE when it maps vector modes to BLKmode. */
+ if (mode == BLKmode)
+ {
+ gcc_assert (VECTOR_TYPE_P (type));
+ mode = type->type_common.mode;
+ }
+
+ machine_mode pmode = promote_mode (type, mode, &unsignedp);
+ if (punsignedp)
+ *punsignedp = unsignedp;
+
+ return pmode;
+}
+
+
\f
/* Controls the behaviour of {anti_,}adjust_stack. */
static bool suppress_reg_args_size;
{
rtx sa = *psave;
/* The default is that we use a move insn and save in a Pmode object. */
- rtx (*fcn) (rtx, rtx) = gen_move_insn_uncast;
+ rtx_insn *(*fcn) (rtx, rtx) = gen_move_insn;
machine_mode mode = STACK_SAVEAREA_MODE (save_level);
/* See if this machine has anything special to do for this kind of save. */
switch (save_level)
{
-#ifdef HAVE_save_stack_block
case SAVE_BLOCK:
- if (HAVE_save_stack_block)
- fcn = gen_save_stack_block;
+ if (targetm.have_save_stack_block ())
+ fcn = targetm.gen_save_stack_block;
break;
-#endif
-#ifdef HAVE_save_stack_function
case SAVE_FUNCTION:
- if (HAVE_save_stack_function)
- fcn = gen_save_stack_function;
+ if (targetm.have_save_stack_function ())
+ fcn = targetm.gen_save_stack_function;
break;
-#endif
-#ifdef HAVE_save_stack_nonlocal
case SAVE_NONLOCAL:
- if (HAVE_save_stack_nonlocal)
- fcn = gen_save_stack_nonlocal;
+ if (targetm.have_save_stack_nonlocal ())
+ fcn = targetm.gen_save_stack_nonlocal;
break;
-#endif
default:
break;
}
emit_stack_restore (enum save_level save_level, rtx sa)
{
/* The default is that we use a move insn. */
- rtx (*fcn) (rtx, rtx) = gen_move_insn_uncast;
+ rtx_insn *(*fcn) (rtx, rtx) = gen_move_insn;
/* If stack_realign_drap, the x86 backend emits a prologue that aligns both
STACK_POINTER and HARD_FRAME_POINTER.
/* See if this machine has anything special to do for this kind of save. */
switch (save_level)
{
-#ifdef HAVE_restore_stack_block
case SAVE_BLOCK:
- if (HAVE_restore_stack_block)
- fcn = gen_restore_stack_block;
+ if (targetm.have_restore_stack_block ())
+ fcn = targetm.gen_restore_stack_block;
break;
-#endif
-#ifdef HAVE_restore_stack_function
case SAVE_FUNCTION:
- if (HAVE_restore_stack_function)
- fcn = gen_restore_stack_function;
+ if (targetm.have_restore_stack_function ())
+ fcn = targetm.gen_restore_stack_function;
break;
-#endif
-#ifdef HAVE_restore_stack_nonlocal
case SAVE_NONLOCAL:
- if (HAVE_restore_stack_nonlocal)
- fcn = gen_restore_stack_nonlocal;
+ if (targetm.have_restore_stack_nonlocal ())
+ fcn = targetm.gen_restore_stack_nonlocal;
break;
-#endif
default:
break;
}
available_label = NULL;
-#ifdef HAVE_split_stack_space_check
- if (HAVE_split_stack_space_check)
+ if (targetm.have_split_stack_space_check ())
{
available_label = gen_label_rtx ();
/* This instruction will branch to AVAILABLE_LABEL if there
are SIZE bytes available on the stack. */
- emit_insn (gen_split_stack_space_check (size, available_label));
+ emit_insn (targetm.gen_split_stack_space_check
+ (size, available_label));
}
-#endif
/* The __morestack_allocate_stack_space function will allocate
memory using malloc. If the alignment of the memory returned
/* Perform the required allocation from the stack. Some systems do
this differently than simply incrementing/decrementing from the
stack pointer, such as acquiring the space by calling malloc(). */
-#ifdef HAVE_allocate_stack
- if (HAVE_allocate_stack)
+ if (targetm.have_allocate_stack ())
{
struct expand_operand ops[2];
/* We don't have to check against the predicate for operand 0 since
be valid for the operand. */
create_fixed_operand (&ops[0], target);
create_convert_operand_to (&ops[1], size, STACK_SIZE_MODE, true);
- expand_insn (CODE_FOR_allocate_stack, 2, ops);
+ expand_insn (targetm.code_for_allocate_stack, 2, ops);
}
else
-#endif
{
int saved_stack_pointer_delta;
emit_cmp_and_jump_insns (available, size, GEU, NULL_RTX, Pmode, 1,
space_available);
-#ifdef HAVE_trap
- if (HAVE_trap)
- emit_insn (gen_trap ());
+ if (targetm.have_trap ())
+ emit_insn (targetm.gen_trap ());
else
-#endif
error ("stack limits not supported on this target");
emit_barrier ();
emit_label (space_available);
void
emit_stack_probe (rtx address)
{
-#ifdef HAVE_probe_stack_address
- if (HAVE_probe_stack_address)
- emit_insn (gen_probe_stack_address (address));
+ if (targetm.have_probe_stack_address ())
+ emit_insn (targetm.gen_probe_stack_address (address));
else
-#endif
{
rtx memref = gen_rtx_MEM (word_mode, address);
MEM_VOLATILE_P (memref) = 1;
/* See if we have an insn to probe the stack. */
-#ifdef HAVE_probe_stack
- if (HAVE_probe_stack)
- emit_insn (gen_probe_stack (memref));
+ if (targetm.have_probe_stack ())
+ emit_insn (targetm.gen_probe_stack (memref));
else
-#endif
emit_move_insn (memref, const0_rtx);
}
}
}
/* Next see if we have an insn to check the stack. */
-#ifdef HAVE_check_stack
- else if (HAVE_check_stack)
+ else if (targetm.have_check_stack ())
{
struct expand_operand ops[1];
rtx addr = memory_address (Pmode,
size, first)));
bool success;
create_input_operand (&ops[0], addr, Pmode);
- success = maybe_expand_insn (CODE_FOR_check_stack, 1, ops);
+ success = maybe_expand_insn (targetm.code_for_check_stack, 1, ops);
gcc_assert (success);
}
-#endif
/* Otherwise we have to generate explicit probes. If we have a constant
small number of them to generate, that's the easy case. */
}
/* Look up the tree code for a given rtx code
- to provide the arithmetic operation for REAL_ARITHMETIC.
+ to provide the arithmetic operation for real_arithmetic.
The function returns an int because the caller may not know
what `enum tree_code' means. */