#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "rtl.h"
#include "gimple.h"
#include "tree-iterator.h"
#include "tree-inline.h"
-#include "diagnostic.h"
+#include "tree-pretty-print.h"
#include "langhooks.h"
-#include "langhooks-def.h"
#include "tree-flow.h"
#include "cgraph.h"
#include "timevar.h"
-#include "except.h"
#include "hashtab.h"
#include "flags.h"
-#include "real.h"
#include "function.h"
#include "output.h"
-#include "expr.h"
#include "ggc.h"
+#include "diagnostic-core.h"
#include "toplev.h"
#include "target.h"
-#include "optabs.h"
#include "pointer-set.h"
#include "splay-tree.h"
#include "vec.h"
#include "gimple.h"
#include "tree-pass.h"
+#include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name. */
+#include "expr.h" /* FIXME: for can_move_by_pieces
+ and STACK_CHECK_MAX_VAR_SIZE. */
enum gimplify_omp_var_data
{
{
while (handled_component_p (x))
x = TREE_OPERAND (x, 0);
+ if (TREE_CODE (x) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
+ x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
if (TREE_CODE (x) != VAR_DECL
&& TREE_CODE (x) != PARM_DECL
&& TREE_CODE (x) != RESULT_DECL)
- return ;
+ return;
TREE_ADDRESSABLE (x) = 1;
}
/* Return true if T is a CALL_EXPR or an expression that can be
- assignmed to a temporary. Note that this predicate should only be
+ assigned to a temporary. Note that this predicate should only be
used during gimplification. See the rationale for this in
gimplify_modify_expr. */
mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
- if (EXPR_HAS_LOCATION (val))
- SET_EXPR_LOCATION (mod, EXPR_LOCATION (val));
- else
- SET_EXPR_LOCATION (mod, input_location);
+ SET_EXPR_LOCATION (mod, EXPR_LOC_OR_HERE (val));
/* gimplify_modify_expr might want to reduce this further. */
gimplify_and_add (mod, pre_p);
gcc_assert (!block || TREE_CODE (block) == BLOCK);
if (!block || !debug_info)
{
- TREE_CHAIN (last) = gimple_bind_vars (scope);
+ DECL_CHAIN (last) = gimple_bind_vars (scope);
gimple_bind_set_vars (scope, temps);
}
else
void
gimple_add_tmp_var (tree tmp)
{
- gcc_assert (!TREE_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
+ gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
/* Later processing assumes that the object size is constant, which might
not be true at this point. Force the use of a constant upper bound in
if (gimplify_ctxp)
{
- TREE_CHAIN (tmp) = gimplify_ctxp->temps;
+ DECL_CHAIN (tmp) = gimplify_ctxp->temps;
gimplify_ctxp->temps = tmp;
/* Mark temporaries local within the nearest enclosing parallel. */
tree t = *tp;
enum tree_code code = TREE_CODE (t);
- /* Do not copy SAVE_EXPR or TARGET_EXPR nodes themselves, but copy
- their subtrees if we can make sure to do it only once. */
- if (code == SAVE_EXPR || code == TARGET_EXPR)
+ /* Do not copy SAVE_EXPR, TARGET_EXPR or BIND_EXPR nodes themselves, but
+ copy their subtrees if we can make sure to do it only once. */
+ if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
{
if (data && !pointer_set_insert ((struct pointer_set_t *)data, t))
;
/* Leave the bulk of the work to copy_tree_r itself. */
else
- {
- gcc_assert (code != BIND_EXPR);
- copy_tree_r (tp, walk_subtrees, NULL);
- }
+ copy_tree_r (tp, walk_subtrees, NULL);
return NULL_TREE;
}
tree temp = voidify_wrapper_expr (bind_expr, NULL);
/* Mark variables seen in this bind expr. */
- for (t = BIND_EXPR_VARS (bind_expr); t ; t = TREE_CHAIN (t))
+ for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
{
if (TREE_CODE (t) == VAR_DECL)
{
/* Preliminarily mark non-addressed complex variables as eligible
for promotion to gimple registers. We'll transform their uses
- as we find them.
- We exclude complex types if not optimizing because they can be
- subject to partial stores in GNU C by means of the __real__ and
- __imag__ operators and we cannot promote them to total stores
- (see gimplify_modify_expr_complex_part). */
- if (optimize
- && (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
- || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+ as we find them. */
+ if ((TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
+ || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
&& !TREE_THIS_VOLATILE (t)
&& (TREE_CODE (t) == VAR_DECL && !DECL_HARD_REGISTER (t))
&& !needs_to_live_in_memory (t))
t = built_in_decls[BUILT_IN_ALLOCA];
t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl));
+ /* The call has been built for a variable-sized object. */
+ ALLOCA_FOR_VAR_P (t) = 1;
t = fold_convert (ptr_type, t);
t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
STACK_CHECK_MAX_VAR_SIZE) > 0))
gimplify_vla_decl (decl, seq_p);
+ /* Some front ends do not explicitly declare all anonymous
+ artificial variables. We compensate here by declaring the
+ variables, though it would be better if the front ends would
+ explicitly declare them. */
+ if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
+ && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
+ gimple_add_tmp_var (decl);
+
if (init && init != error_mark_node)
{
if (!TREE_STATIC (decl))
as they may contain a label address. */
walk_tree (&init, force_labels_r, NULL, NULL);
}
-
- /* Some front ends do not explicitly declare all anonymous
- artificial variables. We compensate here by declaring the
- variables, though it would be better if the front ends would
- explicitly declare them. */
- if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
- && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
- gimple_add_tmp_var (decl);
}
return GS_ALL_DONE;
void
sort_case_labels (VEC(tree,heap)* label_vec)
{
- size_t len = VEC_length (tree, label_vec);
- qsort (VEC_address (tree, label_vec), len, sizeof (tree),
- compare_case_labels);
+ VEC_qsort (tree, label_vec, compare_case_labels);
}
&& !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
&& decl_function_context (decl) == current_function_decl)
{
- gcc_assert (errorcount || sorrycount);
+ gcc_assert (seen_error ());
return GS_ERROR;
}
tree copy = copy_node (decl), block;
lang_hooks.dup_lang_specific_decl (copy);
- SET_DECL_RTL (copy, NULL_RTX);
+ SET_DECL_RTL (copy, 0);
TREE_USED (copy) = 1;
block = DECL_INITIAL (current_function_decl);
- TREE_CHAIN (copy) = BLOCK_VARS (block);
+ DECL_CHAIN (copy) = BLOCK_VARS (block);
BLOCK_VARS (block) = copy;
SET_DECL_VALUE_EXPR (copy, unshare_expr (value_expr));
DECL_HAS_VALUE_EXPR_P (copy) = 1;
{
/* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
have to do is replicate it as a GIMPLE_CALL tuple. */
+ gimple_stmt_iterator gsi;
call = gimple_build_call_from_tree (*expr_p);
gimplify_seq_add_stmt (pre_p, call);
+ gsi = gsi_last (*pre_p);
+ fold_stmt (&gsi);
*expr_p = NULL_TREE;
}
while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
{
/* Keep the original source location on the first 'if'. */
- location_t locus = EXPR_HAS_LOCATION (expr)
- ? EXPR_LOCATION (expr) : input_location;
+ location_t locus = EXPR_LOC_OR_HERE (expr);
TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
/* Set the source location of the && on the second 'if'. */
if (EXPR_HAS_LOCATION (pred))
while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
{
/* Keep the original source location on the first 'if'. */
- location_t locus = EXPR_HAS_LOCATION (expr)
- ? EXPR_LOCATION (expr) : input_location;
+ location_t locus = EXPR_LOC_OR_HERE (expr);
TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
/* Set the source location of the || on the second 'if'. */
if (EXPR_HAS_LOCATION (pred))
/* If there was nothing else in our arms, just forward the label(s). */
if (!then_se && !else_se)
return shortcut_cond_r (pred, true_label_p, false_label_p,
- EXPR_HAS_LOCATION (expr)
- ? EXPR_LOCATION (expr) : input_location);
+ EXPR_LOC_OR_HERE (expr));
/* If our last subexpression already has a terminal label, reuse it. */
if (else_se)
jump_over_else = block_may_fallthru (then_);
pred = shortcut_cond_r (pred, true_label_p, false_label_p,
- EXPR_HAS_LOCATION (expr)
- ? EXPR_LOCATION (expr) : input_location);
+ EXPR_LOC_OR_HERE (expr));
expr = NULL;
append_to_statement_list (pred, &expr);
= build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
tmp = create_tmp_var (type, "iftmp");
- result = build_fold_indirect_ref_loc (loc, tmp);
+ result = build_simple_mem_ref_loc (loc, tmp);
}
/* Build the new then clause, `tmp = then_;'. But don't build the
gimple_call_set_lhs (gs, t);
gimplify_seq_add_stmt (seq_p, gs);
- *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
+ *expr_p = build_simple_mem_ref (t);
return GS_ALL_DONE;
}
/* If the constructor component is indirect, determine if we have a
potential overlap with the lhs. The only bits of information we
have to go on at this point are addressability and alias sets. */
- if (TREE_CODE (t) == INDIRECT_REF
+ if ((INDIRECT_REF_P (t)
+ || TREE_CODE (t) == MEM_REF)
&& (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
&& alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
return t;
/* If the constructor component is a call, determine if it can hide a
- potential overlap with the lhs through an INDIRECT_REF like above. */
+ potential overlap with the lhs through an INDIRECT_REF like above.
+ ??? Ugh - this is completely broken. In fact this whole analysis
+ doesn't look conservative. */
if (TREE_CODE (t) == CALL_EXPR)
{
tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
constructor_elt *ce;
VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (*expr_p);
- for (ix = 0; VEC_iterate (constructor_elt, v, ix, ce); ix++)
+ FOR_EACH_VEC_ELT (constructor_elt, v, ix, ce)
gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data);
return;
if (notify_temp_creation)
return GS_ERROR;
- walk_tree (&ctor, force_labels_r, NULL, NULL);
- TREE_OPERAND (*expr_p, 1) = tree_output_constant_def (ctor);
+ walk_tree (&ctor, force_labels_r, NULL, NULL);
+ ctor = tree_output_constant_def (ctor);
+ if (!useless_type_conversion_p (type, TREE_TYPE (ctor)))
+ ctor = build1 (VIEW_CONVERT_EXPR, type, ctor);
+ TREE_OPERAND (*expr_p, 1) = ctor;
/* This is no longer an assignment of a CONSTRUCTOR, but
we still may have processing to do on the LHS. So
}
}
- /* If the target is volatile and we have non-zero elements
- initialize the target from a temporary. */
+ /* If the target is volatile, we have non-zero elements and more than
+ one field to assign, initialize the target from a temporary. */
if (TREE_THIS_VOLATILE (object)
&& !TREE_ADDRESSABLE (type)
- && num_nonzero_elements > 0)
+ && num_nonzero_elements > 0
+ && VEC_length (constructor_elt, elts) > 1)
{
tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type), NULL);
TREE_OPERAND (*expr_p, 0) = temp;
/* Vector types use CONSTRUCTOR all the way through gimple
compilation as a general initializer. */
- for (ix = 0; VEC_iterate (constructor_elt, elts, ix, ce); ix++)
+ FOR_EACH_VEC_ELT (constructor_elt, elts, ix, ce)
{
enum gimplify_status tret;
tret = gimplify_expr (&ce->value, pre_p, post_p, is_gimple_val,
tree
gimple_fold_indirect_ref (tree t)
{
- tree type = TREE_TYPE (TREE_TYPE (t));
+ tree ptype = TREE_TYPE (t), type = TREE_TYPE (ptype);
tree sub = t;
tree subtype;
}
}
- /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
+ /* *(p + CST) -> ... */
if (TREE_CODE (sub) == POINTER_PLUS_EXPR
&& TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
{
- tree op00 = TREE_OPERAND (sub, 0);
- tree op01 = TREE_OPERAND (sub, 1);
- tree op00type;
+ tree addr = TREE_OPERAND (sub, 0);
+ tree off = TREE_OPERAND (sub, 1);
+ tree addrtype;
+
+ STRIP_NOPS (addr);
+ addrtype = TREE_TYPE (addr);
- STRIP_NOPS (op00);
- op00type = TREE_TYPE (op00);
- if (TREE_CODE (op00) == ADDR_EXPR
- && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE
- && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type))))
+ /* ((foo*)&vectorfoo)[1] -> BIT_FIELD_REF<vectorfoo,...> */
+ if (TREE_CODE (addr) == ADDR_EXPR
+ && TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE
+ && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))))
{
- HOST_WIDE_INT offset = tree_low_cst (op01, 0);
- tree part_width = TYPE_SIZE (type);
- unsigned HOST_WIDE_INT part_widthi
- = tree_low_cst (part_width, 0) / BITS_PER_UNIT;
- unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
- tree index = bitsize_int (indexi);
- if (offset / part_widthi
- <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (op00type)))
- return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
- part_width, index);
+ HOST_WIDE_INT offset = tree_low_cst (off, 0);
+ tree part_width = TYPE_SIZE (type);
+ unsigned HOST_WIDE_INT part_widthi
+ = tree_low_cst (part_width, 0) / BITS_PER_UNIT;
+ unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
+ tree index = bitsize_int (indexi);
+ if (offset / part_widthi
+ <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype)))
+ return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0),
+ part_width, index);
}
- }
- /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
- if (TREE_CODE (sub) == POINTER_PLUS_EXPR
- && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
- {
- tree op00 = TREE_OPERAND (sub, 0);
- tree op01 = TREE_OPERAND (sub, 1);
- tree op00type;
+ /* ((foo*)&complexfoo)[1] -> __imag__ complexfoo */
+ if (TREE_CODE (addr) == ADDR_EXPR
+ && TREE_CODE (TREE_TYPE (addrtype)) == COMPLEX_TYPE
+ && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))))
+ {
+ tree size = TYPE_SIZE_UNIT (type);
+ if (tree_int_cst_equal (size, off))
+ return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (addr, 0));
+ }
- STRIP_NOPS (op00);
- op00type = TREE_TYPE (op00);
- if (TREE_CODE (op00) == ADDR_EXPR
- && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE
- && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type))))
- {
- tree size = TYPE_SIZE_UNIT (type);
- if (tree_int_cst_equal (size, op01))
- return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (op00, 0));
- }
+ /* *(p + CST) -> MEM_REF <p, CST>. */
+ if (TREE_CODE (addr) != ADDR_EXPR
+ || DECL_P (TREE_OPERAND (addr, 0)))
+ return fold_build2 (MEM_REF, type,
+ addr,
+ build_int_cst_wide (ptype,
+ TREE_INT_CST_LOW (off),
+ TREE_INT_CST_HIGH (off)));
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
This kind of code arises in C++ when an object is bound
to a const reference, and if "x" is a TARGET_EXPR we want
to take advantage of the optimization below. */
+ bool volatile_p = TREE_THIS_VOLATILE (*from_p);
tree t = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0));
if (t)
{
+ if (TREE_THIS_VOLATILE (t) != volatile_p)
+ {
+ if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_declaration)
+ t = build_simple_mem_ref_loc (EXPR_LOCATION (*from_p),
+ build_fold_addr_expr (t));
+ if (REFERENCE_CLASS_P (t))
+ TREE_THIS_VOLATILE (t) = volatile_p;
+ }
*from_p = t;
ret = GS_OK;
changed = true;
break;
case CONSTRUCTOR:
+ /* If we already made some changes, let the front end have a
+ crack at this before we break it down. */
+ if (ret != GS_UNHANDLED)
+ break;
/* If we're initializing from a CONSTRUCTOR, break this into
individual MODIFY_EXPRs. */
return gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
/* Try to alleviate the effects of the gimplification creating artificial
temporaries (see for example is_gimple_reg_rhs) on the debug info. */
if (!gimplify_ctxp->into_ssa
- && DECL_P (*from_p)
+ && TREE_CODE (*from_p) == VAR_DECL
&& DECL_IGNORED_P (*from_p)
&& DECL_P (*to_p)
&& !DECL_IGNORED_P (*to_p))
SET_DECL_DEBUG_EXPR (*from_p, *to_p);
}
+ if (want_value && TREE_THIS_VOLATILE (*to_p))
+ *from_p = get_initialized_tmp_var (*from_p, pre_p, post_p);
+
if (TREE_CODE (*from_p) == CALL_EXPR)
{
/* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
if (want_value)
{
- *expr_p = unshare_expr (*to_p);
+ *expr_p = TREE_THIS_VOLATILE (*to_p) ? *from_p : unshare_expr (*to_p);
return GS_OK;
}
else
static enum gimplify_status
gimplify_variable_sized_compare (tree *expr_p)
{
+ location_t loc = EXPR_LOCATION (*expr_p);
tree op0 = TREE_OPERAND (*expr_p, 0);
tree op1 = TREE_OPERAND (*expr_p, 1);
- tree t, arg, dest, src;
- location_t loc = EXPR_LOCATION (*expr_p);
+ tree t, arg, dest, src, expr;
arg = TYPE_SIZE_UNIT (TREE_TYPE (op0));
arg = unshare_expr (arg);
dest = build_fold_addr_expr_loc (loc, op0);
t = implicit_built_in_decls[BUILT_IN_MEMCMP];
t = build_call_expr_loc (loc, t, 3, dest, src, arg);
- *expr_p
+
+ expr
= build2 (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node);
+ SET_EXPR_LOCATION (expr, loc);
+ *expr_p = expr;
return GS_OK;
}
switch (TREE_CODE (op0))
{
case INDIRECT_REF:
- case MISALIGNED_INDIRECT_REF:
do_indirect_ref:
/* Check if we are dealing with an expression of the form '&*ptr'.
While the front end folds away '&*ptr' into 'ptr', these
{
/* Note that gsi_insert_seq_before and gsi_remove do not
scan operands, unlike some other sequence mutators. */
- gsi_insert_seq_before_without_update (&iter,
- gimple_wce_cleanup (wce),
- GSI_SAME_STMT);
+ if (!gimple_wce_cleanup_eh_only (wce))
+ gsi_insert_seq_before_without_update (&iter,
+ gimple_wce_cleanup (wce),
+ GSI_SAME_STMT);
gsi_remove (&iter, true);
break;
}
/* Errors can result in improperly nested cleanups. Which results in
confusion when trying to resolve the GIMPLE_WITH_CLEANUP_EXPR. */
- if (errorcount || sorrycount)
+ if (seen_error ())
return;
if (gimple_conditional_context ())
case QUAL_UNION_TYPE:
{
tree field;
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
omp_firstprivatize_variable (ctx, DECL_FIELD_OFFSET (field));
{
case OMP_CLAUSE_DEFAULT_NONE:
error ("%qE not specified in enclosing parallel",
- DECL_NAME (decl));
+ DECL_NAME (lang_hooks.decls.omp_report_decl (decl)));
if ((ctx->region_type & ORT_TASK) != 0)
error_at (ctx->location, "enclosing task");
else
{
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case TRUTH_XOR_EXPR:
saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
lhs_addr, lhs_var);
+ case TRUTH_NOT_EXPR:
saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
lhs_addr, lhs_var);
break;
GIMPLE_TEST_F points to a function that takes a tree T and
returns nonzero if T is in the GIMPLE form requested by the
- caller. The GIMPLE predicates are in tree-gimple.c.
+ caller. The GIMPLE predicates are in gimple.c.
FALLBACK tells the function what sort of a temporary we want if
gimplification cannot produce an expression that complies with
|| gimple_test_f == is_gimple_mem_rhs_or_call
|| gimple_test_f == is_gimple_reg_rhs
|| gimple_test_f == is_gimple_reg_rhs_or_call
- || gimple_test_f == is_gimple_asm_val)
+ || gimple_test_f == is_gimple_asm_val
+ || gimple_test_f == is_gimple_mem_ref_addr)
gcc_assert (fallback & fb_rvalue);
else if (gimple_test_f == is_gimple_min_lval
|| gimple_test_f == is_gimple_lvalue)
break;
case INDIRECT_REF:
- *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
- if (*expr_p != save_expr)
+ {
+ bool volatilep = TREE_THIS_VOLATILE (*expr_p);
+ bool notrap = TREE_THIS_NOTRAP (*expr_p);
+ tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
+
+ *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
+ if (*expr_p != save_expr)
+ {
+ ret = GS_OK;
+ break;
+ }
+
+ ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+ is_gimple_reg, fb_rvalue);
+ if (ret == GS_ERROR)
+ break;
+
+ recalculate_side_effects (*expr_p);
+ *expr_p = fold_build2_loc (input_location, MEM_REF,
+ TREE_TYPE (*expr_p),
+ TREE_OPERAND (*expr_p, 0),
+ build_int_cst (saved_ptr_type, 0));
+ TREE_THIS_VOLATILE (*expr_p) = volatilep;
+ TREE_THIS_NOTRAP (*expr_p) = notrap;
+ ret = GS_OK;
+ break;
+ }
+
+ /* We arrive here through the various re-gimplifcation paths. */
+ case MEM_REF:
+ /* First try re-folding the whole thing. */
+ tmp = fold_binary (MEM_REF, TREE_TYPE (*expr_p),
+ TREE_OPERAND (*expr_p, 0),
+ TREE_OPERAND (*expr_p, 1));
+ if (tmp)
{
+ *expr_p = tmp;
+ recalculate_side_effects (*expr_p);
ret = GS_OK;
break;
}
- /* else fall through. */
- case ALIGN_INDIRECT_REF:
- case MISALIGNED_INDIRECT_REF:
ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
- is_gimple_reg, fb_rvalue);
+ is_gimple_mem_ref_addr, fb_rvalue);
+ if (ret == GS_ERROR)
+ break;
recalculate_side_effects (*expr_p);
+ ret = GS_ALL_DONE;
break;
/* Constants need not be gimplified. */
if (fallback == fb_none)
{
unsigned HOST_WIDE_INT ix;
- constructor_elt *ce;
+ tree val;
tree temp = NULL_TREE;
- for (ix = 0;
- VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (*expr_p),
- ix, ce);
- ix++)
- if (TREE_SIDE_EFFECTS (ce->value))
- append_to_statement_list (ce->value, &temp);
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (*expr_p), ix, val)
+ if (TREE_SIDE_EFFECTS (val))
+ append_to_statement_list (val, &temp);
*expr_p = temp;
ret = temp ? GS_OK : GS_ALL_DONE;
{
enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
- if (TMR_SYMBOL (*expr_p))
- r0 = gimplify_expr (&TMR_SYMBOL (*expr_p), pre_p,
- post_p, is_gimple_lvalue, fb_either);
- else if (TMR_BASE (*expr_p))
+ if (TMR_BASE (*expr_p))
r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
- post_p, is_gimple_val, fb_either);
+ post_p, is_gimple_mem_ref_addr, fb_either);
if (TMR_INDEX (*expr_p))
r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p,
post_p, is_gimple_val, fb_rvalue);
+ if (TMR_INDEX2 (*expr_p))
+ r1 = gimplify_expr (&TMR_INDEX2 (*expr_p), pre_p,
+ post_p, is_gimple_val, fb_rvalue);
/* TMR_STEP and TMR_OFFSET are always integer constants. */
ret = MIN (r0, r1);
}
that temporary. */
tmp = build_fold_addr_expr_loc (input_location, *expr_p);
gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
- *expr_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (tmp)), tmp);
+ *expr_p = build_simple_mem_ref (tmp);
}
else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
{
/* Ensure VLA bounds aren't removed, for -O0 they should be variables
with assigned stack slots, for -O1+ -g they should be tracked
by VTA. */
- if (TYPE_DOMAIN (type)
+ if (!(TYPE_NAME (type)
+ && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && DECL_IGNORED_P (TYPE_NAME (type)))
+ && TYPE_DOMAIN (type)
&& INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
{
t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
*expr_p = create_tmp_var (type, NULL);
tmp = build1 (NOP_EXPR, type, expr);
stmt = gimplify_assign (*expr_p, tmp, stmt_p);
- if (EXPR_HAS_LOCATION (expr))
- gimple_set_location (stmt, EXPR_LOCATION (expr));
- else
- gimple_set_location (stmt, input_location);
+ gimple_set_location (stmt, EXPR_LOC_OR_HERE (expr));
}
}
gimple_bind_set_body (outer_bind, parm_stmts);
for (parm = DECL_ARGUMENTS (current_function_decl);
- parm; parm = TREE_CHAIN (parm))
+ parm; parm = DECL_CHAIN (parm))
if (DECL_HAS_VALUE_EXPR_P (parm))
{
DECL_HAS_VALUE_EXPR_P (parm) = 0;
gcc_assert (gimplify_ctxp == NULL);
#ifdef ENABLE_TYPES_CHECKING
- if (!errorcount && !sorrycount)
+ if (!seen_error ())
verify_types_in_gimple_seq (gimple_bind_body (outer_bind));
#endif
else
push_struct_function (fndecl);
- for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = TREE_CHAIN (parm))
+ for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = DECL_CHAIN (parm))
{
/* Preliminarily mark non-addressed complex variables as eligible
for promotion to gimple registers. We'll transform their uses
}
-/* Expands EXPR to list of gimple statements STMTS. If SIMPLE is true,
- force the result to be either ssa_name or an invariant, otherwise
- just force it to be a rhs expression. If VAR is not NULL, make the
+/* Expands EXPR to list of gimple statements STMTS. GIMPLE_TEST_F specifies
+ the predicate that will hold for the result. If VAR is not NULL, make the
base variable of the final destination be VAR if suitable. */
tree
-force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var)
+force_gimple_operand_1 (tree expr, gimple_seq *stmts,
+ gimple_predicate gimple_test_f, tree var)
{
tree t;
enum gimplify_status ret;
- gimple_predicate gimple_test_f;
struct gimplify_ctx gctx;
*stmts = NULL;
if (is_gimple_val (expr))
return expr;
- gimple_test_f = simple ? is_gimple_val : is_gimple_reg_rhs;
-
push_gimplify_context (&gctx);
gimplify_ctxp->into_ssa = gimple_in_ssa_p (cfun);
gimplify_ctxp->allow_rhs_cond_expr = true;
}
if (gimple_referenced_vars (cfun))
- for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
+ for (t = gimplify_ctxp->temps; t ; t = DECL_CHAIN (t))
add_referenced_var (t);
pop_gimplify_context (NULL);
return expr;
}
-/* Invokes force_gimple_operand for EXPR with parameters SIMPLE_P and VAR. If
- some statements are produced, emits them at GSI. If BEFORE is true.
- the statements are appended before GSI, otherwise they are appended after
- it. M specifies the way GSI moves after insertion (GSI_SAME_STMT or
- GSI_CONTINUE_LINKING are the usual values). */
+/* Expands EXPR to list of gimple statements STMTS. If SIMPLE is true,
+ force the result to be either ssa_name or an invariant, otherwise
+ just force it to be a rhs expression. If VAR is not NULL, make the
+ base variable of the final destination be VAR if suitable. */
tree
-force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr,
- bool simple_p, tree var, bool before,
- enum gsi_iterator_update m)
+force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var)
+{
+ return force_gimple_operand_1 (expr, stmts,
+ simple ? is_gimple_val : is_gimple_reg_rhs,
+ var);
+}
+
+/* Invokes force_gimple_operand_1 for EXPR with parameters GIMPLE_TEST_F
+ and VAR. If some statements are produced, emits them at GSI.
+ If BEFORE is true. the statements are appended before GSI, otherwise
+ they are appended after it. M specifies the way GSI moves after
+ insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING are the usual values). */
+
+tree
+force_gimple_operand_gsi_1 (gimple_stmt_iterator *gsi, tree expr,
+ gimple_predicate gimple_test_f,
+ tree var, bool before,
+ enum gsi_iterator_update m)
{
gimple_seq stmts;
- expr = force_gimple_operand (expr, &stmts, simple_p, var);
+ expr = force_gimple_operand_1 (expr, &stmts, gimple_test_f, var);
if (!gimple_seq_empty_p (stmts))
{
return expr;
}
+/* Invokes force_gimple_operand_1 for EXPR with parameter VAR.
+ If SIMPLE is true, force the result to be either ssa_name or an invariant,
+ otherwise just force it to be a rhs expression. If some statements are
+ produced, emits them at GSI. If BEFORE is true, the statements are
+ appended before GSI, otherwise they are appended after it. M specifies
+ the way GSI moves after insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING
+ are the usual values). */
+
+tree
+force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr,
+ bool simple_p, tree var, bool before,
+ enum gsi_iterator_update m)
+{
+ return force_gimple_operand_gsi_1 (gsi, expr,
+ simple_p
+ ? is_gimple_val : is_gimple_reg_rhs,
+ var, before, m);
+}
+
+
#include "gt-gimplify.h"