before the def/use vectors have been constructed. */
void
-gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs)
+gimple_seq_add_stmt_without_update (gimple_seq *seq_p, gimple gs)
{
gimple_stmt_iterator si;
gsi_insert_after_without_update (&si, gs, GSI_NEW_STMT);
}
+/* Shorter alias name for the above function for use in gimplify.c
+ only. */
+
+static inline void
+gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs)
+{
+ gimple_seq_add_stmt_without_update (seq_p, gs);
+}
+
/* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
NULL, a new sequence is allocated. This function is
similar to gimple_seq_add_seq, but does not scan the operands.
char *preftmp = ASTRDUP (prefix);
remove_suffix (preftmp, strlen (preftmp));
+ clean_symbol_name (preftmp);
+
prefix = preftmp;
}
}
break;
+ case TRANSACTION_EXPR:
+ TREE_SIDE_EFFECTS (*p) = 1;
+ TREE_TYPE (*p) = void_type_node;
+ p = &TRANSACTION_EXPR_BODY (*p);
+ break;
+
default:
+ /* Assume that any tree upon which voidify_wrapper_expr is
+ directly called is a wrapper, and that its body is op0. */
+ if (p == &wrapper)
+ {
+ TREE_SIDE_EFFECTS (*p) = 1;
+ TREE_TYPE (*p) = void_type_node;
+ p = &TREE_OPERAND (*p, 0);
+ break;
+ }
goto out;
}
}
{
tree tmp_var;
- *save = gimple_build_call (implicit_built_in_decls[BUILT_IN_STACK_SAVE], 0);
+ *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
gimple_call_set_lhs (*save, tmp_var);
*restore
- = gimple_build_call (implicit_built_in_decls[BUILT_IN_STACK_RESTORE],
+ = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
1, tmp_var);
}
bool old_save_stack = gimplify_ctxp->save_stack;
tree t;
gimple gimple_bind;
- gimple_seq body;
+ gimple_seq body, cleanup;
+ gimple stack_save;
tree temp = voidify_wrapper_expr (bind_expr, NULL);
gimplify_stmt (&BIND_EXPR_BODY (bind_expr), &body);
gimple_bind_set_body (gimple_bind, body);
+ cleanup = NULL;
+ stack_save = NULL;
if (gimplify_ctxp->save_stack)
{
- gimple stack_save, stack_restore, gs;
- gimple_seq cleanup, new_body;
+ gimple stack_restore;
/* Save stack on entry and restore it on exit. Add a try_finally
block to achieve this. Note that mudflap depends on the
format of the emitted code: see mx_register_decls(). */
build_stack_save_restore (&stack_save, &stack_restore);
- cleanup = new_body = NULL;
gimplify_seq_add_stmt (&cleanup, stack_restore);
+ }
+
+ /* Add clobbers for all variables that go out of scope. */
+ for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
+ {
+ if (TREE_CODE (t) == VAR_DECL
+ && !is_global_var (t)
+ && DECL_CONTEXT (t) == current_function_decl
+ && !DECL_HARD_REGISTER (t)
+ && !TREE_THIS_VOLATILE (t)
+ && !DECL_HAS_VALUE_EXPR_P (t)
+ /* Only care for variables that have to be in memory. Others
+ will be rewritten into SSA names, hence moved to the top-level. */
+ && needs_to_live_in_memory (t))
+ {
+ tree clobber = build_constructor (TREE_TYPE (t), NULL);
+ TREE_THIS_VOLATILE (clobber) = 1;
+ gimplify_seq_add_stmt (&cleanup, gimple_build_assign (t, clobber));
+ }
+ }
+
+ if (cleanup)
+ {
+ gimple gs;
+ gimple_seq new_body;
+
+ new_body = NULL;
gs = gimple_build_try (gimple_bind_body (gimple_bind), cleanup,
GIMPLE_TRY_FINALLY);
- gimplify_seq_add_stmt (&new_body, stack_save);
+ if (stack_save)
+ gimplify_seq_add_stmt (&new_body, stack_save);
gimplify_seq_add_stmt (&new_body, gs);
gimple_bind_set_body (gimple_bind, new_body);
}
SET_DECL_VALUE_EXPR (decl, t);
DECL_HAS_VALUE_EXPR_P (decl) = 1;
- t = built_in_decls[BUILT_IN_ALLOCA];
- t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl));
+ t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
+ t = build_call_expr (t, 2, DECL_SIZE_UNIT (decl),
+ size_int (DECL_ALIGN (decl)));
/* The call has been built for a variable-sized object. */
CALL_ALLOCA_FOR_VAR_P (t) = 1;
t = fold_convert (ptr_type, t);
CALL_EXPR_RETURN_SLOT_OPT (*expr_p)
= CALL_EXPR_RETURN_SLOT_OPT (call);
CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call);
- CALL_CANNOT_INLINE_P (*expr_p) = CALL_CANNOT_INLINE_P (call);
SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (call));
TREE_BLOCK (*expr_p) = TREE_BLOCK (call);
to_ptr = build_fold_addr_expr_loc (loc, to);
gimplify_arg (&to_ptr, seq_p, loc);
- t = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ t = builtin_decl_implicit (BUILT_IN_MEMCPY);
gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
to_ptr = build_fold_addr_expr_loc (loc, to);
gimplify_arg (&to_ptr, seq_p, loc);
- t = implicit_built_in_decls[BUILT_IN_MEMSET];
+ t = builtin_decl_implicit (BUILT_IN_MEMSET);
gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
|| TREE_CODE (*expr_p) == INIT_EXPR);
+ /* Trying to simplify a clobber using normal logic doesn't work,
+ so handle it here. */
+ if (TREE_CLOBBER_P (*from_p))
+ {
+ gcc_assert (!want_value && TREE_CODE (*to_p) == VAR_DECL);
+ gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p));
+ *expr_p = NULL;
+ return GS_ALL_DONE;
+ }
+
/* Insert pointer conversions required by the middle-end that are not
required by the frontend. This fixes middle-end type checking for
for example gcc.dg/redecl-6.c. */
arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
src = build_fold_addr_expr_loc (loc, op1);
dest = build_fold_addr_expr_loc (loc, op0);
- t = implicit_built_in_decls[BUILT_IN_MEMCMP];
+ t = builtin_decl_implicit (BUILT_IN_MEMCMP);
t = build_call_expr_loc (loc, t, 3, dest, src, arg);
expr
if (init)
{
+ tree cleanup = NULL_TREE;
+
/* TARGET_EXPR temps aren't part of the enclosing block, so add it
to the temps list. Handle also variable length TARGET_EXPRs. */
if (TREE_CODE (DECL_SIZE (temp)) != INTEGER_CST)
/* If needed, push the cleanup for the temp. */
if (TARGET_EXPR_CLEANUP (targ))
- gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
- CLEANUP_EH_ONLY (targ), pre_p);
+ {
+ if (CLEANUP_EH_ONLY (targ))
+ gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
+ CLEANUP_EH_ONLY (targ), pre_p);
+ else
+ cleanup = TARGET_EXPR_CLEANUP (targ);
+ }
+
+ /* Add a clobber for the temporary going out of scope, like
+ gimplify_bind_expr. */
+ if (needs_to_live_in_memory (temp))
+ {
+ tree clobber = build_constructor (TREE_TYPE (temp), NULL);
+ TREE_THIS_VOLATILE (clobber) = true;
+ clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
+ if (cleanup)
+ cleanup = build2 (COMPOUND_EXPR, void_type_node, cleanup,
+ clobber);
+ else
+ cleanup = clobber;
+ }
+
+ if (cleanup)
+ gimple_push_cleanup (temp, cleanup, false, pre_p);
/* Only expand this once. */
TREE_OPERAND (targ, 3) = init;
return GS_ALL_DONE;
}
+/* Gimplify a TRANSACTION_EXPR. This involves gimplification of the
+ body, and adding some EH bits. */
+
+static enum gimplify_status
+gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
+{
+ tree expr = *expr_p, temp, tbody = TRANSACTION_EXPR_BODY (expr);
+ gimple g;
+ gimple_seq body = NULL;
+ struct gimplify_ctx gctx;
+ int subcode = 0;
+
+ /* Wrap the transaction body in a BIND_EXPR so we have a context
+ where to put decls for OpenMP. */
+ if (TREE_CODE (tbody) != BIND_EXPR)
+ {
+ tree bind = build3 (BIND_EXPR, void_type_node, NULL, tbody, NULL);
+ TREE_SIDE_EFFECTS (bind) = 1;
+ SET_EXPR_LOCATION (bind, EXPR_LOCATION (tbody));
+ TRANSACTION_EXPR_BODY (expr) = bind;
+ }
+
+ push_gimplify_context (&gctx);
+ temp = voidify_wrapper_expr (*expr_p, NULL);
+
+ g = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
+ pop_gimplify_context (g);
+
+ g = gimple_build_transaction (body, NULL);
+ if (TRANSACTION_EXPR_OUTER (expr))
+ subcode = GTMA_IS_OUTER;
+ else if (TRANSACTION_EXPR_RELAXED (expr))
+ subcode = GTMA_IS_RELAXED;
+ gimple_transaction_set_subcode (g, subcode);
+
+ gimplify_seq_add_stmt (pre_p, g);
+
+ if (temp)
+ {
+ *expr_p = temp;
+ return GS_OK;
+ }
+
+ *expr_p = NULL_TREE;
+ return GS_ALL_DONE;
+}
+
/* Convert the GENERIC expression tree *EXPR_P to GIMPLE. If the
expression produces a value to be used as an operand inside a GIMPLE
statement, the value will be stored back in *EXPR_P. This value will
ret = gimplify_omp_atomic (expr_p, pre_p);
break;
+ case TRANSACTION_EXPR:
+ ret = gimplify_transaction (expr_p, pre_p);
+ break;
+
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
{
tree orig_type = TREE_TYPE (*expr_p);
+ tree new_type, xop0, xop1;
*expr_p = gimple_boolify (*expr_p);
- if (!useless_type_conversion_p (orig_type, TREE_TYPE (*expr_p)))
+ new_type = TREE_TYPE (*expr_p);
+ if (!useless_type_conversion_p (orig_type, new_type))
{
*expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
ret = GS_OK;
default:
break;
}
-
+ /* Now make sure that operands have compatible type to
+ expression's new_type. */
+ xop0 = TREE_OPERAND (*expr_p, 0);
+ xop1 = TREE_OPERAND (*expr_p, 1);
+ if (!useless_type_conversion_p (new_type, TREE_TYPE (xop0)))
+ TREE_OPERAND (*expr_p, 0) = fold_convert_loc (input_location,
+ new_type,
+ xop0);
+ if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
+ TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
+ new_type,
+ xop1);
/* Continue classified as tcc_binary. */
goto expr_2;
}
case FMA_EXPR:
- case VEC_SHUFFLE_EXPR:
+ case VEC_PERM_EXPR:
/* Classified as tcc_expression. */
goto expr_3;
tree tmp_var;
gimple call;
- x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS];
+ x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
call = gimple_build_call (x, 1, integer_zero_node);
tmp_var = create_tmp_var (ptr_type_node, "return_addr");
gimple_call_set_lhs (call, tmp_var);
gimplify_seq_add_stmt (&cleanup, call);
- x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT];
+ x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_EXIT);
call = gimple_build_call (x, 2,
build_fold_addr_expr (current_function_decl),
tmp_var);
gimplify_seq_add_stmt (&cleanup, call);
tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
- x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS];
+ x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
call = gimple_build_call (x, 1, integer_zero_node);
tmp_var = create_tmp_var (ptr_type_node, "return_addr");
gimple_call_set_lhs (call, tmp_var);
gimplify_seq_add_stmt (&body, call);
- x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER];
+ x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_ENTER);
call = gimple_build_call (x, 2,
build_fold_addr_expr (current_function_decl),
tmp_var);