From 48dc22270749d443800d5ed71d2f0c07569febe1 Mon Sep 17 00:00:00 2001 From: jakub Date: Wed, 5 Sep 2007 20:45:27 +0000 Subject: * 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 --- gcc/builtins.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) (limited to 'gcc/builtins.c') 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; -- cgit v1.2.1