This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH,c++] introduce cp_build_function_call_nary
- From: Nathan Froyd <froydnj at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 26 May 2010 04:20:20 -0700
- Subject: [PATCH,c++] introduce cp_build_function_call_nary
The patch below introduces cp_build_function_call_nary and uses it to
eliminate nearly all of the calls to cp_build_function_call. The
benefits are fewer uses of TREE_LIST and slightly less consing during
compilation. cp_build_function_call can't be totally delted at the
moment, as it's used by build_function_call, which is used by the ObjC++
front-end. I have a WIP patch to convert ObjC{,++} to use a non
TREE_LIST interface, but it's somewhat invasive.
Tested on x86_64-unknown-linux-gnu. OK to commit?
-Nathan
* cp-tree.h (cp_build_function_call_nary): Declare.
* typeck.c (cp_build_function_call_nary): Define.
* decl.c (register_dtor_fn): Use it instead of
cp_build_function_call.
(cxx_maybe_build_cleanup): Likewise.
* decl2.c (generate_ctor_or_dtor_function): Likewise.
* except.c (do_get_exception_ptr): Likewise.
(do_begin_catch): Likewise.
(do_allocate_exception): Likewise.
(do_free_exception): Likewise.
(build_throw): Likewise. Use cp_build_function_call_vec instead
of cp_build_function_call.
(do_end_catch): Likewise.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3e1b310..5c73fa8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5376,6 +5376,8 @@ extern tree cp_build_array_ref (location_t, tree, tree,
tsubst_flags_t);
extern tree get_member_function_from_ptrfunc (tree *, tree);
extern tree cp_build_function_call (tree, tree, tsubst_flags_t);
+extern tree cp_build_function_call_nary (tree, tsubst_flags_t,
+ int n, ...);
extern tree cp_build_function_call_vec (tree, VEC(tree,gc) **,
tsubst_flags_t);
extern tree build_x_binary_op (enum tree_code, tree,
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 5420f71..fa81e92 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6241,10 +6241,11 @@ register_dtor_fn (tree decl)
{
tree cleanup;
tree compound_stmt;
- tree args;
tree fcall;
tree type;
bool use_dtor;
+ tree arg0, arg1 = NULL_TREE, arg2 = NULL_TREE;
+ int nargs;
type = TREE_TYPE (decl);
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
@@ -6322,25 +6323,27 @@ register_dtor_fn (tree decl)
in, and, in general, it's cheaper to pass NULL than any
other value. */
addr = null_pointer_node;
- args = tree_cons (NULL_TREE,
- cp_build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0,
- tf_warning_or_error),
- NULL_TREE);
+ arg2 = cp_build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0,
+ tf_warning_or_error);
if (targetm.cxx.use_aeabi_atexit ())
{
- args = tree_cons (NULL_TREE, cleanup, args);
- args = tree_cons (NULL_TREE, addr, args);
+ arg1 = cleanup;
+ arg0 = addr;
}
else
{
- args = tree_cons (NULL_TREE, addr, args);
- args = tree_cons (NULL_TREE, cleanup, args);
+ arg1 = addr;
+ arg0 = cleanup;
}
+ nargs = 3;
}
else
- args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
- return cp_build_function_call (get_atexit_node (), args,
- tf_warning_or_error);
+ {
+ arg0 = cleanup;
+ nargs = 1;
+ }
+ return cp_build_function_call_nary (get_atexit_node (), tf_warning_or_error,
+ nargs, arg0, arg1, arg2);
}
/* DECL is a VAR_DECL with static storage duration. INIT, if present,
@@ -12882,9 +12885,7 @@ cxx_maybe_build_cleanup (tree decl)
fn = lookup_name (id);
arg = build_address (decl);
mark_used (decl);
- cleanup = cp_build_function_call (fn, build_tree_list (NULL_TREE,
- arg),
- tf_warning_or_error);
+ cleanup = cp_build_function_call_nary (fn, tf_warning_or_error, 1, arg);
}
/* Handle ordinary C++ destructors. */
type = TREE_TYPE (decl);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 2fd6305..0edb6da 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3276,7 +3276,6 @@ generate_ctor_or_dtor_function (bool constructor_p, int priority,
location_t *locus)
{
char function_key;
- tree arguments;
tree fndecl;
tree body;
size_t i;
@@ -3309,17 +3308,18 @@ generate_ctor_or_dtor_function (bool constructor_p, int priority,
/* Calls to pure or const functions will expand to nothing. */
if (! (flags_from_decl_or_type (fndecl) & (ECF_CONST | ECF_PURE)))
{
+ tree call;
+
if (! body)
body = start_objects (function_key, priority);
- arguments = tree_cons (NULL_TREE,
- build_int_cst (NULL_TREE, priority),
- NULL_TREE);
- arguments = tree_cons (NULL_TREE,
- build_int_cst (NULL_TREE, constructor_p),
- arguments);
- finish_expr_stmt (cp_build_function_call (fndecl, arguments,
- tf_warning_or_error));
+ call = cp_build_function_call_nary (fndecl, tf_warning_or_error,
+ 2,
+ build_int_cst (NULL_TREE,
+ constructor_p),
+ build_int_cst (NULL_TREE,
+ priority));
+ finish_expr_stmt (call);
}
}
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index c0867ef..cab287b 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -183,9 +183,8 @@ do_get_exception_ptr (void)
fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node);
}
- return cp_build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
- NULL_TREE),
- tf_warning_or_error);
+ return cp_build_function_call_nary (fn, tf_warning_or_error,
+ 1, build_exc_ptr ());
}
/* Build up a call to __cxa_begin_catch, to tell the runtime that the
@@ -203,9 +202,8 @@ do_begin_catch (void)
fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node);
}
- return cp_build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
- NULL_TREE),
- tf_warning_or_error);
+ return cp_build_function_call_nary (fn, tf_warning_or_error,
+ 1, build_exc_ptr ());
}
/* Returns nonzero if cleaning up an exception of type TYPE (which can be
@@ -243,7 +241,7 @@ do_end_catch (tree type)
TREE_NOTHROW (fn) = 0;
}
- cleanup = cp_build_function_call (fn, NULL_TREE, tf_warning_or_error);
+ cleanup = cp_build_function_call_vec (fn, NULL, tf_warning_or_error);
TREE_NOTHROW (cleanup) = dtor_nothrow (type);
return cleanup;
@@ -568,10 +566,8 @@ do_allocate_exception (tree type)
fn = declare_nothrow_library_fn (fn, ptr_type_node, size_type_node);
}
- return cp_build_function_call (fn,
- tree_cons (NULL_TREE, size_in_bytes (type),
- NULL_TREE),
- tf_warning_or_error);
+ return cp_build_function_call_nary (fn, tf_warning_or_error,
+ 1, size_in_bytes (type));
}
/* Call __cxa_free_exception from a cleanup. This is never invoked
@@ -589,8 +585,7 @@ do_free_exception (tree ptr)
fn = declare_nothrow_library_fn (fn, void_type_node, ptr_type_node);
}
- return cp_build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE),
- tf_warning_or_error);
+ return cp_build_function_call_nary (fn, tf_warning_or_error, 1, ptr);
}
/* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR.
@@ -668,8 +663,7 @@ build_throw (tree exp)
return error_mark_node;
}
fn = OVL_CURRENT (fn);
- exp = cp_build_function_call (fn, tree_cons (NULL_TREE, exp, NULL_TREE),
- tf_warning_or_error);
+ exp = cp_build_function_call_nary (fn, tf_warning_or_error, 1, exp);
}
else if (exp)
{
@@ -800,11 +794,9 @@ build_throw (tree exp)
else
cleanup = build_int_cst (cleanup_type, 0);
- tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE);
- tmp = tree_cons (NULL_TREE, throw_type, tmp);
- tmp = tree_cons (NULL_TREE, ptr, tmp);
/* ??? Indicate that this function call throws throw_type. */
- tmp = cp_build_function_call (fn, tmp, tf_warning_or_error);
+ tmp = cp_build_function_call_nary (fn, tf_warning_or_error,
+ 3, ptr, throw_type, cleanup);
/* Tack on the initialization stuff. */
exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
@@ -823,7 +815,7 @@ build_throw (tree exp)
/* ??? Indicate that this function call allows exceptions of the type
of the enclosing catch block (if known). */
- exp = cp_build_function_call (fn, NULL_TREE, tf_warning_or_error);
+ exp = cp_build_function_call_vec (fn, NULL, tf_warning_or_error);
}
exp = build1 (THROW_EXPR, void_type_node, exp);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 77cf8fd..96f2c8e 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3217,6 +3217,26 @@ cp_build_function_call (tree function, tree params, tsubst_flags_t complain)
return ret;
}
+/* Build a function call using varargs. */
+
+tree
+cp_build_function_call_nary (tree function, tsubst_flags_t complain,
+ int nargs, ...)
+{
+ VEC(tree,gc) *vec;
+ va_list args;
+ tree ret;
+ int i;
+
+ vec = make_tree_vector ();
+ va_start (args, nargs);
+ for (i = 0; i < nargs; i++)
+ VEC_safe_push (tree, gc, vec, va_arg (args, tree));
+ ret = cp_build_function_call_vec (function, &vec, complain);
+ release_tree_vector (vec);
+ return ret;
+}
+
/* Build a function call using a vector of arguments. PARAMS may be
NULL if there are no parameters. This changes the contents of
PARAMS. */