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 | |
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')
-rw-r--r-- | gcc/ChangeLog | 122 | ||||
-rw-r--r-- | gcc/builtins.c | 41 | ||||
-rw-r--r-- | gcc/builtins.def | 1 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 26 | ||||
-rw-r--r-- | gcc/expr.c | 4 | ||||
-rw-r--r-- | gcc/gimplify.c | 46 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/va-arg-pack-1.c | 143 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/va-arg-pack-1.c | 52 | ||||
-rw-r--r-- | gcc/tree-inline.c | 53 | ||||
-rw-r--r-- | gcc/tree-inline.h | 4 | ||||
-rw-r--r-- | gcc/tree-pretty-print.c | 9 | ||||
-rw-r--r-- | gcc/tree.h | 7 |
13 files changed, 457 insertions, 56 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6f0ea185226..ea2f73f8ed3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2007-09-05 Jakub Jelinek <jakub@redhat.com> + + * 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. + 2007-09-05 Adam Nemet <anemet@caviumnetworks.com> PR tree-optimization/21513 @@ -92,7 +114,7 @@ (was_mips16_p): New. (mips_set_mips16_mode): New, split out from override_options. (mips_set_current_function): New. - (override_options): Add sorry for unsupported mips16/pic + (override_options): Add sorry for unsupported mips16/pic combination. Remove error for mips16/dsp combination. Save base option settings. (mips_file_start): Move mips16 mode setting output from here.... @@ -114,7 +136,7 @@ * config/mips/mips.c (mips_legitimize_tls_address): Call sorry if we encounter TLS address in MIPS16 mode. - (mips_legitimize_const_move): Check cannot_force_const_mem for + (mips_legitimize_const_move): Check cannot_force_const_mem for the (const (plus symbol offset)) case; this forces invalid TLS address in MIPS16 mode to be caught by the above call to sorry. (override_options): Don't reset targetm.have_tls in MIPS16 mode, @@ -134,7 +156,7 @@ * function.h: Here. (set_cfun): Declare. * tree-inline.c (cfun_stack, push_cfun, pop_cfun): Moved to... - * function.c: Here. + * function.c: Here. (push_function_context_to): Use allocate_struct_function to create null context, not init_dummy_function_start. Use set_cfun. (pop_function_context_from): Use set_cfun. @@ -168,7 +190,7 @@ 2007-09-05 Kenneth Zadeck <zadeck@naturalbridge.com> - * regrename.c (rerename_optimize): Use deferred rescanning and + * regrename.c (rerename_optimize): Use deferred rescanning and insert explicit calls to rescan insns when changed. 2007-09-05 Jan Hubicka <jh@suse.cz> @@ -1178,9 +1200,9 @@ * toplev.c (init_alignments): New, split out from... (process_options): ...here. - (backend_init_target): New, split out from... + (backend_init_target): New, split out from... (backend_init): ...here. - (lang_dependent_init_target): New, split out from... + (lang_dependent_init_target): New, split out from... (lang_dependent_init): ...here. (target_reinit): New. * toplev.h (target_reinit): Declare. @@ -3338,7 +3360,7 @@ 2007-08-11 David Daney <ddaney@avtrex.com> - * config/mips/mips.c (mips_sched_reorder): Mark cycle parameter + * config/mips/mips.c (mips_sched_reorder): Mark cycle parameter as ATTRIBUTE_UNUSED. 2007-08-11 David Edelsohn <edelsohn@gnu.org> @@ -3514,17 +3536,17 @@ 2007-08-09 Sandra Loosemore <sandra@codesourcery.com> - * config/mips/mips.opt (mhard-float, msoft-float): Make these + * config/mips/mips.opt (mhard-float, msoft-float): Make these control TARGET_HARD_FLOAT_ABI and TARGET_SOFT_FLOAT_ABI, rather than TARGET_HARD_FLOAT and TARGET_SOFT_FLOAT. * config/mips/mips.h (mips16_hard_float): Delete. - (TARGET_HARD_FLOAT_ABI, TARGET_SOFT_FLOAT_ABI): Delete these + (TARGET_HARD_FLOAT_ABI, TARGET_SOFT_FLOAT_ABI): Delete these definitions, and replace with.... (TARGET_HARD_FLOAT, TARGET_SOFT_FLOAT): Define. * config/mips/mips.c (mips16_hard_float): Delete. Replace all references with (TARGET_MIPS16 && TARGET_HARD_FLOAT_ABI). (MIPS_MARCH_CONTROLS_SOFT_FLOAT): Update comments. - (override_options): Replace MASK_SOFT_FLOAT references with + (override_options): Replace MASK_SOFT_FLOAT references with MASK_SOFT_FLOAT_ABI. Delete twiddling with MASK_SOFT_FLOAT and mips16_hard_float when TARGET_MIPS16. @@ -3562,7 +3584,7 @@ tri-state integer. * optabs.c (expand_ffs, expand_ctz): New functions to compute ffs and ctz using clz. - (expand_unop): Call them. + (expand_unop): Call them. * config/rs6000/rs6000.h (CLZ_DEFINED_VALUE_AT_ZERO): Fix its result value. (CTZ_DEFINED_VALUE_AT_ZERO): Likewise. @@ -4687,7 +4709,7 @@ 2007-08-01 Sandra Loosemore <sandra@codesourcery.com> - * reload.c (find_reloads_address_part): Pass correct MEMREFLOC + * reload.c (find_reloads_address_part): Pass correct MEMREFLOC argument to find_reloads_address. 2007-08-01 Daniel Jacobowitz <dan@codesourcery.com> @@ -4846,7 +4868,7 @@ 2007-07-31 Sandra Loosemore <sandra@codesourcery.com> - * config/mips/mips.h (ISA_HAS_SYNCI): Add !TARGET_MIPS16 test. + * config/mips/mips.h (ISA_HAS_SYNCI): Add !TARGET_MIPS16 test. 2007-07-31 Revital Eres <eres@il.ibm.com> @@ -6228,7 +6250,7 @@ 2007-07-18 Caroline Tice <ctice@apple.com> - * var-tracking.c (find_src_status): Check for COND_EXEC insns + * var-tracking.c (find_src_status): Check for COND_EXEC insns and handle them correctly; check that src is not NULL before trying to use it. (find_src_set_src): Likewise. @@ -6392,7 +6414,7 @@ 2007-07-16 Sandra Loosemore <sandra@codesourcery.com> Nigel Stephens <nigel@mips.com> - * config/mips/mips.md: Include 20kc.md. + * config/mips/mips.md: Include 20kc.md. * config/mips/20kc.md: New file. * config/mips/mips.c (mips_rtx_cost_data): Fill in 20Kc costs. (mips_adjust_cost): Tweak for 20Kc. @@ -8876,7 +8898,7 @@ * df-problems.c (df_ru_alloc, df_rd_alloc, df_lr_alloc, df_live_alloc, df_urec_alloc, df_note_alloc): set optional_p. (problem_RU, problem_RD, problem_LR, problem_UREC, problem_CHAIN, - problem_NOTE): Initialize free_blocks_on_set_blocks. + problem_NOTE): Initialize free_blocks_on_set_blocks. (df_lr_bb_local_compute): Recompute luids if df_live problem is not active. (df_live_set_all_dirty, df_note_alloc): New function. @@ -9341,7 +9363,7 @@ * tree-ssa.c (tree_ssa_useless_type_conversion_1): Convert the MIN/MAX of the inner type to the outer type before comparing them. - * tree-ssa-loop-prefetch.c (idx_analyze_ref): Handle + * tree-ssa-loop-prefetch.c (idx_analyze_ref): Handle POINTER_PLUS_EXPR instead of PLUS_EXPR. (issue_prefetch_ref): Create a POINTER_PLUS_EXPR instead of PLUS_EXPR for pointers. @@ -10916,7 +10938,7 @@ * config/mn10300/mn10300.md: Include. * config/mn10300/mn10300.c(mn10300_secondary_reload_class): Fix up for removed macro. - * config/mn10300/predicates.md (call_address_operand): Ditto. + * config/mn10300/predicates.md (call_address_operand): Ditto. * config/mn10300/mn10300.h (REG_CLASS_FROM_LETTER): Delete. (CONST_OK_FOR_I): Ditto. (CONST_OK_FOR_J): Ditto. @@ -11279,10 +11301,10 @@ * doc/extend.texi (Function Attributes): Document MIPS "near" and "far" attributes. - * testsuite/gcc.target/mips/near-far-1.c: New test case. - * testsuite/gcc.target/mips/near-far-2.c: New test case. - * testsuite/gcc.target/mips/near-far-3.c: New test case. - * testsuite/gcc.target/mips/near-far-4.c: New test case. + * testsuite/gcc.target/mips/near-far-1.c: New test case. + * testsuite/gcc.target/mips/near-far-2.c: New test case. + * testsuite/gcc.target/mips/near-far-3.c: New test case. + * testsuite/gcc.target/mips/near-far-4.c: New test case. 2007-05-25 Eric Christopher <echristo@apple.com> @@ -11444,7 +11466,7 @@ stmt_dominates_stmt_p, get_lsm_tmp_name): Declare. * Makefile.in (tree-predcom.o): Add. (tree-affine.o): Add TREE_GIMPLE_H dependency. - * passes.c (init_optimization_passes): Add dceloop after + * passes.c (init_optimization_passes): Add dceloop after copy propagation in loop optimizer. Add predictive commoning to loop optimizer passes. @@ -12692,7 +12714,7 @@ 2007-05-14 Dave Korn <dave.korn@artimi.com> - * genautomata.c (gen_regexp_el): Allocate correct size for regexp. + * genautomata.c (gen_regexp_el): Allocate correct size for regexp. 2007-05-14 Rafael Avila de Espindola <espindola@google.com> @@ -13905,7 +13927,7 @@ 2007-04-26 Steve Ellcey <sje@cup.hp.com> - * config/ia64/ia64.md (ip_value): Fix itanium_class attribute. + * config/ia64/ia64.md (ip_value): Fix itanium_class attribute. 2007-04-26 Richard Guenther <rguenther@suse.de> @@ -14219,7 +14241,7 @@ (create_phi_node): Use set_phi_nodes. * omp-low.c (expand_omp_parallel): Use bb_stmt_list. * tree-if-conv.c (process_phi_nodes): Use set_phi_nodes. - (combine_blocks): Use bb_stmt_list and set_bb_stmt_list. + (combine_blocks): Use bb_stmt_list and set_bb_stmt_list. * tree-flow-inline.h (phi_nodes, set_phi_nodes, (bsi_start, bsi_last): Use bb_stmt_list. (phi_nodes_ptr, bb_stmt_list, set_bb_stmt_list): New functions. @@ -14788,7 +14810,7 @@ * tree-ssa-loop-ivopts.c (ivopts_global_cost_for_size): Use estimate_reg_pressure_cost. Add number of ivs. (determine_set_costs): Dump target_reg_cost. - * loop-invariant.c (gain_for_invariant): Use + * loop-invariant.c (gain_for_invariant): Use estimate_reg_pressure_cost. Removed n_inv_uses argument. (best_gain_for_invariant, find_invariants_to_move): Remove n_inv_uses. @@ -15663,7 +15685,7 @@ 2007-04-07 Bruce Korb <bkorb@gnu.org> * c.opt: Add -Wformat-contains-nul. - * c-format.c (set_Wformat): Set warn_format_contains_nul to the + * c-format.c (set_Wformat): Set warn_format_contains_nul to the -Wformat setting. (check_format_info_main): Check OPT_Wformat_contains_nul before emitting the NUL byte warning. @@ -15689,7 +15711,7 @@ argument "reliable". (infer_loop_bounds_from_ref, infer_loop_bounds_from_array): Add argument "reliable". Propagate it through calls. - (infer_loop_bounds_from_undefined): Derive number of iterations + (infer_loop_bounds_from_undefined): Derive number of iterations estimates from references in blocks that do not dominate loop latch. (gcov_type_to_double_int): New function. (estimate_numbers_of_iterations_loop): Use gcov_type_to_double_int @@ -17893,7 +17915,7 @@ (dsp_32only_bdesc): New description table for 32-bit only DSP REV 1 and 2 builtins. (bdesc_map): Add one field of unsupported_target_flags. - (bdesc_arrays): Update entries to have extra fields. Add + (bdesc_arrays): Update entries to have extra fields. Add dsp_32only_bdesc. (mips_init_builtins): Initialize new function types. Check unsupported_target_fileds to filter out builtins. @@ -18896,7 +18918,7 @@ 2007-03-01 Zdenek Dvorak <dvorakz@suse.cz> - * tree-ssa-loop-prefetch.c (determine_unroll_factor): Bound the + * tree-ssa-loop-prefetch.c (determine_unroll_factor): Bound the unroll factor by the estimated number of iterations. (loop_prefetch_arrays): Do not prefetch in loops that iterate less than prefetch latency. @@ -19352,7 +19374,7 @@ 2007-02-23 Steve Ellcey <sje@cup.hp.com> PR debug/29614 - * varpool.c (varpool_assemble_pending_decls): Set + * varpool.c (varpool_assemble_pending_decls): Set varpool_last_needed_node to null. 2007-02-23 DJ Delorie <dj@redhat.com> @@ -19456,8 +19478,8 @@ * config/spu/spu-protos.h (spu_init_expanders): Declare. * config/spu/spu.c (spu_expand_prologue): Set REGNO_POINTER_ALIGN for HARD_FRAME_POINTER_REGNUM. - (spu_legitimate_address): Use regno_aligned_for_reload. - (regno_aligned_for_load): HARD_FRAME_POINTER_REGNUM is only 16 byte + (spu_legitimate_address): Use regno_aligned_for_reload. + (regno_aligned_for_load): HARD_FRAME_POINTER_REGNUM is only 16 byte aligned when frame_pointer_needed is true. (spu_init_expanders): New. Set alignment of HARD_FRAME_POINTER_REGNUM to 8 bits. @@ -19473,7 +19495,7 @@ rotqmbi_<mode>, rotqmby_<mode>, ashr<mode>3, rotma_<mode>, rotl<mode>3, rotlti3, rotqbybi_ti, rotqby_ti, rotqbi_ti): Use spu_nonmem_operand instead of spu_shift_operands. Use new modifiers. - (lshr<mode>3_reg): Fix rtl description. + (lshr<mode>3_reg): Fix rtl description. Make sure mulhisi immediate operands are valid. * config/spu/predicates.md (imm_K_operand): Add. @@ -19488,7 +19510,7 @@ * config/spu/spu.c (print_operand): Handle HIGH correctly. (spu_split_immediate): Split CONST_VECTORs with -mlarge-mem. (immediate_load_p): Allow symbols that use 2 instructions to create. - (classify_immediate, spu_builtin_splats): Don't accept a CONST_VECTOR + (classify_immediate, spu_builtin_splats): Don't accept a CONST_VECTOR with symbols when flag_pic is set. (const_vector_immediate_p): New. (logical_immediate_p, iohl_immediate_p, arith_immediate_p): Don't @@ -19531,14 +19553,14 @@ * config/spu/spu_internals.h: Ditto. Fix incorrect operand modifiers. - * config/spu/spu-builtins.md (spu_mpy, spu_mpyu): Remove use of %H. - * config/spu/spu.md (xor<mode>3): Change %S to %J. + * config/spu/spu-builtins.md (spu_mpy, spu_mpyu): Remove use of %H. + * config/spu/spu.md (xor<mode>3): Change %S to %J. Optimize one case of zero_extend of a vec_select. - * config/spu/spu.md (_vec_extractv8hi_ze): Add. + * config/spu/spu.md (_vec_extractv8hi_ze): Add. Accept any immediate for hbr. - * config/spu/spu.md (hbr): Change s constraints to i. + * config/spu/spu.md (hbr): Change s constraints to i. 2007-02-21 Paul Brook <paul@codesourcery.com> @@ -19843,7 +19865,7 @@ 2007-02-18 Roger Sayle <roger@eyesopen.com> PR rtl-optimization/28173 - * simplify-rtx.c (simplify_binary_operation_1) <IOR>: Optimize + * simplify-rtx.c (simplify_binary_operation_1) <IOR>: Optimize (X & C1) | C2 as C2 when (C1 & C2) == C1 and X has no side-effects. Optimize (X & C1) | C2 as X | C2 when (C1 | C2) == ~0. Canonicalize (X & C1) | C2 as (X & (C1 & ~C2)) | C2. @@ -20275,7 +20297,7 @@ of an arglist. Change return type to bool. Use new CALL_EXPR accessors. - (fold_builtin_strstr): Pass call arguments individually instead + (fold_builtin_strstr): Pass call arguments individually instead of as an arglist, fixing callers appropriately. Use new CALL_EXPR accessors and constructors. Return NULL_TREE instead of 0. (fold_builtin_strchr): Likewise. @@ -20320,7 +20342,7 @@ (fold_ternary): Remove CALL_EXPR case, since they are no longer ternary expressions. (fold): Add logic for tcc_vl_exp. - (fold_checksum_tree): Make it know about tcc_vl_exp. Use + (fold_checksum_tree): Make it know about tcc_vl_exp. Use TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH. (fold_build3_stat): Add assertion to flag broken interface for constructing CALL_EXPRs. @@ -20350,7 +20372,7 @@ * tree-vrp.c (stmt_interesting_for_vrp): Use new CALL_EXPR accessors. (vrp_visit_stmt): Likewise. - * tree-ssa-loop-im.c (outermost_invariant_loop_expr): Make it + * tree-ssa-loop-im.c (outermost_invariant_loop_expr): Make it know about tcc_vl_exp. Use TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH. (force_move_till_expr): Likewise. @@ -20544,7 +20566,7 @@ (estimate_num_insns_1): Use new CALL_EXPR accessors. (expand_call_inline): Tidy up call to initialize_inlined_parameters. - * tree-vect-transform.c (vect_create_epilog_for_reduction): Use + * tree-vect-transform.c (vect_create_epilog_for_reduction): Use TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH. (vectorizable_reduction): Likewise. (vectorizable_call): Use new CALL_EXPR iterators. @@ -20647,7 +20669,7 @@ (arm_expand_unop_builtin): Likewise. (arm_expand_builtin): Use new CALL_EXPR accessors. - * config/mips/mips.c (mips_expand_builtin): Use new CALL_EXPR + * config/mips/mips.c (mips_expand_builtin): Use new CALL_EXPR accessors. * config/bfin/bfin.c (bfin_expand_binop_builtin): Pass entire @@ -22819,7 +22841,7 @@ * tree-data-ref.c (tree_fold_divides_p): Don't use tree_fold_gcd to test whether one constant integer is a multiple of another. Instead call int_const_binop with TRUNC_MOD_EXPR and test for a zero result. - * fold-const.c (multiple_of_p): We've determined both TOP and + * fold-const.c (multiple_of_p): We've determined both TOP and BOTTOM are integer constants so we can call int_const_binop directly instead of the more generic const_binop. @@ -22962,7 +22984,7 @@ PR other/30182 * config/pa/pa.c (pa_init_builtins): Set asm names for finite routines. - * config/ia64/ia64.c (ia64_init_builtins): Ditto. + * config/ia64/ia64.c (ia64_init_builtins): Ditto. 2007-01-25 Richard Guenther <rguenther@suse.de> @@ -23505,7 +23527,7 @@ * longlong.h (count_leading_zeros, COUNT_LEADING_ZEROS_0): Add ColdFire alternatives. * config/m68k/m68k.h (CLZ_DEFINED_VALUE_AT_ZERO): New macro. - * config/m68k/m68k.md (clzsi2): Define for ColdFire + * config/m68k/m68k.md (clzsi2): Define for ColdFire architectures that support ff1 instruction. 2007-01-19 Richard Sandiford <richard@codesourcery.com> @@ -25667,7 +25689,7 @@ 2007-01-02 Steve Ellcey <sje@cup.hp.com> - * sbitmap.c (HOST_BITS_PER_LONG_LONG): Change to + * sbitmap.c (HOST_BITS_PER_LONG_LONG): Change to HOST_BITS_PER_LONGLONG 2007-01-02 Manuel Lopez-Ibanez <manu@gcc.gnu.org> 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; diff --git a/gcc/builtins.def b/gcc/builtins.def index 8bedfbf30e9..01ba3b36587 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -701,6 +701,7 @@ DEF_GCC_BUILTIN (BUILT_IN_UPDATE_SETJMP_BUF, "update_setjmp_buf", BT_FN_V DEF_GCC_BUILTIN (BUILT_IN_VA_COPY, "va_copy", BT_FN_VOID_VALIST_REF_VALIST_ARG, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_VA_END, "va_end", BT_FN_VOID_VALIST_REF, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_VA_START, "va_start", BT_FN_VOID_VALIST_REF_VAR, ATTR_NULL) +DEF_GCC_BUILTIN (BUILT_IN_VA_ARG_PACK, "va_arg_pack", BT_FN_INT, ATTR_PURE_NOTHROW_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN__EXIT, "_exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST) DEF_C99_BUILTIN (BUILT_IN__EXIT2, "_Exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 0012740476b..9f306a44e48 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -556,6 +556,32 @@ the containing function. You should specify, for @var{result}, a value returned by @code{__builtin_apply}. @end deftypefn +@deftypefn {Built-in Function} __builtin_va_arg_pack () +This built-in function represents all anonymous arguments of an inline +function. It can be used only in inline functions which will be always +inlined, never compiled as a separate function, such as those using +@code{__attribute__ ((__always_inline__))} or +@code{__attribute__ ((__gnu_inline__))} extern inline functions. +It must be only passed as last argument to some other function +with variable arguments. This is useful for writing small wrapper +inlines for variable argument functions, when using preprocessor +macros is undesirable. For example: +@smallexample +extern int myprintf (FILE *f, const char *format, ...); +extern inline __attribute__ ((__gnu_inline__)) int +myprintf (FILE *f, const char *format, ...) +@{ + int r = fprintf (f, "myprintf: "); + if (r < 0) + return r; + int s = fprintf (f, format, __builtin_va_arg_pack ()); + if (s < 0) + return s; + return r + s; +@} +@end smallexample +@end deftypefn + @node Typeof @section Referring to a Type with @code{typeof} @findex typeof diff --git a/gcc/expr.c b/gcc/expr.c index 13f447cc8b6..054f4f13add 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -7935,6 +7935,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, return expand_expr (OBJ_TYPE_REF_EXPR (exp), target, tmode, modifier); case CALL_EXPR: + /* All valid uses of __builtin_va_arg_pack () are removed during + inlining. */ + if (CALL_EXPR_VA_ARG_PACK (exp)) + error ("invalid use of %<__builtin_va_arg_pack ()%>"); /* Check for a built-in function. */ if (TREE_CODE (CALL_EXPR_FN (exp)) == ADDR_EXPR && (TREE_CODE (TREE_OPERAND (CALL_EXPR_FN (exp), 0)) diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 5c376ac5060..ee8ef09a103 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -2170,8 +2170,50 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value) } } } - else if (nargs != 0) - CALL_CANNOT_INLINE_P (*expr_p) = 1; + else + { + if (nargs != 0) + CALL_CANNOT_INLINE_P (*expr_p) = 1; + i = 0; + p = NULL_TREE; + } + + /* If the last argument is __builtin_va_arg_pack () and it is not + passed as a named argument, decrease the number of CALL_EXPR + arguments and set instead the CALL_EXPR_VA_ARG_PACK flag. */ + if (!p + && i < nargs + && TREE_CODE (CALL_EXPR_ARG (*expr_p, nargs - 1)) == CALL_EXPR) + { + tree last_arg = CALL_EXPR_ARG (*expr_p, nargs - 1); + tree last_arg_fndecl = get_callee_fndecl (last_arg); + + if (last_arg_fndecl + && TREE_CODE (last_arg_fndecl) == FUNCTION_DECL + && DECL_BUILT_IN_CLASS (last_arg_fndecl) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (last_arg_fndecl) == BUILT_IN_VA_ARG_PACK) + { + tree call = *expr_p; + + --nargs; + *expr_p = build_call_array (TREE_TYPE (call), CALL_EXPR_FN (call), + nargs, CALL_EXPR_ARGP (call)); + /* Copy all CALL_EXPR flags, locus and block, except + CALL_EXPR_VA_ARG_PACK flag. */ + CALL_EXPR_STATIC_CHAIN (*expr_p) = CALL_EXPR_STATIC_CHAIN (call); + CALL_EXPR_TAILCALL (*expr_p) = CALL_EXPR_TAILCALL (call); + CALL_EXPR_RETURN_SLOT_OPT (*expr_p) + = CALL_EXPR_RETURN_SLOT_OPT (call); + CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call); + CALL_CANNOT_INLINE_P (*expr_p) + = CALL_CANNOT_INLINE_P (call); + TREE_NOTHROW (*expr_p) = TREE_NOTHROW (call); + SET_EXPR_LOCUS (*expr_p, EXPR_LOCUS (call)); + TREE_BLOCK (*expr_p) = TREE_BLOCK (call); + /* Set CALL_EXPR_VA_ARG_PACK. */ + CALL_EXPR_VA_ARG_PACK (*expr_p) = 1; + } + } /* Finally, gimplify the function arguments. */ for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index aeaad7277a5..7a2a20bd149 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-09-05 Jakub Jelinek <jakub@redhat.com> + + * gcc.c-torture/execute/va-arg-pack-1.c: New test. + * gcc.dg/va-arg-pack-1.c: New test. + 2007-09-05 Adam Nemet <anemet@caviumnetworks.com> * gcc.dg/tree-ssa/builtin-expect-1.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/va-arg-pack-1.c b/gcc/testsuite/gcc.c-torture/execute/va-arg-pack-1.c new file mode 100644 index 00000000000..baefe875821 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/va-arg-pack-1.c @@ -0,0 +1,143 @@ +/* __builtin_va_arg_pack () builtin tests. */ + +#include <stdarg.h> + +extern void abort (void); + +int v1 = 8; +long int v2 = 3; +void *v3 = (void *) &v2; +struct A { char c[16]; } v4 = { "foo" }; +long double v5 = 40; +char seen[20]; +int cnt; + +__attribute__ ((noinline)) int +foo1 (int x, int y, ...) +{ + int i; + long int l; + void *v; + struct A a; + long double ld; + va_list ap; + + va_start (ap, y); + if (x < 0 || x >= 20 || seen[x]) + abort (); + seen[x] = ++cnt; + if (y != 6) + abort (); + i = va_arg (ap, int); + if (i != 5) + abort (); + switch (x) + { + case 0: + i = va_arg (ap, int); + if (i != 9 || v1 != 9) + abort (); + a = va_arg (ap, struct A); + if (__builtin_memcmp (a.c, v4.c, sizeof (a.c)) != 0) + abort (); + v = (void *) va_arg (ap, struct A *); + if (v != (void *) &v4) + abort (); + l = va_arg (ap, long int); + if (l != 3 || v2 != 4) + abort (); + break; + case 1: + ld = va_arg (ap, long double); + if (ld != 41 || v5 != ld) + abort (); + i = va_arg (ap, int); + if (i != 8) + abort (); + v = va_arg (ap, void *); + if (v != &v2) + abort (); + break; + case 2: + break; + default: + abort (); + } + va_end (ap); + return x; +} + +__attribute__ ((noinline)) int +foo2 (int x, int y, ...) +{ + long long int ll; + void *v; + struct A a, b; + long double ld; + va_list ap; + + va_start (ap, y); + if (x < 0 || x >= 20 || seen[x]) + abort (); + seen[x] = ++cnt | 64; + if (y != 10) + abort (); + switch (x) + { + case 11: + break; + case 12: + ld = va_arg (ap, long double); + if (ld != 41 || v5 != 40) + abort (); + a = va_arg (ap, struct A); + if (__builtin_memcmp (a.c, v4.c, sizeof (a.c)) != 0) + abort (); + b = va_arg (ap, struct A); + if (__builtin_memcmp (b.c, v4.c, sizeof (b.c)) != 0) + abort (); + v = va_arg (ap, void *); + if (v != &v2) + abort (); + ll = va_arg (ap, long long int); + if (ll != 16LL) + abort (); + break; + case 2: + break; + default: + abort (); + } + va_end (ap); + return x + 8; +} + +__attribute__ ((noinline)) int +foo3 (void) +{ + return 6; +} + +extern inline __attribute__ ((always_inline, gnu_inline)) int +bar (int x, ...) +{ + if (x < 10) + return foo1 (x, foo3 (), 5, __builtin_va_arg_pack ()); + return foo2 (x, foo3 () + 4, __builtin_va_arg_pack ()); +} + +int +main (void) +{ + if (bar (0, ++v1, v4, &v4, v2++) != 0) + abort (); + if (bar (1, ++v5, 8, v3) != 1) + abort (); + if (bar (2) != 2) + abort (); + if (bar (v1 + 2) != 19) + abort (); + if (bar (v1 + 3, v5--, v4, v4, v3, 16LL) != 20) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/va-arg-pack-1.c b/gcc/testsuite/gcc.dg/va-arg-pack-1.c new file mode 100644 index 00000000000..09ae97917e4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/va-arg-pack-1.c @@ -0,0 +1,52 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int bar (int, const char *, int, ...); +int baz (int, const char *, long int); + +int +f1 (int x, ...) +{ + return bar (5, "", 6, __builtin_va_arg_pack ()); /* { dg-error "invalid use of" } */ +} + +extern inline __attribute__((always_inline)) int +f2 (int y, ...) +{ + return bar (y, "", __builtin_va_arg_pack ()); /* { dg-error "invalid use of" } */ +} + +extern inline __attribute__((always_inline)) int +f3 (int y, ...) +{ + return bar (y, "", 5, __builtin_va_arg_pack ()); +} + +extern inline __attribute__((always_inline)) int +f4 (int y, ...) +{ + return bar (y, "", 4, __builtin_va_arg_pack (), 6); /* { dg-error "invalid use of" } */ +} + +extern inline __attribute__((always_inline)) int +f5 (int y, ...) +{ + return baz (y, "", __builtin_va_arg_pack ()); /* { dg-error "invalid use of" } */ +} + +extern inline __attribute__((always_inline)) int +f6 (int y, ...) +{ + return __builtin_va_arg_pack (); /* { dg-error "invalid use of" } */ +} + +int +test (void) +{ + int a = f2 (5, "a", 6); + a += f3 (6, "ab", 17LL); + a += f4 (7, 1, 2, 3); + a += f5 (8, 7L); + a += f6 (9); + return a; +} 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); diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h index 574b1d70040..1fa360ad345 100644 --- a/gcc/tree-inline.h +++ b/gcc/tree-inline.h @@ -56,6 +56,10 @@ typedef struct copy_body_data /* Current BLOCK. */ tree block; + /* CALL_EXPR if va arg parameter packs should be expanded or NULL + is not. */ + tree call_expr; + /* Exception region the inlined call lie in. */ int eh_region; /* Take region number in the function being copied, add this value and diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 8da7ade6a11..bc7ebf4ea79 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -1228,6 +1228,15 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, } } } + if (CALL_EXPR_VA_ARG_PACK (node)) + { + if (call_expr_nargs (node) > 0) + { + pp_character (buffer, ','); + pp_space (buffer); + } + pp_string (buffer, "__builtin_va_arg_pack ()"); + } pp_character (buffer, ')'); op1 = CALL_EXPR_STATIC_CHAIN (node); diff --git a/gcc/tree.h b/gcc/tree.h index 5fda4d4b3a1..c274fb6ec24 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -464,6 +464,8 @@ struct gimple_stmt GTY(()) VAR_DECL or FUNCTION_DECL or IDENTIFIER_NODE ASM_VOLATILE_P in ASM_EXPR + CALL_EXPR_VA_ARG_PACK in + CALL_EXPR TYPE_CACHED_VALUES_P in ..._TYPE SAVE_EXPR_RESOLVED_P in @@ -1222,6 +1224,11 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, #define SAVE_EXPR_RESOLVED_P(NODE) \ (TREE_CHECK (NODE, SAVE_EXPR)->base.public_flag) +/* Set on a CALL_EXPR if this stdarg call should be passed the argument + pack. */ +#define CALL_EXPR_VA_ARG_PACK(NODE) \ + (CALL_EXPR_CHECK(NODE)->base.public_flag) + /* In any expression, decl, or constant, nonzero means it has side effects or reevaluation of the whole expression could produce a different value. This is set if any subexpression is a function call, a side effect or a |