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/builtins.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/builtins.c')
-rw-r--r-- | gcc/builtins.c | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 166792c4a40..566e1cc2e1b 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -6270,6 +6270,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_ARGS_INFO: return expand_builtin_args_info (exp); + case BUILT_IN_VA_ARG_PACK: + /* All valid uses of __builtin_va_arg_pack () are removed during + inlining. */ + error ("invalid use of %<__builtin_va_arg_pack ()%>"); + return const0_rtx; + /* Return the address of the first anonymous stack arg. */ case BUILT_IN_NEXT_ARG: if (fold_builtin_next_arg (exp, false)) @@ -10472,14 +10478,32 @@ fold_call_expr (tree exp, bool ignore) tree fndecl = get_callee_fndecl (exp); if (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL - && DECL_BUILT_IN (fndecl)) - { + && DECL_BUILT_IN (fndecl) + /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized + yet. Defer folding until we see all the arguments + (after inlining). */ + && !CALL_EXPR_VA_ARG_PACK (exp)) + { + int nargs = call_expr_nargs (exp); + + /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but + instead last argument is __builtin_va_arg_pack (). Defer folding + even in that case, until arguments are finalized. */ + if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR) + { + tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1)); + if (fndecl2 + && TREE_CODE (fndecl2) == FUNCTION_DECL + && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK) + return NULL_TREE; + } + /* FIXME: Don't use a list in this interface. */ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore); else { - int nargs = call_expr_nargs (exp); if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN) { tree *args = CALL_EXPR_ARGP (exp); @@ -10565,6 +10589,17 @@ fold_builtin_call_array (tree type, if (TREE_CODE (fndecl) == FUNCTION_DECL && DECL_BUILT_IN (fndecl)) { + /* If last argument is __builtin_va_arg_pack (), arguments to this + function are not finalized yet. Defer folding until they are. */ + if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR) + { + tree fndecl2 = get_callee_fndecl (argarray[n - 1]); + if (fndecl2 + && TREE_CODE (fndecl2) == FUNCTION_DECL + && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK) + return build_call_array (type, fn, n, argarray); + } if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) { tree arglist = NULL_TREE; |