diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-09-05 20:45:27 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-09-05 20:45:27 +0000 |
commit | 48dc22270749d443800d5ed71d2f0c07569febe1 (patch) | |
tree | 0065cd65b39b8419a3be598915506370819405f7 /gcc/tree-inline.c | |
parent | dfa01d1ac0918d4e00fe5c139008def6c8c913ad (diff) | |
download | gcc-48dc22270749d443800d5ed71d2f0c07569febe1.tar.gz |
* builtins.def (BUILT_IN_VA_ARG_PACK): New built-in.
* tree.h (CALL_EXPR_VA_ARG_PACK): Define.
* tree-inline.h (copy_body_data): Add call_expr field.
* tree-inline.c (expand_call_inline): Initialize call_expr.
(copy_bb): Append anonymous inline fn arguments to arguments
when inlining a CALL_EXPR_VA_ARG_PACK call.
* builtins.c (expand_builtin): Issue an error if
BUILT_IN_VA_ARG_PACK is seen during expand.
(fold_call_expr, fold_builtin_call_array): Don't fold
CALL_EXPR_VA_ARG_PACK CALL_EXPRs or calls with
__builtin_va_arg_pack () call as last argument.
* gimplify.c (gimplify_call_expr): If last argument to a vararg
function is __builtin_va_arg_pack (), decrease number of call
arguments and instead set CALL_EXPR_VA_ARG_PACK on the CALL_EXPR.
* expr.c (expand_expr_real_1): Issue an error if
CALL_EXPR_VA_ARG_PACK CALL_EXPR is seen during expand.
* tree-pretty-print.c (dump_generic_node): Handle printing
CALL_EXPR_VA_ARG_PACK bit on CALL_EXPRs.
* doc/extend.texi (__builtin_va_arg_pack): Document.
* gcc.c-torture/execute/va-arg-pack-1.c: New test.
* gcc.dg/va-arg-pack-1.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@128150 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r-- | gcc/tree-inline.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index b655b79ac01..d49c3c8c490 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -815,9 +815,59 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, int count_scal into multiple statements, we need to process all of them. */ while (!bsi_end_p (copy_bsi)) { - stmt = bsi_stmt (copy_bsi); + tree *stmtp = bsi_stmt_ptr (copy_bsi); + tree stmt = *stmtp; call = get_call_expr_in (stmt); + if (call && CALL_EXPR_VA_ARG_PACK (call) && id->call_expr) + { + /* __builtin_va_arg_pack () should be replaced by + all arguments corresponding to ... in the caller. */ + tree p, *argarray, new_call, *call_ptr; + int nargs = call_expr_nargs (id->call_expr); + + for (p = DECL_ARGUMENTS (id->src_fn); p; p = TREE_CHAIN (p)) + nargs--; + + argarray = (tree *) alloca ((nargs + call_expr_nargs (call)) + * sizeof (tree)); + + memcpy (argarray, CALL_EXPR_ARGP (call), + call_expr_nargs (call) * sizeof (*argarray)); + memcpy (argarray + call_expr_nargs (call), + CALL_EXPR_ARGP (id->call_expr) + + (call_expr_nargs (id->call_expr) - nargs), + nargs * sizeof (*argarray)); + + new_call = build_call_array (TREE_TYPE (call), + CALL_EXPR_FN (call), + nargs + call_expr_nargs (call), + argarray); + /* Copy all CALL_EXPR flags, locus and block, except + CALL_EXPR_VA_ARG_PACK flag. */ + CALL_EXPR_STATIC_CHAIN (new_call) + = CALL_EXPR_STATIC_CHAIN (call); + CALL_EXPR_TAILCALL (new_call) = CALL_EXPR_TAILCALL (call); + CALL_EXPR_RETURN_SLOT_OPT (new_call) + = CALL_EXPR_RETURN_SLOT_OPT (call); + CALL_FROM_THUNK_P (new_call) = CALL_FROM_THUNK_P (call); + CALL_CANNOT_INLINE_P (new_call) + = CALL_CANNOT_INLINE_P (call); + TREE_NOTHROW (new_call) = TREE_NOTHROW (call); + SET_EXPR_LOCUS (new_call, EXPR_LOCUS (call)); + TREE_BLOCK (new_call) = TREE_BLOCK (call); + + call_ptr = stmtp; + if (TREE_CODE (*call_ptr) == GIMPLE_MODIFY_STMT) + call_ptr = &GIMPLE_STMT_OPERAND (*call_ptr, 1); + if (TREE_CODE (*call_ptr) == WITH_SIZE_EXPR) + call_ptr = &TREE_OPERAND (*call_ptr, 0); + gcc_assert (*call_ptr == call); + *call_ptr = new_call; + stmt = *stmtp; + update_stmt (stmt); + } + /* Statements produced by inlining can be unfolded, especially when we constant propagated some operands. We can't fold them right now for two reasons: @@ -2518,6 +2568,7 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data) id->src_fn = fn; id->src_node = cg_edge->callee; id->src_cfun = DECL_STRUCT_FUNCTION (fn); + id->call_expr = t; initialize_inlined_parameters (id, t, fn, bb); |