#endif
static void do_tablejump (rtx, enum machine_mode, rtx, rtx, rtx);
static rtx const_vector_from_tree (tree);
-static void execute_expand (void);
/* Record for each mode whether we can move a register directly to or
from an object of that mode in memory. If we can't, we won't try
else if (TREE_CODE (exp) == COMPONENT_REF)
{
tree field = TREE_OPERAND (exp, 1);
- tree this_offset = DECL_FIELD_OFFSET (field);
+ tree this_offset = component_ref_field_offset (exp);
/* If this field hasn't been filled in yet, don't go
past it. This should only happen when folding expressions
made during type construction. */
if (this_offset == 0)
break;
- else
- this_offset = SUBSTITUTE_PLACEHOLDER_IN_EXPR (this_offset, exp);
offset = size_binop (PLUS_EXPR, offset, this_offset);
bit_offset = size_binop (PLUS_EXPR, bit_offset,
|| TREE_CODE (exp) == ARRAY_RANGE_REF)
{
tree index = TREE_OPERAND (exp, 1);
- tree array = TREE_OPERAND (exp, 0);
- tree domain = TYPE_DOMAIN (TREE_TYPE (array));
- tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
- tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array)));
+ tree low_bound = array_ref_low_bound (exp);
+ tree unit_size = array_ref_element_size (exp);
/* We assume all arrays have sizes that are a multiple of a byte.
First subtract the lower bound, if any, in the type of the
index, then convert to sizetype and multiply by the size of the
array element. */
- if (low_bound != 0 && ! integer_zerop (low_bound))
+ if (! integer_zerop (low_bound))
index = fold (build (MINUS_EXPR, TREE_TYPE (index),
index, low_bound));
- /* If the index has a self-referential type, instantiate it with
- the object; likewise for the component size. */
- index = SUBSTITUTE_PLACEHOLDER_IN_EXPR (index, exp);
- unit_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (unit_size, array);
offset = size_binop (PLUS_EXPR, offset,
size_binop (MULT_EXPR,
convert (sizetype, index),
return exp;
}
+/* Return a tree of sizetype representing the size, in bytes, of the element
+ of EXP, an ARRAY_REF. */
+
+tree
+array_ref_element_size (tree exp)
+{
+ tree aligned_size = TREE_OPERAND (exp, 3);
+ tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+
+ /* If a size was specified in the ARRAY_REF, it's the size measured
+ in alignment units of the element type. So multiply by that value. */
+ if (aligned_size)
+ return size_binop (MULT_EXPR, aligned_size,
+ size_int (TYPE_ALIGN (elmt_type) / BITS_PER_UNIT));
+
+ /* Otherwise, take the size from that of the element type. Substitute
+ any PLACEHOLDER_EXPR that we have. */
+ else
+ return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp);
+}
+
+/* Return a tree representing the lower bound of the array mentioned in
+ EXP, an ARRAY_REF. */
+
+tree
+array_ref_low_bound (tree exp)
+{
+ tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
+
+ /* If a lower bound is specified in EXP, use it. */
+ if (TREE_OPERAND (exp, 2))
+ return TREE_OPERAND (exp, 2);
+
+ /* Otherwise, if there is a domain type and it has a lower bound, use it,
+ substituting for a PLACEHOLDER_EXPR as needed. */
+ if (domain_type && TYPE_MIN_VALUE (domain_type))
+ return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), exp);
+
+ /* Otherwise, return a zero of the appropriate type. */
+ return fold_convert (TREE_TYPE (TREE_OPERAND (exp, 1)), integer_zero_node);
+}
+
+/* Return a tree representing the offset, in bytes, of the field referenced
+ by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */
+
+tree
+component_ref_field_offset (tree exp)
+{
+ tree aligned_offset = TREE_OPERAND (exp, 2);
+ tree field = TREE_OPERAND (exp, 1);
+
+ /* If an offset was specified in the COMPONENT_REF, it's the offset measured
+ in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT. So multiply by that
+ value. */
+ if (aligned_offset)
+ return size_binop (MULT_EXPR, aligned_offset,
+ size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT));
+
+ /* Otherwise, take the offset from that of the field. Substitute
+ any PLACEHOLDER_EXPR that we have. */
+ else
+ return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
+}
+
/* Return 1 if T is an expression that get_inner_reference handles. */
int
{
tree array = TREE_OPERAND (exp, 0);
- tree domain = TYPE_DOMAIN (TREE_TYPE (array));
- tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
+ tree low_bound = array_ref_low_bound (exp);
tree index = convert (sizetype, TREE_OPERAND (exp, 1));
HOST_WIDE_INT i;
/* Mark it as expanded. */
TREE_OPERAND (exp, 1) = NULL_TREE;
- store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0);
+ if (VOID_TYPE_P (TREE_TYPE (exp1)))
+ /* If the initializer is void, just expand it; it will initialize
+ the object directly. */
+ expand_expr (exp1, const0_rtx, VOIDmode, 0);
+ else
+ store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0);
expand_decl_cleanup_eh (NULL_TREE, cleanups, CLEANUP_EH_ONLY (exp));
return gen_rtx_raw_CONST_VECTOR (mode, v);
}
-\f
-/* Called to move the SAVE_EXPRs for parameter declarations in a
- nested function into the nested function. DATA is really the
- nested FUNCTION_DECL. */
-
-static tree
-set_save_expr_context (tree *tp,
- int *walk_subtrees,
- void *data)
-{
- if (TREE_CODE (*tp) == SAVE_EXPR && !SAVE_EXPR_CONTEXT (*tp))
- SAVE_EXPR_CONTEXT (*tp) = (tree) data;
- /* Do not walk back into the SAVE_EXPR_CONTEXT; that will cause
- circularity. */
- else if (DECL_P (*tp))
- *walk_subtrees = 0;
-
- return NULL;
-}
-
-
-static void
-execute_expand (void)
-{
- /* If the function has a variably modified type, there may be
- SAVE_EXPRs in the parameter types. Their context must be set to
- refer to this function; they cannot be expanded in the containing
- function. */
- if (decl_function_context (current_function_decl) == current_function_decl
- && variably_modified_type_p (TREE_TYPE (current_function_decl)))
- walk_tree (&TREE_TYPE (current_function_decl), set_save_expr_context,
- current_function_decl, NULL);
-
- /* Expand the variables recorded during gimple lowering. This must
- occur before the call to expand_function_start to ensure that
- all used variables are expanded before we expand anything on the
- PENDING_SIZES list. */
- expand_used_vars ();
-
- /* Set up parameters and prepare for return, for the function. */
- expand_function_start (current_function_decl, 0);
-
- /* If this function is `main', emit a call to `__main'
- to run global initializers, etc. */
- if (DECL_NAME (current_function_decl)
- && MAIN_NAME_P (DECL_NAME (current_function_decl))
- && DECL_FILE_SCOPE_P (current_function_decl))
- expand_main_function ();
-
- /* Generate the RTL for this function. */
- expand_expr_stmt_value (DECL_SAVED_TREE (current_function_decl), 0, 0);
-
- /* We hard-wired immediate_size_expand to zero above.
- expand_function_end will decrement this variable. So, we set the
- variable to one here, so that after the decrement it will remain
- zero. */
- immediate_size_expand = 1;
-
- /* Make sure the locus is set to the end of the function, so that
- epilogue line numbers and warnings are set properly. */
- if (cfun->function_end_locus.file)
- input_location = cfun->function_end_locus;
-
- /* The following insns belong to the top scope. */
- record_block_change (DECL_INITIAL (current_function_decl));
-
- /* Generate rtl for function exit. */
- expand_function_end ();
-}
-
-struct tree_opt_pass pass_expand =
-{
- "expand", /* name */
- NULL, /* gate */
- execute_expand, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_EXPAND, /* tv_id */
- /* ??? If TER is enabled, we actually receive GENERIC. */
- PROP_gimple_leh, /* properties_required */
- PROP_rtl, /* properties_provided */
- PROP_cfg | PROP_gimple_leh, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0 /* todo_flags_finish */
-};
-
-
#include "gt-expr.h"