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);
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);
}
{
/* 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);
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;
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
recalculate_side_effects (*expr_p);
break;
- case MISALIGNED_INDIRECT_REF:
- /* We can only reach this through re-gimplification from
- tree optimizers. */
- ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
- is_gimple_reg, fb_rvalue);
- recalculate_side_effects (*expr_p);
- break;
-
case INDIRECT_REF:
{
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);
ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
is_gimple_reg, fb_rvalue);
- recalculate_side_effects (*expr_p);
+ 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;
}
}
ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
is_gimple_mem_ref_addr, fb_rvalue);
+ if (ret == GS_ERROR)
+ break;
recalculate_side_effects (*expr_p);
ret = GS_ALL_DONE;
break;
{
enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
- if (TMR_SYMBOL (*expr_p))
- /* We can't gimplify the symbol part. Assert it is
- already gimple instead.
- ??? This isn't exactly the same as ADDR_EXPR
- plus is_gimple_mem_ref_addr (), see fixed_address_object_p. */
- gcc_assert (TREE_CODE (TMR_SYMBOL (*expr_p)) == ADDR_EXPR
- && (TREE_CODE (TREE_OPERAND (TMR_SYMBOL (*expr_p), 0))
- == VAR_DECL));
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);
}
/* 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));
*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));
}
}
}
-/* 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;
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"