enclosing block, but we have no way of testing that right now.
??? We used to essentially set the TREE_ADDRESSABLE flag on the variable
- here, but it can now be removed by the Tree aliasing machinery if the
- address of the variable is never taken. All we can do is to make the
- variable volatile, which might incur the generation of temporaries just
- to access the memory in some circumstances. This can be avoided for
- variables of non-constant size because they are automatically allocated
- to memory. There might be no way of allocating a proper temporary for
+ here, but it can now be removed by the Tree aliasing machinery if the
+ address of the variable is never taken. All we can do is to make the
+ variable volatile, which might incur the generation of temporaries just
+ to access the memory in some circumstances. This can be avoided for
+ variables of non-constant size because they are automatically allocated
+ to memory. There might be no way of allocating a proper temporary for
them in any case. We only do this for SJLJ though. */
if (TREE_VALUE (gnu_except_ptr_stack)
&& TREE_CODE (gnu_result) == VAR_DECL
gnu_actual_list = tree_cons (NULL_TREE, gnu_actual, gnu_actual_list);
}
- gnu_subprog_call = build3 (CALL_EXPR, TREE_TYPE (gnu_subprog_type),
- gnu_subprog_addr, nreverse (gnu_actual_list),
- NULL_TREE);
+ gnu_subprog_call = build_call_list (TREE_TYPE (gnu_subprog_type),
+ gnu_subprog_addr,
+ nreverse (gnu_actual_list));
/* If we return by passing a target, we emit the call and return the target
as our result. */
case tcc_statement:
case tcc_expression:
case tcc_reference:
+ case tcc_vl_exp:
/* If this is a COMPONENT_REF of a fat pointer, save the entire
fat pointer. This may be more efficient, but will also allow
us to more easily find the match for the PLACEHOLDER_EXPR. */
case tcc_constant:
return exp;
- case tcc_exceptional:
- if (code == TREE_LIST)
- return tree_cons (TREE_PURPOSE (exp),
- max_size (TREE_VALUE (exp), max_p),
- TREE_CHAIN (exp)
- ? max_size (TREE_CHAIN (exp), max_p) : NULL_TREE);
+ case tcc_vl_exp:
+ if (code == CALL_EXPR)
+ {
+ tree *argarray;
+ int i, n = call_expr_nargs (exp);
+ gcc_assert (n > 0);
+
+ argarray = (tree *) alloca (n * sizeof (tree));
+ for (i = 0; i < n; i++)
+ argarray[i] = max_size (CALL_EXPR_ARG (exp, i), max_p);
+ return build_call_array (type, CALL_EXPR_FN (exp), n, argarray);
+ }
break;
case tcc_reference:
return fold (build2 (max_p ? MAX_EXPR : MIN_EXPR, type,
max_size (TREE_OPERAND (exp, 1), max_p),
max_size (TREE_OPERAND (exp, 2), max_p)));
- else if (code == CALL_EXPR && TREE_OPERAND (exp, 1))
- return build3 (CALL_EXPR, type, TREE_OPERAND (exp, 0),
- max_size (TREE_OPERAND (exp, 1), max_p), NULL);
}
/* Other tree classes cannot happen. */
{
tree fntype = TREE_TYPE (vec[i]);
tree fnaddr = build1 (ADDR_EXPR, build_pointer_type (fntype), vec[i]);
- tree fncall = build3 (CALL_EXPR, TREE_TYPE (fntype), fnaddr, NULL_TREE,
- NULL_TREE);
+ tree fncall = build_call_nary (TREE_TYPE (fntype), fnaddr, 0);
append_to_statement_list (fncall, &body);
}
tree
build_call_1_expr (tree fundecl, tree arg)
{
- tree call = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fundecl)),
- build_unary_op (ADDR_EXPR, NULL_TREE, fundecl),
- chainon (NULL_TREE, build_tree_list (NULL_TREE, arg)),
- NULL_TREE);
-
+ tree call = build_call_nary (TREE_TYPE (TREE_TYPE (fundecl)),
+ build_unary_op (ADDR_EXPR, NULL_TREE, fundecl),
+ 1, arg);
TREE_SIDE_EFFECTS (call) = 1;
-
return call;
}
tree
build_call_2_expr (tree fundecl, tree arg1, tree arg2)
{
- tree call = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fundecl)),
- build_unary_op (ADDR_EXPR, NULL_TREE, fundecl),
- chainon (chainon (NULL_TREE,
- build_tree_list (NULL_TREE, arg1)),
- build_tree_list (NULL_TREE, arg2)),
- NULL_TREE);
-
+ tree call = build_call_nary (TREE_TYPE (TREE_TYPE (fundecl)),
+ build_unary_op (ADDR_EXPR, NULL_TREE, fundecl),
+ 2, arg1, arg2);
TREE_SIDE_EFFECTS (call) = 1;
-
return call;
}
tree
build_call_0_expr (tree fundecl)
{
- tree call = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fundecl)),
- build_unary_op (ADDR_EXPR, NULL_TREE, fundecl),
- NULL_TREE, NULL_TREE);
-
- /* We rely on build3 to compute TREE_SIDE_EFFECTS. This makes it possible
- to propagate the DECL_IS_PURE flag on parameterless functions. */
-
+ /* We rely on build_call_nary to compute TREE_SIDE_EFFECTS. This makes
+ it possible to propagate DECL_IS_PURE on parameterless functions. */
+ tree call = build_call_nary (TREE_TYPE (TREE_TYPE (fundecl)),
+ build_unary_op (ADDR_EXPR, NULL_TREE, fundecl),
+ 0);
return call;
}
\f
tree gnu_proc_addr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_proc);
tree gnu_pool = gnat_to_gnu (gnat_pool);
tree gnu_pool_addr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_pool);
- tree gnu_args = NULL_TREE;
tree gnu_call;
+ gnu_size = convert (gnu_size_type, gnu_size);
+ gnu_align = convert (gnu_size_type, gnu_align);
+
/* The first arg is always the address of the storage pool; next
comes the address of the object, for a deallocator, then the
size and alignment. */
- gnu_args
- = chainon (gnu_args, build_tree_list (NULL_TREE, gnu_pool_addr));
-
if (gnu_obj)
- gnu_args
- = chainon (gnu_args, build_tree_list (NULL_TREE, gnu_obj));
-
- gnu_args
- = chainon (gnu_args,
- build_tree_list (NULL_TREE,
- convert (gnu_size_type, gnu_size)));
- gnu_args
- = chainon (gnu_args,
- build_tree_list (NULL_TREE,
- convert (gnu_size_type, gnu_align)));
-
- gnu_call = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (gnu_proc)),
- gnu_proc_addr, gnu_args, NULL_TREE);
+ gnu_call = build_call_nary (TREE_TYPE (TREE_TYPE (gnu_proc)),
+ gnu_proc_addr, 4, gnu_pool_addr,
+ gnu_obj, gnu_size, gnu_align);
+ else
+ gnu_call = build_call_nary (TREE_TYPE (TREE_TYPE (gnu_proc)),
+ gnu_proc_addr, 3, gnu_pool_addr,
+ gnu_size, gnu_align);
TREE_SIDE_EFFECTS (gnu_call) = 1;
return gnu_call;
}
tree gnu_size_type = gnat_to_gnu_type (gnat_size_type);
tree gnu_proc = gnat_to_gnu (gnat_proc);
tree gnu_proc_addr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_proc);
- tree gnu_args = NULL_TREE;
tree gnu_call;
+ gnu_size = convert (gnu_size_type, gnu_size);
+
/* The first arg is the address of the object, for a
deallocator, then the size */
if (gnu_obj)
- gnu_args
- = chainon (gnu_args, build_tree_list (NULL_TREE, gnu_obj));
-
- gnu_args
- = chainon (gnu_args,
- build_tree_list (NULL_TREE,
- convert (gnu_size_type, gnu_size)));
-
- gnu_call = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (gnu_proc)),
- gnu_proc_addr, gnu_args, NULL_TREE);
+ gnu_call = build_call_nary (TREE_TYPE (TREE_TYPE (gnu_proc)),
+ gnu_proc_addr, 2, gnu_obj, gnu_size);
+ else
+ gnu_call = build_call_nary (TREE_TYPE (TREE_TYPE (gnu_proc)),
+ gnu_proc_addr, 1, gnu_size);
TREE_SIDE_EFFECTS (gnu_call) = 1;
return gnu_call;
}