gimple_assign_rhs_to_tree (gimple stmt)
{
tree t;
- enum gimple_rhs_class class;
+ enum gimple_rhs_class grhs_class;
- class = get_gimple_rhs_class (gimple_expr_code (stmt));
+ grhs_class = get_gimple_rhs_class (gimple_expr_code (stmt));
- if (class == GIMPLE_BINARY_RHS)
+ if (grhs_class == GIMPLE_BINARY_RHS)
t = build2 (gimple_assign_rhs_code (stmt),
TREE_TYPE (gimple_assign_lhs (stmt)),
gimple_assign_rhs1 (stmt),
gimple_assign_rhs2 (stmt));
- else if (class == GIMPLE_UNARY_RHS)
+ else if (grhs_class == GIMPLE_UNARY_RHS)
t = build1 (gimple_assign_rhs_code (stmt),
TREE_TYPE (gimple_assign_lhs (stmt)),
gimple_assign_rhs1 (stmt));
- else if (class == GIMPLE_SINGLE_RHS)
+ else if (grhs_class == GIMPLE_SINGLE_RHS)
t = gimple_assign_rhs1 (stmt);
else
gcc_unreachable ();
t = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
- fn = gimple_call_fn (stmt);
- if (TREE_CODE (fn) == FUNCTION_DECL)
- CALL_EXPR_FN (t) = build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (fn)),
- fn);
- else
- CALL_EXPR_FN (t) = fn;
-
+ CALL_EXPR_FN (t) = gimple_call_fn (stmt);
TREE_TYPE (t) = gimple_call_return_type (stmt);
-
CALL_EXPR_STATIC_CHAIN (t) = gimple_call_chain (stmt);
for (i = 0; i < gimple_call_num_args (stmt); i++)
/* Record the original call statement, as it may be used
to retrieve profile information during expansion. */
- if (TREE_CODE (fn) == FUNCTION_DECL && DECL_BUILT_IN (fn))
+
+ if ((fn = gimple_call_fndecl (stmt)) != NULL_TREE
+ && DECL_BUILT_IN (fn))
{
ann = get_tree_common_ann (t);
ann->stmt = stmt;
case GIMPLE_CALL:
if (gimple_call_lhs (stmt))
{
- if (TREE_CODE (gimple_call_fn (stmt)) == FUNCTION_DECL)
- ggc_free (CALL_EXPR_FN (TREE_OPERAND (stmt_tree, 1)));
ann = tree_common_ann (TREE_OPERAND (stmt_tree, 1));
if (ann)
ggc_free (ann);
ggc_free (TREE_OPERAND (stmt_tree, 1));
}
- else if (TREE_CODE (gimple_call_fn (stmt)) == FUNCTION_DECL)
- ggc_free (CALL_EXPR_FN (stmt_tree));
break;
default:
break;
static void
expand_used_vars (void)
{
- tree t, outer_block = DECL_INITIAL (current_function_decl);
+ tree t, next, outer_block = DECL_INITIAL (current_function_decl);
/* Compute the phase of the stack frame for this function. */
{
/* At this point all variables on the local_decls with TREE_USED
set are not associated with any block scope. Lay them out. */
- for (t = cfun->local_decls; t; t = TREE_CHAIN (t))
+ t = cfun->local_decls;
+ cfun->local_decls = NULL_TREE;
+ for (; t; t = next)
{
tree var = TREE_VALUE (t);
bool expand_now = false;
+ next = TREE_CHAIN (t);
+
/* We didn't set a block for static or extern because it's hard
to tell the difference between a global variable (re)declared
in a local scope, and one that's really declared there to
TREE_USED (var) = 1;
if (expand_now)
- expand_one_var (var, true, true);
+ {
+ expand_one_var (var, true, true);
+ if (DECL_ARTIFICIAL (var) && !DECL_IGNORED_P (var))
+ {
+ rtx rtl = DECL_RTL_IF_SET (var);
+
+ /* Keep artificial non-ignored vars in cfun->local_decls
+ chain until instantiate_decls. */
+ if (rtl && (MEM_P (rtl) || GET_CODE (rtl) == CONCAT))
+ {
+ TREE_CHAIN (t) = cfun->local_decls;
+ cfun->local_decls = t;
+ continue;
+ }
+ }
+ }
+
+ ggc_free (t);
}
- cfun->local_decls = NULL_TREE;
/* At this point, all variables within the block tree with TREE_USED
set are actually used by the optimized function. Lay them out. */
add_reg_br_prob_note (last, true_edge->probability);
maybe_dump_rtl_for_gimple_stmt (stmt, last);
if (true_edge->goto_locus)
- set_curr_insn_source_location (true_edge->goto_locus);
+ {
+ set_curr_insn_source_location (true_edge->goto_locus);
+ set_curr_insn_block (true_edge->goto_block);
+ true_edge->goto_locus = curr_insn_locator ();
+ }
+ true_edge->goto_block = NULL;
false_edge->flags |= EDGE_FALLTHRU;
ggc_free (pred);
return NULL;
add_reg_br_prob_note (last, false_edge->probability);
maybe_dump_rtl_for_gimple_stmt (stmt, last);
if (false_edge->goto_locus)
- set_curr_insn_source_location (false_edge->goto_locus);
+ {
+ set_curr_insn_source_location (false_edge->goto_locus);
+ set_curr_insn_block (false_edge->goto_block);
+ false_edge->goto_locus = curr_insn_locator ();
+ }
+ false_edge->goto_block = NULL;
true_edge->flags |= EDGE_FALLTHRU;
ggc_free (pred);
return NULL;
jumpif (pred, label_rtx_for_bb (true_edge->dest));
add_reg_br_prob_note (last, true_edge->probability);
last = get_last_insn ();
+ if (false_edge->goto_locus)
+ {
+ set_curr_insn_source_location (false_edge->goto_locus);
+ set_curr_insn_block (false_edge->goto_block);
+ false_edge->goto_locus = curr_insn_locator ();
+ }
+ false_edge->goto_block = NULL;
emit_jump (label_rtx_for_bb (false_edge->dest));
BB_END (bb) = last;
maybe_dump_rtl_for_gimple_stmt (stmt, last2);
- if (false_edge->goto_locus)
- set_curr_insn_source_location (false_edge->goto_locus);
+ if (true_edge->goto_locus)
+ {
+ set_curr_insn_source_location (true_edge->goto_locus);
+ set_curr_insn_block (true_edge->goto_block);
+ true_edge->goto_locus = curr_insn_locator ();
+ }
+ true_edge->goto_block = NULL;
ggc_free (pred);
return new_bb;
}
}
- /* Expand implicit goto. */
+ /* Expand implicit goto and convert goto_locus. */
FOR_EACH_EDGE (e, ei, bb->succs)
{
- if (e->flags & EDGE_FALLTHRU)
- break;
- }
-
- if (e && e->dest != bb->next_bb)
- {
- emit_jump (label_rtx_for_bb (e->dest));
- if (e->goto_locus)
- set_curr_insn_source_location (e->goto_locus);
- e->flags &= ~EDGE_FALLTHRU;
+ if (e->goto_locus && e->goto_block)
+ {
+ set_curr_insn_source_location (e->goto_locus);
+ set_curr_insn_block (e->goto_block);
+ e->goto_locus = curr_insn_locator ();
+ }
+ e->goto_block = NULL;
+ if ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb)
+ {
+ emit_jump (label_rtx_for_bb (e->dest));
+ e->flags &= ~EDGE_FALLTHRU;
+ }
}
do_pending_stack_adjust ();
expand_stack_alignment (void)
{
rtx drap_rtx;
- unsigned int preferred_stack_boundary;
+ unsigned int preferred_stack_boundary, incoming_stack_boundary;
if (! SUPPORTS_STACK_ALIGNMENT)
return;
if (preferred_stack_boundary > crtl->stack_alignment_needed)
crtl->stack_alignment_needed = preferred_stack_boundary;
+ /* The incoming stack frame has to be aligned at least at
+ parm_stack_boundary. */
+ if (crtl->parm_stack_boundary > INCOMING_STACK_BOUNDARY)
+ incoming_stack_boundary = crtl->parm_stack_boundary;
+ else
+ incoming_stack_boundary = INCOMING_STACK_BOUNDARY;
+
crtl->stack_realign_needed
- = INCOMING_STACK_BOUNDARY < crtl->stack_alignment_estimated;
+ = incoming_stack_boundary < crtl->stack_alignment_estimated;
crtl->stack_realign_tried = crtl->stack_realign_needed;
crtl->stack_realign_processed = true;
gcc_assert (targetm.calls.get_drap_rtx != NULL);
drap_rtx = targetm.calls.get_drap_rtx ();
+ /* stack_realign_drap and drap_rtx must match. */
+ gcc_assert ((stack_realign_drap != 0) == (drap_rtx != NULL));
+
/* Do nothing if NULL is returned, which means DRAP is not needed. */
if (NULL != drap_rtx)
{
insn_locators_alloc ();
if (!DECL_BUILT_IN (current_function_decl))
- set_curr_insn_source_location (DECL_SOURCE_LOCATION (current_function_decl));
+ {
+ /* Eventually, all FEs should explicitly set function_start_locus. */
+ if (cfun->function_start_locus == UNKNOWN_LOCATION)
+ set_curr_insn_source_location
+ (DECL_SOURCE_LOCATION (current_function_decl));
+ else
+ set_curr_insn_source_location (cfun->function_start_locus);
+ }
set_curr_insn_block (DECL_INITIAL (current_function_decl));
prologue_locator = curr_insn_locator ();