builtins.def (BUILT_IN_VA_ARG_PACK): New built-in.

* 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.

From-SVN: r128150
This commit is contained in:
Jakub Jelinek 2007-09-05 22:45:27 +02:00
parent e050d7958c
commit 6ef5231bdf
13 changed files with 456 additions and 55 deletions

View File

@ -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>

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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))

View File

@ -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);

View File

@ -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.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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