#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "toplev.h"
#include "rtl.h"
#include "tree.h"
#include "insn-config.h"
#include "ggc.h"
#include "recog.h"
+#include "langhooks.h"
static rtx break_out_memory_refs PARAMS ((rtx));
static void emit_stack_probe PARAMS ((rtx));
{
int width = GET_MODE_BITSIZE (mode);
+ /* You want to truncate to a _what_? */
+ if (! SCALAR_INT_MODE_P (mode))
+ abort ();
+
/* Canonicalize BImode to 0 and STORE_FLAG_VALUE. */
if (mode == BImode)
return c & 1 ? STORE_FLAG_VALUE : 0;
expr_size (exp)
tree exp;
{
- tree size;
-
- if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd'
- && DECL_SIZE_UNIT (exp) != 0)
- size = DECL_SIZE_UNIT (exp);
- else
- size = size_in_bytes (TREE_TYPE (exp));
+ tree size = (*lang_hooks.expr_size) (exp);
- if (TREE_CODE (size) != INTEGER_CST
- && contains_placeholder_p (size))
+ if (CONTAINS_PLACEHOLDER_P (size))
size = build (WITH_RECORD_EXPR, sizetype, size, exp);
return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
+}
+
+/* Return a wide integer for the size in bytes of the value of EXP, or -1
+ if the size can vary or is larger than an integer. */
+HOST_WIDE_INT
+int_expr_size (exp)
+ tree exp;
+{
+ tree t = (*lang_hooks.expr_size) (exp);
+
+ if (t == 0
+ || TREE_CODE (t) != INTEGER_CST
+ || TREE_OVERFLOW (t)
+ || TREE_INT_CST_HIGH (t) != 0
+ /* If the result would appear negative, it's too big to represent. */
+ || (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0)
+ return -1;
+
+ return TREE_INT_CST_LOW (t);
}
\f
/* Return a copy of X in which all memory references
break;
case SYMBOL_REF:
- temp = gen_rtx_SYMBOL_REF (to_mode, XSTR (x, 0));
- SYMBOL_REF_FLAG (temp) = SYMBOL_REF_FLAG (x);
- CONSTANT_POOL_ADDRESS_P (temp) = CONSTANT_POOL_ADDRESS_P (x);
- STRING_POOL_ADDRESS_P (temp) = STRING_POOL_ADDRESS_P (x);
+ temp = shallow_copy_rtx (x);
+ PUT_MODE (temp, to_mode);
return temp;
break;
/* We can set RTX_UNCHANGING_P from TREE_READONLY for decls whose
initialization is only executed once, or whose initializer always
has the same value. Currently we simplify this to PARM_DECLs in the
- first case, and decls with TREE_CONSTANT initializers in the second. */
+ first case, and decls with TREE_CONSTANT initializers in the second.
+
+ We cannot do this for non-static aggregates, because of the double
+ writes that can be generated by store_constructor, depending on the
+ contents of the initializer. Yes, this does eliminate a good fraction
+ of the number of uses of RTX_UNCHANGING_P for a language like Ada.
+ It also eliminates a good quantity of bugs. Let this be incentive to
+ eliminate RTX_UNCHANGING_P entirely in favour of a more reliable
+ solution, perhaps based on alias sets. */
+
if ((TREE_READONLY (t) && DECL_P (t)
+ && (TREE_STATIC (t) || ! AGGREGATE_TYPE_P (TREE_TYPE (t)))
&& (TREE_CODE (t) == PARM_DECL
- || DECL_INITIAL (t) == NULL_TREE
- || TREE_CONSTANT (DECL_INITIAL (t))))
+ || (DECL_INITIAL (t) && TREE_CONSTANT (DECL_INITIAL (t)))))
|| TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
RTX_UNCHANGING_P (ref) = 1;
}
stabilize (x)
rtx x;
{
-
if (GET_CODE (x) != MEM
|| ! rtx_unstable_p (XEXP (x, 0)))
return x;
if INSN set something else (such as a SUBREG of TEMP). */
if (CONSTANT_P (x)
&& (set = single_set (insn)) != 0
- && SET_DEST (set) == temp)
+ && SET_DEST (set) == temp
+ && ! rtx_equal_p (x, SET_SRC (set)))
set_unique_reg_note (insn, REG_EQUAL, x);
return temp;
PUNSIGNEDP points to the signedness of the type and may be adjusted
to show what signedness to use on extension operations.
- FOR_CALL is non-zero if this call is promoting args for a call. */
+ FOR_CALL is nonzero if this call is promoting args for a call. */
enum machine_mode
promote_mode (type, mode, punsignedp, for_call)
rtx size;
{
int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
+
if (align == 1)
return size;
+
if (GET_CODE (size) == CONST_INT)
{
- int new = (INTVAL (size) + align - 1) / align * align;
+ HOST_WIDE_INT new = (INTVAL (size) + align - 1) / align * align;
+
if (INTVAL (size) != new)
size = GEN_INT (new);
}
NULL_RTX, 1);
size = expand_mult (Pmode, size, GEN_INT (align), NULL_RTX, 1);
}
+
return size;
}
\f
}
if (sa != 0)
- sa = validize_mem (sa);
+ {
+ sa = validize_mem (sa);
+ /* These clobbers prevent the scheduler from moving
+ references to variable arrays below the code
+ that deletes (pops) the arrays. */
+ emit_insn (gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_MEM (BLKmode,
+ gen_rtx_SCRATCH (VOIDmode))));
+ emit_insn (gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_MEM (BLKmode, stack_pointer_rtx)));
+ }
if (after)
{
always know its final value at this point in the compilation (it
might depend on the size of the outgoing parameter lists, for
example), so we must align the value to be returned in that case.
- (Note that STACK_DYNAMIC_OFFSET will have a default non-zero value if
+ (Note that STACK_DYNAMIC_OFFSET will have a default nonzero value if
STACK_POINTER_OFFSET or ACCUMULATE_OUTGOING_ARGS are defined).
We must also do an alignment operation on the returned value if
the stack pointer alignment is less strict that BIGGEST_ALIGNMENT.
pred = insn_data[(int) CODE_FOR_allocate_stack].operand[1].predicate;
if (pred && ! ((*pred) (size, mode)))
- size = copy_to_mode_reg (mode, size);
+ size = copy_to_mode_reg (mode, convert_to_mode (mode, size, 1));
emit_insn (gen_allocate_stack (target, size));
}
NULL_RTX, 1);
}
- /* Some systems require a particular insn to refer to the stack
- to make the pages exist. */
-#ifdef HAVE_probe
- if (HAVE_probe)
- emit_insn (gen_probe ());
-#endif
-
/* Record the new stack level for nonlocal gotos. */
if (nonlocal_goto_handler_slots != 0)
emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
}
#include "gt-explow.h"
-