/* Nested function decomposition for trees.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GCC.
bool any_parm_remapped;
bool any_tramp_created;
+ char static_chain_added;
};
DECL_CONTEXT (tmp_var) = info->context;
TREE_CHAIN (tmp_var) = info->new_local_var_chain;
DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1;
+ if (TREE_CODE (type) == COMPLEX_TYPE
+ || TREE_CODE (type) == VECTOR_TYPE)
+ DECL_GIMPLE_REG_P (tmp_var) = 1;
+
info->new_local_var_chain = tmp_var;
return tmp_var;
save_context = current_function_decl;
current_function_decl = context;
retval = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
- current_function_decl = save_context;;
+ current_function_decl = save_context;
return retval;
}
tree t, stmt;
t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
- stmt = build2 (MODIFY_EXPR, TREE_TYPE (t), t, exp);
+ stmt = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (t), t, exp);
SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
tsi_link_before (tsi, stmt, TSI_SAME_STMT);
tree t, stmt;
t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
- stmt = build2 (MODIFY_EXPR, TREE_TYPE (t), exp, t);
+ stmt = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (t), exp, t);
SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
tsi_link_after (tsi, stmt, TSI_SAME_STMT);
return field;
}
\f
+/* Helper function for walk_stmts. Walk output operands of an ASM_EXPR. */
+
+static void
+walk_asm_expr (struct walk_stmt_info *wi, tree stmt)
+{
+ int noutputs = list_length (ASM_OUTPUTS (stmt));
+ const char **oconstraints
+ = (const char **) alloca ((noutputs) * sizeof (const char *));
+ int i;
+ tree link;
+ const char *constraint;
+ bool allows_mem, allows_reg, is_inout;
+
+ wi->is_lhs = true;
+ for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
+ {
+ constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+ oconstraints[i] = constraint;
+ parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
+ &allows_reg, &is_inout);
+
+ wi->val_only = (allows_reg || !allows_mem);
+ walk_tree (&TREE_VALUE (link), wi->callback, wi, NULL);
+ }
+
+ for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
+ {
+ constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+ parse_input_constraint (&constraint, 0, 0, noutputs, 0,
+ oconstraints, &allows_mem, &allows_reg);
+
+ wi->val_only = (allows_reg || !allows_mem);
+ /* Although input "m" is not really a LHS, we need a lvalue. */
+ wi->is_lhs = !wi->val_only;
+ walk_tree (&TREE_VALUE (link), wi->callback, wi, NULL);
+ }
+
+ wi->is_lhs = false;
+ wi->val_only = true;
+}
+
/* Iterate over all sub-statements of *TP calling walk_tree with
WI->CALLBACK for every sub-expression in each statement found. */
walk_stmts (wi, &TREE_OPERAND (t, 0));
break;
- case MODIFY_EXPR:
+ case GIMPLE_MODIFY_STMT:
/* A formal temporary lhs may use a COMPONENT_REF rhs. */
- wi->val_only = !is_gimple_formal_tmp_var (TREE_OPERAND (t, 0));
- walk_tree (&TREE_OPERAND (t, 1), wi->callback, wi, NULL);
+ wi->val_only = !is_gimple_formal_tmp_var (GIMPLE_STMT_OPERAND (t, 0));
+ walk_tree (&GIMPLE_STMT_OPERAND (t, 1), wi->callback, wi, NULL);
/* If the rhs is appropriate for a memory, we may use a
COMPONENT_REF on the lhs. */
- wi->val_only = !is_gimple_mem_rhs (TREE_OPERAND (t, 1));
+ wi->val_only = !is_gimple_mem_rhs (GIMPLE_STMT_OPERAND (t, 1));
wi->is_lhs = true;
- walk_tree (&TREE_OPERAND (t, 0), wi->callback, wi, NULL);
+ walk_tree (&GIMPLE_STMT_OPERAND (t, 0), wi->callback, wi, NULL);
wi->val_only = true;
wi->is_lhs = false;
break;
+ case ASM_EXPR:
+ walk_asm_expr (wi, *tp);
+ break;
+
default:
wi->val_only = true;
walk_tree (tp, wi->callback, wi, NULL);
save_suppress = info->suppress_expansion;
if (convert_nonlocal_omp_clauses (&OMP_PARALLEL_CLAUSES (t), wi))
{
- tree c;
- c = get_chain_decl (info);
- c = build1 (OMP_CLAUSE_FIRSTPRIVATE, void_type_node, c);
+ tree c, decl;
+ decl = get_chain_decl (info);
+ c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (c) = decl;
OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
OMP_PARALLEL_CLAUSES (t) = c;
}
walk_body (convert_nonlocal_reference, info, &OMP_PARALLEL_BODY (t));
if (info->new_local_var_chain)
- declare_tmp_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t));
+ declare_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t), false);
info->new_local_var_chain = save_local_var_chain;
info->suppress_expansion = save_suppress;
break;
for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
{
- switch (TREE_CODE (clause))
+ switch (OMP_CLAUSE_CODE (clause))
{
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_NUM_THREADS:
wi->val_only = true;
wi->is_lhs = false;
- convert_nonlocal_reference (&TREE_OPERAND (clause, 0), &dummy, wi);
+ convert_nonlocal_reference (&OMP_CLAUSE_OPERAND (clause, 0), &dummy,
+ wi);
break;
case OMP_CLAUSE_NOWAIT:
TREE_CHAIN (new_decl) = info->debug_var_chain;
info->debug_var_chain = new_decl;
+ /* Do not emit debug info twice. */
+ DECL_IGNORED_P (decl) = 1;
+
return new_decl;
}
{
tree c;
(void) get_frame_type (info);
- c = build1 (OMP_CLAUSE_SHARED, void_type_node, info->frame_decl);
+ c = build_omp_clause (OMP_CLAUSE_SHARED);
+ OMP_CLAUSE_DECL (c) = info->frame_decl;
OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
OMP_PARALLEL_CLAUSES (t) = c;
}
walk_body (convert_local_reference, info, &OMP_PARALLEL_BODY (t));
if (info->new_local_var_chain)
- declare_tmp_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t));
+ declare_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t), false);
info->new_local_var_chain = save_local_var_chain;
info->suppress_expansion = save_suppress;
break;
for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
{
- switch (TREE_CODE (clause))
+ switch (OMP_CLAUSE_CODE (clause))
{
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_NUM_THREADS:
wi->val_only = true;
wi->is_lhs = false;
- convert_local_reference (&TREE_OPERAND (clause, 0), &dummy, wi);
+ convert_local_reference (&OMP_CLAUSE_OPERAND (clause, 0), &dummy, wi);
break;
case OMP_CLAUSE_NOWAIT:
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info;
tree t = *tp, decl, target_context;
+ char save_static_chain_added;
+ int i;
*walk_subtrees = 0;
switch (TREE_CODE (t))
break;
target_context = decl_function_context (decl);
if (target_context && !DECL_NO_STATIC_CHAIN (decl))
- TREE_OPERAND (t, 2)
- = get_static_chain (info, target_context, &wi->tsi);
+ {
+ TREE_OPERAND (t, 2)
+ = get_static_chain (info, target_context, &wi->tsi);
+ info->static_chain_added
+ |= (1 << (info->context != target_context));
+ }
break;
case RETURN_EXPR:
- case MODIFY_EXPR:
+ case GIMPLE_MODIFY_STMT:
case WITH_SIZE_EXPR:
/* Only return modify and with_size_expr may contain calls. */
*walk_subtrees = 1;
break;
+ case OMP_PARALLEL:
+ save_static_chain_added = info->static_chain_added;
+ info->static_chain_added = 0;
+ walk_body (convert_call_expr, info, &OMP_PARALLEL_BODY (t));
+ for (i = 0; i < 2; i++)
+ {
+ tree c, decl;
+ if ((info->static_chain_added & (1 << i)) == 0)
+ continue;
+ decl = i ? get_chain_decl (info) : info->frame_decl;
+ /* Don't add CHAIN.* or FRAME.* twice. */
+ for (c = OMP_PARALLEL_CLAUSES (t); c; c = OMP_CLAUSE_CHAIN (c))
+ if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
+ && OMP_CLAUSE_DECL (c) == decl)
+ break;
+ if (c == NULL)
+ {
+ c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (c) = decl;
+ OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
+ OMP_PARALLEL_CLAUSES (t) = c;
+ }
+ }
+ info->static_chain_added |= save_static_chain_added;
+ break;
+
case OMP_FOR:
case OMP_SECTIONS:
+ case OMP_SECTION:
case OMP_SINGLE:
case OMP_MASTER:
case OMP_ORDERED:
y = build3 (COMPONENT_REF, TREE_TYPE (field),
root->frame_decl, field, NULL_TREE);
- x = build2 (MODIFY_EXPR, TREE_TYPE (field), y, x);
+ x = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (field), y, x);
append_to_statement_list (x, &stmt_list);
}
}
{
tree x = build3 (COMPONENT_REF, TREE_TYPE (root->chain_field),
root->frame_decl, root->chain_field, NULL_TREE);
- x = build2 (MODIFY_EXPR, TREE_TYPE (x), x, get_chain_decl (root));
+ x = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (x), x, get_chain_decl (root));
append_to_statement_list (x, &stmt_list);
}
/* Make sure all new local variables get inserted into the
proper BIND_EXPR. */
if (root->new_local_var_chain)
- declare_tmp_vars (root->new_local_var_chain,
- DECL_SAVED_TREE (root->context));
+ declare_vars (root->new_local_var_chain, DECL_SAVED_TREE (root->context),
+ false);
if (root->debug_var_chain)
- declare_tmp_vars (root->debug_var_chain,
- DECL_SAVED_TREE (root->context));
+ declare_vars (root->debug_var_chain, DECL_SAVED_TREE (root->context),
+ true);
/* Dump the translated tree function. */
dump_function (TDI_nested, root->context);