summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2007-09-05 20:45:27 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2007-09-05 20:45:27 +0000
commit48dc22270749d443800d5ed71d2f0c07569febe1 (patch)
tree0065cd65b39b8419a3be598915506370819405f7 /gcc
parentdfa01d1ac0918d4e00fe5c139008def6c8c913ad (diff)
downloadgcc-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/ChangeLog122
-rw-r--r--gcc/builtins.c41
-rw-r--r--gcc/builtins.def1
-rw-r--r--gcc/doc/extend.texi26
-rw-r--r--gcc/expr.c4
-rw-r--r--gcc/gimplify.c46
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/va-arg-pack-1.c143
-rw-r--r--gcc/testsuite/gcc.dg/va-arg-pack-1.c52
-rw-r--r--gcc/tree-inline.c53
-rw-r--r--gcc/tree-inline.h4
-rw-r--r--gcc/tree-pretty-print.c9
-rw-r--r--gcc/tree.h7
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