tree exp;
rtx target;
{
+ tree type = TREE_TYPE (exp);
+
/* We know our target cannot conflict, since safe_from_p has been called. */
#if 0
/* Don't try copying piece by piece into a hard register
}
#endif
- if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
- || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE)
+ if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
{
register tree elt;
- if (TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE)
- /* Inform later passes that the whole union value is dead. */
+ /* Inform later passes that the whole union value is dead. */
+ if (TREE_CODE (type) == UNION_TYPE)
emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
+
+ /* If we are building a static constructor into a register,
+ set the initial value as zero so we can fold the value into
+ a constant. */
+ else if (GET_CODE (target) == REG && TREE_STATIC (exp))
+ emit_move_insn (target, const0_rtx);
+
/* If the constructor has fewer fields than the structure,
clear the whole structure first. */
else if (list_length (CONSTRUCTOR_ELTS (exp))
- != list_length (TYPE_FIELDS (TREE_TYPE (exp))))
- clear_storage (target, int_size_in_bytes (TREE_TYPE (exp)));
+ != list_length (TYPE_FIELDS (type)))
+ clear_storage (target, int_size_in_bytes (type));
else
/* Inform later passes that the old value is dead. */
emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
/* The alignment of TARGET is
at least what its type requires. */
VOIDmode, 0,
- TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT,
- int_size_in_bytes (TREE_TYPE (exp)));
+ TYPE_ALIGN (type) / BITS_PER_UNIT,
+ int_size_in_bytes (type));
}
}
- else if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+ else if (TREE_CODE (type) == ARRAY_TYPE)
{
register tree elt;
register int i;
- tree domain = TYPE_DOMAIN (TREE_TYPE (exp));
+ tree domain = TYPE_DOMAIN (type);
int minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain));
int maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain));
- tree elttype = TREE_TYPE (TREE_TYPE (exp));
+ tree elttype = TREE_TYPE (type);
/* If the constructor has fewer fields than the structure,
- clear the whole structure first. */
+ clear the whole structure first. Similarly if this this is
+ static constructor of a non-BLKmode object. */
- if (list_length (CONSTRUCTOR_ELTS (exp)) < maxelt - minelt + 1)
+ if (list_length (CONSTRUCTOR_ELTS (exp)) < maxelt - minelt + 1
+ || (GET_CODE (target) == REG && TREE_STATIC (exp)))
clear_storage (target, maxelt - minelt + 1);
else
/* Inform later passes that the old value is dead. */
/* The alignment of TARGET is
at least what its type requires. */
VOIDmode, 0,
- TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT,
- int_size_in_bytes (TREE_TYPE (exp)));
+ TYPE_ALIGN (type) / BITS_PER_UNIT,
+ int_size_in_bytes (type));
}
}
exp_rtl = SAVE_EXPR_RTL (exp);
break;
+ case BIND_EXPR:
+ /* The only operand we look at is operand 1. The rest aren't
+ part of the expression. */
+ return safe_from_p (x, TREE_OPERAND (exp, 1));
+
case METHOD_CALL_EXPR:
/* This takes a rtx argument, but shouldn't appear here. */
abort ();
switch (code)
{
case LABEL_DECL:
- if (modifier == EXPAND_INITIALIZER)
- forced_labels = gen_rtx (EXPR_LIST, VOIDmode,
- label_rtx (exp), forced_labels);
- return gen_rtx (MEM, FUNCTION_MODE,
- gen_rtx (LABEL_REF, Pmode, label_rtx (exp)));
+ {
+ tree function = decl_function_context (exp);
+ /* Handle using a label in a containing function. */
+ if (function != current_function_decl && function != 0)
+ {
+ struct function *p = find_function_data (function);
+ /* Allocate in the memory associated with the function
+ that the label is in. */
+ push_obstacks (p->function_obstack,
+ p->function_maybepermanent_obstack);
+
+ p->forced_labels = gen_rtx (EXPR_LIST, VOIDmode,
+ label_rtx (exp), p->forced_labels);
+ pop_obstacks ();
+ }
+ else if (modifier == EXPAND_INITIALIZER)
+ forced_labels = gen_rtx (EXPR_LIST, VOIDmode,
+ label_rtx (exp), forced_labels);
+ return gen_rtx (MEM, FUNCTION_MODE,
+ gen_rtx (LABEL_REF, Pmode, label_rtx (exp)));
+ }
case PARM_DECL:
if (DECL_RTL (exp) == 0)
{
error_with_decl (exp, "prior parameter's size depends on `%s'");
- return const0_rtx;
+ return CONST0_RTX (mode);
}
case FUNCTION_DECL:
addr = fix_lexical_addr (addr, exp);
return change_address (DECL_RTL (exp), mode, addr);
}
+
/* This is the case of an array whose size is to be determined
from its initializer, while the initializer is still being parsed.
See expand_decl. */
return RTL_EXPR_RTL (exp);
case CONSTRUCTOR:
- /* All elts simple constants => refer to a constant in memory. */
- if (TREE_STATIC (exp))
- /* For aggregate types with non-BLKmode modes,
- this should ideally construct a CONST_INT. */
+ /* All elts simple constants => refer to a constant in memory. But
+ if this is a non-BLKmode mode, let it store a field at a time
+ since that should make a CONST_INT or CONST_DOUBLE when we
+ fold. */
+ if (TREE_STATIC (exp) && (mode == BLKmode || TREE_ADDRESSABLE (exp)))
{
rtx constructor = output_constant_def (exp);
- if (! memory_address_p (GET_MODE (constructor),
- XEXP (constructor, 0)))
+ if (modifier != EXPAND_CONST_ADDRESS
+ && modifier != EXPAND_INITIALIZER
+ && modifier != EXPAND_SUM
+ && !memory_address_p (GET_MODE (constructor),
+ XEXP (constructor, 0)))
constructor = change_address (constructor, VOIDmode,
XEXP (constructor, 0));
return constructor;
}
/* If this is a constant index into a constant array,
- just get the value from the array. */
- if (TREE_READONLY (TREE_OPERAND (exp, 0))
- && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == ARRAY_TYPE
- && TREE_CODE (TREE_OPERAND (exp, 0)) == VAR_DECL
- && DECL_INITIAL (TREE_OPERAND (exp, 0))
- && TREE_CODE (DECL_INITIAL (TREE_OPERAND (exp, 0))) != ERROR_MARK)
+ just get the value from the array. Handle both the cases when
+ we have an explicit constructor and when our operand is a variable
+ that was declared const. */
+
+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
+ && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)))
+ {
+ tree index = fold (TREE_OPERAND (exp, 1));
+ if (TREE_CODE (index) == INTEGER_CST
+ && TREE_INT_CST_HIGH (index) == 0)
+ {
+ int i = TREE_INT_CST_LOW (index);
+ tree elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
+
+ while (elem && i--)
+ elem = TREE_CHAIN (elem);
+ if (elem)
+ return expand_expr (fold (TREE_VALUE (elem)), target,
+ tmode, modifier);
+ }
+ }
+
+ else if (TREE_READONLY (TREE_OPERAND (exp, 0))
+ && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == ARRAY_TYPE
+ && TREE_CODE (TREE_OPERAND (exp, 0)) == VAR_DECL
+ && DECL_INITIAL (TREE_OPERAND (exp, 0))
+ && optimize >= 1
+ && (TREE_CODE (DECL_INITIAL (TREE_OPERAND (exp, 0)))
+ != ERROR_MARK))
{
tree index = fold (TREE_OPERAND (exp, 1));
if (TREE_CODE (index) == INTEGER_CST
case COMPONENT_REF:
case BIT_FIELD_REF:
+ /* If the operand is a CONSTRUCTOR, we can just extract the
+ appropriate field if it is present. */
+ if (code != ARRAY_REF
+ && TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR)
+ {
+ tree elt;
+
+ for (elt = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); elt;
+ elt = TREE_CHAIN (elt))
+ if (TREE_PURPOSE (elt) == TREE_OPERAND (exp, 1))
+ return expand_expr (TREE_VALUE (elt), target, tmode, modifier);
+ }
+
{
enum machine_mode mode1;
int bitsize;
just return the result we got. */
if (CALL_EXPR_RTL (exp) != 0)
return CALL_EXPR_RTL (exp);
- return expand_call (exp, target, ignore, modifier);
+ return expand_call (exp, target, ignore);
case NON_LVALUE_EXPR:
case NOP_EXPR:
lab2 = gen_label_rtx ();
/* By default check the arguments. If flag_fast_math is turned on,
- then assume sqrt will always be called with valid arguments. */
+ then assume sqrt will always be called with valid arguments.
+ Note changing the test below from "> 0" to ">= 0" would cause
+ incorrect results when computing sqrt(-0.0). */
+
if (! flag_fast_math)
{
/* By checking op > 0 we are able to catch all of the
GET_MODE (op0), 0, 0);
emit_jump_insn (gen_bgt (lab1));
- /* The argument was not in the domain; do this via library call. */
- expand_call (exp, target, 0, 0);
+ /* The argument was not in the domain; do this via library call.
+ Pop the arguments right away in case the call gets deleted. */
+ NO_DEFER_POP;
+ expand_call (exp, target, 0);
+ OK_DEFER_POP;
/* Branch around open coded version */
emit_jump_insn (gen_jump (lab2));
if (TREE_CODE (TREE_OPERAND (exp, 0)) != ADDR_EXPR
|| TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != FUNCTION_DECL
|| ! DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
- CALL_EXPR_RTL (exp) = expand_call (exp, 0, 0, 0);
+ CALL_EXPR_RTL (exp) = expand_call (exp, 0, 0);
return;
case COMPOUND_EXPR:
/* INDEX is the value being switched on, with the lowest value
in the table already subtracted.
- MODE is its expected mode (needed if INDEX is ever constant).
+ MODE is its expected mode (needed if INDEX is constant).
RANGE is the length of the jump table.
TABLE_LABEL is a CODE_LABEL rtx for the table itself.
{
register rtx temp, vector;
- /* Code below assumes that MODE is Pmode,
- but I think that is a mistake. Let's see if that is true. */
- if (mode != Pmode)
- abort ();
+ /* Do an unsigned comparison (in the proper mode) between the index
+ expression and the value which represents the length of the range.
+ Since we just finished subtracting the lower bound of the range
+ from the index expression, this comparison allows us to simultaneously
+ check that the original index expression value is both greater than
+ or equal to the minimum value of the range and less than or equal to
+ the maximum value of the range. */
emit_cmp_insn (range, index, LTU, 0, mode, 0, 0);
emit_jump_insn (gen_bltu (default_label));
+
+ /* If index is in range, it must fit in Pmode.
+ Convert to Pmode so we can index with it. */
+ if (mode != Pmode)
+ index = convert_to_mode (Pmode, index, 1);
+
/* If flag_force_addr were to affect this address
it could interfere with the tricky assumptions made
about addresses that contain label-refs,