diff options
author | sandra <sandra@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-02-15 23:50:49 +0000 |
---|---|---|
committer | sandra <sandra@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-02-15 23:50:49 +0000 |
commit | c2f47e150f3c68a813f92460462c2e70155f2c67 (patch) | |
tree | 4c9dae557e2aa52bff7b845dd7b1270c19be7a2f /gcc | |
parent | 3ba510aa5b8a07f6fa5a2d163354b0ff5b5c7484 (diff) | |
download | gcc-c2f47e150f3c68a813f92460462c2e70155f2c67.tar.gz |
2007-02-15 Sandra Loosemore <sandra@codesourcery.com>
Brooks Moses <brooks.moses@codesourcery.com>
Lee Millward <lee.millward@codesourcery.com>
* tree.h (enum tree_code_class): Add tcc_vl_exp.
(VL_EXP_CLASS_P): New.
(TREE_OPERAND_CHECK): Use TREE_OPERAND_LENGTH instead of
TREE_CODE_LENGTH.
(TREE_OPERAND_CHECK_CODE): Likewise.
(GIMPLE_STMT_OPERAND_CHECK): Likewise.
(TREE_RTL_OPERAND_CHECK): Likewise.
(tree_operand_check_failed): Make second parameter the whole tree
instead of its code. Fixed callers.
(VL_EXP_CHECK): New.
(TREE_OPERAND_LENGTH): New.
(VL_EXP_OPERAND_LENGTH): New.
(CALL_EXPR_FN): New.
(CALL_EXPR_STATIC_CHAIN): New.
(CALL_EXPR_ARGS): New.
(CALL_EXPR_ARG): New.
(call_expr_nargs): New.
(CALL_EXPR_ARGP): New.
(build_nt_call_list): Declare.
(build_vl_exp_stat): Declare.
(build_vl_exp): New.
(build_call_list): Declare.
(build_call_nary): Declare.
(build_call_valist): Declare.
(build_call_array): Declare.
(call_expr_arg): Declare.
(call_expr_argp): Declare.
(call_expr_arglist): Declare.
(fold_build_call_list): Declare.
(fold_build_call_list_initializer): Declare.
(fold_call_expr): Declare to replace fold_builtin.
(fold_builtin_fputs): Update to agree with modified definition.
(fold_builtin_strcpy): Likewise.
(fold_builtin_strncpy): Likewise.
(fold_builtin_memory_chk): Likewise.
(fold_builtin_stxcpy_chk): Likewise.
(fold_builtin_strncpy_chk): Likewise.
(fold_builtin_next_arg): Likewise.
(fold_build_call_expr): Declare.
(fold_builtin_call_list): Declare.
(fold_builtin_call_valist): Declare.
(build_call_expr): Declare.
(validate_arglist): Update to agree with modified definition.
(tree_operand_length): New.
(call_expr_arg_iterator): New.
(init_call_expr_arg_iterator): New.
(next_call_expr_arg): New.
(first_call_expr_arg): New.
(more_call_expr_args_p): New.
(FOR_EACH_CALL_EXPR_ARG): New.
* tree.c (tree_code_class_string): Add entries for tcc_vl_exp
and tcc_gimple_stmt.
(tree_code_size): Update documentation. Use sizeof (tree) rather
than sizeof (char *).
(tree_size): Likewise. Add case for tcc_vl_exp.
(tree_node_structure): Add case for tcc_vl_exp.
(contains_placeholder_p): Likewise.
(substitute_in_expr): Likewise.
(substitute_placeholder_in_expr): Likewise.
(stabilize_reference_1): Likewise.
(build3_stat): Remove logic for CALL_EXPRs. Replace with assertion
to diagnose breakage of this interface for constructing CALL_EXPRs.
(build_nt): Add similar assertion here.
(build_nt_call_list): New.
(simple_cst_equal) <CALL_EXPR>: Rewrite to use new accessors.
(iterative_hash_expr): Use TREE_OPERAND_LENGTH instead of
TREE_CODE_LENGTH.
(get_callee_fndecl): Use new CALL_EXPR accessors.
(tree_operand_check_failed): Change parameters to pass entire node
instead of its code, so that we can call TREE_OPERAND_LENGTH on it.
(process_call_operands): New.
(build_vl_exp_stat): New.
(build_call_list): New.
(build_call_nary): New.
(build_call_valist): New.
(build_call_array): New.
(walk_tree): Use TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH.
(call_expr_arglist): New.
* tree.def (CALL_EXPR): Change representation of CALL_EXPRs to use
tcc_vl_exp instead of a fixed-size tcc_expression.
* doc/c-tree.texi (CALL_EXPR): Document new representation and
accessors for CALL_EXPRs.
(AGGR_INIT_EXPR): Likewise.
2007-02-15 Sandra Loosemore <sandra@codesourcery.com>
Brooks Moses <brooks.moses@codesourcery.com>
Lee Millward <lee.millward@codesourcery.com>
* builtins.c (c_strlen): Return NULL_TREE instead of 0.
(expand_builtin_nonlocal_goto): Change parameter to be entire
CALL_EXPR instead of an arglist. Use new CALL_EXPR accessors.
(expand_builtin_prefetch): Likewise.
(expand_builtin_classify_type): Likewise.
(mathfn_built_in): Return NULL_TREE instead of 0.
(expand_errno_check): Use new CALL_EXPR accessors.
(expand_builtin_mathfn): Use new CALL_EXPR accessors and constructors.
Return NULL_RTX instead of 0.
(expand_builtin_mathfn_2): Likewise.
(expand_builtin_mathfn_3): Likewise.
(expand_builtin_interclass_mathfn): Likewise.
(expand_builtin_sincos): Likewise.
(expand_builtin_cexpi): Likewise.
(expand_builtin_int_roundingfn): Likewise.
(expand_builtin_int_roundingfn_2): Likewise.
(expand_builtin_pow): Likewise.
(expand_builtin_powi): Likewise.
(expand_builtin_strlen): Pass entire CALL_EXPR as parameter instead
of arglist, fixing callers appropriately. Use new CALL_EXPR
accessors and constructors. Return NULL_RTX instead of 0.
(expand_builtin_strstr): Likewise.
(expand_builtin_strchr): Likewise.
(expand_builtin_strrchr): Likewise.
(expand_builtin_strpbrk): Likewise.
(expand_builtin_memcpy): Likewise.
(expand_builtin_mempcpy): Likewise.
(expand_builtin_mempcpy_args): New.
(expand_builtin_memmove): Similarly to expand_builtin_mempcpy.
(expand_builtin_memmove_args): New.
(expand_builtin_bcopy): Similarly to expand_builtin_mempcpy.
(expand_movstr): Likewise.
(expand_builtin_strcpy): Likewise.
(expand_builtin_strcpy_args): New.
(expand_builtin_stpcpy): Similarly to expand_builtin_strcpy.
(expand_builtin_strncpy): Likewise.
(expand_builtin_memset): Likewise.
(expand_builtin_memset_args): New.
(expand_builtin_bzero): Similarly to expand_builtin_memset.
(expand_builtin_memcmp): Likewise.
(expand_builtin_strcmp): Likewise.
(expand_builtin_strncmp): Likewise.
(expand_builtin_strcat): Likewise.
(expand_builtin_strncat): Likewise.
(expand_builtin_strspn): Likewise.
(expand_builtin_strcspn): Likewise.
(expand_builtin_args_info): Likewise.
(expand_builtin_va_start): Likewise.
(gimplify_va_arg_expr): Likewise.
(expand_builtin_va_end): Likewise.
(expand_builtin_va_copy): Likewise.
(expand_builtin_frame_address): Likewise.
(expand_builtin_alloca): Likewise.
(expand_builtin_bswap): Likewise.
(expand_builtin_unop): Likewise.
(expand_builtin_fputs): Likewise.
(expand_builtin_expect): Likewise.
(expand_builtin_fabs): Likewise.
(expand_builtin_copysign): Likewise.
(expand_builtin_printf): Likewise.
(expand_builtin_fprintf): Likewise.
(expand_builtin_sprintf): Likewise.
(expand_builtin_init_trampoline): Likewise.
(expand_builtin_signbit): Likewise.
(expand_builtin_fork_or_exec): Likewise.
(expand_builtin_sync_operation): Likewise.
(expand_builtin_compare_and_swap): Likewise.
(expand_builtin_lock_test_and_set): Likewise.
(expand_builtin_lock_release): Likewise.
(expand_builtin): Likewise.
(builtin_mathfn_code): Likewise.
(fold_builtin_constant_p): 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_expect): Likewise.
(fold_builtin_classify_type): Likewise.
(fold_builtin_strlen): Likewise.
(fold_builtin_nan): Likewise.
(integer_valued_real_p): Likewise.
(fold_trunc_transparent_mathfn): Likewise.
(fold_fixed_mathfn): Likewise.
(fold_builtin_cabs): Likewise.
(fold_builtin_sqrt): Likewise.
(fold_builtin_cbrt): Likewise.
(fold_builtin_cos): Likewise.
(fold_builtin_cosh): Likewise.
(fold_builtin_tan): Likewise.
(fold_builtin_sincos): Likewise.
(fold_builtin_cexp): Likewise.
(fold_builtin_trunc): Likewise.
(fold_builtin_floor): Likewise.
(fold_builtin_ceil): Likewise.
(fold_builtin_round): Likewise.
(fold_builtin_int_roundingfn): Likewise.
(fold_builtin_bitop): Likewise.
(fold_builtin_bswap): Likewise.
(fold_builtin_logarithm): Likewise.
(fold_builtin_hypot): Likewise.
(fold_builtin_pow): Likewise.
(fold_builtin_powi): Likewise.
(fold_builtin_exponent): Likewise.
(fold_builtin_memset): Likewise.
(fold_builtin_bzero): Likewise.
(fold_builtin_memory_op): Likewise.
(fold_builtin_bcopy): Deleted; call site changed to invoke
fold_builtin_memory_op directly.
(fold_builtin_strcpy): Similarly as for fold_builtin_memory_op.
(fold_builtin_strncpy): Likewise.
(fold_builtin_memcmp): Likewise.
(fold_builtin_strcmp): Likewise.
(fold_builtin_strncmp): Likewise.
(fold_builtin_signbit): Likewise.
(fold_builtin_copysign): Likewise.
(fold_builtin_isascii): Likewise.
(fold_builtin_toascii): Likewise.
(fold_builtin_isdigit): Likewise.
(fold_builtin_fabs): Likewise.
(fold_builtin_abs): Likewise.
(fold_builtin_fmin_fmax): Likewise.
(fold_builtin_carg): Likewise.
(fold_builtin_classify): Likewise.
(fold_builtin_unordered_cmp): Likewise.
(fold_builtin_0, fold_builtin_2, fold_builtin_3, fold_builtin_4):
New functions split out from fold_builtin_1.
(fold_builtin_n): New.
(fold_builtin_varargs): New.
(fold_builtin): Deleted. Most callers changed to use fold_call_expr
instead.
(fold_call_expr): New.
(build_function_call_expr): Rewrite to use new helper function.
(fold_builtin_call_list): New.
(build_call_expr): New.
(fold_builtin_call_valist): New.
(rewrite_call_expr): New.
(validate_arg): New.
(validate_arglist): Change parameter to be entire CALL_EXPR instead
of an arglist. Change return type to bool. Use new CALL_EXPR
accessors.
(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.
(fold_builtin_strrchr): Likewise.
(fold_builtin_strpbrk): Likewise.
(fold_builtin_strcat): Likewise.
(fold_builtin_strncat): Likewise.
(fold_builtin_strspn): Likewise.
(fold_builtin_strcspn): Likewise.
(fold_builtin_fputs): Likewise.
(fold_builtin_next_arg): Likewise.
(fold_builtin_sprintf): Likewise.
(expand_builtin_object_size): Use new CALL_EXPR accessors. Use
NULL_RTX instead of 0.
(expand_builtin_memory_chk): Likewise.
(maybe_emit_chk_warning): Likewise.
(maybe_emit_sprintf_chk_warning): Likewise.
(fold_builtin_object_size): 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_memory_chk): Likewise.
(fold_builtin_stxcpy_chk): Likewise.
(fold_builtin_strncpy_chk): Likewise.
(fold_builtin_strcat_chk): Likewise.
(fold_builtin_strcat_chk): Likewise.
(fold_builtin_strncat_chk): Likewise.
(fold_builtin_sprintf_chk): Likewise.
(fold_builtin_snprintf_chk): Likewise.
(fold_builtin_printf): Likewise.
(fold_builtin_vprintf): Likewise.
* fold-const.c (negate_expr_p): Use new CALL_EXPR accessors and
constructors.
(operand_equal_p): Add separate tcc_vl_exp/CALL_EXPR case.
(make_range): Use TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH.
(extract_muldiv_1): Add VL_EXP_CLASS_P case.
(fold_mathfn_compare): Use new CALL_EXPR accessors and constructors.
(fold_unary): Likewise.
(fold_binary): Likewise.
(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
TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH.
(fold_build3_stat): Add assertion to flag broken interface for
constructing CALL_EXPRs.
(fold_build_call_list): New.
(fold_build_call_list_initializer): New.
(tree_expr_nonnegative_p): Use new CALL_EXPR accessors and
constructors.
(fold_strip_sign_ops): Likewise.
2007-02-15 Sandra Loosemore <sandra@codesourcery.com>
Brooks Moses <brooks.moses@codesourcery.com>
Lee Millward <lee.millward@codesourcery.com>
* tree-dump.c (dequeue_and_dump) <CALL_EXPR>: Use new CALL_EXPR
accessors and dump arguments explicitly.
* tree-pretty-print.c (do_niy): Use TREE_OPERAND_LENGTH instead of
TREE_CODE_LENGTH.
(dump_generic_node): Use new CALL_EXPR accessors and walk arguments
explicitly.
(print_call_name): Use new CALL_EXPR accessors.
* print-tree.c (print_node): Add case tcc_vl_exp. Print
CALL_EXPR arguments explicitly instead of as a list. Use
TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH.
* 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
know about tcc_vl_exp. Use TREE_OPERAND_LENGTH instead of
TREE_CODE_LENGTH.
(force_move_till_expr): Likewise.
* targhooks.c (default_external_stack_protect_fail): Use
build_call_expr instead of build_function_call_expr.
(default_hidden_stack_protect_fail): Likewise.
* tree-complex.c (expand_complex_libcall): Use build_call_expr to
build the call.
* cgraphbuild.c (build_cgraph_edges): Use new CALL_EXPR accessors
and walk arguments explicitly.
* tree-ssa-loop-niter.c (simplify_replace_tree): Use
TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH.
(expand_simple_operations): Likewise.
(infer_loop_bounds_from_array): Use new CALL_EXPR accessors.
* gengtype.c (adjust_field_tree_exp): Use TREE_OPERAND_LENGTH instead
of TREE_CODE_LENGTH.
(walk_type): Tweak walking of arrays not to blow up on CALL_EXPRs.
* optabs.c (expand_widen_pattern-expr): Use TREE_OPERAND_LENGTH
instead of TREE_CODE_LENGTH.
* value_prof.c (tree_ic): Use new CALL_EXPR accessors.
(tree_ic_transform): Likewise.
(interesting_stringop_to_profile_p): Pass entire CALL_EXPR as
parameter instead of arglist. Fix callers.
(tree_stringop_fixed_value): Use new CALL_EXPR accessors.
(tree_stringops_transform): Likewise.
(tree_indirect_call_to_profile): Likewise.
(tree_stringops_values_to_profile): Likewise.
* tree-tailcall.c (find_tail_calls): Use new CALL_EXPR iterator.
(eliminate_tail_call): Likewise.
* ipa-cp.c (ipcp_update_callgraph): Use new CALL_EXPR accessors.
* tree-scalar-evolution.c (chrec_contains_symbols_defined_in_loop):
Use TREE_OPERAND_LENGTH and generalize to handle any number of
operands.
(instantiate_parameters_1): Can't handle tcc_vl_exp here.
* omp-low.c (build_omp_barrier): Use build_call_expr.
(lower_rec_input_clauses): Likewise.
(lower_reduction_clauses): Likewise.
(expand_parallel_call): Likewise.
(maybe_catch_exception): Likewise.
(expand_omp_for_generic): Likewise.
(expand_omp_for_static_nochunk): Likewise.
(expand_omp_sections): Likewise.
(lower_omp_single_simple): Likewise.
(lower_omp_single_copy): Likewise.
(lower_omp_master): Likewise.
(lower_omp_ordered): Likewise.
(lower_omp_critical): Likewise.
* ipa-reference.c (check-call): Use new CALL_EXPR iterator.
(scan_for_static_refs): Create tcc_vl_exp case for CALL_EXPR.
* tree-gimple.c (is_gimple_call_addr): Fix doc.
(recalculate_side_effects): Use TREE_OPERAND_LENGTH instead of
TREE_CODE_LENGTH. Add tcc_vl_exp case.
* tree-chrec.c (chrec_contains_symbols): Use TREE_OPERAND_LENGTH
and generalize to handle any number of operands.
(chrec_contains_undetermined): Likewise.
(tree_contains_chrecs): Likewise.
(evolution_function_is_invariant_rec_p): Use TREE_OPERAND_LENGTH.
* cgraphunit.c (update_call_expr): Use new CALL_EXPR accessors.
* tree-ssa-ccp.c (ccp_fold): Use new CALL_EXPR accessors. Use
fold_call_expr instead of fold_builtin.
(ccp_fold_builtin): Likewise. Update calls into builtins.c to
match declarations there.
(fold_stmt): Use new CALL_EXPR constructor and accessors. Doc
updates.
* tree-ssa-loop-ivopts.c (expr_invariant_in_loop_p): Use
TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH.
* ipa-pure-const.c (check_call): Use new CALL_EXPR accessors.
(scan_function): Add case tcc_vl_exp for CALL_EXPR.
* tree-stdarg.c (execute_optimize_stdarg): Use new CALL_EXPR
accessors.
* tree-ssa-math-opts.c (execute_cse_sincos_1): Use build_call_expr.
(execute_cse_sincos): Use new CALL_EXPR accessors.
* tree-ssa-alias.c (find_used_portions): Use new CALL_EXPR iterator.
* gimple-low.c (lower_function_body): Use build_call_expr.
(lower_builtin_setjmp): Likewise.
* expr.c (emit_block_move_via_libcall): Use build_call_expr.
(set_storage_via_libcall): Likewise.
(safe_from_p): Add tcc_vl_exp case. Use TREE_OPERAND_LENGTH
instead of TREE_CODE_LENGTH.
(expand_expr_real_1): Use new CALL_EXPR accessors.
* tree-browser.c (store_child_info): Use TREE_OPERAND_LENGTH and
generalize to handle any number of operands.
(TB_parent_eq): Likewise.
* predict.c (expr_expected_value): Use new CALL_EXPR accessors.
(strip_builtin_expect): Likewise.
* function.c (gimplify_parameters): Use build_call_expr.
* tree-vectorizer.c (vect_is_simple_reduction): Use TREE_OPERAND_LENGTH
instead of TREE_CODE_LENGTH.
* ipa-type-escape.c (check_call): Use new CALL_EXPR iterators.
(scan_for_refs): Add case tcc_vl_exp for CALL_EXPR.
* tree-data-ref.c (get_references_in_stmt): Use new CALL_EXPR
iterators.
* gimplify.c (build_stack_save_restore): Use build_call_expr.
(gimplify_decl_expr): Likewise.
(gimplify_call_expr): Use fold_call_expr instead of fold_builtin.
Use new CALL_EXPR iterators.
(gimplify_modify_expr_to_memcpy): Use build_call_expr.
(gimplify_modify_expr_to_memset): Likewise.
(gimplify_variable_sized_compare): Likewise.
(gimplify_omp_atomic_fetch_op): Likewise.
(gimplify_omp_atomic_pipeline): Likewise.
(gimplify_omp_atomic_mutex): Likewise.
(gimplify_function_tree): Likewise.
* calls.c (alloca_call_p): Use new CALL_EXPR accessors.
(call_expr_flags): Likewise.
(expand_call): Likewise.
* except.c (expand_builtin_eh_return_data_regno): Pass entire
CALL_EXPR as parameter instead of arglist. Use new CALL_EXPR
accessors.
* coverage.c (create_coverage): Use build_call_expr.
* tree-ssa-pre.c (expression_node_pool, list_node_pool): Delete.
(temp_call_expr_obstack): New.
(pool_copy_list): Delete.
(temp_copy_call_expr): New.
(phi_translate): Add case tcc_vl_exp for CALL_EXPR. Use new
CALL_EXPR accessors. Get rid of special goo for copying argument
lists and use temp_copy_call_expr instead.
(valid_in_sets): Add case tcc_vl_exp for CALL_EXPR. Use new
CALL_EXPR accessors.
(create_expression_by_pieces): Likewise. Use build_call_array
to construct the result instead of fold_build3.
(create_value_expr_from): Add tcc_vl_exp. Delete special goo for
dealing with argument lists.
(init_pre): Remove references to expression_node_pool and
list_node_pool. Init temp_call_expr_obstack instead.
(fini_pre): Remove references to expression_node_pool and
list_node_pool.
* tree-sra.c (sra_walk_call_expr): Use new CALL_EXPR accessors
and walk arguments explicitly instead of as a list.
* tree-mudflap.c (mf_build_check_statement_for): Use build_call_expr.
(mx_register_decls): Likewise.
(mudflap_register_call): Likewise.
(mudflap_finish_file): Likewise.
* ipa-prop.c (ipa_callsite_compute_count): Use new CALL_EXPR accessors.
(ipa_callsite_compute_param): Likewise.
* tree-vect-patterns.c (vect_recog_pow_pattern): Use new CALL_EXPR
accessors and constructor.
* tree-nested.c (convert_nl_goto_reference): Use new CALL_EXPR
accessors and constructor.
(convert_tramp_reference): Likewise.
(convert_call_expr): Likewise.
(finalize_nesting_tree_1): Likewise.
* tree-ssa.c (tree_ssa_useless_type_conversion): Use new CALL_EXPR
accessors.
* tree-ssa-loop-prefetch.c (issue_prefetch_ref): Use build_call_expr.
* tree-inline.c (initialize_inlined_parameters): Pass entire
CALL_EXPR as parameter instead of arglist. Use new CALL_EXPR
accessors.
(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_OPERAND_LENGTH instead of TREE_CODE_LENGTH.
(vectorizable_reduction): Likewise.
(vectorizable_call): Use new CALL_EXPR iterators.
(vectorizable_conversion): Use build_call_expr.
(vectorizable_operation): Use TREE_OPERAND_LENGTH.
(vect_gen_widened_results_half): Use build_call_expr.
(vect_setup_realignment): Likewise.
(vectorizable_live_operation): Use TREE_OPERAND_LENGTH.
* tree-object-size.c (alloc_object_size): Use new CALL_EXPR accessors.
(pass_through_call): Likewise.
(compute_object_sizes): Likewise. Use fold_call_expr instead of
fold_builtin.
* tree-profile.c (tree_gen_interval_profiler): Use build_call_expr.
(tree_gen_pow2_profiler): Likewise.
(tree_gen_one_value_profiler): Likewise.
(tree_gen_ic_func_profiler): Likewise.
(tree_gen_average_profiler): Likewise.
(tree_gen_ior_profiler): Likewise.
* tree-ssa-structalias.c (get_constraint_for): Add case tcc_vl_exp.
(find_func_aliases): Use new CALL_EXPR accessors. Add case
tcc_vl_exp. Use TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH.
* tree-ssa-reassoc.c (get_rank): Use TREE_OPERAND_LENGTH instead
of TREE_CODE_LENGTH.
* stmt.c (warn_if_unused_value): Use TREE_OPERAND_LENGTH instead
of TREE_CODE_LENGTH.
* convert.c (convert_to_real): Use new CALL_EXPR accessors and
constructor.
(convert_to_integer): Likewise.
* tree-ssa-operands.c (get_call_expr_operands): Use new CALL_EXPR
accessors.
2007-02-15 Sandra Loosemore <sandra@codesourcery.com>
Brooks Moses <brooks.moses@codesourcery.com>
Lee Millward <lee.millward@codesourcery.com>
* config/alpha/alpha.c (alpha_expand_builtin): Use new CALL_EXPR
accessors.
* config/frv/frv.c (frv_expand_builtin): Likewise.
* config/s390/s390.c (s390_expand_builtin): Likewise.
* config/sparc/sparc.c (sparc_gimplify_va_arg): Use build_call_expr.
(sparc_expand_builtin): Use new CALL_EXPR accessors.
* config/i386/i386.c (ix86_function_ok_for_sibcall): Likewise.
(ix86_expand_binop_builtin): Pass entire CALL_EXPR as parameter
instead of arglist. Use new CALL_EXPR accessors on it. Fix callers.
(ix86_expand_store_builtin): Likewise.
(ix86_expand_unop_builtin): Likewise.
(ix86_expand_unop1_builtin): Likewise.
(ix86_expand_sse_compare): Likewise.
(ix86_expand_sse_comi): Likewise.
(ix86_expand_vec_init_builtin): Likewise.
(ix86_expand_vec_ext_builtin): Likewise.
(ix86_expand_vec_set_builtin): Likewise.
(ix86_expand_builtin): Use new CALL_EXPR accessors.
* config/sh/sh.c (sh_expand_builtin): Use new CALL_EXPR accessors.
* config/c4x/c4x.c (c4x_expand_builtin): Likewise.
* config/iq2000/iq2000.c (expand_one_builtin): Pass entire CALL_EXPR
instead of arglist. Use new CALL_EXPR accessors. Fix callers.
(iq2000_expand_builtin): Use new CALL_EXPR accessors.
* config/rs6000/rs6000-c.c (altivec_build_resolved_builtin): Use
build_call_expr.
* config/rs6000/rs6000.c (rs6000_gimplify_va_arg): Likewise.
(rs6000_expand_unop_builtin): Pass entire CALL_EXPR instead of
arglist. Use new CALL_EXPR accessors. Fix callers.
(altivec_expand_abs_builtin): Likewise.
(rs6000_expand_binop_builtin): Likewise.
(altivec_expand_predicate_builtin): Likewise.
(altivec_expand_lv_builtin): Likewise.
(spe_expand_stv_builtin): Likewise.
(altivec_expand_stv_builtin): Likewise.
(rs6000_expand_ternop_builtin): Likewise.
(altivec_expand_ld_builtin): Use new CALL_EXPR accessors.
(altivec_expand_st_builtin): Likewise.
(altivec_expand_dst_builtin): Likewise.
(altivec_expand_vec_init_builtin): Pass entire CALL_EXPR instead of
arglist. Use new CALL_EXPR accessors. Fix callers.
(altivec_expand_vec_set_builtin): Likewise.
(altivec_expand_vec_ext_builtin): Likewise.
(altivec_expand_builtin): Use new CALL_EXPR accessors.
(spe_expand_builtin): Likewise.
(spe_expand_predicate_builtin): Pass entire CALL_EXPR instead of
arglist. Use new CALL_EXPR accessors. Fix callers.
(spe_expand_evsel_builtin): Likewise.
(rs6000_expand_builtin): Use new CALL_EXPR accessors. VCFUX and
FCFSX cases must construct whole new CALL_EXPR, not just arglist.
* config/arm/arm.c (arm_expand_binop_builtin): Pass entire CALL_EXPR
instead of arglist. Use new CALL_EXPR accessors. Fix callers.
(arm_expand_unop_builtin): Likewise.
(arm_expand_builtin): Use new CALL_EXPR accessors.
* config/mips/mips.c (mips_expand_builtin): Use new CALL_EXPR
accessors.
* config/bfin/bfin.c (bfin_expand_binop_builtin): Pass entire CALL_EXPR
instead of arglist. Use new CALL_EXPR accessors. Fix callers.
(bfin_expand_unop_builtin): Likewise.
(bfin_expand_builtin): Use new CALL_EXPR accessors.
2007-02-15 Sandra Loosemore <sandra@codesourcery.com>
Brooks Moses <brooks.moses@codesourcery.com>
Lee Millward <lee.millward@codesourcery.com>
* c-semantics.c (build_stmt): Add internal diagnostic check.
* c-pretty-print.c (pp_c_postfix_expression): Use new CALL_EXPR
accessors. Print arguments explicitly instead of as a list.
* c-typeck.c (build_function_call): Use new CALL_EXPR constructors.
* c-omp.c (c_finish_omp_barrier): Use build_call_expr.
(c_finish_omp_flish): Likewise.
* c-common.c (verify_tree): Use new CALL_EXPR accessors. Traverse
arguments explicitly instead of as a list. Use TREE_OPERAND_LENGTH
instead of TREE_CODE_LENGTH.
(check_function_arguments_recurse): Use new CALL_EXPR accessors.
(c_warn_unused_result): Likewise.
2007-02-15 Sandra Loosemore <sandra@codesourcery.com>
Brooks Moses <brooks.moses@codesourcery.com>
Lee Millward <lee.millward@codesourcery.com>
* cp-tree.def (AGGR_INIT_EXPR): Adjust documentation.
Change class to tcc_vl_exp.
* call.c (build_call): Use build_call_list instead
of build3.
(build_over_call): Likewise.
(build_new_method_call): Use build_min_non_dep_call_list
instead of build_min_non_dep.
* error.c (dump_call_expr_args): New function.
(dump_aggr_init_expr_args): New function.
(dump_expr) <AGGR_INIT_EXPR, CALL_EXPR, INDIRECT_REF>: Use them.
Update to use new CALL_EXPR and AGGR_INIT_EXPR accessor macros.
* cvt.c (convert_to_void): Use build_call_array instead
of build3; use new AGGR_INIT_EXPR accessor macros.
* mangle.c (write_expression): Use TREE_OPERAND_LENGTH
instead of TREE_CODE_LENGTH.
* dump.c (cp_dump_tree) <AGGR_INIT_EXPR>: Update to use new
AGGR_INIT_EXPR accessor macros.
* cp-gimplify.c (cp_gimplify_init_expr): Use
AGGR_INIT_EXPR_SLOT to set the slot operand.
* cp-tree.h (AGGR_INIT_EXPR_FN): New macro.
(AGGR_INIT_EXPR_SLOT): New macro.
(AGGR_INIT_EXPR_ARG): New macro.
(aggr_init_expr_nargs): New macro.
(AGGR_INIT_EXPR_ARGP): New macro.
(aggr_init_expr_arg_iterator): New.
(init_aggr_init_expr_arg_iterator): New.
(next_aggr_init_expr_arg): New.
(first_aggr_init_expr_arg): New.
(more_aggr_init_expr_args_p): New.
(FOR_EACH_AGGR_INIT_EXPR_ARG): New.
(stabilize_aggr_init): New declaration.
(build_min_non_dep_call_list): Likewise.
* tree.c (process_aggr_init_operands): New function.
(build_aggr_init_array) New function.
(build_cplus_new): Update to use new CALL_EXPR and
AGGR_INIT_EXPR accessor macros. Replace use of build3 with
build_aggr_init_array.
(build_min_non_dep_call_list) New function.
(build_min_nt): Assert input code parameter is not a variable
length expression class.
(build_min, build_min_non_dep): Likewise.
(cp_tree_equal) <CALL_EXPR>: Iterate through the arguments
to check for equality instead of recursing. Handle tcc_vl_exp
tree code classes.
(stabilize_call): Update to only handle CALL_EXPRs, not
AGGR_INIT_EXPRs; use new CALL_EXPR accessor macros.
(stabilize_aggr_init): New function.
(stabilize_init): Use it.
* cxx-pretty-print.c (pp_cxx_postfix_expression)
<AGGR_INIT_EXPR, CALL_EXPR>: Update to use new CALL_EXPR and
AGGR_INIT_EXPR accessor macros and argument iterators.
* pt.c (tsubst_copy) <CALL_EXPR>: Replace build_nt with
build_vl_exp. Iterate through the operands, recursively
processing each one.
(tsubst_copy_and_build) <CALL_EXPR>: Update to use new
CALL_EXPR accessor macros.
(value_dependent_expression_p) <default>: Handle tcc_vl_exp
tree code classes. Use TREE_OPERAND_LENGTH instead of
TREE_CODE_LENGTH.
* semantics.c (finish_call_expr): Use build_nt_call_list
instead of build_nt.
(simplify_aggr_init_expr): Update to use new AGGR_INIT_EXPR
accessor macros. Use build_call_array to construct the
CALL_EXPR node instead of build3
* decl2.c (build_offset_ref_call_from_tree): Use
build_nt_call_list and build_min_non_dep_call_list instead
of build_min_nt and build_min_non_dep.
* parser.c (cp_parser_postfix_expression) <CPP_OPEN_PAREN>:
Use build_nt_call_list instead of build_min_nt.
2007-02-15 Sandra Loosemore <sandra@codesourcery.com>
Brooks Moses <brooks.moses@codesourcery.com>
Lee Millward <lee.millward@codesourcery.com>
* java-tree.h (BUILD_MONITOR_ENTER): Use build_call_nary instead
of build3.
(BUILD_MONITOR_EXIT): Likewise.
* java-gimplify.c (java_gimplify_component_ref): Use build_call_expr.
(java_gimplify_modify_expr): Likewise.
* class.c (cache_this_class_ref): Use build_call_expr.
(build_static_field_ref): Likewise.
(emit_indirect_register_classes): Likewise.
(emit_register_classes): Likewise.
* resource.c (write_resource_constructor): Use build_call_expr.
* builtins.c (builtin_creator_function): Change interpretation of
the second parameter to be the whole CALL_EXPR instead of the arglist.
(max_builtin): Tweak parameter list. Use new CALL_EXPR accessors.
(min_builtin): Likewise.
(abs_builtin): Likewise.
(java_build_function_call_expr): Likewise.
(convert_real): Likewise.
(UNMARSHAL3): Likewise.
(UNMARSHAL4): Likewise.
(UNMARSHAL5): Likewise.
(build_arglist_for_builtin): Delete. Fix callers to use
build_call_expr instead.
(putObject_builtin): Tweak parameter list. Use new CALL_EXPR
accessors.
(compareAndSwapInt_builtin): Likewise.
(compareAndSwapLong_builtin): Likewise.
(compareAndSwapObject_builtin): Likewise.
(putVolatile_builtin): Likewise.
(getVolatile_builtin): Likewise.
(VMSupportsCS8_builtin): Likewise.
(check_for_builtin): Pass entire CALL_EXPR to builtin expander
instead of arglist.
* expr.c (build_java_athrow): Use build_call_nary instead of build3.
(build_java_throw_out_of_bounds_exception): Likewise.
(java_check_reference): Likewise.
(build_java_arraystore_check): Likewise.
(build_newarray): Likewise.
(build_anewarray): Likewise.
(expand_java_multinewarray): Use build_call_list instead of build3.
(build_java_monitor): Use build_call_nary instead of build3.
(java_create_object): Likewise.
(expand_java_NEW): Likewise.
(build_instanceof): Likewise.
(expand_java_CHECKCAST): Likewise.
(build_java_soft_divmod): Likewise.
(build_java_binop): Likewise.
(build_field_ref): Likewise.
(build_class_init): Likewise.
(rewrite_arglist_getcaller): Use build_call_expr.
(build_invokeinterface): Use build_call_nary instead of build3.
(expand_invoke): Use build_call_list instead of build3.
(build_jni_stub): Use build_call_nary, build_call_list, or
build_call_expr instead of build3.
(expand_java_field_op): Use build_call_expr instead of build3.
(force_evaluation_order): Use new CALL_EXPR accessors.
* lang.c (java_get_callee_fndecl): Use new CALL_EXPR accessors.
2007-02-15 Sandra Loosemore <sandra@codesourcery.com>
Brooks Moses <brooks.moses@codesourcery.com>
Lee Millward <lee.millward@codesourcery.com>
* objc-act.c (receiver_is_class_object): Use new CALL_EXPR accessors.
(objc_get_callee_fndecl): Likewise.
2007-02-15 Sandra Loosemore <sandra@codesourcery.com>
Brooks Moses <brooks.moses@codesourcery.com>
Lee Millward <lee.millward@codesourcery.com>
* trans-expr.c (gfc_conv_power_op): Use build_call_expr.
(gfc_conv_string_tmp): Likewise.
(gfc_conv_concat_op): Likewise.
(gfc_build_compare_string): Likewise.
(gfc_conv_function_call): Use build_call_list instead of build3.
* trans-array.c (gfc_trans_allocate_array_storage): Use
build_call_expr.
(gfc_grow_array): Likewise.
(gfc_trans_array_ctor_element): Likewise.
(gfc_trans_array_constructor_value): Likewise.
(gfc_array_allocate): Likewise.
(gfc_array_deallocate): Likewise.
(gfc_trans_auto_array_allocation): Likewise.
(gfc_trans_dummy_array_bias): Likewise.
(gfc_conv_array_parameter): Likewise.
(gfc_trans_dealloc_allocated): Likewise.
(gfc_duplicate_allocatable): Likewise.
* trans-openmp.c (gfc_trans_omp_barrier): Use build_call_expr.
(gfc_trans_omp_flush): Likewise.
* trans-stmt.c (gfc_conv_elementel_dependencies): Use build_call_expr.
(gfc_trans_pause): Likewise.
(gfc_trans_stop): Likewise.
(gfc_trans_character_select): Likewise.
(gfc_do_allocate): Likewise.
(gfc_trans_assign_need_temp): Likewise.
(gfc_trans_pointer_assign_need_temp): Likewise.
(gfc_trans_forall_1): Likewise.
(gfc_trans_where_2): Likewise.
(gfc_trans_allocate): Likewise.
(gfc_trans_deallocate): Likewise.
* trans.c (gfc_trans_runtime_check): Use build_call_expr.
* trans-io.c (gfc_trans_open): Use build_call_expr.
(gfc_trans_close): Likewise.
(build_filepos): Likewise.
(gfc_trans_inquire): Likewise.
(NML_FIRST_ARG): Delete.
(NML_ADD_ARG): Delete.
(transfer_namelist_element): Use build_call_expr.
(build_dt): Likewise.
(gfc_trans_dt_end): Likewise.
(transfer_expr): Likewise.
(transfer_array-desc): Likewise.
* trans-decl.c (gfc_generate_function_code): Use build_call_expr.
(gfc_generate_constructors): Likewise.
* trans-intrinsic.c (gfc_conv_intrinsic_ctime): Use build_call_expr.
(gfc_conv_intrinsic_fdate): Likewise.
(gfc_conv_intrinsic_ttynam): Likewise.
(gfc_conv_intrinsic_array_transfer): Likewise.
(gfc_conv_associated): Likewise.
(gfc_conv_intrinsic_si_kind): Likewise.
(gfc_conv_intrinsic_trim): Likewise.
(gfc_conv_intrinsic_repeat: Likewise.
(gfc_conv_intrinsic_iargc): Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122018 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
115 files changed, 5817 insertions, 4720 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 70efcfe0116..22af3fdef3f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,639 @@ +2007-02-15 Sandra Loosemore <sandra@codesourcery.com> + Brooks Moses <brooks.moses@codesourcery.com> + Lee Millward <lee.millward@codesourcery.com> + + * tree.h (enum tree_code_class): Add tcc_vl_exp. + (VL_EXP_CLASS_P): New. + (TREE_OPERAND_CHECK): Use TREE_OPERAND_LENGTH instead of + TREE_CODE_LENGTH. + (TREE_OPERAND_CHECK_CODE): Likewise. + (GIMPLE_STMT_OPERAND_CHECK): Likewise. + (TREE_RTL_OPERAND_CHECK): Likewise. + (tree_operand_check_failed): Make second parameter the whole tree + instead of its code. Fixed callers. + (VL_EXP_CHECK): New. + (TREE_OPERAND_LENGTH): New. + (VL_EXP_OPERAND_LENGTH): New. + (CALL_EXPR_FN): New. + (CALL_EXPR_STATIC_CHAIN): New. + (CALL_EXPR_ARGS): New. + (CALL_EXPR_ARG): New. + (call_expr_nargs): New. + (CALL_EXPR_ARGP): New. + (build_nt_call_list): Declare. + (build_vl_exp_stat): Declare. + (build_vl_exp): New. + (build_call_list): Declare. + (build_call_nary): Declare. + (build_call_valist): Declare. + (build_call_array): Declare. + (call_expr_arg): Declare. + (call_expr_argp): Declare. + (call_expr_arglist): Declare. + (fold_build_call_list): Declare. + (fold_build_call_list_initializer): Declare. + (fold_call_expr): Declare to replace fold_builtin. + (fold_builtin_fputs): Update to agree with modified definition. + (fold_builtin_strcpy): Likewise. + (fold_builtin_strncpy): Likewise. + (fold_builtin_memory_chk): Likewise. + (fold_builtin_stxcpy_chk): Likewise. + (fold_builtin_strncpy_chk): Likewise. + (fold_builtin_next_arg): Likewise. + (fold_build_call_expr): Declare. + (fold_builtin_call_list): Declare. + (fold_builtin_call_valist): Declare. + (build_call_expr): Declare. + (validate_arglist): Update to agree with modified definition. + (tree_operand_length): New. + (call_expr_arg_iterator): New. + (init_call_expr_arg_iterator): New. + (next_call_expr_arg): New. + (first_call_expr_arg): New. + (more_call_expr_args_p): New. + (FOR_EACH_CALL_EXPR_ARG): New. + + * tree.c (tree_code_class_string): Add entries for tcc_vl_exp + and tcc_gimple_stmt. + (tree_code_size): Update documentation. Use sizeof (tree) rather + than sizeof (char *). + (tree_size): Likewise. Add case for tcc_vl_exp. + (tree_node_structure): Add case for tcc_vl_exp. + (contains_placeholder_p): Likewise. + (substitute_in_expr): Likewise. + (substitute_placeholder_in_expr): Likewise. + (stabilize_reference_1): Likewise. + (build3_stat): Remove logic for CALL_EXPRs. Replace with assertion + to diagnose breakage of this interface for constructing CALL_EXPRs. + (build_nt): Add similar assertion here. + (build_nt_call_list): New. + (simple_cst_equal) <CALL_EXPR>: Rewrite to use new accessors. + (iterative_hash_expr): Use TREE_OPERAND_LENGTH instead of + TREE_CODE_LENGTH. + (get_callee_fndecl): Use new CALL_EXPR accessors. + (tree_operand_check_failed): Change parameters to pass entire node + instead of its code, so that we can call TREE_OPERAND_LENGTH on it. + (process_call_operands): New. + (build_vl_exp_stat): New. + (build_call_list): New. + (build_call_nary): New. + (build_call_valist): New. + (build_call_array): New. + (walk_tree): Use TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH. + (call_expr_arglist): New. + + * tree.def (CALL_EXPR): Change representation of CALL_EXPRs to use + tcc_vl_exp instead of a fixed-size tcc_expression. + + * doc/c-tree.texi (CALL_EXPR): Document new representation and + accessors for CALL_EXPRs. + (AGGR_INIT_EXPR): Likewise. + +2007-02-15 Sandra Loosemore <sandra@codesourcery.com> + Brooks Moses <brooks.moses@codesourcery.com> + Lee Millward <lee.millward@codesourcery.com> + + * builtins.c (c_strlen): Return NULL_TREE instead of 0. + (expand_builtin_nonlocal_goto): Change parameter to be entire + CALL_EXPR instead of an arglist. Use new CALL_EXPR accessors. + (expand_builtin_prefetch): Likewise. + (expand_builtin_classify_type): Likewise. + (mathfn_built_in): Return NULL_TREE instead of 0. + (expand_errno_check): Use new CALL_EXPR accessors. + (expand_builtin_mathfn): Use new CALL_EXPR accessors and constructors. + Return NULL_RTX instead of 0. + (expand_builtin_mathfn_2): Likewise. + (expand_builtin_mathfn_3): Likewise. + (expand_builtin_interclass_mathfn): Likewise. + (expand_builtin_sincos): Likewise. + (expand_builtin_cexpi): Likewise. + (expand_builtin_int_roundingfn): Likewise. + (expand_builtin_int_roundingfn_2): Likewise. + (expand_builtin_pow): Likewise. + (expand_builtin_powi): Likewise. + (expand_builtin_strlen): Pass entire CALL_EXPR as parameter instead + of arglist, fixing callers appropriately. Use new CALL_EXPR + accessors and constructors. Return NULL_RTX instead of 0. + (expand_builtin_strstr): Likewise. + (expand_builtin_strchr): Likewise. + (expand_builtin_strrchr): Likewise. + (expand_builtin_strpbrk): Likewise. + (expand_builtin_memcpy): Likewise. + (expand_builtin_mempcpy): Likewise. + (expand_builtin_mempcpy_args): New. + (expand_builtin_memmove): Similarly to expand_builtin_mempcpy. + (expand_builtin_memmove_args): New. + (expand_builtin_bcopy): Similarly to expand_builtin_mempcpy. + (expand_movstr): Likewise. + (expand_builtin_strcpy): Likewise. + (expand_builtin_strcpy_args): New. + (expand_builtin_stpcpy): Similarly to expand_builtin_strcpy. + (expand_builtin_strncpy): Likewise. + (expand_builtin_memset): Likewise. + (expand_builtin_memset_args): New. + (expand_builtin_bzero): Similarly to expand_builtin_memset. + (expand_builtin_memcmp): Likewise. + (expand_builtin_strcmp): Likewise. + (expand_builtin_strncmp): Likewise. + (expand_builtin_strcat): Likewise. + (expand_builtin_strncat): Likewise. + (expand_builtin_strspn): Likewise. + (expand_builtin_strcspn): Likewise. + (expand_builtin_args_info): Likewise. + (expand_builtin_va_start): Likewise. + (gimplify_va_arg_expr): Likewise. + (expand_builtin_va_end): Likewise. + (expand_builtin_va_copy): Likewise. + (expand_builtin_frame_address): Likewise. + (expand_builtin_alloca): Likewise. + (expand_builtin_bswap): Likewise. + (expand_builtin_unop): Likewise. + (expand_builtin_fputs): Likewise. + (expand_builtin_expect): Likewise. + (expand_builtin_fabs): Likewise. + (expand_builtin_copysign): Likewise. + (expand_builtin_printf): Likewise. + (expand_builtin_fprintf): Likewise. + (expand_builtin_sprintf): Likewise. + (expand_builtin_init_trampoline): Likewise. + (expand_builtin_signbit): Likewise. + (expand_builtin_fork_or_exec): Likewise. + (expand_builtin_sync_operation): Likewise. + (expand_builtin_compare_and_swap): Likewise. + (expand_builtin_lock_test_and_set): Likewise. + (expand_builtin_lock_release): Likewise. + (expand_builtin): Likewise. + (builtin_mathfn_code): Likewise. + + (fold_builtin_constant_p): 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_expect): Likewise. + (fold_builtin_classify_type): Likewise. + (fold_builtin_strlen): Likewise. + (fold_builtin_nan): Likewise. + (integer_valued_real_p): Likewise. + (fold_trunc_transparent_mathfn): Likewise. + (fold_fixed_mathfn): Likewise. + (fold_builtin_cabs): Likewise. + (fold_builtin_sqrt): Likewise. + (fold_builtin_cbrt): Likewise. + (fold_builtin_cos): Likewise. + (fold_builtin_cosh): Likewise. + (fold_builtin_tan): Likewise. + (fold_builtin_sincos): Likewise. + (fold_builtin_cexp): Likewise. + (fold_builtin_trunc): Likewise. + (fold_builtin_floor): Likewise. + (fold_builtin_ceil): Likewise. + (fold_builtin_round): Likewise. + (fold_builtin_int_roundingfn): Likewise. + (fold_builtin_bitop): Likewise. + (fold_builtin_bswap): Likewise. + (fold_builtin_logarithm): Likewise. + (fold_builtin_hypot): Likewise. + (fold_builtin_pow): Likewise. + (fold_builtin_powi): Likewise. + (fold_builtin_exponent): Likewise. + (fold_builtin_memset): Likewise. + (fold_builtin_bzero): Likewise. + (fold_builtin_memory_op): Likewise. + (fold_builtin_bcopy): Deleted; call site changed to invoke + fold_builtin_memory_op directly. + (fold_builtin_strcpy): Similarly as for fold_builtin_memory_op. + (fold_builtin_strncpy): Likewise. + (fold_builtin_memcmp): Likewise. + (fold_builtin_strcmp): Likewise. + (fold_builtin_strncmp): Likewise. + (fold_builtin_signbit): Likewise. + (fold_builtin_copysign): Likewise. + (fold_builtin_isascii): Likewise. + (fold_builtin_toascii): Likewise. + (fold_builtin_isdigit): Likewise. + (fold_builtin_fabs): Likewise. + (fold_builtin_abs): Likewise. + (fold_builtin_fmin_fmax): Likewise. + (fold_builtin_carg): Likewise. + (fold_builtin_classify): Likewise. + (fold_builtin_unordered_cmp): Likewise. + + (fold_builtin_0, fold_builtin_2, fold_builtin_3, fold_builtin_4): + New functions split out from fold_builtin_1. + (fold_builtin_n): New. + (fold_builtin_varargs): New. + (fold_builtin): Deleted. Most callers changed to use fold_call_expr + instead. + (fold_call_expr): New. + (build_function_call_expr): Rewrite to use new helper function. + (fold_builtin_call_list): New. + (build_call_expr): New. + (fold_builtin_call_valist): New. + (rewrite_call_expr): New. + (validate_arg): New. + (validate_arglist): Change parameter to be entire CALL_EXPR instead + of an arglist. Change return type to bool. Use new CALL_EXPR + accessors. + + (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. + (fold_builtin_strrchr): Likewise. + (fold_builtin_strpbrk): Likewise. + (fold_builtin_strcat): Likewise. + (fold_builtin_strncat): Likewise. + (fold_builtin_strspn): Likewise. + (fold_builtin_strcspn): Likewise. + (fold_builtin_fputs): Likewise. + (fold_builtin_next_arg): Likewise. + (fold_builtin_sprintf): Likewise. + + (expand_builtin_object_size): Use new CALL_EXPR accessors. Use + NULL_RTX instead of 0. + (expand_builtin_memory_chk): Likewise. + (maybe_emit_chk_warning): Likewise. + (maybe_emit_sprintf_chk_warning): Likewise. + + (fold_builtin_object_size): 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_memory_chk): Likewise. + (fold_builtin_stxcpy_chk): Likewise. + (fold_builtin_strncpy_chk): Likewise. + (fold_builtin_strcat_chk): Likewise. + (fold_builtin_strcat_chk): Likewise. + (fold_builtin_strncat_chk): Likewise. + (fold_builtin_sprintf_chk): Likewise. + (fold_builtin_snprintf_chk): Likewise. + (fold_builtin_printf): Likewise. + (fold_builtin_vprintf): Likewise. + + * fold-const.c (negate_expr_p): Use new CALL_EXPR accessors and + constructors. + (operand_equal_p): Add separate tcc_vl_exp/CALL_EXPR case. + (make_range): Use TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH. + (extract_muldiv_1): Add VL_EXP_CLASS_P case. + (fold_mathfn_compare): Use new CALL_EXPR accessors and constructors. + (fold_unary): Likewise. + (fold_binary): Likewise. + (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 + TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH. + (fold_build3_stat): Add assertion to flag broken interface for + constructing CALL_EXPRs. + (fold_build_call_list): New. + (fold_build_call_list_initializer): New. + (tree_expr_nonnegative_p): Use new CALL_EXPR accessors and + constructors. + (fold_strip_sign_ops): Likewise. + +2007-02-15 Sandra Loosemore <sandra@codesourcery.com> + Brooks Moses <brooks.moses@codesourcery.com> + Lee Millward <lee.millward@codesourcery.com> + + * tree-dump.c (dequeue_and_dump) <CALL_EXPR>: Use new CALL_EXPR + accessors and dump arguments explicitly. + + * tree-pretty-print.c (do_niy): Use TREE_OPERAND_LENGTH instead of + TREE_CODE_LENGTH. + (dump_generic_node): Use new CALL_EXPR accessors and walk arguments + explicitly. + (print_call_name): Use new CALL_EXPR accessors. + + * print-tree.c (print_node): Add case tcc_vl_exp. Print + CALL_EXPR arguments explicitly instead of as a list. Use + TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH. + + * 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 + know about tcc_vl_exp. Use TREE_OPERAND_LENGTH instead of + TREE_CODE_LENGTH. + (force_move_till_expr): Likewise. + + * targhooks.c (default_external_stack_protect_fail): Use + build_call_expr instead of build_function_call_expr. + (default_hidden_stack_protect_fail): Likewise. + + * tree-complex.c (expand_complex_libcall): Use build_call_expr to + build the call. + + * cgraphbuild.c (build_cgraph_edges): Use new CALL_EXPR accessors + and walk arguments explicitly. + + * tree-ssa-loop-niter.c (simplify_replace_tree): Use + TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH. + (expand_simple_operations): Likewise. + (infer_loop_bounds_from_array): Use new CALL_EXPR accessors. + + * gengtype.c (adjust_field_tree_exp): Use TREE_OPERAND_LENGTH instead + of TREE_CODE_LENGTH. + (walk_type): Tweak walking of arrays not to blow up on CALL_EXPRs. + + * optabs.c (expand_widen_pattern-expr): Use TREE_OPERAND_LENGTH + instead of TREE_CODE_LENGTH. + + * value_prof.c (tree_ic): Use new CALL_EXPR accessors. + (tree_ic_transform): Likewise. + (interesting_stringop_to_profile_p): Pass entire CALL_EXPR as + parameter instead of arglist. Fix callers. + (tree_stringop_fixed_value): Use new CALL_EXPR accessors. + (tree_stringops_transform): Likewise. + (tree_indirect_call_to_profile): Likewise. + (tree_stringops_values_to_profile): Likewise. + + * tree-tailcall.c (find_tail_calls): Use new CALL_EXPR iterator. + (eliminate_tail_call): Likewise. + + * ipa-cp.c (ipcp_update_callgraph): Use new CALL_EXPR accessors. + + * tree-scalar-evolution.c (chrec_contains_symbols_defined_in_loop): + Use TREE_OPERAND_LENGTH and generalize to handle any number of + operands. + (instantiate_parameters_1): Can't handle tcc_vl_exp here. + + * omp-low.c (build_omp_barrier): Use build_call_expr. + (lower_rec_input_clauses): Likewise. + (lower_reduction_clauses): Likewise. + (expand_parallel_call): Likewise. + (maybe_catch_exception): Likewise. + (expand_omp_for_generic): Likewise. + (expand_omp_for_static_nochunk): Likewise. + (expand_omp_sections): Likewise. + (lower_omp_single_simple): Likewise. + (lower_omp_single_copy): Likewise. + (lower_omp_master): Likewise. + (lower_omp_ordered): Likewise. + (lower_omp_critical): Likewise. + + * ipa-reference.c (check-call): Use new CALL_EXPR iterator. + (scan_for_static_refs): Create tcc_vl_exp case for CALL_EXPR. + + * tree-gimple.c (is_gimple_call_addr): Fix doc. + (recalculate_side_effects): Use TREE_OPERAND_LENGTH instead of + TREE_CODE_LENGTH. Add tcc_vl_exp case. + + * tree-chrec.c (chrec_contains_symbols): Use TREE_OPERAND_LENGTH + and generalize to handle any number of operands. + (chrec_contains_undetermined): Likewise. + (tree_contains_chrecs): Likewise. + (evolution_function_is_invariant_rec_p): Use TREE_OPERAND_LENGTH. + + * cgraphunit.c (update_call_expr): Use new CALL_EXPR accessors. + + * tree-ssa-ccp.c (ccp_fold): Use new CALL_EXPR accessors. Use + fold_call_expr instead of fold_builtin. + (ccp_fold_builtin): Likewise. Update calls into builtins.c to + match declarations there. + (fold_stmt): Use new CALL_EXPR constructor and accessors. Doc + updates. + + * tree-ssa-loop-ivopts.c (expr_invariant_in_loop_p): Use + TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH. + + * ipa-pure-const.c (check_call): Use new CALL_EXPR accessors. + (scan_function): Add case tcc_vl_exp for CALL_EXPR. + + * tree-stdarg.c (execute_optimize_stdarg): Use new CALL_EXPR + accessors. + + * tree-ssa-math-opts.c (execute_cse_sincos_1): Use build_call_expr. + (execute_cse_sincos): Use new CALL_EXPR accessors. + + * tree-ssa-alias.c (find_used_portions): Use new CALL_EXPR iterator. + + * gimple-low.c (lower_function_body): Use build_call_expr. + (lower_builtin_setjmp): Likewise. + + * expr.c (emit_block_move_via_libcall): Use build_call_expr. + (set_storage_via_libcall): Likewise. + (safe_from_p): Add tcc_vl_exp case. Use TREE_OPERAND_LENGTH + instead of TREE_CODE_LENGTH. + (expand_expr_real_1): Use new CALL_EXPR accessors. + + * tree-browser.c (store_child_info): Use TREE_OPERAND_LENGTH and + generalize to handle any number of operands. + (TB_parent_eq): Likewise. + + * predict.c (expr_expected_value): Use new CALL_EXPR accessors. + (strip_builtin_expect): Likewise. + + * function.c (gimplify_parameters): Use build_call_expr. + + * tree-vectorizer.c (vect_is_simple_reduction): Use TREE_OPERAND_LENGTH + instead of TREE_CODE_LENGTH. + + * ipa-type-escape.c (check_call): Use new CALL_EXPR iterators. + (scan_for_refs): Add case tcc_vl_exp for CALL_EXPR. + + * tree-data-ref.c (get_references_in_stmt): Use new CALL_EXPR + iterators. + + * gimplify.c (build_stack_save_restore): Use build_call_expr. + (gimplify_decl_expr): Likewise. + (gimplify_call_expr): Use fold_call_expr instead of fold_builtin. + Use new CALL_EXPR iterators. + (gimplify_modify_expr_to_memcpy): Use build_call_expr. + (gimplify_modify_expr_to_memset): Likewise. + (gimplify_variable_sized_compare): Likewise. + (gimplify_omp_atomic_fetch_op): Likewise. + (gimplify_omp_atomic_pipeline): Likewise. + (gimplify_omp_atomic_mutex): Likewise. + (gimplify_function_tree): Likewise. + + * calls.c (alloca_call_p): Use new CALL_EXPR accessors. + (call_expr_flags): Likewise. + (expand_call): Likewise. + + * except.c (expand_builtin_eh_return_data_regno): Pass entire + CALL_EXPR as parameter instead of arglist. Use new CALL_EXPR + accessors. + + * coverage.c (create_coverage): Use build_call_expr. + + * tree-ssa-pre.c (expression_node_pool, list_node_pool): Delete. + (temp_call_expr_obstack): New. + (pool_copy_list): Delete. + (temp_copy_call_expr): New. + (phi_translate): Add case tcc_vl_exp for CALL_EXPR. Use new + CALL_EXPR accessors. Get rid of special goo for copying argument + lists and use temp_copy_call_expr instead. + (valid_in_sets): Add case tcc_vl_exp for CALL_EXPR. Use new + CALL_EXPR accessors. + (create_expression_by_pieces): Likewise. Use build_call_array + to construct the result instead of fold_build3. + (create_value_expr_from): Add tcc_vl_exp. Delete special goo for + dealing with argument lists. + (init_pre): Remove references to expression_node_pool and + list_node_pool. Init temp_call_expr_obstack instead. + (fini_pre): Remove references to expression_node_pool and + list_node_pool. + + * tree-sra.c (sra_walk_call_expr): Use new CALL_EXPR accessors + and walk arguments explicitly instead of as a list. + + * tree-mudflap.c (mf_build_check_statement_for): Use build_call_expr. + (mx_register_decls): Likewise. + (mudflap_register_call): Likewise. + (mudflap_finish_file): Likewise. + + * ipa-prop.c (ipa_callsite_compute_count): Use new CALL_EXPR accessors. + (ipa_callsite_compute_param): Likewise. + + * tree-vect-patterns.c (vect_recog_pow_pattern): Use new CALL_EXPR + accessors and constructor. + + * tree-nested.c (convert_nl_goto_reference): Use new CALL_EXPR + accessors and constructor. + (convert_tramp_reference): Likewise. + (convert_call_expr): Likewise. + (finalize_nesting_tree_1): Likewise. + + * tree-ssa.c (tree_ssa_useless_type_conversion): Use new CALL_EXPR + accessors. + + * tree-ssa-loop-prefetch.c (issue_prefetch_ref): Use build_call_expr. + + * tree-inline.c (initialize_inlined_parameters): Pass entire + CALL_EXPR as parameter instead of arglist. Use new CALL_EXPR + accessors. + (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_OPERAND_LENGTH instead of TREE_CODE_LENGTH. + (vectorizable_reduction): Likewise. + (vectorizable_call): Use new CALL_EXPR iterators. + (vectorizable_conversion): Use build_call_expr. + (vectorizable_operation): Use TREE_OPERAND_LENGTH. + (vect_gen_widened_results_half): Use build_call_expr. + (vect_setup_realignment): Likewise. + (vectorizable_live_operation): Use TREE_OPERAND_LENGTH. + + * tree-object-size.c (alloc_object_size): Use new CALL_EXPR accessors. + (pass_through_call): Likewise. + (compute_object_sizes): Likewise. Use fold_call_expr instead of + fold_builtin. + + * tree-profile.c (tree_gen_interval_profiler): Use build_call_expr. + (tree_gen_pow2_profiler): Likewise. + (tree_gen_one_value_profiler): Likewise. + (tree_gen_ic_func_profiler): Likewise. + (tree_gen_average_profiler): Likewise. + (tree_gen_ior_profiler): Likewise. + + * tree-ssa-structalias.c (get_constraint_for): Add case tcc_vl_exp. + (find_func_aliases): Use new CALL_EXPR accessors. Add case + tcc_vl_exp. Use TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH. + + * tree-ssa-reassoc.c (get_rank): Use TREE_OPERAND_LENGTH instead + of TREE_CODE_LENGTH. + + * stmt.c (warn_if_unused_value): Use TREE_OPERAND_LENGTH instead + of TREE_CODE_LENGTH. + + * convert.c (convert_to_real): Use new CALL_EXPR accessors and + constructor. + (convert_to_integer): Likewise. + + * tree-ssa-operands.c (get_call_expr_operands): Use new CALL_EXPR + accessors. + +2007-02-15 Sandra Loosemore <sandra@codesourcery.com> + Brooks Moses <brooks.moses@codesourcery.com> + Lee Millward <lee.millward@codesourcery.com> + + * config/alpha/alpha.c (alpha_expand_builtin): Use new CALL_EXPR + accessors. + * config/frv/frv.c (frv_expand_builtin): Likewise. + * config/s390/s390.c (s390_expand_builtin): Likewise. + + * config/sparc/sparc.c (sparc_gimplify_va_arg): Use build_call_expr. + (sparc_expand_builtin): Use new CALL_EXPR accessors. + + * config/i386/i386.c (ix86_function_ok_for_sibcall): Likewise. + (ix86_expand_binop_builtin): Pass entire CALL_EXPR as parameter + instead of arglist. Use new CALL_EXPR accessors on it. Fix callers. + (ix86_expand_store_builtin): Likewise. + (ix86_expand_unop_builtin): Likewise. + (ix86_expand_unop1_builtin): Likewise. + (ix86_expand_sse_compare): Likewise. + (ix86_expand_sse_comi): Likewise. + (ix86_expand_vec_init_builtin): Likewise. + (ix86_expand_vec_ext_builtin): Likewise. + (ix86_expand_vec_set_builtin): Likewise. + (ix86_expand_builtin): Use new CALL_EXPR accessors. + + * config/sh/sh.c (sh_expand_builtin): Use new CALL_EXPR accessors. + * config/c4x/c4x.c (c4x_expand_builtin): Likewise. + + * config/iq2000/iq2000.c (expand_one_builtin): Pass entire CALL_EXPR + instead of arglist. Use new CALL_EXPR accessors. Fix callers. + (iq2000_expand_builtin): Use new CALL_EXPR accessors. + + * config/rs6000/rs6000-c.c (altivec_build_resolved_builtin): Use + build_call_expr. + * config/rs6000/rs6000.c (rs6000_gimplify_va_arg): Likewise. + (rs6000_expand_unop_builtin): Pass entire CALL_EXPR instead of + arglist. Use new CALL_EXPR accessors. Fix callers. + (altivec_expand_abs_builtin): Likewise. + (rs6000_expand_binop_builtin): Likewise. + (altivec_expand_predicate_builtin): Likewise. + (altivec_expand_lv_builtin): Likewise. + (spe_expand_stv_builtin): Likewise. + (altivec_expand_stv_builtin): Likewise. + (rs6000_expand_ternop_builtin): Likewise. + (altivec_expand_ld_builtin): Use new CALL_EXPR accessors. + (altivec_expand_st_builtin): Likewise. + (altivec_expand_dst_builtin): Likewise. + (altivec_expand_vec_init_builtin): Pass entire CALL_EXPR instead of + arglist. Use new CALL_EXPR accessors. Fix callers. + (altivec_expand_vec_set_builtin): Likewise. + (altivec_expand_vec_ext_builtin): Likewise. + (altivec_expand_builtin): Use new CALL_EXPR accessors. + (spe_expand_builtin): Likewise. + (spe_expand_predicate_builtin): Pass entire CALL_EXPR instead of + arglist. Use new CALL_EXPR accessors. Fix callers. + (spe_expand_evsel_builtin): Likewise. + (rs6000_expand_builtin): Use new CALL_EXPR accessors. VCFUX and + FCFSX cases must construct whole new CALL_EXPR, not just arglist. + + * config/arm/arm.c (arm_expand_binop_builtin): Pass entire CALL_EXPR + instead of arglist. Use new CALL_EXPR accessors. Fix callers. + (arm_expand_unop_builtin): Likewise. + (arm_expand_builtin): Use new CALL_EXPR accessors. + + * config/mips/mips.c (mips_expand_builtin): Use new CALL_EXPR + accessors. + + * config/bfin/bfin.c (bfin_expand_binop_builtin): Pass entire CALL_EXPR + instead of arglist. Use new CALL_EXPR accessors. Fix callers. + (bfin_expand_unop_builtin): Likewise. + (bfin_expand_builtin): Use new CALL_EXPR accessors. + +2007-02-15 Sandra Loosemore <sandra@codesourcery.com> + Brooks Moses <brooks.moses@codesourcery.com> + Lee Millward <lee.millward@codesourcery.com> + + * c-semantics.c (build_stmt): Add internal diagnostic check. + + * c-pretty-print.c (pp_c_postfix_expression): Use new CALL_EXPR + accessors. Print arguments explicitly instead of as a list. + + * c-typeck.c (build_function_call): Use new CALL_EXPR constructors. + + * c-omp.c (c_finish_omp_barrier): Use build_call_expr. + (c_finish_omp_flish): Likewise. + + * c-common.c (verify_tree): Use new CALL_EXPR accessors. Traverse + arguments explicitly instead of as a list. Use TREE_OPERAND_LENGTH + instead of TREE_CODE_LENGTH. + (check_function_arguments_recurse): Use new CALL_EXPR accessors. + (c_warn_unused_result): Likewise. + 2007-02-15 Manuel Lopez-Ibanez <manu@gcc.gnu.org> PR c/26494 diff --git a/gcc/builtins.c b/gcc/builtins.c index 8e9d9e4c484..ac1e1b4a058 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -105,7 +105,7 @@ static rtx expand_builtin_next_arg (void); static rtx expand_builtin_va_start (tree); static rtx expand_builtin_va_end (tree); static rtx expand_builtin_va_copy (tree); -static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode); +static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode); static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode); static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode); static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode); @@ -114,21 +114,27 @@ static rtx expand_builtin_strncat (tree, rtx, enum machine_mode); static rtx expand_builtin_strspn (tree, rtx, enum machine_mode); static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode); static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode); -static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int); -static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode); -static rtx expand_builtin_bcopy (tree); +static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode); +static rtx expand_builtin_mempcpy_args (tree, tree, tree, tree, rtx, + enum machine_mode, int); +static rtx expand_builtin_memmove (tree, rtx, enum machine_mode, int); +static rtx expand_builtin_memmove_args (tree, tree, tree, tree, rtx, + enum machine_mode, int); +static rtx expand_builtin_bcopy (tree, int); static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode); +static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx, enum machine_mode); static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode); static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode); static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode); static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode); -static rtx expand_builtin_memset (tree, rtx, enum machine_mode, tree); +static rtx expand_builtin_memset (tree, rtx, enum machine_mode); +static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree); static rtx expand_builtin_bzero (tree); static rtx expand_builtin_strlen (tree, rtx, enum machine_mode); -static rtx expand_builtin_strstr (tree, tree, rtx, enum machine_mode); -static rtx expand_builtin_strpbrk (tree, tree, rtx, enum machine_mode); -static rtx expand_builtin_strchr (tree, tree, rtx, enum machine_mode); -static rtx expand_builtin_strrchr (tree, tree, rtx, enum machine_mode); +static rtx expand_builtin_strstr (tree, rtx, enum machine_mode); +static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode); +static rtx expand_builtin_strchr (tree, rtx, enum machine_mode); +static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode); static rtx expand_builtin_alloca (tree, rtx); static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab); static rtx expand_builtin_frame_address (tree, tree); @@ -139,10 +145,13 @@ static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode); static tree stabilize_va_list (tree, int); static rtx expand_builtin_expect (tree, rtx); static tree fold_builtin_constant_p (tree); +static tree fold_builtin_expect (tree); static tree fold_builtin_classify_type (tree); static tree fold_builtin_strlen (tree); static tree fold_builtin_inf (tree, int); static tree fold_builtin_nan (tree, tree, int); +static tree rewrite_call_expr (tree, int, tree, int, ...); +static bool validate_arg (tree, enum tree_code code); static bool integer_valued_real_p (tree); static tree fold_trunc_transparent_mathfn (tree, tree); static bool readonly_data_expr (tree); @@ -150,8 +159,8 @@ static rtx expand_builtin_fabs (tree, rtx, rtx); static rtx expand_builtin_signbit (tree, rtx); static tree fold_builtin_sqrt (tree, tree); static tree fold_builtin_cbrt (tree, tree); -static tree fold_builtin_pow (tree, tree, tree); -static tree fold_builtin_powi (tree, tree, tree); +static tree fold_builtin_pow (tree, tree, tree, tree); +static tree fold_builtin_powi (tree, tree, tree, tree); static tree fold_builtin_cos (tree, tree, tree); static tree fold_builtin_cosh (tree, tree, tree); static tree fold_builtin_tan (tree, tree); @@ -161,42 +170,49 @@ static tree fold_builtin_ceil (tree, tree); static tree fold_builtin_round (tree, tree); static tree fold_builtin_int_roundingfn (tree, tree); static tree fold_builtin_bitop (tree, tree); -static tree fold_builtin_memory_op (tree, tree, bool, int); -static tree fold_builtin_strchr (tree, tree); -static tree fold_builtin_memcmp (tree); -static tree fold_builtin_strcmp (tree); -static tree fold_builtin_strncmp (tree); +static tree fold_builtin_memory_op (tree, tree, tree, tree, bool, int); +static tree fold_builtin_strchr (tree, tree, tree); +static tree fold_builtin_memcmp (tree, tree, tree); +static tree fold_builtin_strcmp (tree, tree); +static tree fold_builtin_strncmp (tree, tree, tree); static tree fold_builtin_signbit (tree, tree); -static tree fold_builtin_copysign (tree, tree, tree); +static tree fold_builtin_copysign (tree, tree, tree, tree); static tree fold_builtin_isascii (tree); static tree fold_builtin_toascii (tree); static tree fold_builtin_isdigit (tree); static tree fold_builtin_fabs (tree, tree); static tree fold_builtin_abs (tree, tree); -static tree fold_builtin_unordered_cmp (tree, tree, enum tree_code, +static tree fold_builtin_unordered_cmp (tree, tree, tree, enum tree_code, enum tree_code); +static tree fold_builtin_n (tree, tree *, int, bool); +static tree fold_builtin_0 (tree, bool); static tree fold_builtin_1 (tree, tree, bool); - -static tree fold_builtin_strpbrk (tree, tree); -static tree fold_builtin_strstr (tree, tree); -static tree fold_builtin_strrchr (tree, tree); -static tree fold_builtin_strcat (tree); -static tree fold_builtin_strncat (tree); -static tree fold_builtin_strspn (tree); -static tree fold_builtin_strcspn (tree); -static tree fold_builtin_sprintf (tree, int); +static tree fold_builtin_2 (tree, tree, tree, bool); +static tree fold_builtin_3 (tree, tree, tree, tree, bool); +static tree fold_builtin_4 (tree, tree, tree, tree, tree, bool); +static tree fold_builtin_varargs (tree, tree, bool); + +static tree fold_builtin_strpbrk (tree, tree, tree); +static tree fold_builtin_strstr (tree, tree, tree); +static tree fold_builtin_strrchr (tree, tree, tree); +static tree fold_builtin_strcat (tree, tree); +static tree fold_builtin_strncat (tree, tree, tree); +static tree fold_builtin_strspn (tree, tree); +static tree fold_builtin_strcspn (tree, tree); +static tree fold_builtin_sprintf (tree, tree, tree, int); static rtx expand_builtin_object_size (tree); static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode, enum built_in_function); static void maybe_emit_chk_warning (tree, enum built_in_function); static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function); -static tree fold_builtin_object_size (tree); -static tree fold_builtin_strcat_chk (tree, tree); -static tree fold_builtin_strncat_chk (tree, tree); +static tree fold_builtin_object_size (tree, tree); +static tree fold_builtin_strcat_chk (tree, tree, tree, tree); +static tree fold_builtin_strncat_chk (tree, tree, tree, tree, tree); static tree fold_builtin_sprintf_chk (tree, enum built_in_function); -static tree fold_builtin_printf (tree, tree, bool, enum built_in_function); -static tree fold_builtin_fprintf (tree, tree, bool, enum built_in_function); +static tree fold_builtin_printf (tree, tree, tree, bool, enum built_in_function); +static tree fold_builtin_fprintf (tree, tree, tree, tree, bool, + enum built_in_function); static bool init_target_chars (void); static unsigned HOST_WIDE_INT target_newline; @@ -387,7 +403,7 @@ c_strlen (tree src, int only_value) src = string_constant (src, &offset_node); if (src == 0) - return 0; + return NULL_TREE; max = TREE_STRING_LENGTH (src) - 1; ptr = TREE_STRING_POINTER (src); @@ -401,7 +417,7 @@ c_strlen (tree src, int only_value) for (i = 0; i < max; i++) if (ptr[i] == 0) - return 0; + return NULL_TREE; /* We don't know the starting offset, but we do know that the string has no internal zero bytes. We can assume that the offset falls @@ -427,7 +443,7 @@ c_strlen (tree src, int only_value) if (offset < 0 || offset > max) { warning (0, "offset outside bounds of constant string"); - return 0; + return NULL_TREE; } /* Use strlen to search for the first zero byte. Since any strings @@ -840,17 +856,16 @@ expand_builtin_longjmp (rtx buf_addr, rtx value) and the address of the save area. */ static rtx -expand_builtin_nonlocal_goto (tree arglist) +expand_builtin_nonlocal_goto (tree exp) { tree t_label, t_save_area; rtx r_label, r_save_area, r_fp, r_sp, insn; - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) + if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) return NULL_RTX; - t_label = TREE_VALUE (arglist); - arglist = TREE_CHAIN (arglist); - t_save_area = TREE_VALUE (arglist); + t_label = CALL_EXPR_ARG (exp, 0); + t_save_area = CALL_EXPR_ARG (exp, 1); r_label = expand_normal (t_label); r_label = convert_memory_address (Pmode, r_label); @@ -950,31 +965,29 @@ expand_builtin_update_setjmp_buf (rtx buf_addr) effects. */ static void -expand_builtin_prefetch (tree arglist) +expand_builtin_prefetch (tree exp) { tree arg0, arg1, arg2; + int nargs; rtx op0, op1, op2; - if (!validate_arglist (arglist, POINTER_TYPE, 0)) + if (!validate_arglist (exp, POINTER_TYPE, 0)) return; - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); + /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to zero (read) and argument 2 (locality) defaults to 3 (high degree of locality). */ - if (TREE_CHAIN (arglist)) - { - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - if (TREE_CHAIN (TREE_CHAIN (arglist))) - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); - else - arg2 = build_int_cst (NULL_TREE, 3); - } + nargs = call_expr_nargs (exp); + if (nargs > 1) + arg1 = CALL_EXPR_ARG (exp, 1); else - { - arg1 = integer_zero_node; - arg2 = build_int_cst (NULL_TREE, 3); - } + arg1 = integer_zero_node; + if (nargs > 2) + arg2 = CALL_EXPR_ARG (exp, 2); + else + arg2 = build_int_cst (NULL_TREE, 3); /* Argument 0 is an address. */ op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL); @@ -1614,14 +1627,13 @@ type_to_class (tree type) } } -/* Expand a call to __builtin_classify_type with arguments found in - ARGLIST. */ +/* Expand a call EXP to __builtin_classify_type. */ static rtx -expand_builtin_classify_type (tree arglist) +expand_builtin_classify_type (tree exp) { - if (arglist != 0) - return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist)))); + if (call_expr_nargs (exp)) + return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))); return GEN_INT (no_type_class); } @@ -1725,7 +1737,7 @@ mathfn_built_in (tree type, enum built_in_function fn) CASE_MATHFN (BUILT_IN_YN) default: - return 0; + return NULL_TREE; } if (TYPE_MAIN_VARIANT (type) == double_type_node) @@ -1735,7 +1747,7 @@ mathfn_built_in (tree type, enum built_in_function fn) else if (TYPE_MAIN_VARIANT (type) == long_double_type_node) return implicit_built_in_decls[fcodel]; else - return 0; + return NULL_TREE; } /* If errno must be maintained, expand the RTL to check if the result, @@ -1754,7 +1766,7 @@ expand_errno_check (tree exp, rtx target) #ifdef TARGET_EDOM /* If this built-in doesn't throw an exception, set errno directly. */ - if (TREE_NOTHROW (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) + if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0))) { #ifdef GEN_ERRNO_RTX rtx errno_rtx = GEN_ERRNO_RTX; @@ -1776,10 +1788,9 @@ expand_errno_check (tree exp, rtx target) emit_label (lab); } - /* Expand a call to one of the builtin math functions (sqrt, exp, or log). - Return 0 if a normal call should be emitted rather than expanding the - function in-line. EXP is the expression that is a call to the builtin + Return NULL_RTX if a normal call should be emitted rather than expanding + the function in-line. EXP is the expression that is a call to the builtin function; if convenient, the result should be placed in TARGET. SUBTARGET may be used as the target for computing one of EXP's operands. */ @@ -1789,15 +1800,14 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget) optab builtin_optab; rtx op0, insns, before_call; tree fndecl = get_callee_fndecl (exp); - tree arglist = TREE_OPERAND (exp, 1); enum machine_mode mode; bool errno_set = false; tree arg, narg; - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) + return NULL_RTX; - arg = TREE_VALUE (arglist); + arg = CALL_EXPR_ARG (exp, 0); switch (DECL_FUNCTION_CODE (fndecl)) { @@ -1869,8 +1879,7 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget) if (narg != arg) { arg = narg; - arglist = build_tree_list (NULL_TREE, arg); - exp = build_function_call_expr (fndecl, arglist); + exp = build_call_expr (fndecl, 1, arg); } op0 = expand_expr (arg, subtarget, VOIDmode, 0); @@ -1946,7 +1955,7 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget) } /* Expand a call to the builtin binary math functions (pow and atan2). - Return 0 if a normal call should be emitted rather than expanding the + Return NULL_RTX if a normal call should be emitted rather than expanding the function in-line. EXP is the expression that is a call to the builtin function; if convenient, the result should be placed in TARGET. SUBTARGET may be used as the target for computing one of EXP's @@ -1959,22 +1968,21 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget) rtx op0, op1, insns; int op1_type = REAL_TYPE; tree fndecl = get_callee_fndecl (exp); - tree arglist = TREE_OPERAND (exp, 1); - tree arg0, arg1, temp, narg; + tree arg0, arg1, narg; enum machine_mode mode; bool errno_set = true; bool stable = true; - if ((DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXP) - || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPF) - || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL)) + if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXP + || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPF + || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL) op1_type = INTEGER_TYPE; - if (!validate_arglist (arglist, REAL_TYPE, op1_type, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE)) + return NULL_RTX; - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); switch (DECL_FUNCTION_CODE (fndecl)) { @@ -1998,7 +2006,7 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget) /* Before working hard, check whether the instruction is available. */ if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) - return 0; + return NULL_RTX; target = gen_reg_rtx (mode); @@ -2010,24 +2018,17 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget) if (narg != arg1) { arg1 = narg; - temp = build_tree_list (NULL_TREE, narg); stable = false; } - else - temp = TREE_CHAIN (arglist); - narg = builtin_save_expr (arg0); if (narg != arg0) { arg0 = narg; - arglist = tree_cons (NULL_TREE, narg, temp); stable = false; } - else if (! stable) - arglist = tree_cons (NULL_TREE, arg0, temp); if (! stable) - exp = build_function_call_expr (fndecl, arglist); + exp = build_call_expr (fndecl, 2, arg0, arg1); op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL); op1 = expand_normal (arg1); @@ -2060,7 +2061,7 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget) } /* Expand a call to the builtin sin and cos math functions. - Return 0 if a normal call should be emitted rather than expanding the + Return NULL_RTX if a normal call should be emitted rather than expanding the function in-line. EXP is the expression that is a call to the builtin function; if convenient, the result should be placed in TARGET. SUBTARGET may be used as the target for computing one of EXP's @@ -2072,14 +2073,13 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget) optab builtin_optab; rtx op0, insns; tree fndecl = get_callee_fndecl (exp); - tree arglist = TREE_OPERAND (exp, 1); enum machine_mode mode; tree arg, narg; - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) + return NULL_RTX; - arg = TREE_VALUE (arglist); + arg = CALL_EXPR_ARG (exp, 0); switch (DECL_FUNCTION_CODE (fndecl)) { @@ -2118,8 +2118,7 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget) if (narg != arg) { arg = narg; - arglist = build_tree_list (NULL_TREE, arg); - exp = build_function_call_expr (fndecl, arglist); + exp = build_call_expr (fndecl, 1, arg); } op0 = expand_expr (arg, subtarget, VOIDmode, 0); @@ -2185,15 +2184,14 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) enum insn_code icode; rtx op0; tree fndecl = get_callee_fndecl (exp); - tree arglist = TREE_OPERAND (exp, 1); enum machine_mode mode; bool errno_set = false; tree arg, narg; - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) + return NULL_RTX; - arg = TREE_VALUE (arglist); + arg = CALL_EXPR_ARG (exp, 0); switch (DECL_FUNCTION_CODE (fndecl)) { @@ -2232,8 +2230,7 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) if (narg != arg) { arg = narg; - arglist = build_tree_list (NULL_TREE, arg); - exp = build_function_call_expr (fndecl, arglist); + exp = build_call_expr (fndecl, 1, arg); } op0 = expand_expr (arg, subtarget, VOIDmode, 0); @@ -2253,7 +2250,7 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) } /* Expand a call to the builtin sincos math function. - Return 0 if a normal call should be emitted rather than expanding the + Return NULL_RTX if a normal call should be emitted rather than expanding the function in-line. EXP is the expression that is a call to the builtin function. */ @@ -2261,18 +2258,17 @@ static rtx expand_builtin_sincos (tree exp) { rtx op0, op1, op2, target1, target2; - tree arglist = TREE_OPERAND (exp, 1); enum machine_mode mode; tree arg, sinp, cosp; int result; - if (!validate_arglist (arglist, REAL_TYPE, - POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, REAL_TYPE, + POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) + return NULL_RTX; - arg = TREE_VALUE (arglist); - sinp = TREE_VALUE (TREE_CHAIN (arglist)); - cosp = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg = CALL_EXPR_ARG (exp, 0); + sinp = CALL_EXPR_ARG (exp, 1); + cosp = CALL_EXPR_ARG (exp, 2); /* Make a suitable register to place result in. */ mode = TYPE_MODE (TREE_TYPE (arg)); @@ -2310,15 +2306,14 @@ static rtx expand_builtin_cexpi (tree exp, rtx target, rtx subtarget) { tree fndecl = get_callee_fndecl (exp); - tree arglist = TREE_OPERAND (exp, 1); - enum machine_mode mode; tree arg, type; + enum machine_mode mode; rtx op0, op1, op2; - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) + return NULL_RTX; - arg = TREE_VALUE (arglist); + arg = CALL_EXPR_ARG (exp, 0); type = TREE_TYPE (arg); mode = TYPE_MODE (TREE_TYPE (arg)); @@ -2337,7 +2332,7 @@ expand_builtin_cexpi (tree exp, rtx target, rtx subtarget) } else if (TARGET_HAS_SINCOS) { - tree call, narglist, fn = NULL_TREE; + tree call, fn = NULL_TREE; tree top1, top2; rtx op1a, op2a; @@ -2347,6 +2342,8 @@ expand_builtin_cexpi (tree exp, rtx target, rtx subtarget) fn = built_in_decls[BUILT_IN_SINCOS]; else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL) fn = built_in_decls[BUILT_IN_SINCOSL]; + else + gcc_unreachable (); op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1); op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1); @@ -2355,14 +2352,10 @@ expand_builtin_cexpi (tree exp, rtx target, rtx subtarget) top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a); top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a); - narglist = build_tree_list (NULL_TREE, top2); - narglist = tree_cons (NULL_TREE, top1, narglist); - narglist = tree_cons (NULL_TREE, arg, narglist); - /* Make sure not to fold the sincos call again. */ call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); - expand_normal (build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), - call, narglist, NULL_TREE)); + expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)), + call, 3, arg, top1, top2)); } else { @@ -2378,14 +2371,15 @@ expand_builtin_cexpi (tree exp, rtx target, rtx subtarget) fn = built_in_decls[BUILT_IN_CEXP]; else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL) fn = built_in_decls[BUILT_IN_CEXPL]; + else + gcc_unreachable (); narg = fold_build2 (COMPLEX_EXPR, ctype, build_real (type, dconst0), arg); /* Make sure not to fold the cexp call again. */ call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); - return expand_expr (build3 (CALL_EXPR, ctype, call, - build_tree_list (NULL_TREE, narg), - NULL_TREE), target, VOIDmode, 0); + return expand_expr (build_call_nary (ctype, call, 1, arg), + target, VOIDmode, 0); } /* Now build the proper return type. */ @@ -2409,16 +2403,15 @@ expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget) convert_optab builtin_optab; rtx op0, insns, tmp; tree fndecl = get_callee_fndecl (exp); - tree arglist = TREE_OPERAND (exp, 1); enum built_in_function fallback_fn; tree fallback_fndecl; enum machine_mode mode; tree arg, narg; - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) gcc_unreachable (); - arg = TREE_VALUE (arglist); + arg = CALL_EXPR_ARG (exp, 0); switch (DECL_FUNCTION_CODE (fndecl)) { @@ -2450,8 +2443,7 @@ expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget) if (narg != arg) { arg = narg; - arglist = build_tree_list (NULL_TREE, arg); - exp = build_function_call_expr (fndecl, arglist); + exp = build_call_expr (fndecl, 1, arg); } op0 = expand_expr (arg, subtarget, VOIDmode, 0); @@ -2477,7 +2469,7 @@ expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget) /* We shouldn't get here on targets without TARGET_C99_FUNCTIONS. ??? Perhaps convert (int)floorf(x) into (int)floor((double)x). */ gcc_assert (fallback_fndecl != NULL_TREE); - exp = build_function_call_expr (fallback_fndecl, arglist); + exp = build_call_expr (fallback_fndecl, 1, arg); tmp = expand_normal (exp); @@ -2502,18 +2494,17 @@ expand_builtin_int_roundingfn_2 (tree exp, rtx target, rtx subtarget) convert_optab builtin_optab; rtx op0, insns; tree fndecl = get_callee_fndecl (exp); - tree arglist = TREE_OPERAND (exp, 1); - enum machine_mode mode; tree arg, narg; + enum machine_mode mode; /* There's no easy way to detect the case we need to set EDOM. */ if (flag_errno_math) return NULL_RTX; - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return NULL_RTX; - - arg = TREE_VALUE (arglist); + if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) + gcc_unreachable (); + + arg = CALL_EXPR_ARG (exp, 0); switch (DECL_FUNCTION_CODE (fndecl)) { @@ -2539,8 +2530,7 @@ expand_builtin_int_roundingfn_2 (tree exp, rtx target, rtx subtarget) if (narg != arg) { arg = narg; - arglist = build_tree_list (NULL_TREE, arg); - exp = build_function_call_expr (fndecl, arglist); + exp = build_call_expr (fndecl, 1, arg); } op0 = expand_expr (arg, subtarget, VOIDmode, 0); @@ -2771,7 +2761,7 @@ expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n) return result; } -/* Expand a call to the pow built-in mathematical function. Return 0 if +/* Expand a call to the pow built-in mathematical function. Return NULL_RTX if a normal call should be emitted rather than expanding the function in-line. EXP is the expression that is a call to the builtin function; if convenient, the result should be placed in TARGET. */ @@ -2779,19 +2769,19 @@ expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n) static rtx expand_builtin_pow (tree exp, rtx target, rtx subtarget) { - tree arg0, arg1, fn, narg0, narglist; - tree arglist = TREE_OPERAND (exp, 1); + tree arg0, arg1; + tree fn, narg0; tree type = TREE_TYPE (exp); REAL_VALUE_TYPE cint, c, c2; HOST_WIDE_INT n; rtx op, op2; enum machine_mode mode = TYPE_MODE (type); - if (! validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) - return 0; + if (! validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE)) + return NULL_RTX; - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); if (TREE_CODE (arg1) != REAL_CST || TREE_OVERFLOW (arg1)) @@ -2820,7 +2810,6 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget) } narg0 = builtin_save_expr (arg0); - narglist = build_tree_list (NULL_TREE, narg0); /* If the exponent is not integer valued, check if it is half of an integer. In this case we can expand to sqrt (x) * x**(n/2). */ @@ -2836,7 +2825,7 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget) && powi_cost (n/2) <= POWI_MAX_MULTS) || n == 1)) { - tree call_expr = build_function_call_expr (fn, narglist); + tree call_expr = build_call_expr (fn, 1, narg0); op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0); if (n != 1) { @@ -2877,7 +2866,7 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget) && powi_cost (n/3) <= POWI_MAX_MULTS) || n == 1)) { - tree call_expr = build_function_call_expr (fn, narglist); + tree call_expr = build_call_expr (fn, 1,narg0); op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0); if (abs (n) % 3 == 2) op = expand_simple_binop (mode, MULT, op, op, op, @@ -2903,7 +2892,7 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget) return expand_builtin_mathfn_2 (exp, target, subtarget); } -/* Expand a call to the powi built-in mathematical function. Return 0 if +/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if a normal call should be emitted rather than expanding the function in-line. EXP is the expression that is a call to the builtin function; if convenient, the result should be placed in TARGET. */ @@ -2911,17 +2900,16 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget) static rtx expand_builtin_powi (tree exp, rtx target, rtx subtarget) { - tree arglist = TREE_OPERAND (exp, 1); tree arg0, arg1; rtx op0, op1; enum machine_mode mode; enum machine_mode mode2; - if (! validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE)) + return NULL_RTX; - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); mode = TYPE_MODE (TREE_TYPE (exp)); /* Handle constant power. */ @@ -2947,7 +2935,7 @@ expand_builtin_powi (tree exp, rtx target, rtx subtarget) /* Emit a libcall to libgcc. */ - /* Mode of the 2nd argument must match that of an int. */ + /* Mode of the 2nd argument must match that of an int. */ mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0); if (target == NULL_RTX) @@ -2967,20 +2955,21 @@ expand_builtin_powi (tree exp, rtx target, rtx subtarget) return target; } -/* Expand expression EXP which is a call to the strlen builtin. Return 0 - if we failed the caller should emit a normal call, otherwise +/* Expand expression EXP which is a call to the strlen builtin. Return + NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient. */ static rtx -expand_builtin_strlen (tree arglist, rtx target, +expand_builtin_strlen (tree exp, rtx target, enum machine_mode target_mode) { - if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE)) + return NULL_RTX; else { rtx pat; - tree len, src = TREE_VALUE (arglist); + tree len; + tree src = CALL_EXPR_ARG (exp, 0); rtx result, src_reg, char_rtx, before_strlen; enum machine_mode insn_mode = target_mode, char_mode; enum insn_code icode = CODE_FOR_nothing; @@ -3007,7 +2996,7 @@ expand_builtin_strlen (tree arglist, rtx target, /* If SRC is not a pointer type, don't do this operation inline. */ if (align == 0) - return 0; + return NULL_RTX; /* Bail out if we can't compute strlen in the right mode. */ while (insn_mode != VOIDmode) @@ -3019,7 +3008,7 @@ expand_builtin_strlen (tree arglist, rtx target, insn_mode = GET_MODE_WIDER_MODE (insn_mode); } if (insn_mode == VOIDmode) - return 0; + return NULL_RTX; /* Make a place to write the result of the instruction. */ result = target; @@ -3047,7 +3036,7 @@ expand_builtin_strlen (tree arglist, rtx target, pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg), char_rtx, GEN_INT (align)); if (! pat) - return 0; + return NULL_RTX; emit_insn (pat); /* Now that we are assured of success, expand the source. */ @@ -3075,70 +3064,78 @@ expand_builtin_strlen (tree arglist, rtx target, } } -/* Expand a call to the strstr builtin. Return 0 if we failed the +/* Expand a call to the strstr builtin. Return NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE if that's convenient). */ static rtx -expand_builtin_strstr (tree arglist, tree type, rtx target, enum machine_mode mode) +expand_builtin_strstr (tree exp, rtx target, enum machine_mode mode) { - if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) { - tree result = fold_builtin_strstr (arglist, type); + tree type = TREE_TYPE (exp); + tree result = fold_builtin_strstr (CALL_EXPR_ARG (exp, 0), + CALL_EXPR_ARG (exp, 1), type); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); } - return 0; + return NULL_RTX; } -/* Expand a call to the strchr builtin. Return 0 if we failed the +/* Expand a call to the strchr builtin. Return NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE if that's convenient). */ static rtx -expand_builtin_strchr (tree arglist, tree type, rtx target, enum machine_mode mode) +expand_builtin_strchr (tree exp, rtx target, enum machine_mode mode) { - if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) { - tree result = fold_builtin_strchr (arglist, type); + tree type = TREE_TYPE (exp); + tree result = fold_builtin_strchr (CALL_EXPR_ARG (exp, 0), + CALL_EXPR_ARG (exp, 1), type); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); /* FIXME: Should use strchrM optab so that ports can optimize this. */ } - return 0; + return NULL_RTX; } -/* Expand a call to the strrchr builtin. Return 0 if we failed the +/* Expand a call to the strrchr builtin. Return NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE if that's convenient). */ static rtx -expand_builtin_strrchr (tree arglist, tree type, rtx target, enum machine_mode mode) +expand_builtin_strrchr (tree exp, rtx target, enum machine_mode mode) { - if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) { - tree result = fold_builtin_strrchr (arglist, type); + tree type = TREE_TYPE (exp); + tree result = fold_builtin_strrchr (CALL_EXPR_ARG (exp, 0), + CALL_EXPR_ARG (exp, 1), type); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); } - return 0; + return NULL_RTX; } -/* Expand a call to the strpbrk builtin. Return 0 if we failed the +/* Expand a call to the strpbrk builtin. Return NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE if that's convenient). */ static rtx -expand_builtin_strpbrk (tree arglist, tree type, rtx target, enum machine_mode mode) +expand_builtin_strpbrk (tree exp, rtx target, enum machine_mode mode) { - if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) { - tree result = fold_builtin_strpbrk (arglist, type); + tree type = TREE_TYPE (exp); + tree result = fold_builtin_strpbrk (CALL_EXPR_ARG (exp, 0), + CALL_EXPR_ARG (exp, 1), type); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); } - return 0; + return NULL_RTX; } /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE) @@ -3158,29 +3155,31 @@ builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset, return c_readstr (str + offset, mode); } -/* Expand a call to the memcpy builtin, with arguments in ARGLIST. - Return 0 if we failed, the caller should emit a normal call, +/* Expand a call EXP to the memcpy builtin. + Return NULL_RTX if we failed, the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE if that's convenient). */ + static rtx expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode) { tree fndecl = get_callee_fndecl (exp); - tree arglist = TREE_OPERAND (exp, 1); - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + + if (!validate_arglist (exp, + POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + return NULL_RTX; else { - tree dest = TREE_VALUE (arglist); - tree src = TREE_VALUE (TREE_CHAIN (arglist)); - tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + tree dest = CALL_EXPR_ARG (exp, 0); + tree src = CALL_EXPR_ARG (exp, 1); + tree len = CALL_EXPR_ARG (exp, 2); const char *src_str; unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); unsigned int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); rtx dest_mem, src_mem, dest_addr, len_rtx; - tree result = fold_builtin_memory_op (arglist, TREE_TYPE (TREE_TYPE (fndecl)), + tree result = fold_builtin_memory_op (dest, src, len, + TREE_TYPE (TREE_TYPE (fndecl)), false, /*endp=*/0); HOST_WIDE_INT expected_size = -1; unsigned int expected_align = 0; @@ -3198,12 +3197,12 @@ expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode) /* If DEST is not a pointer type, call the normal function. */ if (dest_align == 0) - return 0; + return NULL_RTX; /* If either SRC is not a pointer type, don't do this operation in-line. */ if (src_align == 0) - return 0; + return NULL_RTX; stringop_block_profile (exp, &expected_align, &expected_size); if (expected_align < dest_align) @@ -3248,8 +3247,8 @@ expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode) } } -/* Expand a call to the mempcpy builtin, with arguments in ARGLIST. - Return 0 if we failed; the caller should emit a normal call, +/* Expand a call EXP to the mempcpy builtin. + Return NULL_RTX if we failed; the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE if that's convenient). If ENDP is 0 return the destination pointer, if ENDP is 1 return the end pointer ala @@ -3257,34 +3256,51 @@ expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode) stpcpy. */ static rtx -expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode mode, - int endp) +expand_builtin_mempcpy(tree exp, rtx target, enum machine_mode mode) { - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; - /* If return value is ignored, transform mempcpy into memcpy. */ - else if (target == const0_rtx) + if (!validate_arglist (exp, + POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + return NULL_RTX; + else + { + tree dest = CALL_EXPR_ARG (exp, 0); + tree src = CALL_EXPR_ARG (exp, 1); + tree len = CALL_EXPR_ARG (exp, 2); + return expand_builtin_mempcpy_args (dest, src, len, + TREE_TYPE (exp), + target, mode, /*endp=*/ 1); + } +} + +/* Helper function to do the actual work for expand_builtin_mempcpy. The + arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out + so that this can also be called without constructing an actual CALL_EXPR. + TYPE is the return type of the call. The other arguments and return value + are the same as for expand_builtin_mempcpy. */ + +static rtx +expand_builtin_mempcpy_args (tree dest, tree src, tree len, tree type, + rtx target, enum machine_mode mode, int endp) +{ + /* If return value is ignored, transform mempcpy into memcpy. */ + if (target == const0_rtx) { tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; if (!fn) - return 0; + return NULL_RTX; - return expand_expr (build_function_call_expr (fn, arglist), + return expand_expr (build_call_expr (fn, 3, dest, src, len), target, mode, EXPAND_NORMAL); } else { - tree dest = TREE_VALUE (arglist); - tree src = TREE_VALUE (TREE_CHAIN (arglist)); - tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); const char *src_str; unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); unsigned int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); rtx dest_mem, src_mem, len_rtx; - tree result = fold_builtin_memory_op (arglist, type, false, endp); + tree result = fold_builtin_memory_op (dest, src, len, type, false, endp); if (result) { @@ -3300,11 +3316,11 @@ expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode m /* If either SRC or DEST is not a pointer type, don't do this operation in-line. */ if (dest_align == 0 || src_align == 0) - return 0; + return NULL_RTX; /* If LEN is not constant, call the normal function. */ if (! host_integerp (len, 1)) - return 0; + return NULL_RTX; len_rtx = expand_normal (len); src_str = c_getstr (src); @@ -3343,68 +3359,81 @@ expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode m return dest_mem; } - return 0; + return NULL_RTX; } } -/* Expand expression EXP, which is a call to the memmove builtin. Return 0 - if we failed; the caller should emit a normal call. */ +/* Expand expression EXP, which is a call to the memmove builtin. Return + NULL_RTX if we failed; the caller should emit a normal call. */ static rtx -expand_builtin_memmove (tree arglist, tree type, rtx target, - enum machine_mode mode) +expand_builtin_memmove (tree exp, rtx target, enum machine_mode mode, int ignore) { - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, + POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + return NULL_RTX; else { - tree result = fold_builtin_memory_op (arglist, type, false, /*endp=*/3); + tree dest = CALL_EXPR_ARG (exp, 0); + tree src = CALL_EXPR_ARG (exp, 1); + tree len = CALL_EXPR_ARG (exp, 2); + return expand_builtin_memmove_args (dest, src, len, TREE_TYPE (exp), + target, mode, ignore); + } +} - if (result) +/* Helper function to do the actual work for expand_builtin_memmove. The + arguments to the builtin_memmove call DEST, SRC, and LEN are broken out + so that this can also be called without constructing an actual CALL_EXPR. + TYPE is the return type of the call. The other arguments and return value + are the same as for expand_builtin_memmove. */ + +static rtx +expand_builtin_memmove_args (tree dest, tree src, tree len, + tree type, rtx target, enum machine_mode mode, + int ignore) +{ + tree result = fold_builtin_memory_op (dest, src, len, type, ignore, /*endp=*/3); + + if (result) + { + while (TREE_CODE (result) == COMPOUND_EXPR) { - while (TREE_CODE (result) == COMPOUND_EXPR) - { - expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode, - EXPAND_NORMAL); - result = TREE_OPERAND (result, 1); - } - return expand_expr (result, target, mode, EXPAND_NORMAL); + expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode, + EXPAND_NORMAL); + result = TREE_OPERAND (result, 1); } - - /* Otherwise, call the normal function. */ - return 0; - } + return expand_expr (result, target, mode, EXPAND_NORMAL); + } + + /* Otherwise, call the normal function. */ + return NULL_RTX; } -/* Expand expression EXP, which is a call to the bcopy builtin. Return 0 - if we failed the caller should emit a normal call. */ +/* Expand expression EXP, which is a call to the bcopy builtin. Return + NULL_RTX if we failed the caller should emit a normal call. */ static rtx -expand_builtin_bcopy (tree exp) +expand_builtin_bcopy (tree exp, int ignore) { - tree arglist = TREE_OPERAND (exp, 1); tree type = TREE_TYPE (exp); - tree src, dest, size, newarglist; + tree src, dest, size; - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + if (!validate_arglist (exp, + POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) return NULL_RTX; - src = TREE_VALUE (arglist); - dest = TREE_VALUE (TREE_CHAIN (arglist)); - size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); - - /* New argument list transforming bcopy(ptr x, ptr y, int z) to - memmove(ptr y, ptr x, size_t z). This is done this way - so that if it isn't expanded inline, we fallback to - calling bcopy instead of memmove. */ + src = CALL_EXPR_ARG (exp, 0); + dest = CALL_EXPR_ARG (exp, 1); + size = CALL_EXPR_ARG (exp, 2); - newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size)); - newarglist = tree_cons (NULL_TREE, src, newarglist); - newarglist = tree_cons (NULL_TREE, dest, newarglist); - - return expand_builtin_memmove (newarglist, type, const0_rtx, VOIDmode); + /* Transform bcopy(ptr x, ptr y, int z) to memmove(ptr y, ptr x, size_t z). + This is done this way so that if it isn't expanded inline, we fall + back to calling bcopy instead of memmove. */ + return expand_builtin_memmove_args (dest, src, + fold_convert (sizetype, size), + type, const0_rtx, VOIDmode, + ignore); } #ifndef HAVE_movstr @@ -3412,7 +3441,7 @@ expand_builtin_bcopy (tree exp) # define CODE_FOR_movstr CODE_FOR_nothing #endif -/* Expand into a movstr instruction, if one is available. Return 0 if +/* Expand into a movstr instruction, if one is available. Return NULL_RTX if we failed, the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient. If ENDP is 0 return the destination pointer, if ENDP is 1 return the end pointer ala @@ -3429,7 +3458,7 @@ expand_movstr (tree dest, tree src, rtx target, int endp) const struct insn_data * data; if (!HAVE_movstr) - return 0; + return NULL_RTX; dest_mem = get_memory_rtx (dest, NULL); src_mem = get_memory_rtx (src, NULL); @@ -3474,80 +3503,81 @@ expand_movstr (tree dest, tree src, rtx target, int endp) return target; } -/* Expand expression EXP, which is a call to the strcpy builtin. Return 0 - if we failed the caller should emit a normal call, otherwise try to get - the result in TARGET, if convenient (and in mode MODE if that's +/* Expand expression EXP, which is a call to the strcpy builtin. Return + NULL_RTX if we failed the caller should emit a normal call, otherwise + try to get the result in TARGET, if convenient (and in mode MODE if that's convenient). */ static rtx -expand_builtin_strcpy (tree fndecl, tree arglist, rtx target, enum machine_mode mode) +expand_builtin_strcpy (tree fndecl, tree exp, rtx target, enum machine_mode mode) { - if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - { - tree result = fold_builtin_strcpy (fndecl, arglist, 0); - if (result) - { - while (TREE_CODE (result) == COMPOUND_EXPR) - { - expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode, - EXPAND_NORMAL); - result = TREE_OPERAND (result, 1); - } - return expand_expr (result, target, mode, EXPAND_NORMAL); - } + if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) + { + tree dest = CALL_EXPR_ARG (exp, 0); + tree src = CALL_EXPR_ARG (exp, 1); + return expand_builtin_strcpy_args (fndecl, dest, src, target, mode); + } + return NULL_RTX; +} + +/* Helper function to do the actual work for expand_builtin_strcpy. The + arguments to the builtin_strcpy call DEST and SRC are broken out + so that this can also be called without constructing an actual CALL_EXPR. + The other arguments and return value are the same as for + expand_builtin_strcpy. */ + +static rtx +expand_builtin_strcpy_args (tree fndecl, tree dest, tree src, + rtx target, enum machine_mode mode) +{ + tree result = fold_builtin_strcpy (fndecl, dest, src, 0); + if (result) + return expand_expr (result, target, mode, EXPAND_NORMAL); + return expand_movstr (dest, src, target, /*endp=*/0); - return expand_movstr (TREE_VALUE (arglist), - TREE_VALUE (TREE_CHAIN (arglist)), - target, /*endp=*/0); - } - return 0; } -/* Expand a call to the stpcpy builtin, with arguments in ARGLIST. - Return 0 if we failed the caller should emit a normal call, +/* Expand a call EXP to the stpcpy builtin. + Return NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE if that's convenient). */ static rtx expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode) { - tree arglist = TREE_OPERAND (exp, 1); + tree dst, src; + + if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) + return NULL_RTX; + + dst = CALL_EXPR_ARG (exp, 0); + src = CALL_EXPR_ARG (exp, 1); + /* If return value is ignored, transform stpcpy into strcpy. */ if (target == const0_rtx) { tree fn = implicit_built_in_decls[BUILT_IN_STRCPY]; if (!fn) - return 0; + return NULL_RTX; - return expand_expr (build_function_call_expr (fn, arglist), - target, mode, EXPAND_NORMAL); + return expand_expr (build_call_expr (fn, 2, dst, src), + target, mode, EXPAND_NORMAL); } - - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - return 0; else { - tree dst, src, len, lenp1; - tree narglist; + tree len, lenp1; rtx ret; /* Ensure we get an actual string whose length can be evaluated at compile-time, not an expression containing a string. This is because the latter will potentially produce pessimized code when used to produce the return value. */ - src = TREE_VALUE (TREE_CHAIN (arglist)); if (! c_getstr (src) || ! (len = c_strlen (src, 0))) - return expand_movstr (TREE_VALUE (arglist), - TREE_VALUE (TREE_CHAIN (arglist)), - target, /*endp=*/2); + return expand_movstr (dst, src, target, /*endp=*/2); - dst = TREE_VALUE (arglist); lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1)); - narglist = build_tree_list (NULL_TREE, lenp1); - narglist = tree_cons (NULL_TREE, src, narglist); - narglist = tree_cons (NULL_TREE, dst, narglist); - ret = expand_builtin_mempcpy (narglist, TREE_TYPE (exp), - target, mode, /*endp=*/2); + ret = expand_builtin_mempcpy_args (dst, src, lenp1, TREE_TYPE (exp), + target, mode, /*endp=*/2); if (ret) return ret; @@ -3558,8 +3588,8 @@ expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode) if (GET_CODE (len_rtx) == CONST_INT) { - ret = expand_builtin_strcpy (get_callee_fndecl (exp), - arglist, target, mode); + ret = expand_builtin_strcpy_args (get_callee_fndecl (exp), + dst, src, target, mode); if (ret) { @@ -3582,9 +3612,7 @@ expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode) } } - return expand_movstr (TREE_VALUE (arglist), - TREE_VALUE (TREE_CHAIN (arglist)), - target, /*endp=*/2); + return expand_movstr (dst, src, target, /*endp=*/2); } } @@ -3604,20 +3632,22 @@ builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset, return c_readstr (str + offset, mode); } -/* Expand expression EXP, which is a call to the strncpy builtin. Return 0 - if we failed the caller should emit a normal call. */ +/* Expand expression EXP, which is a call to the strncpy builtin. Return + NULL_RTX if we failed the caller should emit a normal call. */ static rtx expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode) { tree fndecl = get_callee_fndecl (exp); - tree arglist = TREE_OPERAND (exp, 1); - if (validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + + if (validate_arglist (exp, + POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) { - tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1); - tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); - tree result = fold_builtin_strncpy (fndecl, arglist, slen); + tree dest = CALL_EXPR_ARG (exp, 0); + tree src = CALL_EXPR_ARG (exp, 1); + tree len = CALL_EXPR_ARG (exp, 2); + tree slen = c_strlen (src, 1); + tree result = fold_builtin_strncpy (fndecl, dest, src, len, slen); if (result) { @@ -3632,7 +3662,7 @@ expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode) /* We must be passed a constant len and src parameter. */ if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1)) - return 0; + return NULL_RTX; slen = size_binop (PLUS_EXPR, slen, ssize_int (1)); @@ -3641,17 +3671,16 @@ expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode) use store_by_pieces, if it fails, punt. */ if (tree_int_cst_lt (slen, len)) { - tree dest = TREE_VALUE (arglist); unsigned int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); - const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist))); + const char *p = c_getstr (src); rtx dest_mem; if (!p || dest_align == 0 || !host_integerp (len, 1) || !can_store_by_pieces (tree_low_cst (len, 1), builtin_strncpy_read_str, (void *) p, dest_align)) - return 0; + return NULL_RTX; dest_mem = get_memory_rtx (dest, len); store_by_pieces (dest_mem, tree_low_cst (len, 1), @@ -3662,7 +3691,7 @@ expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode) return dest_mem; } } - return 0; + return NULL_RTX; } /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE) @@ -3707,194 +3736,203 @@ builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED, return force_reg (mode, target); } -/* Expand expression EXP, which is a call to the memset builtin. Return 0 - if we failed the caller should emit a normal call, otherwise try to get - the result in TARGET, if convenient (and in mode MODE if that's +/* Expand expression EXP, which is a call to the memset builtin. Return + NULL_RTX if we failed the caller should emit a normal call, otherwise + try to get the result in TARGET, if convenient (and in mode MODE if that's convenient). */ static rtx -expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode, - tree orig_exp) +expand_builtin_memset (tree exp, rtx target, enum machine_mode mode) { - if (!validate_arglist (arglist, - POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, + POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)) + return NULL_RTX; else { - tree dest = TREE_VALUE (arglist); - tree val = TREE_VALUE (TREE_CHAIN (arglist)); - tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); - tree fndecl, fn; - enum built_in_function fcode; - char c; - unsigned int dest_align; - rtx dest_mem, dest_addr, len_rtx; - HOST_WIDE_INT expected_size = -1; - unsigned int expected_align = 0; + tree dest = CALL_EXPR_ARG (exp, 0); + tree val = CALL_EXPR_ARG (exp, 1); + tree len = CALL_EXPR_ARG (exp, 2); + return expand_builtin_memset_args (dest, val, len, target, mode, exp); + } +} - dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); +/* Helper function to do the actual work for expand_builtin_memset. The + arguments to the builtin_memset call DEST, VAL, and LEN are broken out + so that this can also be called without constructing an actual CALL_EXPR. + The other arguments and return value are the same as for + expand_builtin_memset. */ - /* If DEST is not a pointer type, don't do this - operation in-line. */ - if (dest_align == 0) - return 0; +static rtx +expand_builtin_memset_args (tree dest, tree val, tree len, + rtx target, enum machine_mode mode, tree orig_exp) +{ + tree fndecl, fn; + enum built_in_function fcode; + char c; + unsigned int dest_align; + rtx dest_mem, dest_addr, len_rtx; + HOST_WIDE_INT expected_size = -1; + unsigned int expected_align = 0; - stringop_block_profile (orig_exp, &expected_align, &expected_size); - if (expected_align < dest_align) - expected_align = dest_align; + dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); - /* If the LEN parameter is zero, return DEST. */ - if (integer_zerop (len)) - { - /* Evaluate and ignore VAL in case it has side-effects. */ - expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL); - return expand_expr (dest, target, mode, EXPAND_NORMAL); - } + /* If DEST is not a pointer type, don't do this operation in-line. */ + if (dest_align == 0) + return NULL_RTX; - /* Stabilize the arguments in case we fail. */ - dest = builtin_save_expr (dest); - val = builtin_save_expr (val); - len = builtin_save_expr (len); + stringop_block_profile (orig_exp, &expected_align, &expected_size); + if (expected_align < dest_align) + expected_align = dest_align; - len_rtx = expand_normal (len); - dest_mem = get_memory_rtx (dest, len); + /* If the LEN parameter is zero, return DEST. */ + if (integer_zerop (len)) + { + /* Evaluate and ignore VAL in case it has side-effects. */ + expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL); + return expand_expr (dest, target, mode, EXPAND_NORMAL); + } - if (TREE_CODE (val) != INTEGER_CST) - { - rtx val_rtx; + /* Stabilize the arguments in case we fail. */ + dest = builtin_save_expr (dest); + val = builtin_save_expr (val); + len = builtin_save_expr (len); - val_rtx = expand_normal (val); - val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node), - val_rtx, 0); + len_rtx = expand_normal (len); + dest_mem = get_memory_rtx (dest, len); - /* Assume that we can memset by pieces if we can store the - * the coefficients by pieces (in the required modes). - * We can't pass builtin_memset_gen_str as that emits RTL. */ - c = 1; - if (host_integerp (len, 1) - && !(optimize_size && tree_low_cst (len, 1) > 1) - && can_store_by_pieces (tree_low_cst (len, 1), - builtin_memset_read_str, &c, dest_align)) - { - val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node), - val_rtx); - store_by_pieces (dest_mem, tree_low_cst (len, 1), - builtin_memset_gen_str, val_rtx, dest_align, 0); - } - else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx, - dest_align, expected_align, - expected_size)) - goto do_libcall; + if (TREE_CODE (val) != INTEGER_CST) + { + rtx val_rtx; - dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); - dest_mem = convert_memory_address (ptr_mode, dest_mem); - return dest_mem; - } + val_rtx = expand_normal (val); + val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node), + val_rtx, 0); - if (target_char_cast (val, &c)) + /* Assume that we can memset by pieces if we can store + * the coefficients by pieces (in the required modes). + * We can't pass builtin_memset_gen_str as that emits RTL. */ + c = 1; + if (host_integerp (len, 1) + && !(optimize_size && tree_low_cst (len, 1) > 1) + && can_store_by_pieces (tree_low_cst (len, 1), + builtin_memset_read_str, &c, dest_align)) + { + val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node), + val_rtx); + store_by_pieces (dest_mem, tree_low_cst (len, 1), + builtin_memset_gen_str, val_rtx, dest_align, 0); + } + else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx, + dest_align, expected_align, + expected_size)) goto do_libcall; + + dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); + dest_mem = convert_memory_address (ptr_mode, dest_mem); + return dest_mem; + } - if (c) - { - if (host_integerp (len, 1) - && !(optimize_size && tree_low_cst (len, 1) > 1) - && can_store_by_pieces (tree_low_cst (len, 1), - builtin_memset_read_str, &c, dest_align)) - store_by_pieces (dest_mem, tree_low_cst (len, 1), - builtin_memset_read_str, &c, dest_align, 0); - else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c), - dest_align, expected_align, - expected_size)) - goto do_libcall; + if (target_char_cast (val, &c)) + goto do_libcall; - dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); - dest_mem = convert_memory_address (ptr_mode, dest_mem); - return dest_mem; - } + if (c) + { + if (host_integerp (len, 1) + && !(optimize_size && tree_low_cst (len, 1) > 1) + && can_store_by_pieces (tree_low_cst (len, 1), + builtin_memset_read_str, &c, dest_align)) + store_by_pieces (dest_mem, tree_low_cst (len, 1), + builtin_memset_read_str, &c, dest_align, 0); + else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c), + dest_align, expected_align, + expected_size)) + goto do_libcall; + + dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); + dest_mem = convert_memory_address (ptr_mode, dest_mem); + return dest_mem; + } - set_mem_align (dest_mem, dest_align); - dest_addr = clear_storage_hints (dest_mem, len_rtx, - CALL_EXPR_TAILCALL (orig_exp) - ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, - expected_align, expected_size); + set_mem_align (dest_mem, dest_align); + dest_addr = clear_storage_hints (dest_mem, len_rtx, + CALL_EXPR_TAILCALL (orig_exp) + ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, + expected_align, expected_size); - if (dest_addr == 0) - { - dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX); - dest_addr = convert_memory_address (ptr_mode, dest_addr); - } + if (dest_addr == 0) + { + dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX); + dest_addr = convert_memory_address (ptr_mode, dest_addr); + } - return dest_addr; + return dest_addr; - do_libcall: - fndecl = get_callee_fndecl (orig_exp); - fcode = DECL_FUNCTION_CODE (fndecl); - gcc_assert (fcode == BUILT_IN_MEMSET || fcode == BUILT_IN_BZERO); - arglist = build_tree_list (NULL_TREE, len); - if (fcode == BUILT_IN_MEMSET) - arglist = tree_cons (NULL_TREE, val, arglist); - arglist = tree_cons (NULL_TREE, dest, arglist); - fn = build_function_call_expr (fndecl, arglist); - if (TREE_CODE (fn) == CALL_EXPR) - CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp); - return expand_call (fn, target, target == const0_rtx); - } + do_libcall: + fndecl = get_callee_fndecl (orig_exp); + fcode = DECL_FUNCTION_CODE (fndecl); + if (fcode == BUILT_IN_MEMSET) + fn = build_call_expr (fndecl, 3, dest, val, len); + else if (fcode == BUILT_IN_BZERO) + fn = build_call_expr (fndecl, 2, dest, len); + else + gcc_unreachable (); + if (TREE_CODE (fn) == CALL_EXPR) + CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp); + return expand_call (fn, target, target == const0_rtx); } -/* Expand expression EXP, which is a call to the bzero builtin. Return 0 - if we failed the caller should emit a normal call. */ +/* Expand expression EXP, which is a call to the bzero builtin. Return + NULL_RTX if we failed the caller should emit a normal call. */ static rtx expand_builtin_bzero (tree exp) { - tree arglist = TREE_OPERAND (exp, 1); - tree dest, size, newarglist; + tree dest, size; - if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) return NULL_RTX; - dest = TREE_VALUE (arglist); - size = TREE_VALUE (TREE_CHAIN (arglist)); + dest = CALL_EXPR_ARG (exp, 0); + size = CALL_EXPR_ARG (exp, 1); /* New argument list transforming bzero(ptr x, int y) to memset(ptr x, int 0, size_t y). This is done this way so that if it isn't expanded inline, we fallback to calling bzero instead of memset. */ - newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size)); - newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist); - newarglist = tree_cons (NULL_TREE, dest, newarglist); - - return expand_builtin_memset (newarglist, const0_rtx, VOIDmode, exp); + return expand_builtin_memset_args (dest, integer_zero_node, + fold_convert (sizetype, size), + const0_rtx, VOIDmode, exp); } /* Expand expression EXP, which is a call to the memcmp built-in function. - ARGLIST is the argument list for this call. Return 0 if we failed and the + Return NULL_RTX if we failed and the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE, if that's convenient). */ static rtx -expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target, - enum machine_mode mode) +expand_builtin_memcmp (tree exp, rtx target, enum machine_mode mode) { - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, + POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + return NULL_RTX; else { - tree result = fold_builtin_memcmp (arglist); + tree result = fold_builtin_memcmp (CALL_EXPR_ARG (exp, 0), + CALL_EXPR_ARG (exp, 1), + CALL_EXPR_ARG (exp, 2)); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); } #if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi { - tree arg1 = TREE_VALUE (arglist); - tree arg2 = TREE_VALUE (TREE_CHAIN (arglist)); - tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); rtx arg1_rtx, arg2_rtx, arg3_rtx; rtx result; rtx insn; + tree arg1 = CALL_EXPR_ARG (exp, 0); + tree arg2 = CALL_EXPR_ARG (exp, 1); + tree len = CALL_EXPR_ARG (exp, 2); int arg1_align = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; @@ -3912,11 +3950,11 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target, insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode; else #endif - return 0; + return NULL_RTX; /* If we don't have POINTER_TYPE, call the function. */ if (arg1_align == 0 || arg2_align == 0) - return 0; + return NULL_RTX; /* Make a place to write the result of the instruction. */ result = target; @@ -3975,23 +4013,22 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target, } #endif - return 0; + return NULL_RTX; } -/* Expand expression EXP, which is a call to the strcmp builtin. Return 0 +/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient. */ static rtx expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode) { - tree arglist = TREE_OPERAND (exp, 1); - - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) + return NULL_RTX; else { - tree result = fold_builtin_strcmp (arglist); + tree result = fold_builtin_strcmp (CALL_EXPR_ARG (exp, 0), + CALL_EXPR_ARG (exp, 1)); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); } @@ -4003,9 +4040,9 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode) rtx arg1_rtx, arg2_rtx; rtx result, insn = NULL_RTX; tree fndecl, fn; + tree arg1 = CALL_EXPR_ARG (exp, 0); + tree arg2 = CALL_EXPR_ARG (exp, 1); - tree arg1 = TREE_VALUE (arglist); - tree arg2 = TREE_VALUE (TREE_CHAIN (arglist)); int arg1_align = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; int arg2_align @@ -4013,7 +4050,7 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode) /* If we don't have POINTER_TYPE, call the function. */ if (arg1_align == 0 || arg2_align == 0) - return 0; + return NULL_RTX; /* Stabilize the arguments in case gen_cmpstr(n)si fail. */ arg1 = builtin_save_expr (arg1); @@ -4118,33 +4155,31 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode) #ifdef HAVE_cmpstrnsi do_libcall: #endif - arglist = build_tree_list (NULL_TREE, arg2); - arglist = tree_cons (NULL_TREE, arg1, arglist); fndecl = get_callee_fndecl (exp); - fn = build_function_call_expr (fndecl, arglist); + fn = build_call_expr (fndecl, 2, arg1, arg2); if (TREE_CODE (fn) == CALL_EXPR) CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); return expand_call (fn, target, target == const0_rtx); } #endif - return 0; + return NULL_RTX; } -/* Expand expression EXP, which is a call to the strncmp builtin. Return 0 - if we failed the caller should emit a normal call, otherwise try to get +/* Expand expression EXP, which is a call to the strncmp builtin. Return + NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient. */ static rtx expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) { - tree arglist = TREE_OPERAND (exp, 1); - - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, + POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + return NULL_RTX; else { - tree result = fold_builtin_strncmp (arglist); + tree result = fold_builtin_strncmp (CALL_EXPR_ARG (exp, 0), + CALL_EXPR_ARG (exp, 1), + CALL_EXPR_ARG (exp, 2)); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); } @@ -4155,13 +4190,13 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) #ifdef HAVE_cmpstrnsi if (HAVE_cmpstrnsi) { - tree arg1 = TREE_VALUE (arglist); - tree arg2 = TREE_VALUE (TREE_CHAIN (arglist)); - tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); tree len, len1, len2; rtx arg1_rtx, arg2_rtx, arg3_rtx; rtx result, insn; tree fndecl, fn; + tree arg1 = CALL_EXPR_ARG (exp, 0); + tree arg2 = CALL_EXPR_ARG (exp, 1); + tree arg3 = CALL_EXPR_ARG (exp, 2); int arg1_align = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; @@ -4204,7 +4239,7 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) /* If both arguments have side effects, we cannot optimize. */ if (!len || TREE_SIDE_EFFECTS (len)) - return 0; + return NULL_RTX; /* The actual new length parameter is MIN(len,arg3). */ len = fold_build2 (MIN_EXPR, TREE_TYPE (len), len, @@ -4212,7 +4247,7 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) /* If we don't have POINTER_TYPE, call the function. */ if (arg1_align == 0 || arg2_align == 0) - return 0; + return NULL_RTX; /* Make a place to write the result of the instruction. */ result = target; @@ -4247,32 +4282,29 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) /* Expand the library call ourselves using a stabilized argument list to avoid re-evaluating the function's arguments twice. */ - arglist = build_tree_list (NULL_TREE, len); - arglist = tree_cons (NULL_TREE, arg2, arglist); - arglist = tree_cons (NULL_TREE, arg1, arglist); fndecl = get_callee_fndecl (exp); - fn = build_function_call_expr (fndecl, arglist); + fn = build_call_expr (fndecl, 3, arg1, arg2, len); if (TREE_CODE (fn) == CALL_EXPR) CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); return expand_call (fn, target, target == const0_rtx); } #endif - return 0; + return NULL_RTX; } /* Expand expression EXP, which is a call to the strcat builtin. - Return 0 if we failed the caller should emit a normal call, + Return NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient. */ static rtx -expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode mode) +expand_builtin_strcat (tree fndecl, tree exp, rtx target, enum machine_mode mode) { - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) + return NULL_RTX; else { - tree dst = TREE_VALUE (arglist), - src = TREE_VALUE (TREE_CHAIN (arglist)); + tree dst = CALL_EXPR_ARG (exp, 0); + tree src = CALL_EXPR_ARG (exp, 1); const char *p = c_getstr (src); /* If the string length is zero, return the dst parameter. */ @@ -4288,30 +4320,22 @@ expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode /* Stabilize the argument list. */ newsrc = builtin_save_expr (src); - if (newsrc != src) - arglist = build_tree_list (NULL_TREE, newsrc); - else - arglist = TREE_CHAIN (arglist); /* Reusing arglist if safe. */ - dst = builtin_save_expr (dst); start_sequence (); /* Create strlen (dst). */ - newdst = - build_function_call_expr (strlen_fn, - build_tree_list (NULL_TREE, dst)); + newdst = build_call_expr (strlen_fn, 1, dst); /* Create (dst + (cast) strlen (dst)). */ newdst = fold_convert (TREE_TYPE (dst), newdst); newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst); newdst = builtin_save_expr (newdst); - arglist = tree_cons (NULL_TREE, newdst, arglist); - if (!expand_builtin_strcpy (fndecl, arglist, target, mode)) + if (!expand_builtin_strcpy_args (fndecl, newdst, newsrc, target, mode)) { end_sequence (); /* Stop sequence. */ - return 0; + return NULL_RTX; } /* Output the entire sequence. */ @@ -4322,57 +4346,61 @@ expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode return expand_expr (dst, target, mode, EXPAND_NORMAL); } - return 0; + return NULL_RTX; } } /* Expand expression EXP, which is a call to the strncat builtin. - Return 0 if we failed the caller should emit a normal call, + Return NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient. */ static rtx -expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode) +expand_builtin_strncat (tree exp, rtx target, enum machine_mode mode) { - if (validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, + POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) { - tree result = fold_builtin_strncat (arglist); + tree result = fold_builtin_strncat (CALL_EXPR_ARG (exp, 0), + CALL_EXPR_ARG (exp, 1), + CALL_EXPR_ARG (exp, 2)); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); } - return 0; + return NULL_RTX; } /* Expand expression EXP, which is a call to the strspn builtin. - Return 0 if we failed the caller should emit a normal call, + Return NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient. */ static rtx -expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode) +expand_builtin_strspn (tree exp, rtx target, enum machine_mode mode) { - if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) { - tree result = fold_builtin_strspn (arglist); + tree result = fold_builtin_strspn (CALL_EXPR_ARG (exp, 0), + CALL_EXPR_ARG (exp, 1)); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); } - return 0; + return NULL_RTX; } /* Expand expression EXP, which is a call to the strcspn builtin. - Return 0 if we failed the caller should emit a normal call, + Return NULL_RTX if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient. */ static rtx -expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode) +expand_builtin_strcspn (tree exp, rtx target, enum machine_mode mode) { - if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) { - tree result = fold_builtin_strcspn (arglist); + tree result = fold_builtin_strcspn (CALL_EXPR_ARG (exp, 0), + CALL_EXPR_ARG (exp, 1)); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); } - return 0; + return NULL_RTX; } /* Expand a call to __builtin_saveregs, generating the result in TARGET, @@ -4417,20 +4445,20 @@ expand_builtin_saveregs (void) is controlled by the definition of CUMULATIVE_ARGS. */ static rtx -expand_builtin_args_info (tree arglist) +expand_builtin_args_info (tree exp) { int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int); int *word_ptr = (int *) ¤t_function_args_info; gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0); - if (arglist != 0) + if (call_expr_nargs (exp) != 0) { - if (!host_integerp (TREE_VALUE (arglist), 0)) + if (!host_integerp (CALL_EXPR_ARG (exp, 0), 0)) error ("argument of %<__builtin_args_info%> must be constant"); else { - HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0); + HOST_WIDE_INT wordnum = tree_low_cst (CALL_EXPR_ARG (exp, 0), 0); if (wordnum < 0 || wordnum >= nwords) error ("argument of %<__builtin_args_info%> out of range"); @@ -4523,27 +4551,25 @@ std_expand_builtin_va_start (tree valist, rtx nextarg) expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); } -/* Expand ARGLIST, from a call to __builtin_va_start. */ +/* Expand EXP, a call to __builtin_va_start. */ static rtx -expand_builtin_va_start (tree arglist) +expand_builtin_va_start (tree exp) { rtx nextarg; - tree chain, valist; - - chain = TREE_CHAIN (arglist); + tree valist; - if (!chain) + if (call_expr_nargs (exp) < 2) { error ("too few arguments to function %<va_start%>"); return const0_rtx; } - if (fold_builtin_next_arg (chain)) + if (fold_builtin_next_arg (exp, true)) return const0_rtx; nextarg = expand_builtin_next_arg (); - valist = stabilize_va_list (TREE_VALUE (arglist), 1); + valist = stabilize_va_list (CALL_EXPR_ARG (exp, 0), 1); #ifdef EXPAND_BUILTIN_VA_START EXPAND_BUILTIN_VA_START (valist, nextarg); @@ -4725,8 +4751,7 @@ gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p) /* We can, however, treat "undefined" any way we please. Call abort to encourage the user to fix the program. */ inform ("if this code is reached, the program will abort"); - t = build_function_call_expr (implicit_built_in_decls[BUILT_IN_TRAP], - NULL); + t = build_call_expr (implicit_built_in_decls[BUILT_IN_TRAP], 0); append_to_statement_list (t, pre_p); /* This is dead code, but go ahead and finish so that the @@ -4764,12 +4789,12 @@ gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p) } } -/* Expand ARGLIST, from a call to __builtin_va_end. */ +/* Expand EXP, a call to __builtin_va_end. */ static rtx -expand_builtin_va_end (tree arglist) +expand_builtin_va_end (tree exp) { - tree valist = TREE_VALUE (arglist); + tree valist = CALL_EXPR_ARG (exp, 0); /* Evaluate for side effects, if needed. I hate macros that don't do that. */ @@ -4779,17 +4804,17 @@ expand_builtin_va_end (tree arglist) return const0_rtx; } -/* Expand ARGLIST, from a call to __builtin_va_copy. We do this as a +/* Expand EXP, a call to __builtin_va_copy. We do this as a builtin rather than just as an assignment in stdarg.h because of the nastiness of array-type va_list types. */ static rtx -expand_builtin_va_copy (tree arglist) +expand_builtin_va_copy (tree exp) { tree dst, src, t; - dst = TREE_VALUE (arglist); - src = TREE_VALUE (TREE_CHAIN (arglist)); + dst = CALL_EXPR_ARG (exp, 0); + src = CALL_EXPR_ARG (exp, 1); dst = stabilize_va_list (dst, 1); src = stabilize_va_list (src, 0); @@ -4832,15 +4857,15 @@ expand_builtin_va_copy (tree arglist) __builtin_return_address. */ static rtx -expand_builtin_frame_address (tree fndecl, tree arglist) +expand_builtin_frame_address (tree fndecl, tree exp) { /* The argument must be a nonnegative integer constant. It counts the number of frames to scan up the stack. The value is the return address saved in that frame. */ - if (arglist == 0) + if (call_expr_nargs (exp) == 0) /* Warning about missing arg was already issued. */ return const0_rtx; - else if (! host_integerp (TREE_VALUE (arglist), 1)) + else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1)) { if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS) error ("invalid argument to %<__builtin_frame_address%>"); @@ -4852,7 +4877,7 @@ expand_builtin_frame_address (tree fndecl, tree arglist) { rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl), - tree_low_cst (TREE_VALUE (arglist), 1)); + tree_low_cst (CALL_EXPR_ARG (exp, 0), 1)); /* Some ports cannot access arbitrary stack frames. */ if (tem == NULL) @@ -4875,12 +4900,12 @@ expand_builtin_frame_address (tree fndecl, tree arglist) } } -/* Expand a call to the alloca builtin, with arguments ARGLIST. Return 0 if +/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if we failed and the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient. */ static rtx -expand_builtin_alloca (tree arglist, rtx target) +expand_builtin_alloca (tree exp, rtx target) { rtx op0; rtx result; @@ -4889,13 +4914,13 @@ expand_builtin_alloca (tree arglist, rtx target) should always expand to function calls. These can be intercepted in libmudflap. */ if (flag_mudflap) - return 0; + return NULL_RTX; - if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE)) + return NULL_RTX; /* Compute the argument. */ - op0 = expand_normal (TREE_VALUE (arglist)); + op0 = expand_normal (CALL_EXPR_ARG (exp, 0)); /* Allocate the desired space. */ result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT); @@ -4904,20 +4929,20 @@ expand_builtin_alloca (tree arglist, rtx target) return result; } -/* Expand a call to a bswap builtin. The arguments are in ARGLIST. MODE +/* Expand a call to a bswap builtin with argument ARG0. MODE is the mode to expand with. */ static rtx -expand_builtin_bswap (tree arglist, rtx target, rtx subtarget) +expand_builtin_bswap (tree exp, rtx target, rtx subtarget) { enum machine_mode mode; tree arg; rtx op0; - if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE)) + return NULL_RTX; - arg = TREE_VALUE (arglist); + arg = CALL_EXPR_ARG (exp, 0); mode = TYPE_MODE (TREE_TYPE (arg)); op0 = expand_expr (arg, subtarget, VOIDmode, 0); @@ -4928,24 +4953,25 @@ expand_builtin_bswap (tree arglist, rtx target, rtx subtarget) return convert_to_mode (mode, target, 0); } -/* Expand a call to a unary builtin. The arguments are in ARGLIST. - Return 0 if a normal call should be emitted rather than expanding the +/* Expand a call to a unary builtin in EXP. + Return NULL_RTX if a normal call should be emitted rather than expanding the function in-line. If convenient, the result should be placed in TARGET. SUBTARGET may be used as the target for computing one of EXP's operands. */ static rtx -expand_builtin_unop (enum machine_mode target_mode, tree arglist, rtx target, +expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target, rtx subtarget, optab op_optab) { rtx op0; - if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) - return 0; + + if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE)) + return NULL_RTX; /* Compute the argument. */ - op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0); + op0 = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget, VOIDmode, 0); /* Compute op, into TARGET if possible. Set TARGET to wherever the result comes back. */ - target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))), + target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))), op_optab, op0, target, 1); gcc_assert (target); @@ -4956,17 +4982,19 @@ expand_builtin_unop (enum machine_mode target_mode, tree arglist, rtx target, long, we attempt to transform this call into __builtin_fputc(). */ static rtx -expand_builtin_fputs (tree arglist, rtx target, bool unlocked) +expand_builtin_fputs (tree exp, rtx target, bool unlocked) { /* Verify the arguments in the original call. */ - if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) { - tree result = fold_builtin_fputs (arglist, (target == const0_rtx), + tree result = fold_builtin_fputs (CALL_EXPR_ARG (exp, 0), + CALL_EXPR_ARG (exp, 1), + (target == const0_rtx), unlocked, NULL_TREE); if (result) return expand_expr (result, target, VOIDmode, EXPAND_NORMAL); } - return 0; + return NULL_RTX; } /* Expand a call to __builtin_expect. We just return our argument @@ -4974,17 +5002,16 @@ expand_builtin_fputs (tree arglist, rtx target, bool unlocked) tree branch prediction pass. */ static rtx -expand_builtin_expect (tree arglist, rtx target) +expand_builtin_expect (tree exp, rtx target) { - tree exp, c; + tree arg, c; - if (arglist == NULL_TREE - || TREE_CHAIN (arglist) == NULL_TREE) + if (call_expr_nargs (exp) < 2) return const0_rtx; - exp = TREE_VALUE (arglist); - c = TREE_VALUE (TREE_CHAIN (arglist)); + arg = CALL_EXPR_ARG (exp, 0); + c = CALL_EXPR_ARG (exp, 1); - target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL); + target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL); /* When guessing was done, the hints should be already stripped away. */ gcc_assert (!flag_guess_branch_prob); return target; @@ -5002,46 +5029,46 @@ expand_builtin_trap (void) emit_barrier (); } -/* Expand a call to fabs, fabsf or fabsl with arguments ARGLIST. - Return 0 if a normal call should be emitted rather than expanding +/* Expand EXP, a call to fabs, fabsf or fabsl. + Return NULL_RTX if a normal call should be emitted rather than expanding the function inline. If convenient, the result should be placed in TARGET. SUBTARGET may be used as the target for computing the operand. */ static rtx -expand_builtin_fabs (tree arglist, rtx target, rtx subtarget) +expand_builtin_fabs (tree exp, rtx target, rtx subtarget) { enum machine_mode mode; tree arg; rtx op0; - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) + return NULL_RTX; - arg = TREE_VALUE (arglist); + arg = CALL_EXPR_ARG (exp, 0); mode = TYPE_MODE (TREE_TYPE (arg)); op0 = expand_expr (arg, subtarget, VOIDmode, 0); return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1)); } -/* Expand a call to copysign, copysignf, or copysignl with arguments ARGLIST. +/* Expand EXP, a call to copysign, copysignf, or copysignl. Return NULL is a normal call should be emitted rather than expanding the function inline. If convenient, the result should be placed in TARGET. SUBTARGET may be used as the target for computing the operand. */ static rtx -expand_builtin_copysign (tree arglist, rtx target, rtx subtarget) +expand_builtin_copysign (tree exp, rtx target, rtx subtarget) { rtx op0, op1; tree arg; - if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE)) + return NULL_RTX; - arg = TREE_VALUE (arglist); + arg = CALL_EXPR_ARG (exp, 0); op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL); - arg = TREE_VALUE (TREE_CHAIN (arglist)); + arg = CALL_EXPR_ARG (exp, 1); op1 = expand_normal (arg); return expand_copysign (op0, op1, target); @@ -5073,7 +5100,7 @@ build_string_literal (int len, const char *str) } /* Expand EXP, a call to printf or printf_unlocked. - Return 0 if a normal call should be emitted rather than transforming + Return NULL_RTX if a normal call should be emitted rather than transforming the function inline. If convenient, the result should be placed in TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked call. */ @@ -5081,7 +5108,6 @@ static rtx expand_builtin_printf (tree exp, rtx target, enum machine_mode mode, bool unlocked) { - tree arglist = TREE_OPERAND (exp, 1); /* If we're using an unlocked function, assume the other unlocked functions exist explicitly. */ tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED] @@ -5089,54 +5115,55 @@ expand_builtin_printf (tree exp, rtx target, enum machine_mode mode, tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED] : implicit_built_in_decls[BUILT_IN_PUTS]; const char *fmt_str; - tree fn, fmt, arg; + tree fn = 0; + tree fmt, arg; + int nargs = call_expr_nargs (exp); /* If the return value is used, don't do the transformation. */ if (target != const0_rtx) - return 0; + return NULL_RTX; /* Verify the required arguments in the original call. */ - if (! arglist) - return 0; - fmt = TREE_VALUE (arglist); + if (nargs == 0) + return NULL_RTX; + fmt = CALL_EXPR_ARG (exp, 0); if (! POINTER_TYPE_P (TREE_TYPE (fmt))) - return 0; - arglist = TREE_CHAIN (arglist); + return NULL_RTX; /* Check whether the format is a literal string constant. */ fmt_str = c_getstr (fmt); if (fmt_str == NULL) - return 0; + return NULL_RTX; if (!init_target_chars ()) - return 0; + return NULL_RTX; /* If the format specifier was "%s\n", call __builtin_puts(arg). */ if (strcmp (fmt_str, target_percent_s_newline) == 0) { - if (! arglist - || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist))) - || TREE_CHAIN (arglist)) - return 0; - fn = fn_puts; + if ((nargs != 2) + || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 1)))) + return NULL_RTX; + if (fn_puts) + fn = build_call_expr (fn_puts, 1, CALL_EXPR_ARG (exp, 1)); } /* If the format specifier was "%c", call __builtin_putchar(arg). */ else if (strcmp (fmt_str, target_percent_c) == 0) { - if (! arglist - || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE - || TREE_CHAIN (arglist)) - return 0; - fn = fn_putchar; + if ((nargs != 2) + || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1))) != INTEGER_TYPE) + return NULL_RTX; + if (fn_putchar) + fn = build_call_expr (fn_putchar, 1, CALL_EXPR_ARG (exp, 1)); } else { /* We can't handle anything else with % args or %% ... yet. */ if (strchr (fmt_str, target_percent)) - return 0; + return NULL_RTX; - if (arglist) - return 0; + if (nargs > 1) + return NULL_RTX; /* If the format specifier was "", printf does nothing. */ if (fmt_str[0] == '\0') @@ -5148,8 +5175,8 @@ expand_builtin_printf (tree exp, rtx target, enum machine_mode mode, convert "c"[0] to an int and pass that to the replacement function. */ arg = build_int_cst (NULL_TREE, fmt_str[0]); - arglist = build_tree_list (NULL_TREE, arg); - fn = fn_putchar; + if (fn_putchar) + fn = build_call_expr (fn_putchar, 1, arg); } else { @@ -5162,28 +5189,26 @@ expand_builtin_printf (tree exp, rtx target, enum machine_mode mode, char *newstr = alloca (len); memcpy (newstr, fmt_str, len - 1); newstr[len - 1] = 0; - arg = build_string_literal (len, newstr); - arglist = build_tree_list (NULL_TREE, arg); - fn = fn_puts; + if (fn_puts) + fn = build_call_expr (fn_puts, 1, arg); } else /* We'd like to arrange to call fputs(string,stdout) here, but we need stdout and don't have a way to get it yet. */ - return 0; + return NULL_RTX; } } if (!fn) - return 0; - fn = build_function_call_expr (fn, arglist); + return NULL_RTX; if (TREE_CODE (fn) == CALL_EXPR) CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); return expand_expr (fn, target, mode, EXPAND_NORMAL); } /* Expand EXP, a call to fprintf or fprintf_unlocked. - Return 0 if a normal call should be emitted rather than transforming + Return NULL_RTX if a normal call should be emitted rather than transforming the function inline. If convenient, the result should be placed in TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked call. */ @@ -5191,7 +5216,6 @@ static rtx expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode, bool unlocked) { - tree arglist = TREE_OPERAND (exp, 1); /* If we're using an unlocked function, assume the other unlocked functions exist explicitly. */ tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED] @@ -5199,66 +5223,60 @@ expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode, tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED] : implicit_built_in_decls[BUILT_IN_FPUTS]; const char *fmt_str; - tree fn, fmt, fp, arg; + tree fn = 0; + tree fmt, fp, arg; + int nargs = call_expr_nargs (exp); /* If the return value is used, don't do the transformation. */ if (target != const0_rtx) - return 0; + return NULL_RTX; /* Verify the required arguments in the original call. */ - if (! arglist) - return 0; - fp = TREE_VALUE (arglist); + if (nargs < 2) + return NULL_RTX; + fp = CALL_EXPR_ARG (exp, 0); if (! POINTER_TYPE_P (TREE_TYPE (fp))) - return 0; - arglist = TREE_CHAIN (arglist); - if (! arglist) - return 0; - fmt = TREE_VALUE (arglist); + return NULL_RTX; + fmt = CALL_EXPR_ARG (exp, 1); if (! POINTER_TYPE_P (TREE_TYPE (fmt))) - return 0; - arglist = TREE_CHAIN (arglist); + return NULL_RTX; /* Check whether the format is a literal string constant. */ fmt_str = c_getstr (fmt); if (fmt_str == NULL) - return 0; + return NULL_RTX; if (!init_target_chars ()) - return 0; + return NULL_RTX; /* If the format specifier was "%s", call __builtin_fputs(arg,fp). */ if (strcmp (fmt_str, target_percent_s) == 0) { - if (! arglist - || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist))) - || TREE_CHAIN (arglist)) - return 0; - arg = TREE_VALUE (arglist); - arglist = build_tree_list (NULL_TREE, fp); - arglist = tree_cons (NULL_TREE, arg, arglist); - fn = fn_fputs; + if ((nargs != 3) + || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 2)))) + return NULL_RTX; + arg = CALL_EXPR_ARG (exp, 2); + if (fn_fputs) + fn = build_call_expr (fn_fputs, 2, arg, fp); } /* If the format specifier was "%c", call __builtin_fputc(arg,fp). */ else if (strcmp (fmt_str, target_percent_c) == 0) { - if (! arglist - || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE - || TREE_CHAIN (arglist)) - return 0; - arg = TREE_VALUE (arglist); - arglist = build_tree_list (NULL_TREE, fp); - arglist = tree_cons (NULL_TREE, arg, arglist); - fn = fn_fputc; + if ((nargs != 3) + || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2))) != INTEGER_TYPE) + return NULL_RTX; + arg = CALL_EXPR_ARG (exp, 2); + if (fn_fputc) + fn = build_call_expr (fn_fputc, 2, arg, fp); } else { /* We can't handle anything else with % args or %% ... yet. */ if (strchr (fmt_str, target_percent)) - return 0; + return NULL_RTX; - if (arglist) - return 0; + if (nargs > 2) + return NULL_RTX; /* If the format specifier was "", fprintf does nothing. */ if (fmt_str[0] == '\0') @@ -5271,53 +5289,46 @@ expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode, /* When "string" doesn't contain %, replace all cases of fprintf(stream,string) with fputs(string,stream). The fputs builtin will take care of special cases like length == 1. */ - arglist = build_tree_list (NULL_TREE, fp); - arglist = tree_cons (NULL_TREE, fmt, arglist); - fn = fn_fputs; + if (fn_fputs) + fn = build_call_expr (fn_fputs, 2, fmt, fp); } if (!fn) - return 0; - fn = build_function_call_expr (fn, arglist); + return NULL_RTX; if (TREE_CODE (fn) == CALL_EXPR) CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); return expand_expr (fn, target, mode, EXPAND_NORMAL); } -/* Expand a call to sprintf with argument list ARGLIST. Return 0 if +/* Expand a call EXP to sprintf. Return NULL_RTX if a normal call should be emitted rather than expanding the function inline. If convenient, the result should be placed in TARGET with mode MODE. */ static rtx -expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode) +expand_builtin_sprintf (tree exp, rtx target, enum machine_mode mode) { - tree orig_arglist, dest, fmt; + tree dest, fmt; const char *fmt_str; - - orig_arglist = arglist; + int nargs = call_expr_nargs (exp); /* Verify the required arguments in the original call. */ - if (! arglist) - return 0; - dest = TREE_VALUE (arglist); + if (nargs < 2) + return NULL_RTX; + dest = CALL_EXPR_ARG (exp, 0); if (! POINTER_TYPE_P (TREE_TYPE (dest))) - return 0; - arglist = TREE_CHAIN (arglist); - if (! arglist) - return 0; - fmt = TREE_VALUE (arglist); + return NULL_RTX; + fmt = CALL_EXPR_ARG (exp, 0); if (! POINTER_TYPE_P (TREE_TYPE (fmt))) - return 0; - arglist = TREE_CHAIN (arglist); + return NULL_RTX; /* Check whether the format is a literal string constant. */ fmt_str = c_getstr (fmt); if (fmt_str == NULL) - return 0; + return NULL_RTX; if (!init_target_chars ()) - return 0; + return NULL_RTX; /* If the format doesn't contain % args or %%, use strcpy. */ if (strchr (fmt_str, target_percent) == 0) @@ -5325,9 +5336,9 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode) tree fn = implicit_built_in_decls[BUILT_IN_STRCPY]; tree exp; - if (arglist || ! fn) - return 0; - expand_expr (build_function_call_expr (fn, orig_arglist), + if ((nargs > 2) || ! fn) + return NULL_RTX; + expand_expr (build_call_expr (fn, 2, dest, fmt), const0_rtx, VOIDmode, EXPAND_NORMAL); if (target == const0_rtx) return const0_rtx; @@ -5341,26 +5352,23 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode) fn = implicit_built_in_decls[BUILT_IN_STRCPY]; if (! fn) - return 0; - - if (! arglist || TREE_CHAIN (arglist)) - return 0; - arg = TREE_VALUE (arglist); + return NULL_RTX; + if (nargs != 3) + return NULL_RTX; + arg = CALL_EXPR_ARG (exp, 2); if (! POINTER_TYPE_P (TREE_TYPE (arg))) - return 0; + return NULL_RTX; if (target != const0_rtx) { len = c_strlen (arg, 1); if (! len || TREE_CODE (len) != INTEGER_CST) - return 0; + return NULL_RTX; } else len = NULL_TREE; - arglist = build_tree_list (NULL_TREE, arg); - arglist = tree_cons (NULL_TREE, dest, arglist); - expand_expr (build_function_call_expr (fn, arglist), + expand_expr (build_call_expr (fn, 2, dest, arg), const0_rtx, VOIDmode, EXPAND_NORMAL); if (target == const0_rtx) @@ -5368,7 +5376,7 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode) return expand_expr (len, target, mode, EXPAND_NORMAL); } - return 0; + return NULL_RTX; } /* Expand a call to either the entry or exit function profiler. */ @@ -5421,7 +5429,7 @@ round_trampoline_addr (rtx tramp) } static rtx -expand_builtin_init_trampoline (tree arglist) +expand_builtin_init_trampoline (tree exp) { tree t_tramp, t_func, t_chain; rtx r_tramp, r_func, r_chain; @@ -5429,15 +5437,13 @@ expand_builtin_init_trampoline (tree arglist) rtx blktramp; #endif - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, + if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) return NULL_RTX; - t_tramp = TREE_VALUE (arglist); - arglist = TREE_CHAIN (arglist); - t_func = TREE_VALUE (arglist); - arglist = TREE_CHAIN (arglist); - t_chain = TREE_VALUE (arglist); + t_tramp = CALL_EXPR_ARG (exp, 0); + t_func = CALL_EXPR_ARG (exp, 1); + t_chain = CALL_EXPR_ARG (exp, 2); r_tramp = expand_normal (t_tramp); r_func = expand_normal (t_func); @@ -5458,14 +5464,14 @@ expand_builtin_init_trampoline (tree arglist) } static rtx -expand_builtin_adjust_trampoline (tree arglist) +expand_builtin_adjust_trampoline (tree exp) { rtx tramp; - if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) + if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE)) return NULL_RTX; - tramp = expand_normal (TREE_VALUE (arglist)); + tramp = expand_normal (CALL_EXPR_ARG (exp, 0)); tramp = round_trampoline_addr (tramp); #ifdef TRAMPOLINE_ADJUST_ADDRESS TRAMPOLINE_ADJUST_ADDRESS (tramp); @@ -5485,15 +5491,14 @@ expand_builtin_signbit (tree exp, rtx target) const struct real_format *fmt; enum machine_mode fmode, imode, rmode; HOST_WIDE_INT hi, lo; - tree arg, arglist; + tree arg; int word, bitpos; rtx temp; - arglist = TREE_OPERAND (exp, 1); - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) + return NULL_RTX; - arg = TREE_VALUE (arglist); + arg = CALL_EXPR_ARG (exp, 0); fmode = TYPE_MODE (TREE_TYPE (arg)); rmode = TYPE_MODE (TREE_TYPE (exp)); fmt = REAL_MODE_FORMAT (fmode); @@ -5505,7 +5510,7 @@ expand_builtin_signbit (tree exp, rtx target) { /* But we can't do this if the format supports signed zero. */ if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode)) - return 0; + return NULL_RTX; arg = fold_build2 (LT_EXPR, TREE_TYPE (exp), arg, build_real (TREE_TYPE (arg), dconst0)); @@ -5517,7 +5522,7 @@ expand_builtin_signbit (tree exp, rtx target) { imode = int_mode_for_mode (fmode); if (imode == BLKmode) - return 0; + return NULL_RTX; temp = gen_lowpart (imode, temp); } else @@ -5576,12 +5581,12 @@ expand_builtin_signbit (tree exp, rtx target) } /* Expand fork or exec calls. TARGET is the desired target of the - call. ARGLIST is the list of arguments of the call. FN is the + call. EXP is the call. FN is the identificator of the actual function. IGNORE is nonzero if the value is to be ignored. */ static rtx -expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore) +expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore) { tree id, decl; tree call; @@ -5635,10 +5640,10 @@ expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore) TREE_NOTHROW (decl) = 1; DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; DECL_VISIBILITY_SPECIFIED (decl) = 1; - call = build_function_call_expr (decl, arglist); - + call = rewrite_call_expr (exp, 0, decl, 0); return expand_call (call, target, ignore); -} + } + /* Reconstitute a mode for a __sync intrinsic operation. Since the type of @@ -5680,7 +5685,7 @@ get_builtin_sync_mem (tree loc, enum machine_mode mode) } /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics. - ARGLIST is the operands list to the function. CODE is the rtx code + EXP is the CALL_EXPR. CODE is the rtx code that corresponds to the arithmetic or logical operation from the name; an exception here is that NOT actually means NAND. TARGET is an optional place for us to store the results; AFTER is true if this is the @@ -5688,17 +5693,16 @@ get_builtin_sync_mem (tree loc, enum machine_mode mode) the result of the operation at all. */ static rtx -expand_builtin_sync_operation (enum machine_mode mode, tree arglist, +expand_builtin_sync_operation (enum machine_mode mode, tree exp, enum rtx_code code, bool after, rtx target, bool ignore) { rtx val, mem; /* Expand the operands. */ - mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode); + mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode); - arglist = TREE_CHAIN (arglist); - val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL); + val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL, mode, EXPAND_NORMAL); /* If VAL is promoted to a wider mode, convert it back to MODE. */ val = convert_to_mode (mode, val, 1); @@ -5709,26 +5713,25 @@ expand_builtin_sync_operation (enum machine_mode mode, tree arglist, } /* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap - intrinsics. ARGLIST is the operands list to the function. IS_BOOL is + intrinsics. EXP is the CALL_EXPR. IS_BOOL is true if this is the boolean form. TARGET is a place for us to store the results; this is NOT optional if IS_BOOL is true. */ static rtx -expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist, +expand_builtin_compare_and_swap (enum machine_mode mode, tree exp, bool is_bool, rtx target) { rtx old_val, new_val, mem; /* Expand the operands. */ - mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode); + mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode); + - arglist = TREE_CHAIN (arglist); - old_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL); + old_val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL, mode, EXPAND_NORMAL); /* If OLD_VAL is promoted to a wider mode, convert it back to MODE. */ old_val = convert_to_mode (mode, old_val, 1); - arglist = TREE_CHAIN (arglist); - new_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL); + new_val = expand_expr (CALL_EXPR_ARG (exp, 2), NULL, mode, EXPAND_NORMAL); /* If NEW_VAL is promoted to a wider mode, convert it back to MODE. */ new_val = convert_to_mode (mode, new_val, 1); @@ -5741,20 +5744,18 @@ expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist, /* Expand the __sync_lock_test_and_set intrinsic. Note that the most general form is actually an atomic exchange, and some targets only support a reduced form with the second argument being a constant 1. - ARGLIST is the operands list to the function; TARGET is an optional - place for us to store the results. */ + EXP is the CALL_EXPR; TARGET is an optional place for us to store + the results. */ static rtx -expand_builtin_lock_test_and_set (enum machine_mode mode, tree arglist, +expand_builtin_lock_test_and_set (enum machine_mode mode, tree exp, rtx target) { rtx val, mem; /* Expand the operands. */ - mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode); - - arglist = TREE_CHAIN (arglist); - val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL); + mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode); + val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL, mode, EXPAND_NORMAL); /* If VAL is promoted to a wider mode, convert it back to MODE. */ val = convert_to_mode (mode, val, 1); @@ -5784,18 +5785,17 @@ expand_builtin_synchronize (void) expand_asm_expr (x); } -/* Expand the __sync_lock_release intrinsic. ARGLIST is the operands list - to the function. */ +/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */ static void -expand_builtin_lock_release (enum machine_mode mode, tree arglist) +expand_builtin_lock_release (enum machine_mode mode, tree exp) { enum insn_code icode; rtx mem, insn; rtx val = const0_rtx; /* Expand the operands. */ - mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode); + mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode); /* If there is an explicit operation in the md file, use it. */ icode = sync_lock_release[mode]; @@ -5829,7 +5829,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, int ignore) { tree fndecl = get_callee_fndecl (exp); - tree arglist = TREE_OPERAND (exp, 1); enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp)); @@ -5857,9 +5856,10 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, { bool volatilep = false; tree arg; + call_expr_arg_iterator iter; - for (arg = arglist; arg; arg = TREE_CHAIN (arg)) - if (TREE_THIS_VOLATILE (TREE_VALUE (arg))) + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) + if (TREE_THIS_VOLATILE (arg)) { volatilep = true; break; @@ -5867,9 +5867,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, if (! volatilep) { - for (arg = arglist; arg; arg = TREE_CHAIN (arg)) - expand_expr (TREE_VALUE (arg), const0_rtx, - VOIDmode, EXPAND_NORMAL); + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) + expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL); return const0_rtx; } } @@ -5877,13 +5876,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, switch (fcode) { CASE_FLT_FN (BUILT_IN_FABS): - target = expand_builtin_fabs (arglist, target, subtarget); + target = expand_builtin_fabs (exp, target, subtarget); if (target) return target; break; CASE_FLT_FN (BUILT_IN_COPYSIGN): - target = expand_builtin_copysign (arglist, target, subtarget); + target = expand_builtin_copysign (exp, target, subtarget); if (target) return target; break; @@ -6011,19 +6010,18 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, computed? We'll also need a safe worst case value for varargs functions. */ case BUILT_IN_APPLY: - if (!validate_arglist (arglist, POINTER_TYPE, + if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE) - && !validate_arglist (arglist, REFERENCE_TYPE, + && !validate_arglist (exp, REFERENCE_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) return const0_rtx; else { - int i; - tree t; rtx ops[3]; - for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++) - ops[i] = expand_normal (TREE_VALUE (t)); + ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0)); + ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1)); + ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2)); return expand_builtin_apply (ops[0], ops[1], ops[2]); } @@ -6032,36 +6030,36 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, value described by RESULT. RESULT is address of the block of memory returned by __builtin_apply. */ case BUILT_IN_RETURN: - if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) - expand_builtin_return (expand_normal (TREE_VALUE (arglist))); + if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE)) + expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0))); return const0_rtx; case BUILT_IN_SAVEREGS: return expand_builtin_saveregs (); case BUILT_IN_ARGS_INFO: - return expand_builtin_args_info (arglist); + return expand_builtin_args_info (exp); /* Return the address of the first anonymous stack arg. */ case BUILT_IN_NEXT_ARG: - if (fold_builtin_next_arg (arglist)) + if (fold_builtin_next_arg (exp, false)) return const0_rtx; return expand_builtin_next_arg (); case BUILT_IN_CLASSIFY_TYPE: - return expand_builtin_classify_type (arglist); + return expand_builtin_classify_type (exp); case BUILT_IN_CONSTANT_P: return const0_rtx; case BUILT_IN_FRAME_ADDRESS: case BUILT_IN_RETURN_ADDRESS: - return expand_builtin_frame_address (fndecl, arglist); + return expand_builtin_frame_address (fndecl, exp); /* Returns the address of the area where the structure is returned. 0 otherwise. */ case BUILT_IN_AGGREGATE_INCOMING_ADDRESS: - if (arglist != 0 + if (call_expr_nargs (exp) != 0 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))) || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl)))) return const0_rtx; @@ -6069,7 +6067,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0); case BUILT_IN_ALLOCA: - target = expand_builtin_alloca (arglist, target); + target = expand_builtin_alloca (exp, target); if (target) return target; break; @@ -6078,12 +6076,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, return expand_stack_save (); case BUILT_IN_STACK_RESTORE: - expand_stack_restore (TREE_VALUE (arglist)); + expand_stack_restore (CALL_EXPR_ARG (exp, 0)); return const0_rtx; case BUILT_IN_BSWAP32: case BUILT_IN_BSWAP64: - target = expand_builtin_bswap (arglist, target, subtarget); + target = expand_builtin_bswap (exp, target, subtarget); if (target) return target; @@ -6091,7 +6089,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, CASE_INT_FN (BUILT_IN_FFS): case BUILT_IN_FFSIMAX: - target = expand_builtin_unop (target_mode, arglist, target, + target = expand_builtin_unop (target_mode, exp, target, subtarget, ffs_optab); if (target) return target; @@ -6099,7 +6097,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, CASE_INT_FN (BUILT_IN_CLZ): case BUILT_IN_CLZIMAX: - target = expand_builtin_unop (target_mode, arglist, target, + target = expand_builtin_unop (target_mode, exp, target, subtarget, clz_optab); if (target) return target; @@ -6107,7 +6105,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, CASE_INT_FN (BUILT_IN_CTZ): case BUILT_IN_CTZIMAX: - target = expand_builtin_unop (target_mode, arglist, target, + target = expand_builtin_unop (target_mode, exp, target, subtarget, ctz_optab); if (target) return target; @@ -6115,7 +6113,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, CASE_INT_FN (BUILT_IN_POPCOUNT): case BUILT_IN_POPCOUNTIMAX: - target = expand_builtin_unop (target_mode, arglist, target, + target = expand_builtin_unop (target_mode, exp, target, subtarget, popcount_optab); if (target) return target; @@ -6123,20 +6121,20 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, CASE_INT_FN (BUILT_IN_PARITY): case BUILT_IN_PARITYIMAX: - target = expand_builtin_unop (target_mode, arglist, target, + target = expand_builtin_unop (target_mode, exp, target, subtarget, parity_optab); if (target) return target; break; case BUILT_IN_STRLEN: - target = expand_builtin_strlen (arglist, target, target_mode); + target = expand_builtin_strlen (exp, target, target_mode); if (target) return target; break; case BUILT_IN_STRCPY: - target = expand_builtin_strcpy (fndecl, arglist, target, mode); + target = expand_builtin_strcpy (fndecl, exp, target, mode); if (target) return target; break; @@ -6154,51 +6152,51 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, break; case BUILT_IN_STRCAT: - target = expand_builtin_strcat (fndecl, arglist, target, mode); + target = expand_builtin_strcat (fndecl, exp, target, mode); if (target) return target; break; case BUILT_IN_STRNCAT: - target = expand_builtin_strncat (arglist, target, mode); + target = expand_builtin_strncat (exp, target, mode); if (target) return target; break; case BUILT_IN_STRSPN: - target = expand_builtin_strspn (arglist, target, mode); + target = expand_builtin_strspn (exp, target, mode); if (target) return target; break; case BUILT_IN_STRCSPN: - target = expand_builtin_strcspn (arglist, target, mode); + target = expand_builtin_strcspn (exp, target, mode); if (target) return target; break; case BUILT_IN_STRSTR: - target = expand_builtin_strstr (arglist, TREE_TYPE (exp), target, mode); + target = expand_builtin_strstr (exp, target, mode); if (target) return target; break; case BUILT_IN_STRPBRK: - target = expand_builtin_strpbrk (arglist, TREE_TYPE (exp), target, mode); + target = expand_builtin_strpbrk (exp, target, mode); if (target) return target; break; case BUILT_IN_INDEX: case BUILT_IN_STRCHR: - target = expand_builtin_strchr (arglist, TREE_TYPE (exp), target, mode); + target = expand_builtin_strchr (exp, target, mode); if (target) return target; break; case BUILT_IN_RINDEX: case BUILT_IN_STRRCHR: - target = expand_builtin_strrchr (arglist, TREE_TYPE (exp), target, mode); + target = expand_builtin_strrchr (exp, target, mode); if (target) return target; break; @@ -6210,26 +6208,25 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, break; case BUILT_IN_MEMPCPY: - target = expand_builtin_mempcpy (arglist, TREE_TYPE (exp), target, mode, /*endp=*/ 1); + target = expand_builtin_mempcpy (exp, target, mode); if (target) return target; break; case BUILT_IN_MEMMOVE: - target = expand_builtin_memmove (arglist, TREE_TYPE (exp), target, - mode); + target = expand_builtin_memmove (exp, target, mode, ignore); if (target) return target; break; case BUILT_IN_BCOPY: - target = expand_builtin_bcopy (exp); + target = expand_builtin_bcopy (exp, ignore); if (target) return target; break; case BUILT_IN_MEMSET: - target = expand_builtin_memset (arglist, target, mode, exp); + target = expand_builtin_memset (exp, target, mode); if (target) return target; break; @@ -6254,7 +6251,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_BCMP: case BUILT_IN_MEMCMP: - target = expand_builtin_memcmp (exp, arglist, target, mode); + target = expand_builtin_memcmp (exp, target, mode); if (target) return target; break; @@ -6266,11 +6263,11 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_SETJMP_SETUP: /* __builtin_setjmp_setup is passed a pointer to an array of five words and the receiver label. */ - if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) { - rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget, + rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget, VOIDmode, EXPAND_NORMAL); - tree label = TREE_OPERAND (TREE_VALUE (TREE_CHAIN (arglist)), 0); + tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0); rtx label_r = label_rtx (label); /* This is copied from the handling of non-local gotos. */ @@ -6288,9 +6285,9 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_SETJMP_DISPATCHER: /* __builtin_setjmp_dispatcher is passed the dispatcher label. */ - if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE)) { - tree label = TREE_OPERAND (TREE_VALUE (arglist), 0); + tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0); rtx label_r = label_rtx (label); /* Remove the dispatcher label from the list of non-local labels @@ -6302,9 +6299,9 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_SETJMP_RECEIVER: /* __builtin_setjmp_receiver is passed the receiver label. */ - if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE)) { - tree label = TREE_OPERAND (TREE_VALUE (arglist), 0); + tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0); rtx label_r = label_rtx (label); expand_builtin_setjmp_receiver (label_r); @@ -6316,11 +6313,11 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, It's similar to the C library longjmp function but works with __builtin_setjmp above. */ case BUILT_IN_LONGJMP: - if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) { - rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget, + rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget, VOIDmode, EXPAND_NORMAL); - rtx value = expand_normal (TREE_VALUE (TREE_CHAIN (arglist))); + rtx value = expand_normal (CALL_EXPR_ARG (exp, 1)); if (value != const1_rtx) { @@ -6334,7 +6331,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, break; case BUILT_IN_NONLOCAL_GOTO: - target = expand_builtin_nonlocal_goto (arglist); + target = expand_builtin_nonlocal_goto (exp); if (target) return target; break; @@ -6342,10 +6339,10 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, /* This updates the setjmp buffer that is its argument with the value of the current stack pointer. */ case BUILT_IN_UPDATE_SETJMP_BUF: - if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) + if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE)) { rtx buf_addr - = expand_normal (TREE_VALUE (arglist)); + = expand_normal (CALL_EXPR_ARG (exp, 0)); expand_builtin_update_setjmp_buf (buf_addr); return const0_rtx; @@ -6369,12 +6366,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, break; case BUILT_IN_FPUTS: - target = expand_builtin_fputs (arglist, target, false); + target = expand_builtin_fputs (exp, target, false); if (target) return target; break; case BUILT_IN_FPUTS_UNLOCKED: - target = expand_builtin_fputs (arglist, target, true); + target = expand_builtin_fputs (exp, target, true); if (target) return target; break; @@ -6392,7 +6389,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, break; case BUILT_IN_SPRINTF: - target = expand_builtin_sprintf (arglist, target, mode); + target = expand_builtin_sprintf (exp, target, mode); if (target) return target; break; @@ -6413,35 +6410,35 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_DWARF_SP_COLUMN: return expand_builtin_dwarf_sp_column (); case BUILT_IN_INIT_DWARF_REG_SIZES: - expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist)); + expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0)); return const0_rtx; #endif case BUILT_IN_FROB_RETURN_ADDR: - return expand_builtin_frob_return_addr (TREE_VALUE (arglist)); + return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0)); case BUILT_IN_EXTRACT_RETURN_ADDR: - return expand_builtin_extract_return_addr (TREE_VALUE (arglist)); + return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0)); case BUILT_IN_EH_RETURN: - expand_builtin_eh_return (TREE_VALUE (arglist), - TREE_VALUE (TREE_CHAIN (arglist))); + expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0), + CALL_EXPR_ARG (exp, 1)); return const0_rtx; #ifdef EH_RETURN_DATA_REGNO case BUILT_IN_EH_RETURN_DATA_REGNO: - return expand_builtin_eh_return_data_regno (arglist); + return expand_builtin_eh_return_data_regno (exp); #endif case BUILT_IN_EXTEND_POINTER: - return expand_builtin_extend_pointer (TREE_VALUE (arglist)); + return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0)); case BUILT_IN_VA_START: case BUILT_IN_STDARG_START: - return expand_builtin_va_start (arglist); + return expand_builtin_va_start (exp); case BUILT_IN_VA_END: - return expand_builtin_va_end (arglist); + return expand_builtin_va_end (exp); case BUILT_IN_VA_COPY: - return expand_builtin_va_copy (arglist); + return expand_builtin_va_copy (exp); case BUILT_IN_EXPECT: - return expand_builtin_expect (arglist, target); + return expand_builtin_expect (exp, target); case BUILT_IN_PREFETCH: - expand_builtin_prefetch (arglist); + expand_builtin_prefetch (exp); return const0_rtx; case BUILT_IN_PROFILE_FUNC_ENTER: @@ -6450,9 +6447,9 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, return expand_builtin_profile_func (true); case BUILT_IN_INIT_TRAMPOLINE: - return expand_builtin_init_trampoline (arglist); + return expand_builtin_init_trampoline (exp); case BUILT_IN_ADJUST_TRAMPOLINE: - return expand_builtin_adjust_trampoline (arglist); + return expand_builtin_adjust_trampoline (exp); case BUILT_IN_FORK: case BUILT_IN_EXECL: @@ -6461,7 +6458,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_EXECLE: case BUILT_IN_EXECVP: case BUILT_IN_EXECVE: - target = expand_builtin_fork_or_exec (fndecl, arglist, target, ignore); + target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore); if (target) return target; break; @@ -6472,7 +6469,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_FETCH_AND_ADD_8: case BUILT_IN_FETCH_AND_ADD_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1); - target = expand_builtin_sync_operation (mode, arglist, PLUS, + target = expand_builtin_sync_operation (mode, exp, PLUS, false, target, ignore); if (target) return target; @@ -6484,7 +6481,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_FETCH_AND_SUB_8: case BUILT_IN_FETCH_AND_SUB_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1); - target = expand_builtin_sync_operation (mode, arglist, MINUS, + target = expand_builtin_sync_operation (mode, exp, MINUS, false, target, ignore); if (target) return target; @@ -6496,7 +6493,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_FETCH_AND_OR_8: case BUILT_IN_FETCH_AND_OR_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1); - target = expand_builtin_sync_operation (mode, arglist, IOR, + target = expand_builtin_sync_operation (mode, exp, IOR, false, target, ignore); if (target) return target; @@ -6508,7 +6505,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_FETCH_AND_AND_8: case BUILT_IN_FETCH_AND_AND_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1); - target = expand_builtin_sync_operation (mode, arglist, AND, + target = expand_builtin_sync_operation (mode, exp, AND, false, target, ignore); if (target) return target; @@ -6520,7 +6517,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_FETCH_AND_XOR_8: case BUILT_IN_FETCH_AND_XOR_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1); - target = expand_builtin_sync_operation (mode, arglist, XOR, + target = expand_builtin_sync_operation (mode, exp, XOR, false, target, ignore); if (target) return target; @@ -6532,7 +6529,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_FETCH_AND_NAND_8: case BUILT_IN_FETCH_AND_NAND_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1); - target = expand_builtin_sync_operation (mode, arglist, NOT, + target = expand_builtin_sync_operation (mode, exp, NOT, false, target, ignore); if (target) return target; @@ -6544,7 +6541,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_ADD_AND_FETCH_8: case BUILT_IN_ADD_AND_FETCH_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1); - target = expand_builtin_sync_operation (mode, arglist, PLUS, + target = expand_builtin_sync_operation (mode, exp, PLUS, true, target, ignore); if (target) return target; @@ -6556,7 +6553,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_SUB_AND_FETCH_8: case BUILT_IN_SUB_AND_FETCH_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1); - target = expand_builtin_sync_operation (mode, arglist, MINUS, + target = expand_builtin_sync_operation (mode, exp, MINUS, true, target, ignore); if (target) return target; @@ -6568,7 +6565,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_OR_AND_FETCH_8: case BUILT_IN_OR_AND_FETCH_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1); - target = expand_builtin_sync_operation (mode, arglist, IOR, + target = expand_builtin_sync_operation (mode, exp, IOR, true, target, ignore); if (target) return target; @@ -6580,7 +6577,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_AND_AND_FETCH_8: case BUILT_IN_AND_AND_FETCH_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1); - target = expand_builtin_sync_operation (mode, arglist, AND, + target = expand_builtin_sync_operation (mode, exp, AND, true, target, ignore); if (target) return target; @@ -6592,7 +6589,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_XOR_AND_FETCH_8: case BUILT_IN_XOR_AND_FETCH_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1); - target = expand_builtin_sync_operation (mode, arglist, XOR, + target = expand_builtin_sync_operation (mode, exp, XOR, true, target, ignore); if (target) return target; @@ -6604,7 +6601,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_NAND_AND_FETCH_8: case BUILT_IN_NAND_AND_FETCH_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1); - target = expand_builtin_sync_operation (mode, arglist, NOT, + target = expand_builtin_sync_operation (mode, exp, NOT, true, target, ignore); if (target) return target; @@ -6621,7 +6618,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, target = gen_reg_rtx (mode); mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1); - target = expand_builtin_compare_and_swap (mode, arglist, true, target); + target = expand_builtin_compare_and_swap (mode, exp, true, target); if (target) return target; break; @@ -6632,7 +6629,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_VAL_COMPARE_AND_SWAP_8: case BUILT_IN_VAL_COMPARE_AND_SWAP_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1); - target = expand_builtin_compare_and_swap (mode, arglist, false, target); + target = expand_builtin_compare_and_swap (mode, exp, false, target); if (target) return target; break; @@ -6643,7 +6640,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_LOCK_TEST_AND_SET_8: case BUILT_IN_LOCK_TEST_AND_SET_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1); - target = expand_builtin_lock_test_and_set (mode, arglist, target); + target = expand_builtin_lock_test_and_set (mode, exp, target); if (target) return target; break; @@ -6654,7 +6651,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_LOCK_RELEASE_8: case BUILT_IN_LOCK_RELEASE_16: mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1); - expand_builtin_lock_release (mode, arglist); + expand_builtin_lock_release (mode, exp); return const0_rtx; case BUILT_IN_SYNCHRONIZE: @@ -6706,11 +6703,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, enum built_in_function builtin_mathfn_code (tree t) { - tree fndecl, arglist, parmlist; + tree fndecl, arg, parmlist; tree argtype, parmtype; + call_expr_arg_iterator iter; if (TREE_CODE (t) != CALL_EXPR - || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR) + || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR) return END_BUILTINS; fndecl = get_callee_fndecl (t); @@ -6720,8 +6718,8 @@ builtin_mathfn_code (tree t) || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) return END_BUILTINS; - arglist = TREE_OPERAND (t, 1); parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + init_call_expr_arg_iterator (t, &iter); for (; parmlist; parmlist = TREE_CHAIN (parmlist)) { /* If a function doesn't take a variable number of arguments, @@ -6729,15 +6727,16 @@ builtin_mathfn_code (tree t) parmtype = TREE_VALUE (parmlist); if (VOID_TYPE_P (parmtype)) { - if (arglist) + if (more_call_expr_args_p (&iter)) return END_BUILTINS; return DECL_FUNCTION_CODE (fndecl); } - if (! arglist) + if (! more_call_expr_args_p (&iter)) return END_BUILTINS; - - argtype = TREE_TYPE (TREE_VALUE (arglist)); + + arg = next_call_expr_arg (&iter); + argtype = TREE_TYPE (arg); if (SCALAR_FLOAT_TYPE_P (parmtype)) { @@ -6761,38 +6760,31 @@ builtin_mathfn_code (tree t) } else return END_BUILTINS; - - arglist = TREE_CHAIN (arglist); } /* Variable-length argument list. */ return DECL_FUNCTION_CODE (fndecl); } -/* Fold a call to __builtin_constant_p, if we know it will evaluate to a - constant. ARGLIST is the argument list of the call. */ +/* Fold a call to __builtin_constant_p, if we know its argument ARG will + evaluate to a constant. */ static tree -fold_builtin_constant_p (tree arglist) +fold_builtin_constant_p (tree arg) { - if (arglist == 0) - return 0; - - arglist = TREE_VALUE (arglist); - /* We return 1 for a numeric type that's known to be a constant value at compile-time or for an aggregate type that's a literal constant. */ - STRIP_NOPS (arglist); + STRIP_NOPS (arg); /* If we know this is a constant, emit the constant of one. */ - if (CONSTANT_CLASS_P (arglist) - || (TREE_CODE (arglist) == CONSTRUCTOR - && TREE_CONSTANT (arglist))) + if (CONSTANT_CLASS_P (arg) + || (TREE_CODE (arg) == CONSTRUCTOR + && TREE_CONSTANT (arg))) return integer_one_node; - if (TREE_CODE (arglist) == ADDR_EXPR) + if (TREE_CODE (arg) == ADDR_EXPR) { - tree op = TREE_OPERAND (arglist, 0); + tree op = TREE_OPERAND (arg, 0); if (TREE_CODE (op) == STRING_CST || (TREE_CODE (op) == ARRAY_REF && integer_zerop (TREE_OPERAND (op, 1)) @@ -6807,34 +6799,28 @@ fold_builtin_constant_p (tree arglist) And finally, if we are compiling an initializer, not code, we need to return a definite result now; there's not going to be any more optimization done. */ - if (TREE_SIDE_EFFECTS (arglist) - || AGGREGATE_TYPE_P (TREE_TYPE (arglist)) - || POINTER_TYPE_P (TREE_TYPE (arglist)) + if (TREE_SIDE_EFFECTS (arg) + || AGGREGATE_TYPE_P (TREE_TYPE (arg)) + || POINTER_TYPE_P (TREE_TYPE (arg)) || cfun == 0 || folding_initializer) return integer_zero_node; - return 0; + return NULL_TREE; } -/* Fold a call to __builtin_expect, if we expect that a comparison against - the argument will fold to a constant. In practice, this means a true - constant or the address of a non-weak symbol. ARGLIST is the argument - list of the call. */ +/* Fold a call to __builtin_expect with argument ARG, if we expect that a + comparison against the argument will fold to a constant. In practice, + this means a true constant or the address of a non-weak symbol. */ static tree -fold_builtin_expect (tree arglist) +fold_builtin_expect (tree arg) { - tree arg, inner; - - if (arglist == 0) - return 0; - - arg = TREE_VALUE (arglist); + tree inner; /* If the argument isn't invariant, then there's nothing we can do. */ if (!TREE_INVARIANT (arg)) - return 0; + return NULL_TREE; /* If we're looking at an address of a weak decl, then do not fold. */ inner = arg; @@ -6848,35 +6834,34 @@ fold_builtin_expect (tree arglist) while (TREE_CODE (inner) == COMPONENT_REF || TREE_CODE (inner) == ARRAY_REF); if (DECL_P (inner) && DECL_WEAK (inner)) - return 0; + return NULL_TREE; } /* Otherwise, ARG already has the proper type for the return value. */ return arg; } -/* Fold a call to __builtin_classify_type. */ +/* Fold a call to __builtin_classify_type with argument ARG. */ static tree -fold_builtin_classify_type (tree arglist) +fold_builtin_classify_type (tree arg) { - if (arglist == 0) + if (arg == 0) return build_int_cst (NULL_TREE, no_type_class); - return build_int_cst (NULL_TREE, - type_to_class (TREE_TYPE (TREE_VALUE (arglist)))); + return build_int_cst (NULL_TREE, type_to_class (TREE_TYPE (arg))); } -/* Fold a call to __builtin_strlen. */ +/* Fold a call to __builtin_strlen with argument ARG. */ static tree -fold_builtin_strlen (tree arglist) +fold_builtin_strlen (tree arg) { - if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) + if (!validate_arg (arg, POINTER_TYPE)) return NULL_TREE; else { - tree len = c_strlen (TREE_VALUE (arglist), 0); + tree len = c_strlen (arg, 0); if (len) { @@ -6911,22 +6896,22 @@ fold_builtin_inf (tree type, int warn) return build_real (type, real); } -/* Fold a call to __builtin_nan or __builtin_nans. */ +/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */ static tree -fold_builtin_nan (tree arglist, tree type, int quiet) +fold_builtin_nan (tree arg, tree type, int quiet) { REAL_VALUE_TYPE real; const char *str; - if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) - return 0; - str = c_getstr (TREE_VALUE (arglist)); + if (!validate_arg (arg, POINTER_TYPE)) + return NULL_TREE; + str = c_getstr (arg); if (!str) - return 0; + return NULL_TREE; if (!real_nan (&real, str, quiet, TYPE_MODE (type))) - return 0; + return NULL_TREE; return build_real (type, real); } @@ -6990,8 +6975,8 @@ integer_valued_real_p (tree t) CASE_FLT_FN (BUILT_IN_FMIN): CASE_FLT_FN (BUILT_IN_FMAX): - return integer_valued_real_p (TREE_VALUE (TREE_OPERAND (t, 1))) - && integer_valued_real_p (TREE_VALUE (TREE_CHAIN (TREE_OPERAND (t, 1)))); + return integer_valued_real_p (CALL_EXPR_ARG (t, 0)) + && integer_valued_real_p (CALL_EXPR_ARG (t, 1)); default: break; @@ -7004,20 +6989,18 @@ integer_valued_real_p (tree t) return false; } -/* EXP is assumed to be builtin call where truncation can be propagated +/* FNDECL is assumed to be a builtin where truncation can be propagated across (for instance floor((double)f) == (double)floorf (f). - Do the transformation. */ + Do the transformation for a call with argument ARG. */ static tree -fold_trunc_transparent_mathfn (tree fndecl, tree arglist) +fold_trunc_transparent_mathfn (tree fndecl, tree arg) { enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); - tree arg; - if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (arg, REAL_TYPE)) + return NULL_TREE; - arg = TREE_VALUE (arglist); /* Integer rounding functions are idempotent. */ if (fcode == builtin_mathfn_code (arg)) return arg; @@ -7036,29 +7019,24 @@ fold_trunc_transparent_mathfn (tree fndecl, tree arglist) if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype) && (decl = mathfn_built_in (newtype, fcode))) - { - arglist = - build_tree_list (NULL_TREE, fold_convert (newtype, arg0)); - return fold_convert (ftype, - build_function_call_expr (decl, arglist)); - } + return fold_convert (ftype, + build_call_expr (decl, 1, + fold_convert (newtype, arg0))); } - return 0; + return NULL_TREE; } -/* EXP is assumed to be builtin call which can narrow the FP type of - the argument, for instance lround((double)f) -> lroundf (f). */ +/* FNDECL is assumed to be builtin which can narrow the FP type of + the argument, for instance lround((double)f) -> lroundf (f). + Do the transformation for a call with argument ARG. */ static tree -fold_fixed_mathfn (tree fndecl, tree arglist) +fold_fixed_mathfn (tree fndecl, tree arg) { enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); - tree arg; - - if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; - arg = TREE_VALUE (arglist); + if (!validate_arg (arg, REAL_TYPE)) + return NULL_TREE; /* If argument is already integer valued, and we don't need to worry about setting errno, there's no need to perform rounding. */ @@ -7074,11 +7052,7 @@ fold_fixed_mathfn (tree fndecl, tree arglist) if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype) && (decl = mathfn_built_in (newtype, fcode))) - { - arglist = - build_tree_list (NULL_TREE, fold_convert (newtype, arg0)); - return build_function_call_expr (decl, arglist); - } + return build_call_expr (decl, 1, fold_convert (newtype, arg0)); } /* Canonicalize llround (x) to lround (x) on LP64 targets where @@ -7111,28 +7085,22 @@ fold_fixed_mathfn (tree fndecl, tree arglist) if (newfn) { - tree newcall = build_function_call_expr (newfn, arglist); + tree newcall = build_call_expr(newfn, 1, arg); return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), newcall); } } - return 0; + return NULL_TREE; } -/* Fold function call to builtin cabs, cabsf or cabsl. ARGLIST - is the argument list, TYPE is the return type and FNDECL is the - original function DECL. Return NULL_TREE if no if no simplification - can be made. */ +/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the + return type. Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_cabs (tree arglist, tree type, tree fndecl) +fold_builtin_cabs (tree arg, tree type, tree fndecl) { - tree arg, res; - - if (!arglist || TREE_CHAIN (arglist)) - return NULL_TREE; + tree res; - arg = TREE_VALUE (arglist); if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE) return NULL_TREE; @@ -7170,10 +7138,7 @@ fold_builtin_cabs (tree arglist, tree type, tree fndecl) /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */ if (TREE_CODE (arg) == NEGATE_EXPR || TREE_CODE (arg) == CONJ_EXPR) - { - tree arglist = build_tree_list (NULL_TREE, TREE_OPERAND (arg, 0)); - return build_function_call_expr (fndecl, arglist); - } + return build_call_expr (fndecl, 1, TREE_OPERAND (arg, 0)); /* Don't do this when optimizing for size. */ if (flag_unsafe_math_optimizations @@ -7183,7 +7148,7 @@ fold_builtin_cabs (tree arglist, tree type, tree fndecl) if (sqrtfn != NULL_TREE) { - tree rpart, ipart, result, arglist; + tree rpart, ipart, result; arg = builtin_save_expr (arg); @@ -7199,26 +7164,24 @@ fold_builtin_cabs (tree arglist, tree type, tree fndecl) fold_build2 (MULT_EXPR, type, ipart, ipart)); - arglist = build_tree_list (NULL_TREE, result); - return build_function_call_expr (sqrtfn, arglist); + return build_call_expr (sqrtfn, 1, result); } } return NULL_TREE; } -/* Fold a builtin function call to sqrt, sqrtf, or sqrtl. Return - NULL_TREE if no simplification can be made. */ +/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG. + Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_sqrt (tree arglist, tree type) +fold_builtin_sqrt (tree arg, tree type) { enum built_in_function fcode; - tree arg = TREE_VALUE (arglist); tree res; - - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + + if (!validate_arg (arg, REAL_TYPE)) return NULL_TREE; /* Calculate the result when the argument is a constant. */ @@ -7229,12 +7192,11 @@ fold_builtin_sqrt (tree arglist, tree type) fcode = builtin_mathfn_code (arg); if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode)) { - tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0); + tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0); arg = fold_build2 (MULT_EXPR, type, - TREE_VALUE (TREE_OPERAND (arg, 1)), + CALL_EXPR_ARG (arg, 0), build_real (type, dconsthalf)); - arglist = build_tree_list (NULL_TREE, arg); - return build_function_call_expr (expfn, arglist); + return build_call_expr (expfn, 1, arg); } /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */ @@ -7244,7 +7206,7 @@ fold_builtin_sqrt (tree arglist, tree type) if (powfn) { - tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1)); + tree arg0 = CALL_EXPR_ARG (arg, 0); tree tree_root; /* The inner root was either sqrt or cbrt. */ REAL_VALUE_TYPE dconstroot = @@ -7254,9 +7216,7 @@ fold_builtin_sqrt (tree arglist, tree type) SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1); dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); tree_root = build_real (type, dconstroot); - arglist = tree_cons (NULL_TREE, arg0, - build_tree_list (NULL_TREE, tree_root)); - return build_function_call_expr (powfn, arglist); + return build_call_expr (powfn, 2, arg0, tree_root); } } @@ -7266,32 +7226,30 @@ fold_builtin_sqrt (tree arglist, tree type) || fcode == BUILT_IN_POWF || fcode == BUILT_IN_POWL)) { - tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0); - tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1)); - tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1))); + tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0); + tree arg0 = CALL_EXPR_ARG (arg, 0); + tree arg1 = CALL_EXPR_ARG (arg, 1); tree narg1; if (!tree_expr_nonnegative_p (arg0)) arg0 = build1 (ABS_EXPR, type, arg0); narg1 = fold_build2 (MULT_EXPR, type, arg1, build_real (type, dconsthalf)); - arglist = tree_cons (NULL_TREE, arg0, - build_tree_list (NULL_TREE, narg1)); - return build_function_call_expr (powfn, arglist); + return build_call_expr (powfn, 2, arg0, narg1); } return NULL_TREE; } -/* Fold a builtin function call to cbrt, cbrtf, or cbrtl. Return - NULL_TREE if no simplification can be made. */ +/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG. + Return NULL_TREE if no simplification can be made. */ + static tree -fold_builtin_cbrt (tree arglist, tree type) +fold_builtin_cbrt (tree arg, tree type) { - tree arg = TREE_VALUE (arglist); const enum built_in_function fcode = builtin_mathfn_code (arg); tree res; - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + if (!validate_arg (arg, REAL_TYPE)) return NULL_TREE; /* Calculate the result when the argument is a constant. */ @@ -7303,14 +7261,13 @@ fold_builtin_cbrt (tree arglist, tree type) /* Optimize cbrt(expN(x)) -> expN(x/3). */ if (BUILTIN_EXPONENT_P (fcode)) { - tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0); + tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0); const REAL_VALUE_TYPE third_trunc = real_value_truncate (TYPE_MODE (type), dconstthird); arg = fold_build2 (MULT_EXPR, type, - TREE_VALUE (TREE_OPERAND (arg, 1)), + CALL_EXPR_ARG (arg, 0), build_real (type, third_trunc)); - arglist = build_tree_list (NULL_TREE, arg); - return build_function_call_expr (expfn, arglist); + return build_call_expr (expfn, 1, arg); } /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */ @@ -7320,23 +7277,21 @@ fold_builtin_cbrt (tree arglist, tree type) if (powfn) { - tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1)); + tree arg0 = CALL_EXPR_ARG (arg, 0); tree tree_root; REAL_VALUE_TYPE dconstroot = dconstthird; SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1); dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); tree_root = build_real (type, dconstroot); - arglist = tree_cons (NULL_TREE, arg0, - build_tree_list (NULL_TREE, tree_root)); - return build_function_call_expr (powfn, arglist); + return build_call_expr (powfn, 2, arg0, tree_root); } } /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */ if (BUILTIN_CBRT_P (fcode)) { - tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1)); + tree arg0 = CALL_EXPR_ARG (arg, 0); if (tree_expr_nonnegative_p (arg0)) { tree powfn = mathfn_built_in (type, BUILT_IN_POW); @@ -7349,44 +7304,42 @@ fold_builtin_cbrt (tree arglist, tree type) real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird); dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); tree_root = build_real (type, dconstroot); - arglist = tree_cons (NULL_TREE, arg0, - build_tree_list (NULL_TREE, tree_root)); - return build_function_call_expr (powfn, arglist); + return build_call_expr (powfn, 2, arg0, tree_root); } } } /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */ - if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF + if (fcode == BUILT_IN_POW + || fcode == BUILT_IN_POWF || fcode == BUILT_IN_POWL) { - tree arg00 = TREE_VALUE (TREE_OPERAND (arg, 1)); - tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1))); + tree arg00 = CALL_EXPR_ARG (arg, 0); + tree arg01 = CALL_EXPR_ARG (arg, 1); if (tree_expr_nonnegative_p (arg00)) { - tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0); + tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0); const REAL_VALUE_TYPE dconstroot = real_value_truncate (TYPE_MODE (type), dconstthird); tree narg01 = fold_build2 (MULT_EXPR, type, arg01, build_real (type, dconstroot)); - arglist = tree_cons (NULL_TREE, arg00, - build_tree_list (NULL_TREE, narg01)); - return build_function_call_expr (powfn, arglist); + return build_call_expr (powfn, 2, arg00, narg01); } } } return NULL_TREE; } -/* Fold function call to builtin cos, cosf, or cosl. Return - NULL_TREE if no simplification can be made. */ +/* Fold function call to builtin cos, cosf, or cosl with argument ARG. + TYPE is the type of the return value. Return NULL_TREE if no + simplification can be made. */ + static tree -fold_builtin_cos (tree arglist, tree type, tree fndecl) +fold_builtin_cos (tree arg, tree type, tree fndecl) { - tree arg = TREE_VALUE (arglist); tree res, narg; - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + if (!validate_arg (arg, REAL_TYPE)) return NULL_TREE; /* Calculate the result when the argument is a constant. */ @@ -7395,20 +7348,19 @@ fold_builtin_cos (tree arglist, tree type, tree fndecl) /* Optimize cos(-x) into cos (x). */ if ((narg = fold_strip_sign_ops (arg))) - return build_function_call_expr (fndecl, - build_tree_list (NULL_TREE, narg)); + return build_call_expr (fndecl, 1, narg); return NULL_TREE; } -/* Fold function call to builtin cosh, coshf, or coshl. Return - NULL_TREE if no simplification can be made. */ +/* Fold function call to builtin cosh, coshf, or coshl with argument ARG. + Return NULL_TREE if no simplification can be made. */ + static tree -fold_builtin_cosh (tree arglist, tree type, tree fndecl) +fold_builtin_cosh (tree arg, tree type, tree fndecl) { - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + if (validate_arg (arg, REAL_TYPE)) { - tree arg = TREE_VALUE (arglist); tree res, narg; /* Calculate the result when the argument is a constant. */ @@ -7417,23 +7369,22 @@ fold_builtin_cosh (tree arglist, tree type, tree fndecl) /* Optimize cosh(-x) into cosh (x). */ if ((narg = fold_strip_sign_ops (arg))) - return build_function_call_expr (fndecl, - build_tree_list (NULL_TREE, narg)); + return build_call_expr (fndecl, 1, narg); } return NULL_TREE; } -/* Fold function call to builtin tan, tanf, or tanl. Return - NULL_TREE if no simplification can be made. */ +/* Fold function call to builtin tan, tanf, or tanl with argument ARG. + Return NULL_TREE if no simplification can be made. */ + static tree -fold_builtin_tan (tree arglist, tree type) +fold_builtin_tan (tree arg, tree type) { enum built_in_function fcode; - tree arg = TREE_VALUE (arglist); tree res; - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + if (!validate_arg (arg, REAL_TYPE)) return NULL_TREE; /* Calculate the result when the argument is a constant. */ @@ -7446,7 +7397,7 @@ fold_builtin_tan (tree arglist, tree type) && (fcode == BUILT_IN_ATAN || fcode == BUILT_IN_ATANF || fcode == BUILT_IN_ATANL)) - return TREE_VALUE (TREE_OPERAND (arg, 1)); + return CALL_EXPR_ARG (arg, 0); return NULL_TREE; } @@ -7455,19 +7406,17 @@ fold_builtin_tan (tree arglist, tree type) NULL_TREE if no simplification can be made. */ static tree -fold_builtin_sincos (tree arglist) +fold_builtin_sincos (tree arg0, tree arg1, tree arg2) { - tree type, arg0, arg1, arg2; + tree type; tree res, fn, call; - if (!validate_arglist (arglist, REAL_TYPE, POINTER_TYPE, - POINTER_TYPE, VOID_TYPE)) + if (!validate_arg (arg0, REAL_TYPE) + || !validate_arg (arg1, POINTER_TYPE) + || !validate_arg (arg2, POINTER_TYPE)) return NULL_TREE; - arg0 = TREE_VALUE (arglist); type = TREE_TYPE (arg0); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); /* Calculate the result when the argument is a constant. */ if ((res = do_mpfr_sincos (arg0, arg1, arg2))) @@ -7480,7 +7429,7 @@ fold_builtin_sincos (tree arglist) if (!fn) return NULL_TREE; - call = build_function_call_expr (fn, build_tree_list (NULL_TREE, arg0)); + call = build_call_expr (fn, 1, arg0); call = builtin_save_expr (call); return build2 (COMPOUND_EXPR, type, @@ -7496,15 +7445,14 @@ fold_builtin_sincos (tree arglist) NULL_TREE if no simplification can be made. */ static tree -fold_builtin_cexp (tree arglist, tree type) +fold_builtin_cexp (tree arg0, tree type) { - tree arg0, rtype; + tree rtype; tree realp, imagp, ifn; - if (!validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE)) + if (!validate_arg (arg0, COMPLEX_TYPE)) return NULL_TREE; - arg0 = TREE_VALUE (arglist); rtype = TREE_TYPE (TREE_TYPE (arg0)); /* In case we can figure out the real part of arg0 and it is constant zero @@ -7519,7 +7467,7 @@ fold_builtin_cexp (tree arglist, tree type) && real_zerop (realp)) { tree narg = fold_build1 (IMAGPART_EXPR, rtype, arg0); - return build_function_call_expr (ifn, build_tree_list (NULL_TREE, narg)); + return build_call_expr (ifn, 1, narg); } /* In case we can easily decompose real and imaginary parts split cexp @@ -7537,11 +7485,9 @@ fold_builtin_cexp (tree arglist, tree type) if (!imagp) return NULL_TREE; - icall = build_function_call_expr (ifn, - build_tree_list (NULL_TREE, imagp)); + icall = build_call_expr (ifn, 1, imagp); icall = builtin_save_expr (icall); - rcall = build_function_call_expr (rfn, - build_tree_list (NULL_TREE, realp)); + rcall = build_call_expr (rfn, 1, realp); rcall = builtin_save_expr (rcall); return build2 (COMPLEX_EXPR, type, build2 (MULT_EXPR, rtype, @@ -7555,19 +7501,16 @@ fold_builtin_cexp (tree arglist, tree type) return NULL_TREE; } -/* Fold function call to builtin trunc, truncf or truncl. Return - NULL_TREE if no simplification can be made. */ +/* Fold function call to builtin trunc, truncf or truncl with argument ARG. + Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_trunc (tree fndecl, tree arglist) +fold_builtin_trunc (tree fndecl, tree arg) { - tree arg; - - if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (arg, REAL_TYPE)) + return NULL_TREE; /* Optimize trunc of constant value. */ - arg = TREE_VALUE (arglist); if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)) { REAL_VALUE_TYPE r, x; @@ -7578,22 +7521,19 @@ fold_builtin_trunc (tree fndecl, tree arglist) return build_real (type, r); } - return fold_trunc_transparent_mathfn (fndecl, arglist); + return fold_trunc_transparent_mathfn (fndecl, arg); } -/* Fold function call to builtin floor, floorf or floorl. Return - NULL_TREE if no simplification can be made. */ +/* Fold function call to builtin floor, floorf or floorl with argument ARG. + Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_floor (tree fndecl, tree arglist) +fold_builtin_floor (tree fndecl, tree arg) { - tree arg; - - if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (arg, REAL_TYPE)) + return NULL_TREE; /* Optimize floor of constant value. */ - arg = TREE_VALUE (arglist); if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)) { REAL_VALUE_TYPE x; @@ -7614,25 +7554,22 @@ fold_builtin_floor (tree fndecl, tree arglist) { tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC); if (truncfn) - return build_function_call_expr (truncfn, arglist); + return build_call_expr (truncfn, 1, arg); } - return fold_trunc_transparent_mathfn (fndecl, arglist); + return fold_trunc_transparent_mathfn (fndecl, arg); } -/* Fold function call to builtin ceil, ceilf or ceill. Return - NULL_TREE if no simplification can be made. */ +/* Fold function call to builtin ceil, ceilf or ceill with argument ARG. + Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_ceil (tree fndecl, tree arglist) +fold_builtin_ceil (tree fndecl, tree arg) { - tree arg; - - if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (arg, REAL_TYPE)) + return NULL_TREE; /* Optimize ceil of constant value. */ - arg = TREE_VALUE (arglist); if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)) { REAL_VALUE_TYPE x; @@ -7648,22 +7585,19 @@ fold_builtin_ceil (tree fndecl, tree arglist) } } - return fold_trunc_transparent_mathfn (fndecl, arglist); + return fold_trunc_transparent_mathfn (fndecl, arg); } -/* Fold function call to builtin round, roundf or roundl. Return - NULL_TREE if no simplification can be made. */ +/* Fold function call to builtin round, roundf or roundl with argument ARG. + Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_round (tree fndecl, tree arglist) +fold_builtin_round (tree fndecl, tree arg) { - tree arg; - - if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (arg, REAL_TYPE)) + return NULL_TREE; /* Optimize round of constant value. */ - arg = TREE_VALUE (arglist); if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)) { REAL_VALUE_TYPE x; @@ -7679,23 +7613,21 @@ fold_builtin_round (tree fndecl, tree arglist) } } - return fold_trunc_transparent_mathfn (fndecl, arglist); + return fold_trunc_transparent_mathfn (fndecl, arg); } /* Fold function call to builtin lround, lroundf or lroundl (or the - corresponding long long versions) and other rounding functions. - Return NULL_TREE if no simplification can be made. */ + corresponding long long versions) and other rounding functions. ARG + is the argument to the call. Return NULL_TREE if no simplification + can be made. */ static tree -fold_builtin_int_roundingfn (tree fndecl, tree arglist) +fold_builtin_int_roundingfn (tree fndecl, tree arg) { - tree arg; - - if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (arg, REAL_TYPE)) + return NULL_TREE; /* Optimize lround of constant value. */ - arg = TREE_VALUE (arglist); if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)) { const REAL_VALUE_TYPE x = TREE_REAL_CST (arg); @@ -7747,23 +7679,21 @@ fold_builtin_int_roundingfn (tree fndecl, tree arglist) default:; } - return fold_fixed_mathfn (fndecl, arglist); + return fold_fixed_mathfn (fndecl, arg); } /* Fold function call to builtin ffs, clz, ctz, popcount and parity - and their long and long long variants (i.e. ffsl and ffsll). - Return NULL_TREE if no simplification can be made. */ + and their long and long long variants (i.e. ffsl and ffsll). ARG is + the argument to the call. Return NULL_TREE if no simplification can + be made. */ static tree -fold_builtin_bitop (tree fndecl, tree arglist) +fold_builtin_bitop (tree fndecl, tree arg) { - tree arg; - - if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) + if (!validate_arg (arg, INTEGER_TYPE)) return NULL_TREE; /* Optimize for constant argument. */ - arg = TREE_VALUE (arglist); if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg)) { HOST_WIDE_INT hi, width, result; @@ -7847,15 +7777,12 @@ fold_builtin_bitop (tree fndecl, tree arglist) /* Fold function call to builtin_bswap and the long and long long variants. Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_bswap (tree fndecl, tree arglist) +fold_builtin_bswap (tree fndecl, tree arg) { - tree arg; - - if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (! validate_arg (arg, INTEGER_TYPE)) + return NULL_TREE; /* Optimize constant value. */ - arg = TREE_VALUE (arglist); if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg)) { HOST_WIDE_INT hi, width, r_hi = 0; @@ -7905,6 +7832,7 @@ fold_builtin_bswap (tree fndecl, tree arglist) return NULL_TREE; } + /* Return true if EXPR is the real constant contained in VALUE. */ static bool @@ -7925,13 +7853,12 @@ real_dconstp (tree expr, const REAL_VALUE_TYPE *value) FUNC is the corresponding MPFR logarithm function. */ static tree -fold_builtin_logarithm (tree fndecl, tree arglist, +fold_builtin_logarithm (tree fndecl, tree arg, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t)) { - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + if (validate_arg (arg, REAL_TYPE)) { tree type = TREE_TYPE (TREE_TYPE (fndecl)); - tree arg = TREE_VALUE (arglist); tree res; const enum built_in_function fcode = builtin_mathfn_code (arg); @@ -7961,7 +7888,7 @@ fold_builtin_logarithm (tree fndecl, tree arglist, || fcode == BUILT_IN_EXP2F || fcode == BUILT_IN_EXP2L)) || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode))))) - return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1))); + return fold_convert (type, CALL_EXPR_ARG (arg, 0)); /* Optimize logN(func()) for various exponential functions. We want to determine the value "x" and the power "exponent" in @@ -7976,34 +7903,34 @@ fold_builtin_logarithm (tree fndecl, tree arglist, /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */ x = build_real (type, real_value_truncate (TYPE_MODE (type), dconste)); - exponent = TREE_VALUE (TREE_OPERAND (arg, 1)); + exponent = CALL_EXPR_ARG (arg, 0); break; CASE_FLT_FN (BUILT_IN_EXP2): /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */ x = build_real (type, dconst2); - exponent = TREE_VALUE (TREE_OPERAND (arg, 1)); + exponent = CALL_EXPR_ARG (arg, 0); break; CASE_FLT_FN (BUILT_IN_EXP10): CASE_FLT_FN (BUILT_IN_POW10): /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */ x = build_real (type, dconst10); - exponent = TREE_VALUE (TREE_OPERAND (arg, 1)); + exponent = CALL_EXPR_ARG (arg, 0); break; CASE_FLT_FN (BUILT_IN_SQRT): /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */ - x = TREE_VALUE (TREE_OPERAND (arg, 1)); + x = CALL_EXPR_ARG (arg, 0); exponent = build_real (type, dconsthalf); break; CASE_FLT_FN (BUILT_IN_CBRT): /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */ - x = TREE_VALUE (TREE_OPERAND (arg, 1)); + x = CALL_EXPR_ARG (arg, 0); exponent = build_real (type, real_value_truncate (TYPE_MODE (type), dconstthird)); break; CASE_FLT_FN (BUILT_IN_POW): /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */ - x = TREE_VALUE (TREE_OPERAND (arg, 1)); - exponent = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1))); + x = CALL_EXPR_ARG (arg, 0); + exponent = CALL_EXPR_ARG (arg, 1); break; default: break; @@ -8012,28 +7939,25 @@ fold_builtin_logarithm (tree fndecl, tree arglist, /* Now perform the optimization. */ if (x && exponent) { - tree logfn; - arglist = build_tree_list (NULL_TREE, x); - logfn = build_function_call_expr (fndecl, arglist); + tree logfn = build_call_expr (fndecl, 1, x); return fold_build2 (MULT_EXPR, type, exponent, logfn); } } } - return 0; + return NULL_TREE; } /* Fold a builtin function call to hypot, hypotf, or hypotl. Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_hypot (tree fndecl, tree arglist, tree type) +fold_builtin_hypot (tree fndecl, tree arg0, tree arg1, tree type) { - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); tree res, narg0, narg1; - if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) + if (!validate_arg (arg0, REAL_TYPE) + || !validate_arg (arg1, REAL_TYPE)) return NULL_TREE; /* Calculate the result when the argument is a constant. */ @@ -8046,10 +7970,8 @@ fold_builtin_hypot (tree fndecl, tree arglist, tree type) narg1 = fold_strip_sign_ops (arg1); if (narg0 || narg1) { - tree narglist = tree_cons (NULL_TREE, narg0 ? narg0 : arg0, - build_tree_list (NULL_TREE, - narg1 ? narg1 : arg1)); - return build_function_call_expr (fndecl, narglist); + return build_call_expr (fndecl, 2, narg0 ? narg0 : arg0, + narg1 ? narg1 : arg1); } /* If either argument is zero, hypot is fabs of the other. */ @@ -8076,13 +7998,12 @@ fold_builtin_hypot (tree fndecl, tree arglist, tree type) /* Fold a builtin function call to pow, powf, or powl. Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_pow (tree fndecl, tree arglist, tree type) +fold_builtin_pow (tree fndecl, tree arg0, tree arg1, tree type) { - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); tree res; - if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) + if (!validate_arg (arg0, REAL_TYPE) + || !validate_arg (arg1, REAL_TYPE)) return NULL_TREE; /* Calculate the result when the argument is a constant. */ @@ -8123,10 +8044,7 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT); if (sqrtfn != NULL_TREE) - { - tree arglist = build_tree_list (NULL_TREE, arg0); - return build_function_call_expr (sqrtfn, arglist); - } + return build_call_expr (sqrtfn, 1, arg0); } /* Optimize pow(x,1.0/3.0) = cbrt(x). */ @@ -8139,10 +8057,7 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) { tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT); if (cbrtfn != NULL_TREE) - { - tree arglist = build_tree_list (NULL_TREE, arg0); - return build_function_call_expr (cbrtfn, arglist); - } + return build_call_expr (cbrtfn, 1, arg0); } } @@ -8169,11 +8084,7 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) { tree narg0 = fold_strip_sign_ops (arg0); if (narg0) - { - arglist = build_tree_list (NULL_TREE, arg1); - arglist = tree_cons (NULL_TREE, narg0, arglist); - return build_function_call_expr (fndecl, arglist); - } + return build_call_expr (fndecl, 2, narg0, arg1); } } } @@ -8185,66 +8096,58 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) /* Optimize pow(expN(x),y) = expN(x*y). */ if (BUILTIN_EXPONENT_P (fcode)) { - tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); - tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1)); + tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); + tree arg = CALL_EXPR_ARG (arg0, 0); arg = fold_build2 (MULT_EXPR, type, arg, arg1); - arglist = build_tree_list (NULL_TREE, arg); - return build_function_call_expr (expfn, arglist); + return build_call_expr (expfn, 1, arg); } /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */ if (BUILTIN_SQRT_P (fcode)) { - tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1)); + tree narg0 = CALL_EXPR_ARG (arg0, 0); tree narg1 = fold_build2 (MULT_EXPR, type, arg1, build_real (type, dconsthalf)); - - arglist = tree_cons (NULL_TREE, narg0, - build_tree_list (NULL_TREE, narg1)); - return build_function_call_expr (fndecl, arglist); + return build_call_expr (fndecl, 2, narg0, narg1); } /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */ if (BUILTIN_CBRT_P (fcode)) { - tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1)); + tree arg = CALL_EXPR_ARG (arg0, 0); if (tree_expr_nonnegative_p (arg)) { const REAL_VALUE_TYPE dconstroot = real_value_truncate (TYPE_MODE (type), dconstthird); tree narg1 = fold_build2 (MULT_EXPR, type, arg1, build_real (type, dconstroot)); - arglist = tree_cons (NULL_TREE, arg, - build_tree_list (NULL_TREE, narg1)); - return build_function_call_expr (fndecl, arglist); + return build_call_expr (fndecl, 2, arg, narg1); } } /* Optimize pow(pow(x,y),z) = pow(x,y*z). */ - if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF - || fcode == BUILT_IN_POWL) + if (fcode == BUILT_IN_POW + || fcode == BUILT_IN_POWF + || fcode == BUILT_IN_POWL) { - tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1)); - tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1))); + tree arg00 = CALL_EXPR_ARG (arg0, 0); + tree arg01 = CALL_EXPR_ARG (arg0, 1); tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1); - arglist = tree_cons (NULL_TREE, arg00, - build_tree_list (NULL_TREE, narg1)); - return build_function_call_expr (fndecl, arglist); + return build_call_expr (fndecl, 2, arg00, narg1); } } return NULL_TREE; } -/* Fold a builtin function call to powi, powif, or powil. Return - NULL_TREE if no simplification can be made. */ +/* Fold a builtin function call to powi, powif, or powil with argument ARG. + Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED, tree arglist, tree type) +fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED, + tree arg0, tree arg1, tree type) { - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - - if (!validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE)) + if (!validate_arg (arg0, REAL_TYPE) + || !validate_arg (arg1, INTEGER_TYPE)) return NULL_TREE; /* Optimize pow(1.0,y) = 1.0. */ @@ -8284,17 +8187,16 @@ fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED, tree arglist, tree type) } /* A subroutine of fold_builtin to fold the various exponent - functions. Return NULL_TREE if no simplification can me made. + functions. Return NULL_TREE if no simplification can be made. FUNC is the corresponding MPFR exponent function. */ static tree -fold_builtin_exponent (tree fndecl, tree arglist, +fold_builtin_exponent (tree fndecl, tree arg, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t)) { - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + if (validate_arg (arg, REAL_TYPE)) { tree type = TREE_TYPE (TREE_TYPE (fndecl)); - tree arg = TREE_VALUE (arglist); tree res; /* Calculate the result when the argument is a constant. */ @@ -8318,11 +8220,11 @@ fold_builtin_exponent (tree fndecl, tree arglist, && (fcode == BUILT_IN_LOG10 || fcode == BUILT_IN_LOG10F || fcode == BUILT_IN_LOG10L))) - return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1))); + return fold_convert (type, CALL_EXPR_ARG (arg, 0)); } } - return 0; + return NULL_TREE; } /* Return true if VAR is a VAR_DECL or a component thereof. */ @@ -8340,60 +8242,57 @@ var_decl_component_p (tree var) NULL_TREE if no simplification can be made. */ static tree -fold_builtin_memset (tree arglist, tree type, bool ignore) +fold_builtin_memset (tree dest, tree c, tree len, tree type, bool ignore) { - tree dest, c, len, var, ret; + tree var, ret; unsigned HOST_WIDE_INT length, cval; - if (!validate_arglist (arglist, - POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; - - dest = TREE_VALUE (arglist); - c = TREE_VALUE (TREE_CHAIN (arglist)); - len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + if (! validate_arg (dest, POINTER_TYPE) + || ! validate_arg (c, INTEGER_TYPE) + || ! validate_arg (len, INTEGER_TYPE)) + return NULL_TREE; if (! host_integerp (len, 1)) - return 0; + return NULL_TREE; /* If the LEN parameter is zero, return DEST. */ if (integer_zerop (len)) return omit_one_operand (type, dest, c); if (! host_integerp (c, 1) || TREE_SIDE_EFFECTS (dest)) - return 0; + return NULL_TREE; var = dest; STRIP_NOPS (var); if (TREE_CODE (var) != ADDR_EXPR) - return 0; + return NULL_TREE; var = TREE_OPERAND (var, 0); if (TREE_THIS_VOLATILE (var)) - return 0; + return NULL_TREE; if (!INTEGRAL_TYPE_P (TREE_TYPE (var)) && !POINTER_TYPE_P (TREE_TYPE (var))) - return 0; + return NULL_TREE; if (! var_decl_component_p (var)) - return 0; + return NULL_TREE; length = tree_low_cst (len, 1); if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (var))) != length || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT < (int) length) - return 0; + return NULL_TREE; if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT) - return 0; + return NULL_TREE; if (integer_zerop (c)) cval = 0; else { if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64) - return 0; + return NULL_TREE; cval = tree_low_cst (c, 1); cval &= 0xff; @@ -8414,28 +8313,23 @@ fold_builtin_memset (tree arglist, tree type, bool ignore) NULL_TREE if no simplification can be made. */ static tree -fold_builtin_bzero (tree arglist, bool ignore) +fold_builtin_bzero (tree dest, tree size, bool ignore) { - tree dest, size, newarglist; - - if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (! validate_arg (dest, POINTER_TYPE) + || ! validate_arg (size, INTEGER_TYPE)) + return NULL_TREE; if (!ignore) - return 0; - - dest = TREE_VALUE (arglist); - size = TREE_VALUE (TREE_CHAIN (arglist)); + return NULL_TREE; /* New argument list transforming bzero(ptr x, int y) to memset(ptr x, int 0, size_t y). This is done this way so that if it isn't expanded inline, we fallback to calling bzero instead of memset. */ - newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size)); - newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist); - newarglist = tree_cons (NULL_TREE, dest, newarglist); - return fold_builtin_memset (newarglist, void_type_node, ignore); + return fold_builtin_memset (dest, integer_zero_node, + fold_convert (sizetype, size), + void_type_node, ignore); } /* Fold function call to builtin mem{{,p}cpy,move}. Return @@ -8447,17 +8341,14 @@ fold_builtin_bzero (tree arglist, bool ignore) (memmove). */ static tree -fold_builtin_memory_op (tree arglist, tree type, bool ignore, int endp) +fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, int endp) { - tree dest, src, len, destvar, srcvar, expr; - - if (! validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + tree destvar, srcvar, expr; - dest = TREE_VALUE (arglist); - src = TREE_VALUE (TREE_CHAIN (arglist)); - len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + if (! validate_arg (dest, POINTER_TYPE) + || ! validate_arg (src, POINTER_TYPE) + || ! validate_arg (len, INTEGER_TYPE)) + return NULL_TREE; /* If the LEN parameter is zero, return DEST. */ if (integer_zerop (len)) @@ -8488,14 +8379,14 @@ fold_builtin_memory_op (tree arglist, tree type, bool ignore, int endp) { tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; if (!fn) - return 0; - return build_function_call_expr (fn, arglist); + return NULL_TREE; + return build_call_expr (fn, 3, dest, src, len); } - return 0; + return NULL_TREE; } if (!host_integerp (len, 0)) - return 0; + return NULL_TREE; /* FIXME: This logic lose for arguments like (type *)malloc (sizeof (type)), since we strip the casts of up to VOID return value from malloc. @@ -8511,22 +8402,22 @@ fold_builtin_memory_op (tree arglist, tree type, bool ignore, int endp) || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST || !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len) || !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len)) - return 0; + return NULL_TREE; if (get_pointer_alignment (dest, BIGGEST_ALIGNMENT) < (int) TYPE_ALIGN (desttype) || (get_pointer_alignment (src, BIGGEST_ALIGNMENT) < (int) TYPE_ALIGN (srctype))) - return 0; + return NULL_TREE; if (!ignore) dest = builtin_save_expr (dest); srcvar = build_fold_indirect_ref (src); if (TREE_THIS_VOLATILE (srcvar)) - return 0; + return NULL_TREE; if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len)) - return 0; + return NULL_TREE; /* With memcpy, it is possible to bypass aliasing rules, so without this check i. e. execute/20060930-2.c would be misoptimized, because it use conflicting alias set to hold argument for the memcpy call. @@ -8537,15 +8428,15 @@ fold_builtin_memory_op (tree arglist, tree type, bool ignore, int endp) to char_var='t'; */ || is_gimple_min_invariant (srcvar) || readonly_data_expr (src)) - return 0; + return NULL_TREE; destvar = build_fold_indirect_ref (dest); if (TREE_THIS_VOLATILE (destvar)) - return 0; + return NULL_TREE; if (!tree_int_cst_equal (lang_hooks.expr_size (destvar), len)) - return 0; + return NULL_TREE; if (!var_decl_component_p (destvar)) - return 0; + return NULL_TREE; if (srctype == desttype || (gimple_in_ssa_p (cfun) @@ -8568,7 +8459,7 @@ fold_builtin_memory_op (tree arglist, tree type, bool ignore, int endp) return omit_one_operand (type, dest, expr); if (expr == len) - expr = 0; + expr = NULL_TREE; if (endp == 2) len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len, @@ -8582,95 +8473,55 @@ fold_builtin_memory_op (tree arglist, tree type, bool ignore, int endp) return dest; } -/* Fold function call to builtin bcopy. Return NULL_TREE if no - simplification can be made. */ - -static tree -fold_builtin_bcopy (tree arglist, bool ignore) -{ - tree src, dest, size, newarglist; - - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; - - if (! ignore) - return 0; - - src = TREE_VALUE (arglist); - dest = TREE_VALUE (TREE_CHAIN (arglist)); - size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); - - /* New argument list transforming bcopy(ptr x, ptr y, int z) to - memmove(ptr y, ptr x, size_t z). This is done this way - so that if it isn't expanded inline, we fallback to - calling bcopy instead of memmove. */ - - newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size)); - newarglist = tree_cons (NULL_TREE, src, newarglist); - newarglist = tree_cons (NULL_TREE, dest, newarglist); - - return fold_builtin_memory_op (newarglist, void_type_node, true, /*endp=*/3); -} - -/* Fold function call to builtin strcpy. If LEN is not NULL, it represents - the length of the string to be copied. Return NULL_TREE if no - simplification can be made. */ +/* Fold function call to builtin strcpy with arguments DEST and SRC. + If LEN is not NULL, it represents the length of the string to be + copied. Return NULL_TREE if no simplification can be made. */ tree -fold_builtin_strcpy (tree fndecl, tree arglist, tree len) +fold_builtin_strcpy (tree fndecl, tree dest, tree src, tree len) { - tree dest, src, fn; - - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - return 0; + tree fn; - dest = TREE_VALUE (arglist); - src = TREE_VALUE (TREE_CHAIN (arglist)); + if (!validate_arg (dest, POINTER_TYPE) + || !validate_arg (src, POINTER_TYPE)) + return NULL_TREE; /* If SRC and DEST are the same (and not volatile), return DEST. */ if (operand_equal_p (src, dest, 0)) return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest); if (optimize_size) - return 0; + return NULL_TREE; fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; if (!fn) - return 0; + return NULL_TREE; if (!len) { len = c_strlen (src, 1); if (! len || TREE_SIDE_EFFECTS (len)) - return 0; + return NULL_TREE; } len = size_binop (PLUS_EXPR, len, ssize_int (1)); - arglist = build_tree_list (NULL_TREE, len); - arglist = tree_cons (NULL_TREE, src, arglist); - arglist = tree_cons (NULL_TREE, dest, arglist); return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), - build_function_call_expr (fn, arglist)); + build_call_expr (fn, 3, dest, src, len)); } -/* Fold function call to builtin strncpy. If SLEN is not NULL, it represents - the length of the source string. Return NULL_TREE if no simplification - can be made. */ +/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN. + If SLEN is not NULL, it represents the length of the source string. + Return NULL_TREE if no simplification can be made. */ tree -fold_builtin_strncpy (tree fndecl, tree arglist, tree slen) +fold_builtin_strncpy (tree fndecl, tree dest, tree src, tree len, tree slen) { - tree dest, src, len, fn; - - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + tree fn; - dest = TREE_VALUE (arglist); - src = TREE_VALUE (TREE_CHAIN (arglist)); - len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + if (!validate_arg (dest, POINTER_TYPE) + || !validate_arg (src, POINTER_TYPE) + || !validate_arg (len, INTEGER_TYPE)) + return NULL_TREE; /* If the LEN parameter is zero, return DEST. */ if (integer_zerop (len)) @@ -8679,14 +8530,14 @@ fold_builtin_strncpy (tree fndecl, tree arglist, tree slen) /* We can't compare slen with len as constants below if len is not a constant. */ if (len == 0 || TREE_CODE (len) != INTEGER_CST) - return 0; + return NULL_TREE; if (!slen) slen = c_strlen (src, 1); /* Now, we must be passed a constant src ptr parameter. */ if (slen == 0 || TREE_CODE (slen) != INTEGER_CST) - return 0; + return NULL_TREE; slen = size_binop (PLUS_EXPR, slen, ssize_int (1)); @@ -8694,32 +8545,28 @@ fold_builtin_strncpy (tree fndecl, tree arglist, tree slen) support it when expanding trees into RTL. */ /* FIXME: generate a call to __builtin_memset. */ if (tree_int_cst_lt (slen, len)) - return 0; + return NULL_TREE; /* OK transform into builtin memcpy. */ fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; if (!fn) - return 0; + return NULL_TREE; return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), - build_function_call_expr (fn, arglist)); + build_call_expr (fn, 3, dest, src, len)); } -/* Fold function call to builtin memcmp. Return - NULL_TREE if no simplification can be made. */ +/* Fold function call to builtin memcmp with arguments ARG1 and ARG2. + Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_memcmp (tree arglist) +fold_builtin_memcmp (tree arg1, tree arg2, tree len) { - tree arg1, arg2, len; const char *p1, *p2; - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; - - arg1 = TREE_VALUE (arglist); - arg2 = TREE_VALUE (TREE_CHAIN (arglist)); - len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + if (!validate_arg (arg1, POINTER_TYPE) + || !validate_arg (arg2, POINTER_TYPE) + || !validate_arg (len, INTEGER_TYPE)) + return NULL_TREE; /* If the LEN parameter is zero, return zero. */ if (integer_zerop (len)) @@ -8768,23 +8615,20 @@ fold_builtin_memcmp (tree arglist) return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2); } - return 0; + return NULL_TREE; } -/* Fold function call to builtin strcmp. Return - NULL_TREE if no simplification can be made. */ +/* Fold function call to builtin strcmp with arguments ARG1 and ARG2. + Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_strcmp (tree arglist) +fold_builtin_strcmp (tree arg1, tree arg2) { - tree arg1, arg2; const char *p1, *p2; - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - return 0; - - arg1 = TREE_VALUE (arglist); - arg2 = TREE_VALUE (TREE_CHAIN (arglist)); + if (!validate_arg (arg1, POINTER_TYPE) + || !validate_arg (arg2, POINTER_TYPE)) + return NULL_TREE; /* If ARG1 and ARG2 are the same (and not volatile), return zero. */ if (operand_equal_p (arg1, arg2, 0)) @@ -8831,25 +8675,21 @@ fold_builtin_strcmp (tree arglist) return fold_build1 (NEGATE_EXPR, integer_type_node, temp); } - return 0; + return NULL_TREE; } -/* Fold function call to builtin strncmp. Return - NULL_TREE if no simplification can be made. */ +/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN. + Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_strncmp (tree arglist) +fold_builtin_strncmp (tree arg1, tree arg2, tree len) { - tree arg1, arg2, len; const char *p1, *p2; - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; - - arg1 = TREE_VALUE (arglist); - arg2 = TREE_VALUE (TREE_CHAIN (arglist)); - len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + if (!validate_arg (arg1, POINTER_TYPE) + || !validate_arg (arg2, POINTER_TYPE) + || !validate_arg (len, INTEGER_TYPE)) + return NULL_TREE; /* If the LEN parameter is zero, return zero. */ if (integer_zerop (len)) @@ -8926,23 +8766,20 @@ fold_builtin_strncmp (tree arglist) return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2); } - return 0; + return NULL_TREE; } -/* Fold function call to builtin signbit, signbitf or signbitl. Return - NULL_TREE if no simplification can be made. */ +/* Fold function call to builtin signbit, signbitf or signbitl with argument + ARG. Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_signbit (tree fndecl, tree arglist) +fold_builtin_signbit (tree arg, tree type) { - tree type = TREE_TYPE (TREE_TYPE (fndecl)); - tree arg, temp; + tree temp; - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + if (!validate_arg (arg, REAL_TYPE)) return NULL_TREE; - arg = TREE_VALUE (arglist); - /* If ARG is a compile-time constant, determine the result. */ if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)) @@ -8966,20 +8803,19 @@ fold_builtin_signbit (tree fndecl, tree arglist) return NULL_TREE; } -/* Fold function call to builtin copysign, copysignf or copysignl. - Return NULL_TREE if no simplification can be made. */ +/* Fold function call to builtin copysign, copysignf or copysignl with + arguments ARG1 and ARG2. Return NULL_TREE if no simplification can + be made. */ static tree -fold_builtin_copysign (tree fndecl, tree arglist, tree type) +fold_builtin_copysign (tree fndecl, tree arg1, tree arg2, tree type) { - tree arg1, arg2, tem; + tree tem; - if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) + if (!validate_arg (arg1, REAL_TYPE) + || !validate_arg (arg2, REAL_TYPE)) return NULL_TREE; - arg1 = TREE_VALUE (arglist); - arg2 = TREE_VALUE (TREE_CHAIN (arglist)); - /* copysign(X,X) is X. */ if (operand_equal_p (arg1, arg2, 0)) return fold_convert (type, arg1); @@ -9009,26 +8845,21 @@ fold_builtin_copysign (tree fndecl, tree arglist, tree type) /* Strip sign changing operations for the first argument. */ tem = fold_strip_sign_ops (arg1); if (tem) - { - arglist = tree_cons (NULL_TREE, tem, TREE_CHAIN (arglist)); - return build_function_call_expr (fndecl, arglist); - } + return build_call_expr (fndecl, 2, tem, arg2); return NULL_TREE; } -/* Fold a call to builtin isascii. */ +/* Fold a call to builtin isascii with argument ARG. */ static tree -fold_builtin_isascii (tree arglist) +fold_builtin_isascii (tree arg) { - if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (arg, INTEGER_TYPE)) + return NULL_TREE; else { /* Transform isascii(c) -> ((c & ~0x7f) == 0). */ - tree arg = TREE_VALUE (arglist); - arg = build2 (BIT_AND_EXPR, integer_type_node, arg, build_int_cst (NULL_TREE, ~ (unsigned HOST_WIDE_INT) 0x7f)); @@ -9037,43 +8868,38 @@ fold_builtin_isascii (tree arglist) } } -/* Fold a call to builtin toascii. */ +/* Fold a call to builtin toascii with argument ARG. */ static tree -fold_builtin_toascii (tree arglist) +fold_builtin_toascii (tree arg) { - if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) - return 0; - else - { - /* Transform toascii(c) -> (c & 0x7f). */ - tree arg = TREE_VALUE (arglist); - - return fold_build2 (BIT_AND_EXPR, integer_type_node, arg, - build_int_cst (NULL_TREE, 0x7f)); - } + if (!validate_arg (arg, INTEGER_TYPE)) + return NULL_TREE; + + /* Transform toascii(c) -> (c & 0x7f). */ + return fold_build2 (BIT_AND_EXPR, integer_type_node, arg, + build_int_cst (NULL_TREE, 0x7f)); } -/* Fold a call to builtin isdigit. */ +/* Fold a call to builtin isdigit with argument ARG. */ static tree -fold_builtin_isdigit (tree arglist) +fold_builtin_isdigit (tree arg) { - if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (arg, INTEGER_TYPE)) + return NULL_TREE; else { /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */ /* According to the C standard, isdigit is unaffected by locale. However, it definitely is affected by the target character set. */ - tree arg; unsigned HOST_WIDE_INT target_digit0 = lang_hooks.to_target_charset ('0'); if (target_digit0 == 0) return NULL_TREE; - arg = fold_convert (unsigned_type_node, TREE_VALUE (arglist)); + arg = fold_convert (unsigned_type_node, arg); arg = build2 (MINUS_EXPR, unsigned_type_node, arg, build_int_cst (unsigned_type_node, target_digit0)); return fold_build2 (LE_EXPR, integer_type_node, arg, @@ -9081,34 +8907,28 @@ fold_builtin_isdigit (tree arglist) } } -/* Fold a call to fabs, fabsf or fabsl. */ +/* Fold a call to fabs, fabsf or fabsl with argument ARG. */ static tree -fold_builtin_fabs (tree arglist, tree type) +fold_builtin_fabs (tree arg, tree type) { - tree arg; - - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (arg, REAL_TYPE)) + return NULL_TREE; - arg = TREE_VALUE (arglist); arg = fold_convert (type, arg); if (TREE_CODE (arg) == REAL_CST) return fold_abs_const (arg, type); return fold_build1 (ABS_EXPR, type, arg); } -/* Fold a call to abs, labs, llabs or imaxabs. */ +/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */ static tree -fold_builtin_abs (tree arglist, tree type) +fold_builtin_abs (tree arg, tree type) { - tree arg; - - if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (arg, INTEGER_TYPE)) + return NULL_TREE; - arg = TREE_VALUE (arglist); arg = fold_convert (type, arg); if (TREE_CODE (arg) == INTEGER_CST) return fold_abs_const (arg, type); @@ -9118,12 +8938,10 @@ fold_builtin_abs (tree arglist, tree type) /* Fold a call to builtin fmin or fmax. */ static tree -fold_builtin_fmin_fmax (tree arglist, tree type, bool max) +fold_builtin_fmin_fmax (tree arg0, tree arg1, tree type, bool max) { - if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) + if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE)) { - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); /* Calculate the result when the argument is a constant. */ tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min)); @@ -9164,20 +8982,18 @@ fold_builtin_fmin_fmax (tree arglist, tree type, bool max) /* Fold a call to builtin carg(a+bi) -> atan2(b,a). */ static tree -fold_builtin_carg (tree arglist, tree type) +fold_builtin_carg (tree arg, tree type) { - if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE)) + if (validate_arg (arg, COMPLEX_TYPE)) { tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2); if (atan2_fn) { - tree arg = builtin_save_expr (TREE_VALUE (arglist)); - tree r_arg = fold_build1 (REALPART_EXPR, type, arg); - tree i_arg = fold_build1 (IMAGPART_EXPR, type, arg); - tree newarglist = tree_cons (NULL_TREE, i_arg, - build_tree_list (NULL_TREE, r_arg)); - return build_function_call_expr (atan2_fn, newarglist); + tree new_arg = builtin_save_expr (arg); + tree r_arg = fold_build1 (REALPART_EXPR, type, new_arg); + tree i_arg = fold_build1 (IMAGPART_EXPR, type, new_arg); + return build_call_expr (atan2_fn, 2, i_arg, r_arg); } } @@ -9185,39 +9001,21 @@ fold_builtin_carg (tree arglist, tree type) } /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite. - EXP is the CALL_EXPR for the call. */ + ARG is the argument for the call. */ static tree -fold_builtin_classify (tree fndecl, tree arglist, int builtin_index) +fold_builtin_classify (tree fndecl, tree arg, int builtin_index) { tree type = TREE_TYPE (TREE_TYPE (fndecl)); - tree arg; REAL_VALUE_TYPE r; - if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + if (!validate_arg (arg, REAL_TYPE)) { - /* Check that we have exactly one argument. */ - if (arglist == 0) - { - error ("too few arguments to function %qs", - IDENTIFIER_POINTER (DECL_NAME (fndecl))); - return error_mark_node; - } - else if (TREE_CHAIN (arglist) != 0) - { - error ("too many arguments to function %qs", - IDENTIFIER_POINTER (DECL_NAME (fndecl))); - return error_mark_node; - } - else - { - error ("non-floating-point argument to function %qs", - IDENTIFIER_POINTER (DECL_NAME (fndecl))); - return error_mark_node; - } + error ("non-floating-point argument to function %qs", + IDENTIFIER_POINTER (DECL_NAME (fndecl))); + return error_mark_node; } - arg = TREE_VALUE (arglist); switch (builtin_index) { case BUILT_IN_ISINF: @@ -9270,44 +9068,23 @@ fold_builtin_classify (tree fndecl, tree arglist, int builtin_index) /* Fold a call to an unordered comparison function such as __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function - being called and ARGLIST is the argument list for the call. + being called and ARG0 and ARG1 are the arguments for the call. UNORDERED_CODE and ORDERED_CODE are comparison codes that give the opposite of the desired result. UNORDERED_CODE is used for modes that can hold NaNs and ORDERED_CODE is used for the rest. */ static tree -fold_builtin_unordered_cmp (tree fndecl, tree arglist, +fold_builtin_unordered_cmp (tree fndecl, tree arg0, tree arg1, enum tree_code unordered_code, enum tree_code ordered_code) { tree type = TREE_TYPE (TREE_TYPE (fndecl)); enum tree_code code; - tree arg0, arg1; tree type0, type1; enum tree_code code0, code1; tree cmp_type = NULL_TREE; - if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) - { - /* Check that we have exactly two arguments. */ - if (arglist == 0 || TREE_CHAIN (arglist) == 0) - { - error ("too few arguments to function %qs", - IDENTIFIER_POINTER (DECL_NAME (fndecl))); - return error_mark_node; - } - else if (TREE_CHAIN (TREE_CHAIN (arglist)) != 0) - { - error ("too many arguments to function %qs", - IDENTIFIER_POINTER (DECL_NAME (fndecl))); - return error_mark_node; - } - } - - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - type0 = TREE_TYPE (arg0); type1 = TREE_TYPE (arg1); @@ -9345,79 +9122,51 @@ fold_builtin_unordered_cmp (tree fndecl, tree arglist, fold_build2 (code, type, arg0, arg1)); } -/* Used by constant folding to simplify calls to builtin functions. EXP is - the CALL_EXPR of a call to a builtin function. IGNORE is true if the - result of the function call is ignored. This function returns NULL_TREE - if no simplification was possible. */ +/* Fold a call to built-in function FNDECL with 0 arguments. + IGNORE is true if the result of the function call is ignored. This + function returns NULL_TREE if no simplification was possible. */ static tree -fold_builtin_1 (tree fndecl, tree arglist, bool ignore) +fold_builtin_0 (tree fndecl, bool ignore ATTRIBUTE_UNUSED) { tree type = TREE_TYPE (TREE_TYPE (fndecl)); - enum built_in_function fcode; - - if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) - return targetm.fold_builtin (fndecl, arglist, ignore); - - fcode = DECL_FUNCTION_CODE (fndecl); + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); switch (fcode) { - case BUILT_IN_FPUTS: - return fold_builtin_fputs (arglist, ignore, false, NULL_TREE); - - case BUILT_IN_FPUTS_UNLOCKED: - return fold_builtin_fputs (arglist, ignore, true, NULL_TREE); - - case BUILT_IN_STRSTR: - return fold_builtin_strstr (arglist, type); - - case BUILT_IN_STRCAT: - return fold_builtin_strcat (arglist); - - case BUILT_IN_STRNCAT: - return fold_builtin_strncat (arglist); - - case BUILT_IN_STRSPN: - return fold_builtin_strspn (arglist); - - case BUILT_IN_STRCSPN: - return fold_builtin_strcspn (arglist); - - case BUILT_IN_STRCHR: - case BUILT_IN_INDEX: - return fold_builtin_strchr (arglist, type); - - case BUILT_IN_STRRCHR: - case BUILT_IN_RINDEX: - return fold_builtin_strrchr (arglist, type); - - case BUILT_IN_STRCPY: - return fold_builtin_strcpy (fndecl, arglist, NULL_TREE); - - case BUILT_IN_STRNCPY: - return fold_builtin_strncpy (fndecl, arglist, NULL_TREE); + CASE_FLT_FN (BUILT_IN_INF): + case BUILT_IN_INFD32: + case BUILT_IN_INFD64: + case BUILT_IN_INFD128: + return fold_builtin_inf (type, true); - case BUILT_IN_STRCMP: - return fold_builtin_strcmp (arglist); + CASE_FLT_FN (BUILT_IN_HUGE_VAL): + return fold_builtin_inf (type, false); - case BUILT_IN_STRNCMP: - return fold_builtin_strncmp (arglist); + case BUILT_IN_CLASSIFY_TYPE: + return fold_builtin_classify_type (NULL_TREE); - case BUILT_IN_STRPBRK: - return fold_builtin_strpbrk (arglist, type); + default: + break; + } + return NULL_TREE; +} - case BUILT_IN_BCMP: - case BUILT_IN_MEMCMP: - return fold_builtin_memcmp (arglist); +/* Fold a call to built-in function FNDECL with 1 argument, ARG0. + IGNORE is true if the result of the function call is ignored. This + function returns NULL_TREE if no simplification was possible. */ - case BUILT_IN_SPRINTF: - return fold_builtin_sprintf (arglist, ignore); +static tree +fold_builtin_1 (tree fndecl, tree arg0, bool ignore) +{ + tree type = TREE_TYPE (TREE_TYPE (fndecl)); + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + switch (fcode) + { case BUILT_IN_CONSTANT_P: { - tree val; + tree val = fold_builtin_constant_p (arg0); - val = fold_builtin_constant_p (arglist); /* Gimplification will pull the CALL_EXPR for the builtin out of an if condition. When not optimizing, we'll not CSE it back. To avoid link error types of regressions, return false now. */ @@ -9427,257 +9176,195 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore) return val; } - case BUILT_IN_EXPECT: - return fold_builtin_expect (arglist); - case BUILT_IN_CLASSIFY_TYPE: - return fold_builtin_classify_type (arglist); + return fold_builtin_classify_type (arg0); case BUILT_IN_STRLEN: - return fold_builtin_strlen (arglist); + return fold_builtin_strlen (arg0); CASE_FLT_FN (BUILT_IN_FABS): - return fold_builtin_fabs (arglist, type); + return fold_builtin_fabs (arg0, type); case BUILT_IN_ABS: case BUILT_IN_LABS: case BUILT_IN_LLABS: case BUILT_IN_IMAXABS: - return fold_builtin_abs (arglist, type); + return fold_builtin_abs (arg0, type); CASE_FLT_FN (BUILT_IN_CONJ): - if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE)) - return fold_build1 (CONJ_EXPR, type, TREE_VALUE (arglist)); - break; + if (validate_arg (arg0, COMPLEX_TYPE)) + return fold_build1 (CONJ_EXPR, type, arg0); + break; CASE_FLT_FN (BUILT_IN_CREAL): - if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE)) - return non_lvalue (fold_build1 (REALPART_EXPR, type, - TREE_VALUE (arglist))); - break; + if (validate_arg (arg0, COMPLEX_TYPE)) + return non_lvalue (fold_build1 (REALPART_EXPR, type, arg0));; + break; CASE_FLT_FN (BUILT_IN_CIMAG): - if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE)) - return non_lvalue (fold_build1 (IMAGPART_EXPR, type, - TREE_VALUE (arglist))); - break; + if (validate_arg (arg0, COMPLEX_TYPE)) + return non_lvalue (fold_build1 (IMAGPART_EXPR, type, arg0)); + break; CASE_FLT_FN (BUILT_IN_CCOS): CASE_FLT_FN (BUILT_IN_CCOSH): /* These functions are "even", i.e. f(x) == f(-x). */ - if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE)) - { - tree narg = fold_strip_sign_ops (TREE_VALUE (arglist)); + if (validate_arg (arg0, COMPLEX_TYPE)) + { + tree narg = fold_strip_sign_ops (arg0); if (narg) - return build_function_call_expr (fndecl, - build_tree_list (NULL_TREE, narg)); + return build_call_expr (fndecl, 1, narg); } - break; + break; CASE_FLT_FN (BUILT_IN_CABS): - return fold_builtin_cabs (arglist, type, fndecl); + return fold_builtin_cabs (arg0, type, fndecl); CASE_FLT_FN (BUILT_IN_CARG): - return fold_builtin_carg (arglist, type); + return fold_builtin_carg (arg0, type); CASE_FLT_FN (BUILT_IN_SQRT): - return fold_builtin_sqrt (arglist, type); + return fold_builtin_sqrt (arg0, type); CASE_FLT_FN (BUILT_IN_CBRT): - return fold_builtin_cbrt (arglist, type); + return fold_builtin_cbrt (arg0, type); CASE_FLT_FN (BUILT_IN_ASIN): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_asin, + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_asin, &dconstm1, &dconst1, true); break; CASE_FLT_FN (BUILT_IN_ACOS): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_acos, + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_acos, &dconstm1, &dconst1, true); break; CASE_FLT_FN (BUILT_IN_ATAN): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_atan, - NULL, NULL, 0); + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0); break; CASE_FLT_FN (BUILT_IN_ASINH): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_asinh, - NULL, NULL, 0); + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0); break; CASE_FLT_FN (BUILT_IN_ACOSH): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_acosh, + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_acosh, &dconst1, NULL, true); break; CASE_FLT_FN (BUILT_IN_ATANH): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_atanh, + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_atanh, &dconstm1, &dconst1, false); break; CASE_FLT_FN (BUILT_IN_SIN): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_sin, - NULL, NULL, 0); + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0); break; CASE_FLT_FN (BUILT_IN_COS): - return fold_builtin_cos (arglist, type, fndecl); + return fold_builtin_cos (arg0, type, fndecl); + break; CASE_FLT_FN (BUILT_IN_TAN): - return fold_builtin_tan (arglist, type); - - CASE_FLT_FN (BUILT_IN_SINCOS): - return fold_builtin_sincos (arglist); + return fold_builtin_tan (arg0, type); CASE_FLT_FN (BUILT_IN_CEXP): - return fold_builtin_cexp (arglist, type); + return fold_builtin_cexp (arg0, type); CASE_FLT_FN (BUILT_IN_CEXPI): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_sincos (TREE_VALUE (arglist), NULL_TREE, NULL_TREE); + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE); + break; CASE_FLT_FN (BUILT_IN_SINH): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_sinh, - NULL, NULL, 0); + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0); break; CASE_FLT_FN (BUILT_IN_COSH): - return fold_builtin_cosh (arglist, type, fndecl); + return fold_builtin_cosh (arg0, type, fndecl); CASE_FLT_FN (BUILT_IN_TANH): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_tanh, - NULL, NULL, 0); + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0); break; CASE_FLT_FN (BUILT_IN_ERF): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_erf, - NULL, NULL, 0); + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0); break; CASE_FLT_FN (BUILT_IN_ERFC): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_erfc, - NULL, NULL, 0); + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0); break; CASE_FLT_FN (BUILT_IN_TGAMMA): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_gamma, - NULL, NULL, 0); + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0); break; CASE_FLT_FN (BUILT_IN_EXP): - return fold_builtin_exponent (fndecl, arglist, mpfr_exp); + return fold_builtin_exponent (fndecl, arg0, mpfr_exp); CASE_FLT_FN (BUILT_IN_EXP2): - return fold_builtin_exponent (fndecl, arglist, mpfr_exp2); + return fold_builtin_exponent (fndecl, arg0, mpfr_exp2); CASE_FLT_FN (BUILT_IN_EXP10): CASE_FLT_FN (BUILT_IN_POW10): - return fold_builtin_exponent (fndecl, arglist, mpfr_exp10); + return fold_builtin_exponent (fndecl, arg0, mpfr_exp10); CASE_FLT_FN (BUILT_IN_EXPM1): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_expm1, - NULL, NULL, 0); + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0); break; CASE_FLT_FN (BUILT_IN_LOG): - return fold_builtin_logarithm (fndecl, arglist, mpfr_log); + return fold_builtin_logarithm (fndecl, arg0, mpfr_log); CASE_FLT_FN (BUILT_IN_LOG2): - return fold_builtin_logarithm (fndecl, arglist, mpfr_log2); + return fold_builtin_logarithm (fndecl, arg0, mpfr_log2); CASE_FLT_FN (BUILT_IN_LOG10): - return fold_builtin_logarithm (fndecl, arglist, mpfr_log10); + return fold_builtin_logarithm (fndecl, arg0, mpfr_log10); CASE_FLT_FN (BUILT_IN_LOG1P): - if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_log1p, + if (validate_arg (arg0, REAL_TYPE)) + return do_mpfr_arg1 (arg0, type, mpfr_log1p, &dconstm1, NULL, false); break; - CASE_FLT_FN (BUILT_IN_ATAN2): - if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg2 (TREE_VALUE (arglist), - TREE_VALUE (TREE_CHAIN (arglist)), - type, mpfr_atan2); - break; - - CASE_FLT_FN (BUILT_IN_FDIM): - if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg2 (TREE_VALUE (arglist), - TREE_VALUE (TREE_CHAIN (arglist)), - type, mpfr_dim); - break; - - CASE_FLT_FN (BUILT_IN_FMA): - if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE)) - return do_mpfr_arg3 (TREE_VALUE (arglist), - TREE_VALUE (TREE_CHAIN (arglist)), - TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))), - type, mpfr_fma); - break; - - CASE_FLT_FN (BUILT_IN_FMIN): - return fold_builtin_fmin_fmax (arglist, type, /*max=*/false); - - CASE_FLT_FN (BUILT_IN_FMAX): - return fold_builtin_fmin_fmax (arglist, type, /*max=*/true); - - CASE_FLT_FN (BUILT_IN_HYPOT): - return fold_builtin_hypot (fndecl, arglist, type); - - CASE_FLT_FN (BUILT_IN_POW): - return fold_builtin_pow (fndecl, arglist, type); - - CASE_FLT_FN (BUILT_IN_POWI): - return fold_builtin_powi (fndecl, arglist, type); - - CASE_FLT_FN (BUILT_IN_INF): - case BUILT_IN_INFD32: - case BUILT_IN_INFD64: - case BUILT_IN_INFD128: - return fold_builtin_inf (type, true); - - CASE_FLT_FN (BUILT_IN_HUGE_VAL): - return fold_builtin_inf (type, false); - CASE_FLT_FN (BUILT_IN_NAN): case BUILT_IN_NAND32: case BUILT_IN_NAND64: case BUILT_IN_NAND128: - return fold_builtin_nan (arglist, type, true); + return fold_builtin_nan (arg0, type, true); CASE_FLT_FN (BUILT_IN_NANS): - return fold_builtin_nan (arglist, type, false); + return fold_builtin_nan (arg0, type, false); CASE_FLT_FN (BUILT_IN_FLOOR): - return fold_builtin_floor (fndecl, arglist); + return fold_builtin_floor (fndecl, arg0); CASE_FLT_FN (BUILT_IN_CEIL): - return fold_builtin_ceil (fndecl, arglist); + return fold_builtin_ceil (fndecl, arg0); CASE_FLT_FN (BUILT_IN_TRUNC): - return fold_builtin_trunc (fndecl, arglist); + return fold_builtin_trunc (fndecl, arg0); CASE_FLT_FN (BUILT_IN_ROUND): - return fold_builtin_round (fndecl, arglist); + return fold_builtin_round (fndecl, arg0); CASE_FLT_FN (BUILT_IN_NEARBYINT): CASE_FLT_FN (BUILT_IN_RINT): - return fold_trunc_transparent_mathfn (fndecl, arglist); + return fold_trunc_transparent_mathfn (fndecl, arg0); CASE_FLT_FN (BUILT_IN_LCEIL): CASE_FLT_FN (BUILT_IN_LLCEIL): @@ -9685,139 +9372,411 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore) CASE_FLT_FN (BUILT_IN_LLFLOOR): CASE_FLT_FN (BUILT_IN_LROUND): CASE_FLT_FN (BUILT_IN_LLROUND): - return fold_builtin_int_roundingfn (fndecl, arglist); + return fold_builtin_int_roundingfn (fndecl, arg0); CASE_FLT_FN (BUILT_IN_LRINT): CASE_FLT_FN (BUILT_IN_LLRINT): - return fold_fixed_mathfn (fndecl, arglist); + return fold_fixed_mathfn (fndecl, arg0); case BUILT_IN_BSWAP32: case BUILT_IN_BSWAP64: - return fold_builtin_bswap (fndecl, arglist); + return fold_builtin_bswap (fndecl, arg0); CASE_INT_FN (BUILT_IN_FFS): CASE_INT_FN (BUILT_IN_CLZ): CASE_INT_FN (BUILT_IN_CTZ): CASE_INT_FN (BUILT_IN_POPCOUNT): CASE_INT_FN (BUILT_IN_PARITY): - return fold_builtin_bitop (fndecl, arglist); - - case BUILT_IN_MEMSET: - return fold_builtin_memset (arglist, type, ignore); - - case BUILT_IN_MEMCPY: - return fold_builtin_memory_op (arglist, type, ignore, /*endp=*/0); - - case BUILT_IN_MEMPCPY: - return fold_builtin_memory_op (arglist, type, ignore, /*endp=*/1); - - case BUILT_IN_MEMMOVE: - return fold_builtin_memory_op (arglist, type, ignore, /*endp=*/3); - - case BUILT_IN_BZERO: - return fold_builtin_bzero (arglist, ignore); - - case BUILT_IN_BCOPY: - return fold_builtin_bcopy (arglist, ignore); + return fold_builtin_bitop (fndecl, arg0); CASE_FLT_FN (BUILT_IN_SIGNBIT): - return fold_builtin_signbit (fndecl, arglist); + return fold_builtin_signbit (arg0, type); case BUILT_IN_ISASCII: - return fold_builtin_isascii (arglist); + return fold_builtin_isascii (arg0); case BUILT_IN_TOASCII: - return fold_builtin_toascii (arglist); + return fold_builtin_toascii (arg0); case BUILT_IN_ISDIGIT: - return fold_builtin_isdigit (arglist); - - CASE_FLT_FN (BUILT_IN_COPYSIGN): - return fold_builtin_copysign (fndecl, arglist, type); + return fold_builtin_isdigit (arg0); CASE_FLT_FN (BUILT_IN_FINITE): case BUILT_IN_FINITED32: case BUILT_IN_FINITED64: case BUILT_IN_FINITED128: - return fold_builtin_classify (fndecl, arglist, BUILT_IN_FINITE); + return fold_builtin_classify (fndecl, arg0, BUILT_IN_FINITE); CASE_FLT_FN (BUILT_IN_ISINF): case BUILT_IN_ISINFD32: case BUILT_IN_ISINFD64: case BUILT_IN_ISINFD128: - return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISINF); + return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISINF); CASE_FLT_FN (BUILT_IN_ISNAN): case BUILT_IN_ISNAND32: case BUILT_IN_ISNAND64: case BUILT_IN_ISNAND128: - return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISNAN); + return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISNAN); + + case BUILT_IN_PRINTF: + case BUILT_IN_PRINTF_UNLOCKED: + case BUILT_IN_VPRINTF: + return fold_builtin_printf (fndecl, arg0, NULL_TREE, ignore, fcode); + + default: + break; + } + + return NULL_TREE; + +} + +/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1. + IGNORE is true if the result of the function call is ignored. This + function returns NULL_TREE if no simplification was possible. */ + +static tree +fold_builtin_2 (tree fndecl, tree arg0, tree arg1, bool ignore) +{ + tree type = TREE_TYPE (TREE_TYPE (fndecl)); + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + + switch (fcode) + { + + CASE_FLT_FN (BUILT_IN_ATAN2): + if (validate_arg (arg0, REAL_TYPE) + && validate_arg(arg1, REAL_TYPE)) + return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2); + break; + + CASE_FLT_FN (BUILT_IN_FDIM): + if (validate_arg (arg0, REAL_TYPE) + && validate_arg(arg1, REAL_TYPE)) + return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim); + break; + + CASE_FLT_FN (BUILT_IN_HYPOT): + return fold_builtin_hypot (fndecl, arg0, arg1, type); + + case BUILT_IN_BZERO: + return fold_builtin_bzero (arg0, arg1, ignore); + + case BUILT_IN_FPUTS: + return fold_builtin_fputs (arg0, arg1, ignore, false, NULL_TREE); + + case BUILT_IN_FPUTS_UNLOCKED: + return fold_builtin_fputs (arg0, arg1, ignore, true, NULL_TREE); + + case BUILT_IN_STRSTR: + return fold_builtin_strstr (arg0, arg1, type); + + case BUILT_IN_STRCAT: + return fold_builtin_strcat (arg0, arg1); + + case BUILT_IN_STRSPN: + return fold_builtin_strspn (arg0, arg1); + + case BUILT_IN_STRCSPN: + return fold_builtin_strcspn (arg0, arg1); + + case BUILT_IN_STRCHR: + case BUILT_IN_INDEX: + return fold_builtin_strchr (arg0, arg1, type); + + case BUILT_IN_STRRCHR: + case BUILT_IN_RINDEX: + return fold_builtin_strrchr (arg0, arg1, type); + + case BUILT_IN_STRCPY: + return fold_builtin_strcpy (fndecl, arg0, arg1, NULL_TREE); + + case BUILT_IN_STRCMP: + return fold_builtin_strcmp (arg0, arg1); + + case BUILT_IN_STRPBRK: + return fold_builtin_strpbrk (arg0, arg1, type); + + case BUILT_IN_EXPECT: + return fold_builtin_expect (arg0); + + CASE_FLT_FN (BUILT_IN_POW): + return fold_builtin_pow (fndecl, arg0, arg1, type); + + CASE_FLT_FN (BUILT_IN_POWI): + return fold_builtin_powi (fndecl, arg0, arg1, type); + + CASE_FLT_FN (BUILT_IN_COPYSIGN): + return fold_builtin_copysign (fndecl, arg0, arg1, type); + + CASE_FLT_FN (BUILT_IN_FMIN): + return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/false); + + CASE_FLT_FN (BUILT_IN_FMAX): + return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/true); case BUILT_IN_ISGREATER: - return fold_builtin_unordered_cmp (fndecl, arglist, UNLE_EXPR, LE_EXPR); + return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLE_EXPR, LE_EXPR); case BUILT_IN_ISGREATEREQUAL: - return fold_builtin_unordered_cmp (fndecl, arglist, UNLT_EXPR, LT_EXPR); + return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLT_EXPR, LT_EXPR); case BUILT_IN_ISLESS: - return fold_builtin_unordered_cmp (fndecl, arglist, UNGE_EXPR, GE_EXPR); + return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGE_EXPR, GE_EXPR); case BUILT_IN_ISLESSEQUAL: - return fold_builtin_unordered_cmp (fndecl, arglist, UNGT_EXPR, GT_EXPR); + return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGT_EXPR, GT_EXPR); case BUILT_IN_ISLESSGREATER: - return fold_builtin_unordered_cmp (fndecl, arglist, UNEQ_EXPR, EQ_EXPR); + return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNEQ_EXPR, EQ_EXPR); case BUILT_IN_ISUNORDERED: - return fold_builtin_unordered_cmp (fndecl, arglist, UNORDERED_EXPR, + return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNORDERED_EXPR, NOP_EXPR); /* We do the folding for va_start in the expander. */ case BUILT_IN_VA_START: break; + case BUILT_IN_SPRINTF: + return fold_builtin_sprintf (arg0, arg1, NULL_TREE, ignore); + case BUILT_IN_OBJECT_SIZE: - return fold_builtin_object_size (arglist); - case BUILT_IN_MEMCPY_CHK: - case BUILT_IN_MEMPCPY_CHK: - case BUILT_IN_MEMMOVE_CHK: - case BUILT_IN_MEMSET_CHK: - return fold_builtin_memory_chk (fndecl, arglist, NULL_TREE, ignore, - DECL_FUNCTION_CODE (fndecl)); - case BUILT_IN_STRCPY_CHK: - case BUILT_IN_STPCPY_CHK: - return fold_builtin_stxcpy_chk (fndecl, arglist, NULL_TREE, ignore, - DECL_FUNCTION_CODE (fndecl)); - case BUILT_IN_STRNCPY_CHK: - return fold_builtin_strncpy_chk (arglist, NULL_TREE); - case BUILT_IN_STRCAT_CHK: - return fold_builtin_strcat_chk (fndecl, arglist); - case BUILT_IN_STRNCAT_CHK: - return fold_builtin_strncat_chk (fndecl, arglist); - case BUILT_IN_SPRINTF_CHK: - case BUILT_IN_VSPRINTF_CHK: - return fold_builtin_sprintf_chk (arglist, DECL_FUNCTION_CODE (fndecl)); - case BUILT_IN_SNPRINTF_CHK: - case BUILT_IN_VSNPRINTF_CHK: - return fold_builtin_snprintf_chk (arglist, NULL_TREE, - DECL_FUNCTION_CODE (fndecl)); + return fold_builtin_object_size (arg0, arg1); case BUILT_IN_PRINTF: case BUILT_IN_PRINTF_UNLOCKED: case BUILT_IN_VPRINTF: + return fold_builtin_printf (fndecl, arg0, arg1, ignore, fcode); + case BUILT_IN_PRINTF_CHK: case BUILT_IN_VPRINTF_CHK: - return fold_builtin_printf (fndecl, arglist, ignore, - DECL_FUNCTION_CODE (fndecl)); + if (!validate_arg (arg0, INTEGER_TYPE) + || TREE_SIDE_EFFECTS (arg0)) + return NULL_TREE; + else + return fold_builtin_printf (fndecl, arg1, NULL_TREE, ignore, fcode); + break; case BUILT_IN_FPRINTF: case BUILT_IN_FPRINTF_UNLOCKED: case BUILT_IN_VFPRINTF: + return fold_builtin_fprintf (fndecl, arg0, arg1, NULL_TREE, + ignore, fcode); + + default: + break; + } + return NULL_TREE; +} + +/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1, + and ARG2. IGNORE is true if the result of the function call is ignored. + This function returns NULL_TREE if no simplification was possible. */ + +static tree +fold_builtin_3 (tree fndecl, tree arg0, tree arg1, tree arg2, bool ignore) +{ + tree type = TREE_TYPE (TREE_TYPE (fndecl)); + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + switch (fcode) + { + + CASE_FLT_FN (BUILT_IN_SINCOS): + return fold_builtin_sincos (arg0, arg1, arg2); + + CASE_FLT_FN (BUILT_IN_FMA): + if (validate_arg (arg0, REAL_TYPE) + && validate_arg(arg1, REAL_TYPE) + && validate_arg(arg2, REAL_TYPE)) + return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma); + break; + + case BUILT_IN_MEMSET: + return fold_builtin_memset (arg0, arg1, arg2, type, ignore); + + case BUILT_IN_BCOPY: + return fold_builtin_memory_op (arg1, arg0, arg2, void_type_node, true, /*endp=*/3); + + case BUILT_IN_MEMCPY: + return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/0); + + case BUILT_IN_MEMPCPY: + return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/1); + + case BUILT_IN_MEMMOVE: + return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/3); + + case BUILT_IN_STRNCAT: + return fold_builtin_strncat (arg0, arg1, arg2); + + case BUILT_IN_STRNCPY: + return fold_builtin_strncpy (fndecl, arg0, arg1, arg2, NULL_TREE); + + case BUILT_IN_STRNCMP: + return fold_builtin_strncmp (arg0, arg1, arg2); + + case BUILT_IN_BCMP: + case BUILT_IN_MEMCMP: + return fold_builtin_memcmp (arg0, arg1, arg2);; + + case BUILT_IN_SPRINTF: + return fold_builtin_sprintf (arg0, arg1, arg2, ignore); + + case BUILT_IN_STRCPY_CHK: + case BUILT_IN_STPCPY_CHK: + return fold_builtin_stxcpy_chk (fndecl, arg0, arg1, arg2, NULL_TREE, + ignore, fcode); + + case BUILT_IN_STRCAT_CHK: + return fold_builtin_strcat_chk (fndecl, arg0, arg1, arg2); + + case BUILT_IN_PRINTF_CHK: + case BUILT_IN_VPRINTF_CHK: + if (!validate_arg (arg0, INTEGER_TYPE) + || TREE_SIDE_EFFECTS (arg0)) + return NULL_TREE; + else + return fold_builtin_printf (fndecl, arg1, arg2, ignore, fcode); + break; + + case BUILT_IN_FPRINTF: + case BUILT_IN_FPRINTF_UNLOCKED: + case BUILT_IN_VFPRINTF: + return fold_builtin_fprintf (fndecl, arg0, arg1, arg2, ignore, fcode); + case BUILT_IN_FPRINTF_CHK: case BUILT_IN_VFPRINTF_CHK: - return fold_builtin_fprintf (fndecl, arglist, ignore, - DECL_FUNCTION_CODE (fndecl)); + if (!validate_arg (arg1, INTEGER_TYPE) + || TREE_SIDE_EFFECTS (arg1)) + return NULL_TREE; + else + return fold_builtin_fprintf (fndecl, arg0, arg2, NULL_TREE, + ignore, fcode); default: break; } + return NULL_TREE; +} - return 0; +/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1, + ARG2, and ARG3. IGNORE is true if the result of the function call is + ignored. This function returns NULL_TREE if no simplification was + possible. */ + +static tree +fold_builtin_4 (tree fndecl, tree arg0, tree arg1, tree arg2, tree arg3, + bool ignore) +{ + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + + switch (fcode) + { + case BUILT_IN_MEMCPY_CHK: + case BUILT_IN_MEMPCPY_CHK: + case BUILT_IN_MEMMOVE_CHK: + case BUILT_IN_MEMSET_CHK: + return fold_builtin_memory_chk (fndecl, arg0, arg1, arg2, arg3, + NULL_TREE, ignore, + DECL_FUNCTION_CODE (fndecl)); + + case BUILT_IN_STRNCPY_CHK: + return fold_builtin_strncpy_chk (arg0, arg1, arg2, arg3, NULL_TREE); + + case BUILT_IN_STRNCAT_CHK: + return fold_builtin_strncat_chk (fndecl, arg0, arg1, arg2, arg3); + + case BUILT_IN_FPRINTF_CHK: + case BUILT_IN_VFPRINTF_CHK: + if (!validate_arg (arg1, INTEGER_TYPE) + || TREE_SIDE_EFFECTS (arg1)) + return NULL_TREE; + else + return fold_builtin_fprintf (fndecl, arg0, arg2, arg3, + ignore, fcode); + break; + + default: + break; + } + return NULL_TREE; +} + +/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS + arguments, where NARGS <= 4. IGNORE is true if the result of the + function call is ignored. This function returns NULL_TREE if no + simplification was possible. Note that this only folds builtins with + fixed argument patterns. Foldings that do varargs-to-varargs + transformations, or that match calls with more than 4 arguments, + need to be handled with fold_builtin_varargs instead. */ + +#define MAX_ARGS_TO_FOLD_BUILTIN 4 + +static tree +fold_builtin_n (tree fndecl, tree *args, int nargs, bool ignore) +{ + tree ret = NULL_TREE; + switch (nargs) + { + case 0: + ret = fold_builtin_0 (fndecl, ignore); + break; + case 1: + ret = fold_builtin_1 (fndecl, args[0], ignore); + break; + case 2: + ret = fold_builtin_2 (fndecl, args[0], args[1], ignore); + break; + case 3: + ret = fold_builtin_3 (fndecl, args[0], args[1], args[2], ignore); + break; + case 4: + ret = fold_builtin_4 (fndecl, args[0], args[1], args[2], args[3], + ignore); + break; + default: + break; + } + if (ret) + { + ret = build1 (NOP_EXPR, GENERIC_TREE_TYPE (ret), ret); + TREE_NO_WARNING (ret) = 1; + return ret; + } + return NULL_TREE; +} + +/* Builtins with folding operations that operate on "..." arguments + need special handling; we need to store the arguments in a convenient + data structure before attempting any folding. Fortunately there are + only a few builtins that fall into this category. FNDECL is the + function, EXP is the CALL_EXPR for the call, and IGNORE is true if the + result of the function call is ignored. */ + +static tree +fold_builtin_varargs (tree fndecl, tree exp, bool ignore ATTRIBUTE_UNUSED) +{ + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + tree ret = NULL_TREE; + + switch (fcode) + { + case BUILT_IN_SPRINTF_CHK: + case BUILT_IN_VSPRINTF_CHK: + ret = fold_builtin_sprintf_chk (exp, fcode); + break; + + case BUILT_IN_SNPRINTF_CHK: + case BUILT_IN_VSNPRINTF_CHK: + ret = fold_builtin_snprintf_chk (exp, NULL_TREE, fcode); + + default: + break; + } + if (ret) + { + ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret); + TREE_NO_WARNING (ret) = 1; + return ret; + } + return NULL_TREE; } /* A wrapper function for builtin folding that prevents warnings for @@ -9825,43 +9784,249 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore) call node earlier than the warning is generated. */ tree -fold_builtin (tree fndecl, tree arglist, bool ignore) +fold_call_expr (tree exp, bool ignore) +{ + tree ret = NULL_TREE; + tree fndecl = get_callee_fndecl (exp); + if (fndecl + && TREE_CODE (fndecl) == FUNCTION_DECL + && DECL_BUILT_IN (fndecl)) + { + /* 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); + ret = fold_builtin_n (fndecl, args, nargs, ignore); + } + if (!ret) + ret = fold_builtin_varargs (fndecl, exp, ignore); + if (ret) + { + /* Propagate location information from original call to + expansion of builtin. Otherwise things like + maybe_emit_chk_warning, that operate on the expansion + of a builtin, will use the wrong location information. */ + if (CAN_HAVE_LOCATION_P (exp) && EXPR_HAS_LOCATION (exp)) + { + tree realret = ret; + if (TREE_CODE (ret) == NOP_EXPR) + realret = TREE_OPERAND (ret, 0); + if (CAN_HAVE_LOCATION_P (realret) + && !EXPR_HAS_LOCATION (realret)) + SET_EXPR_LOCATION (realret, EXPR_LOCATION (exp)); + } + return ret; + } + } + } + return NULL_TREE; +} + +/* Conveniently construct a function call expression. FNDECL names the + function to be called and ARGLIST is a TREE_LIST of arguments. */ + +tree +build_function_call_expr (tree fndecl, tree arglist) +{ + tree fntype = TREE_TYPE (fndecl); + tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); + return fold_builtin_call_list (TREE_TYPE (fntype), fn, arglist); +} + +/* Construct a CALL_EXPR with type TYPE with FN as the function expression. + ARGLIST is a TREE_LIST of arguments. */ + +tree +fold_builtin_call_list (tree type, tree fn, tree arglist) { - tree exp = fold_builtin_1 (fndecl, arglist, ignore); - if (exp && !ignore) + tree ret = NULL_TREE; + if (TREE_CODE (fn) == ADDR_EXPR) { - exp = build1 (NOP_EXPR, GENERIC_TREE_TYPE (exp), exp); - TREE_NO_WARNING (exp) = 1; + tree fndecl = TREE_OPERAND (fn, 0); + if (TREE_CODE (fndecl) == FUNCTION_DECL + && DECL_BUILT_IN (fndecl)) + { + /* FIXME: Don't use a list in this interface. */ + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) + { + ret = targetm.fold_builtin (fndecl, arglist, false); + if (ret) + return ret; + } + else + { + tree tail = arglist; + tree args[MAX_ARGS_TO_FOLD_BUILTIN]; + int nargs; + tree exp; + + for (nargs = 0; nargs < MAX_ARGS_TO_FOLD_BUILTIN; nargs++) + { + if (!tail) + break; + args[nargs] = TREE_VALUE (tail); + tail = TREE_CHAIN (tail); + } + if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN) + { + ret = fold_builtin_n (fndecl, args, nargs, false); + if (ret) + return ret; + } + exp = build_call_list (type, fn, arglist); + ret = fold_builtin_varargs (fndecl, exp, false); + return ret ? ret : exp; + } + } } + return build_call_list (type, fn, arglist); +} + +/* Conveniently construct a function call expression. FNDECL names the + function to be called, N is the number of arguments, and the "..." + parameters are the argument expressions. */ + +tree +build_call_expr (tree fndecl, int n, ...) +{ + va_list ap; + tree ret; + tree fntype = TREE_TYPE (fndecl); + tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); - return exp; + va_start (ap, n); + ret = fold_builtin_call_valist (TREE_TYPE (fntype), fn, n, ap); + va_end (ap); + return ret; } -/* Conveniently construct a function call expression. */ +/* Construct a CALL_EXPR with type TYPE with FN as the function expression. + N arguments are passed in the va_list AP. */ tree -build_function_call_expr (tree fn, tree arglist) +fold_builtin_call_valist (tree type, + tree fn, + int n, + va_list ap) { - tree call_expr; + tree ret = NULL_TREE; + int i; + tree exp; + + if (TREE_CODE (fn) == ADDR_EXPR) + { + tree fndecl = TREE_OPERAND (fn, 0); + if (TREE_CODE (fndecl) == FUNCTION_DECL + && DECL_BUILT_IN (fndecl)) + { + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) + { + tree arglist = NULL_TREE; + va_list ap0; + va_copy (ap0, ap); + for (i = 0; i < n; i++) + { + tree arg = va_arg (ap0, tree); + arglist = tree_cons (NULL_TREE, arg, arglist); + } + va_end (ap0); + arglist = nreverse (arglist); + ret = targetm.fold_builtin (fndecl, arglist, false); + if (ret) + return ret; + } + else if (n <= MAX_ARGS_TO_FOLD_BUILTIN) + { + /* First try the transformations that don't require consing up + an exp. */ + tree args[MAX_ARGS_TO_FOLD_BUILTIN]; + va_list ap0; + va_copy (ap0, ap); + for (i = 0; i < n; i++) + args[i] = va_arg (ap0, tree); + va_end (ap0); + ret = fold_builtin_n (fndecl, args, n, false); + if (ret) + return ret; + } + + /* If we got this far, we need to build an exp. */ + exp = build_call_valist (type, fn, n, ap); + ret = fold_builtin_varargs (fndecl, exp, false); + return ret ? ret : exp; + } + } - call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); - return fold_build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), - call_expr, arglist, NULL_TREE); + return build_call_valist (type, fn, n, ap); +} + +/* Construct a new CALL_EXPR using the tail of the argument list of EXP + along with N new arguments specified as the "..." parameters. SKIP + is the number of arguments in EXP to be omitted. This function is used + to do varargs-to-varargs transformations. */ + +static tree +rewrite_call_expr (tree exp, int skip, tree fndecl, int n, ...) +{ + int oldnargs = call_expr_nargs (exp); + int nargs = oldnargs - skip + n; + tree fntype = TREE_TYPE (fndecl); + tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); + tree *buffer; + + if (n > 0) + { + int i, j; + va_list ap; + + buffer = alloca (nargs * sizeof (tree)); + va_start (ap, n); + for (i = 0; i < n; i++) + buffer[i] = va_arg (ap, tree); + va_end (ap); + for (j = skip; j < oldnargs; j++, i++) + buffer[i] = CALL_EXPR_ARG (exp, j); + } + else + buffer = CALL_EXPR_ARGP (exp) + skip; + + return fold (build_call_array (TREE_TYPE (exp), fn, nargs, buffer)); +} + +/* Validate a single argument ARG against a tree code CODE representing + a type. */ + +static bool +validate_arg (tree arg, enum tree_code code) +{ + if (!arg) + return false; + else if (code == POINTER_TYPE) + return POINTER_TYPE_P (TREE_TYPE (arg)); + return code == TREE_CODE (TREE_TYPE (arg)); } /* This function validates the types of a function call argument list - represented as a tree chain of parameters against a specified list - of tree_codes. If the last specifier is a 0, that represents an - ellipses, otherwise the last specifier must be a VOID_TYPE. */ + against a specified list of tree_codes. If the last specifier is a 0, + that represents an ellipses, otherwise the last specifier must be a + VOID_TYPE. */ -int -validate_arglist (tree arglist, ...) +bool +validate_arglist (tree callexpr, ...) { enum tree_code code; - int res = 0; + bool res = 0; va_list ap; + call_expr_arg_iterator iter; + tree arg; - va_start (ap, arglist); + va_start (ap, callexpr); + init_call_expr_arg_iterator (callexpr, &iter); do { @@ -9870,29 +10035,22 @@ validate_arglist (tree arglist, ...) { case 0: /* This signifies an ellipses, any further arguments are all ok. */ - res = 1; + res = true; goto end; case VOID_TYPE: /* This signifies an endlink, if no arguments remain, return true, otherwise return false. */ - res = arglist == 0; + res = !more_call_expr_args_p (&iter); goto end; default: /* If no parameters remain or the parameter's code does not match the specified code, return false. Otherwise continue checking any remaining arguments. */ - if (arglist == 0) - goto end; - if (code == POINTER_TYPE) - { - if (! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))) - goto end; - } - else if (code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist)))) + arg = next_call_expr_arg (&iter); + if (!validate_arg (arg, code)) goto end; break; } - arglist = TREE_CHAIN (arglist); } while (1); @@ -9942,9 +10100,10 @@ readonly_data_expr (tree exp) return false; } -/* Simplify a call to the strstr builtin. +/* Simplify a call to the strstr builtin. S1 and S2 are the arguments + to the call, and TYPE is its return type. - Return 0 if no simplification was possible, otherwise return the + Return NULL_TREE if no simplification was possible, otherwise return the simplified form of the call as a tree. The simplified form may be a constant or other expression which @@ -9960,19 +10119,19 @@ readonly_data_expr (tree exp) form of the builtin function call. */ static tree -fold_builtin_strstr (tree arglist, tree type) +fold_builtin_strstr (tree s1, tree s2, tree type) { - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (s1, POINTER_TYPE) + || !validate_arg (s2, POINTER_TYPE)) + return NULL_TREE; else { - tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); tree fn; const char *p1, *p2; p2 = c_getstr (s2); if (p2 == NULL) - return 0; + return NULL_TREE; p1 = c_getstr (s1); if (p1 != NULL) @@ -9995,24 +10154,22 @@ fold_builtin_strstr (tree arglist, tree type) return fold_convert (type, s1); if (p2[1] != '\0') - return 0; + return NULL_TREE; fn = implicit_built_in_decls[BUILT_IN_STRCHR]; if (!fn) - return 0; + return NULL_TREE; /* New argument list transforming strstr(s1, s2) to strchr(s1, s2[0]). */ - arglist = build_tree_list (NULL_TREE, - build_int_cst (NULL_TREE, p2[0])); - arglist = tree_cons (NULL_TREE, s1, arglist); - return build_function_call_expr (fn, arglist); + return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0])); } } -/* Simplify a call to the strchr builtin. +/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to + the call, and TYPE is its return type. - Return 0 if no simplification was possible, otherwise return the + Return NULL_TREE if no simplification was possible, otherwise return the simplified form of the call as a tree. The simplified form may be a constant or other expression which @@ -10028,17 +10185,17 @@ fold_builtin_strstr (tree arglist, tree type) form of the builtin function call. */ static tree -fold_builtin_strchr (tree arglist, tree type) +fold_builtin_strchr (tree s1, tree s2, tree type) { - if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (s1, POINTER_TYPE) + || !validate_arg (s2, INTEGER_TYPE)) + return NULL_TREE; else { - tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); const char *p1; if (TREE_CODE (s2) != INTEGER_CST) - return 0; + return NULL_TREE; p1 = c_getstr (s1); if (p1 != NULL) @@ -10048,7 +10205,7 @@ fold_builtin_strchr (tree arglist, tree type) tree tem; if (target_char_cast (s2, &c)) - return 0; + return NULL_TREE; r = strchr (p1, c); @@ -10060,13 +10217,14 @@ fold_builtin_strchr (tree arglist, tree type) s1, build_int_cst (TREE_TYPE (s1), r - p1)); return fold_convert (type, tem); } - return 0; + return NULL_TREE; } } -/* Simplify a call to the strrchr builtin. +/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to + the call, and TYPE is its return type. - Return 0 if no simplification was possible, otherwise return the + Return NULL_TREE if no simplification was possible, otherwise return the simplified form of the call as a tree. The simplified form may be a constant or other expression which @@ -10082,18 +10240,18 @@ fold_builtin_strchr (tree arglist, tree type) form of the builtin function call. */ static tree -fold_builtin_strrchr (tree arglist, tree type) +fold_builtin_strrchr (tree s1, tree s2, tree type) { - if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (s1, POINTER_TYPE) + || !validate_arg (s2, INTEGER_TYPE)) + return NULL_TREE; else { - tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); tree fn; const char *p1; if (TREE_CODE (s2) != INTEGER_CST) - return 0; + return NULL_TREE; p1 = c_getstr (s1); if (p1 != NULL) @@ -10103,7 +10261,7 @@ fold_builtin_strrchr (tree arglist, tree type) tree tem; if (target_char_cast (s2, &c)) - return 0; + return NULL_TREE; r = strrchr (p1, c); @@ -10117,20 +10275,21 @@ fold_builtin_strrchr (tree arglist, tree type) } if (! integer_zerop (s2)) - return 0; + return NULL_TREE; fn = implicit_built_in_decls[BUILT_IN_STRCHR]; if (!fn) - return 0; + return NULL_TREE; /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */ - return build_function_call_expr (fn, arglist); + return build_call_expr (fn, 2, s1, s2); } } -/* Simplify a call to the strpbrk builtin. +/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments + to the call, and TYPE is its return type. - Return 0 if no simplification was possible, otherwise return the + Return NULL_TREE if no simplification was possible, otherwise return the simplified form of the call as a tree. The simplified form may be a constant or other expression which @@ -10146,19 +10305,19 @@ fold_builtin_strrchr (tree arglist, tree type) form of the builtin function call. */ static tree -fold_builtin_strpbrk (tree arglist, tree type) +fold_builtin_strpbrk (tree s1, tree s2, tree type) { - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (s1, POINTER_TYPE) + || !validate_arg (s2, POINTER_TYPE)) + return NULL_TREE; else { - tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); tree fn; const char *p1, *p2; p2 = c_getstr (s2); if (p2 == NULL) - return 0; + return NULL_TREE; p1 = c_getstr (s1); if (p1 != NULL) @@ -10181,24 +10340,22 @@ fold_builtin_strpbrk (tree arglist, tree type) return omit_one_operand (TREE_TYPE (s1), integer_zero_node, s1); if (p2[1] != '\0') - return 0; /* Really call strpbrk. */ + return NULL_TREE; /* Really call strpbrk. */ fn = implicit_built_in_decls[BUILT_IN_STRCHR]; if (!fn) - return 0; + return NULL_TREE; /* New argument list transforming strpbrk(s1, s2) to strchr(s1, s2[0]). */ - arglist = build_tree_list (NULL_TREE, - build_int_cst (NULL_TREE, p2[0])); - arglist = tree_cons (NULL_TREE, s1, arglist); - return build_function_call_expr (fn, arglist); + return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0])); } } -/* Simplify a call to the strcat builtin. +/* Simplify a call to the strcat builtin. DST and SRC are the arguments + to the call. - Return 0 if no simplification was possible, otherwise return the + Return NULL_TREE if no simplification was possible, otherwise return the simplified form of the call as a tree. The simplified form may be a constant or other expression which @@ -10214,27 +10371,27 @@ fold_builtin_strpbrk (tree arglist, tree type) form of the builtin function call. */ static tree -fold_builtin_strcat (tree arglist) +fold_builtin_strcat (tree dst, tree src) { - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (dst, POINTER_TYPE) + || !validate_arg (src, POINTER_TYPE)) + return NULL_TREE; else { - tree dst = TREE_VALUE (arglist), - src = TREE_VALUE (TREE_CHAIN (arglist)); const char *p = c_getstr (src); /* If the string length is zero, return the dst parameter. */ if (p && *p == '\0') return dst; - return 0; + return NULL_TREE; } } -/* Simplify a call to the strncat builtin. +/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the + arguments to the call. - Return 0 if no simplification was possible, otherwise return the + Return NULL_TREE if no simplification was possible, otherwise return the simplified form of the call as a tree. The simplified form may be a constant or other expression which @@ -10250,16 +10407,14 @@ fold_builtin_strcat (tree arglist) form of the builtin function call. */ static tree -fold_builtin_strncat (tree arglist) +fold_builtin_strncat (tree dst, tree src, tree len) { - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (dst, POINTER_TYPE) + || !validate_arg (src, POINTER_TYPE) + || !validate_arg (len, INTEGER_TYPE)) + return NULL_TREE; else { - tree dst = TREE_VALUE (arglist); - tree src = TREE_VALUE (TREE_CHAIN (arglist)); - tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); const char *p = c_getstr (src); /* If the requested length is zero, or the src parameter string @@ -10272,24 +10427,23 @@ fold_builtin_strncat (tree arglist) if (TREE_CODE (len) == INTEGER_CST && p && compare_tree_int (len, strlen (p)) >= 0) { - tree newarglist - = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src)); tree fn = implicit_built_in_decls[BUILT_IN_STRCAT]; /* If the replacement _DECL isn't initialized, don't do the transformation. */ if (!fn) - return 0; + return NULL_TREE; - return build_function_call_expr (fn, newarglist); + return build_call_expr (fn, 2, dst, src); } - return 0; + return NULL_TREE; } } -/* Simplify a call to the strspn builtin. +/* Simplify a call to the strspn builtin. S1 and S2 are the arguments + to the call. - Return 0 if no simplification was possible, otherwise return the + Return NULL_TREE if no simplification was possible, otherwise return the simplified form of the call as a tree. The simplified form may be a constant or other expression which @@ -10305,13 +10459,13 @@ fold_builtin_strncat (tree arglist) form of the builtin function call. */ static tree -fold_builtin_strspn (tree arglist) +fold_builtin_strspn (tree s1, tree s2) { - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (s1, POINTER_TYPE) + || !validate_arg (s2, POINTER_TYPE)) + return NULL_TREE; else { - tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); const char *p1 = c_getstr (s1), *p2 = c_getstr (s2); /* If both arguments are constants, evaluate at compile-time. */ @@ -10321,19 +10475,20 @@ fold_builtin_strspn (tree arglist) return size_int (r); } - /* If either argument is "", return 0. */ + /* If either argument is "", return NULL_TREE. */ if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')) /* Evaluate and ignore both arguments in case either one has side-effects. */ return omit_two_operands (integer_type_node, integer_zero_node, s1, s2); - return 0; + return NULL_TREE; } } -/* Simplify a call to the strcspn builtin. +/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments + to the call. - Return 0 if no simplification was possible, otherwise return the + Return NULL_TREE if no simplification was possible, otherwise return the simplified form of the call as a tree. The simplified form may be a constant or other expression which @@ -10349,13 +10504,13 @@ fold_builtin_strspn (tree arglist) form of the builtin function call. */ static tree -fold_builtin_strcspn (tree arglist) +fold_builtin_strcspn (tree s1, tree s2) { - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (s1, POINTER_TYPE) + || !validate_arg (s2, POINTER_TYPE)) + return NULL_TREE; else { - tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); const char *p1 = c_getstr (s1), *p2 = c_getstr (s2); /* If both arguments are constants, evaluate at compile-time. */ @@ -10365,7 +10520,7 @@ fold_builtin_strcspn (tree arglist) return size_int (r); } - /* If the first argument is "", return 0. */ + /* If the first argument is "", return NULL_TREE. */ if (p1 && *p1 == '\0') { /* Evaluate and ignore argument s2 in case it has @@ -10377,30 +10532,29 @@ fold_builtin_strcspn (tree arglist) /* If the second argument is "", return __builtin_strlen(s1). */ if (p2 && *p2 == '\0') { - tree newarglist = build_tree_list (NULL_TREE, s1), - fn = implicit_built_in_decls[BUILT_IN_STRLEN]; + tree fn = implicit_built_in_decls[BUILT_IN_STRLEN]; /* If the replacement _DECL isn't initialized, don't do the transformation. */ if (!fn) - return 0; + return NULL_TREE; - return build_function_call_expr (fn, newarglist); + return build_call_expr (fn, 1, s1); } - return 0; + return NULL_TREE; } } -/* Fold a call to the fputs builtin. IGNORE is true if the value returned +/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments + to the call. IGNORE is true if the value returned by the builtin will be ignored. UNLOCKED is true is true if this actually a call to fputs_unlocked. If LEN in non-NULL, it represents the known length of the string. Return NULL_TREE if no simplification was possible. */ tree -fold_builtin_fputs (tree arglist, bool ignore, bool unlocked, tree len) +fold_builtin_fputs (tree arg0, tree arg1, bool ignore, bool unlocked, tree len) { - tree fn; /* If we're using an unlocked function, assume the other unlocked functions exist explicitly. */ tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED] @@ -10410,84 +10564,68 @@ fold_builtin_fputs (tree arglist, bool ignore, bool unlocked, tree len) /* If the return value is used, don't do the transformation. */ if (!ignore) - return 0; + return NULL_TREE; /* Verify the arguments in the original call. */ - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (arg0, POINTER_TYPE) + || !validate_arg (arg1, POINTER_TYPE)) + return NULL_TREE; if (! len) - len = c_strlen (TREE_VALUE (arglist), 0); + len = c_strlen (arg0, 0); /* Get the length of the string passed to fputs. If the length can't be determined, punt. */ if (!len || TREE_CODE (len) != INTEGER_CST) - return 0; + return NULL_TREE; switch (compare_tree_int (len, 1)) { case -1: /* length is 0, delete the call entirely . */ - return omit_one_operand (integer_type_node, integer_zero_node, - TREE_VALUE (TREE_CHAIN (arglist))); + return omit_one_operand (integer_type_node, integer_zero_node, arg1);; case 0: /* length is 1, call fputc. */ { - const char *p = c_getstr (TREE_VALUE (arglist)); + const char *p = c_getstr (arg0); if (p != NULL) { - /* New argument list transforming fputs(string, stream) to - fputc(string[0], stream). */ - arglist = build_tree_list (NULL_TREE, - TREE_VALUE (TREE_CHAIN (arglist))); - arglist = tree_cons (NULL_TREE, - build_int_cst (NULL_TREE, p[0]), - arglist); - fn = fn_fputc; - break; + if (fn_fputc) + return build_call_expr (fn_fputc, 2, + build_int_cst (NULL_TREE, p[0]), arg1); + else + return NULL_TREE; } } /* FALLTHROUGH */ case 1: /* length is greater than 1, call fwrite. */ { - tree string_arg; - /* If optimizing for size keep fputs. */ if (optimize_size) - return 0; - string_arg = TREE_VALUE (arglist); + return NULL_TREE; /* New argument list transforming fputs(string, stream) to fwrite(string, 1, len, stream). */ - arglist = build_tree_list (NULL_TREE, - TREE_VALUE (TREE_CHAIN (arglist))); - arglist = tree_cons (NULL_TREE, len, arglist); - arglist = tree_cons (NULL_TREE, size_one_node, arglist); - arglist = tree_cons (NULL_TREE, string_arg, arglist); - fn = fn_fwrite; - break; + if (fn_fwrite) + return build_call_expr (fn_fwrite, 4, arg0, size_one_node, len, arg1); + else + return NULL_TREE; } default: gcc_unreachable (); } - - /* If the replacement _DECL isn't initialized, don't do the - transformation. */ - if (!fn) - return 0; - - /* These optimizations are only performed when the result is ignored, - hence there's no need to cast the result to integer_type_node. */ - return build_function_call_expr (fn, arglist); + return NULL_TREE; } -/* Fold the new_arg's arguments (ARGLIST). Returns true if there was an error +/* Fold the next_arg or va_start call EXP. Returns true if there was an error produced. False otherwise. This is done so that we don't output the error or warning twice or three times. */ bool -fold_builtin_next_arg (tree arglist) +fold_builtin_next_arg (tree exp, bool va_start_p) { tree fntype = TREE_TYPE (current_function_decl); + int nargs = call_expr_nargs (exp); + tree arg; if (TYPE_ARG_TYPES (fntype) == 0 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) @@ -10496,28 +10634,41 @@ fold_builtin_next_arg (tree arglist) error ("%<va_start%> used in function with fixed args"); return true; } - else if (!arglist) + + if (va_start_p) { - /* Evidently an out of date version of <stdarg.h>; can't validate - va_start's second argument, but can still work as intended. */ - warning (0, "%<__builtin_next_arg%> called without an argument"); - return true; + if (va_start_p && (nargs != 2)) + { + error ("wrong number of arguments to function %<va_start%>"); + return true; + } + arg = CALL_EXPR_ARG (exp, 1); } /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0) when we checked the arguments and if needed issued a warning. */ - else if (!TREE_CHAIN (arglist) - || !integer_zerop (TREE_VALUE (arglist)) - || !integer_zerop (TREE_VALUE (TREE_CHAIN (arglist))) - || TREE_CHAIN (TREE_CHAIN (arglist))) + else { - tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl)); - tree arg = TREE_VALUE (arglist); - - if (TREE_CHAIN (arglist)) + if (nargs == 0) + { + /* Evidently an out of date version of <stdarg.h>; can't validate + va_start's second argument, but can still work as intended. */ + warning (0, "%<__builtin_next_arg%> called without an argument"); + return true; + } + else if (nargs > 1) { - error ("%<va_start%> used with too many arguments"); + error ("wrong number of arguments to function %<__builtin_next_arg%>"); return true; } + arg = CALL_EXPR_ARG (exp, 0); + } + + /* We destructively modify the call to be __builtin_va_start (ap, 0) + or __builtin_next_arg (0) the first time we see it, after checking + the arguments and if needed issuing a warning. */ + if (!integer_zerop (arg)) + { + tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl)); /* Strip off all nops for the sake of the comparison. This is not quite the same as STRIP_NOPS. It does more. @@ -10542,37 +10693,37 @@ fold_builtin_next_arg (tree arglist) as otherwise we could warn even for correct code like: void foo (int i, ...) { va_list ap; i++; va_start (ap, i); va_end (ap); } */ - TREE_VALUE (arglist) = integer_zero_node; - TREE_CHAIN (arglist) = build_tree_list (NULL, integer_zero_node); + if (va_start_p) + CALL_EXPR_ARG (exp, 1) = integer_zero_node; + else + CALL_EXPR_ARG (exp, 0) = integer_zero_node; } return false; } -/* Simplify a call to the sprintf builtin. +/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG. + ORIG may be null if this is a 2-argument call. We don't attempt to + simplify calls with more than 3 arguments. - Return 0 if no simplification was possible, otherwise return the + Return NULL_TREE if no simplification was possible, otherwise return the simplified form of the call as a tree. If IGNORED is true, it means that the caller does not use the returned value of the function. */ static tree -fold_builtin_sprintf (tree arglist, int ignored) +fold_builtin_sprintf (tree dest, tree fmt, tree orig, int ignored) { - tree call, retval, dest, fmt; + tree call, retval; const char *fmt_str = NULL; /* Verify the required arguments in the original call. We deal with two types of sprintf() calls: 'sprintf (str, fmt)' and 'sprintf (dest, "%s", orig)'. */ - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE) - && !validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE, - VOID_TYPE)) + if (!validate_arg (dest, POINTER_TYPE) + || !validate_arg (fmt, POINTER_TYPE)) + return NULL_TREE; + if (orig && !validate_arg (orig, POINTER_TYPE)) return NULL_TREE; - - /* Get the destination string and the format specifier. */ - dest = TREE_VALUE (arglist); - fmt = TREE_VALUE (TREE_CHAIN (arglist)); - arglist = TREE_CHAIN (TREE_CHAIN (arglist)); /* Check whether the format is a literal string constant. */ fmt_str = c_getstr (fmt); @@ -10583,7 +10734,7 @@ fold_builtin_sprintf (tree arglist, int ignored) retval = NULL_TREE; if (!init_target_chars ()) - return 0; + return NULL_TREE; /* If the format doesn't contain % args or %%, use strcpy. */ if (strchr (fmt_str, target_percent) == NULL) @@ -10594,14 +10745,12 @@ fold_builtin_sprintf (tree arglist, int ignored) return NULL_TREE; /* Don't optimize sprintf (buf, "abc", ptr++). */ - if (arglist) + if (orig) return NULL_TREE; /* Convert sprintf (str, fmt) into strcpy (str, fmt) when 'format' is known to contain no % formats. */ - arglist = build_tree_list (NULL_TREE, fmt); - arglist = tree_cons (NULL_TREE, dest, arglist); - call = build_function_call_expr (fn, arglist); + call = build_call_expr (fn, 2, dest, fmt); if (!ignored) retval = build_int_cst (NULL_TREE, strlen (fmt_str)); } @@ -10609,27 +10758,24 @@ fold_builtin_sprintf (tree arglist, int ignored) /* If the format is "%s", use strcpy if the result isn't used. */ else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0) { - tree fn, orig; + tree fn; fn = implicit_built_in_decls[BUILT_IN_STRCPY]; if (!fn) return NULL_TREE; /* Don't crash on sprintf (str1, "%s"). */ - if (!arglist) + if (!orig) return NULL_TREE; /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */ - orig = TREE_VALUE (arglist); - arglist = build_tree_list (NULL_TREE, orig); - arglist = tree_cons (NULL_TREE, dest, arglist); if (!ignored) { retval = c_strlen (orig, 1); if (!retval || TREE_CODE (retval) != INTEGER_CST) return NULL_TREE; } - call = build_function_call_expr (fn, arglist); + call = build_call_expr (fn, 2, dest, orig); } if (call && retval) @@ -10643,7 +10789,7 @@ fold_builtin_sprintf (tree arglist, int ignored) return call; } -/* Expand a call to __builtin_object_size. */ +/* Expand a call EXP to __builtin_object_size. */ rtx expand_builtin_object_size (tree exp) @@ -10651,10 +10797,9 @@ expand_builtin_object_size (tree exp) tree ost; int object_size_type; tree fndecl = get_callee_fndecl (exp); - tree arglist = TREE_OPERAND (exp, 1); location_t locus = EXPR_LOCATION (exp); - if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) { error ("%Hfirst argument of %D must be a pointer, second integer constant", &locus, fndecl); @@ -10662,7 +10807,7 @@ expand_builtin_object_size (tree exp) return const0_rtx; } - ost = TREE_VALUE (TREE_CHAIN (arglist)); + ost = CALL_EXPR_ARG (exp, 1); STRIP_NOPS (ost); if (TREE_CODE (ost) != INTEGER_CST @@ -10682,7 +10827,7 @@ expand_builtin_object_size (tree exp) /* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin. FCODE is the BUILT_IN_* to use. - Return 0 if we failed; the caller should emit a normal call, + Return NULL_RTX if we failed; the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE if that's convenient). */ @@ -10690,23 +10835,22 @@ static rtx expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode, enum built_in_function fcode) { - tree arglist = TREE_OPERAND (exp, 1); tree dest, src, len, size; - if (!validate_arglist (arglist, + if (!validate_arglist (exp, POINTER_TYPE, fcode == BUILT_IN_MEMSET_CHK ? INTEGER_TYPE : POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + return NULL_RTX; - dest = TREE_VALUE (arglist); - src = TREE_VALUE (TREE_CHAIN (arglist)); - len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); - size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))); + dest = CALL_EXPR_ARG (exp, 0); + src = CALL_EXPR_ARG (exp, 1); + len = CALL_EXPR_ARG (exp, 2); + size = CALL_EXPR_ARG (exp, 3); if (! host_integerp (size, 1)) - return 0; + return NULL_RTX; if (host_integerp (len, 1) || integer_all_onesp (size)) { @@ -10717,13 +10861,9 @@ expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode, location_t locus = EXPR_LOCATION (exp); warning (0, "%Hcall to %D will always overflow destination buffer", &locus, get_callee_fndecl (exp)); - return 0; + return NULL_RTX; } - arglist = build_tree_list (NULL_TREE, len); - arglist = tree_cons (NULL_TREE, src, arglist); - arglist = tree_cons (NULL_TREE, dest, arglist); - fn = NULL_TREE; /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume mem{cpy,pcpy,move,set} is available. */ @@ -10746,15 +10886,15 @@ expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode, } if (! fn) - return 0; + return NULL_RTX; - fn = build_function_call_expr (fn, arglist); + fn = build_call_expr (fn, 3, dest, src, len); if (TREE_CODE (fn) == CALL_EXPR) CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); return expand_expr (fn, target, mode, EXPAND_NORMAL); } else if (fcode == BUILT_IN_MEMSET_CHK) - return 0; + return NULL_RTX; else { unsigned int dest_align @@ -10762,7 +10902,7 @@ expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode, /* If DEST is not a pointer type, call the normal function. */ if (dest_align == 0) - return 0; + return NULL_RTX; /* If SRC and DEST are the same (and not volatile), do nothing. */ if (operand_equal_p (src, dest, 0)) @@ -10788,7 +10928,7 @@ expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode, = get_pointer_alignment (src, BIGGEST_ALIGNMENT); if (src_align == 0) - return 0; + return NULL_RTX; /* If src is categorized for a readonly section we can use normal __memcpy_chk. */ @@ -10796,14 +10936,14 @@ expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode, { tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK]; if (!fn) - return 0; - fn = build_function_call_expr (fn, arglist); + return NULL_RTX; + fn = build_call_expr (fn, 4, dest, src, len, size); if (TREE_CODE (fn) == CALL_EXPR) CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); return expand_expr (fn, target, mode, EXPAND_NORMAL); } } - return 0; + return NULL_RTX; } } @@ -10812,8 +10952,7 @@ expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode, static void maybe_emit_chk_warning (tree exp, enum built_in_function fcode) { - int arg_mask, is_strlen = 0; - tree arglist = TREE_OPERAND (exp, 1), a; + int is_strlen = 0; tree len, size; location_t locus; @@ -10824,42 +10963,27 @@ maybe_emit_chk_warning (tree exp, enum built_in_function fcode) /* For __strcat_chk the warning will be emitted only if overflowing by at least strlen (dest) + 1 bytes. */ case BUILT_IN_STRCAT_CHK: - arg_mask = 6; + len = CALL_EXPR_ARG (exp, 1); + size = CALL_EXPR_ARG (exp, 2); is_strlen = 1; break; case BUILT_IN_STRNCAT_CHK: - /* For __strncat_chk the warning will be emitted only if overflowing - by at least strlen (dest) + 1 bytes. */ - arg_mask = 12; - break; case BUILT_IN_STRNCPY_CHK: - arg_mask = 12; + len = CALL_EXPR_ARG (exp, 2); + size = CALL_EXPR_ARG (exp, 3); break; case BUILT_IN_SNPRINTF_CHK: case BUILT_IN_VSNPRINTF_CHK: - arg_mask = 10; + len = CALL_EXPR_ARG (exp, 1); + size = CALL_EXPR_ARG (exp, 3); break; default: gcc_unreachable (); } - len = NULL_TREE; - size = NULL_TREE; - for (a = arglist; a && arg_mask; a = TREE_CHAIN (a), arg_mask >>= 1) - if (arg_mask & 1) - { - if (len) - size = a; - else - len = a; - } - if (!len || !size) return; - len = TREE_VALUE (len); - size = TREE_VALUE (size); - if (! host_integerp (size, 1) || integer_all_onesp (size)) return; @@ -10871,7 +10995,7 @@ maybe_emit_chk_warning (tree exp, enum built_in_function fcode) } else if (fcode == BUILT_IN_STRNCAT_CHK) { - tree src = TREE_VALUE (TREE_CHAIN (arglist)); + tree src = CALL_EXPR_ARG (exp, 1); if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size)) return; src = c_strlen (src, 1); @@ -10899,27 +11023,18 @@ maybe_emit_chk_warning (tree exp, enum built_in_function fcode) static void maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode) { - tree arglist = TREE_OPERAND (exp, 1); tree dest, size, len, fmt, flag; const char *fmt_str; + int nargs = call_expr_nargs (exp); /* Verify the required arguments in the original call. */ - if (! arglist) - return; - dest = TREE_VALUE (arglist); - arglist = TREE_CHAIN (arglist); - if (! arglist) - return; - flag = TREE_VALUE (arglist); - arglist = TREE_CHAIN (arglist); - if (! arglist) - return; - size = TREE_VALUE (arglist); - arglist = TREE_CHAIN (arglist); - if (! arglist) + + if (nargs < 4) return; - fmt = TREE_VALUE (arglist); - arglist = TREE_CHAIN (arglist); + dest = CALL_EXPR_ARG (exp, 0); + flag = CALL_EXPR_ARG (exp, 1); + size = CALL_EXPR_ARG (exp, 2); + fmt = CALL_EXPR_ARG (exp, 3); if (! host_integerp (size, 1) || integer_all_onesp (size)) return; @@ -10937,13 +11052,14 @@ maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode) len = build_int_cstu (size_type_node, strlen (fmt_str)); /* If the format is "%s" and first ... argument is a string literal, we know it too. */ - else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0) + else if (fcode == BUILT_IN_SPRINTF_CHK + && strcmp (fmt_str, target_percent_s) == 0) { tree arg; - if (! arglist) + if (nargs < 5) return; - arg = TREE_VALUE (arglist); + arg = CALL_EXPR_ARG (exp, 4); if (! POINTER_TYPE_P (TREE_TYPE (arg))) return; @@ -10962,25 +11078,25 @@ maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode) } } -/* Fold a call to __builtin_object_size, if possible. */ +/* Fold a call to __builtin_object_size with arguments PTR and OST, + if possible. */ tree -fold_builtin_object_size (tree arglist) +fold_builtin_object_size (tree ptr, tree ost) { - tree ptr, ost, ret = 0; + tree ret = NULL_TREE; int object_size_type; - if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (!validate_arg (ptr, POINTER_TYPE) + || !validate_arg (ost, INTEGER_TYPE)) + return NULL_TREE; - ptr = TREE_VALUE (arglist); - ost = TREE_VALUE (TREE_CHAIN (arglist)); STRIP_NOPS (ost); if (TREE_CODE (ost) != INTEGER_CST || tree_int_cst_sgn (ost) < 0 || compare_tree_int (ost, 3) > 0) - return 0; + return NULL_TREE; object_size_type = tree_low_cst (ost, 0); @@ -11019,28 +11135,26 @@ fold_builtin_object_size (tree arglist) } /* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin. + DEST, SRC, LEN, and SIZE are the arguments to the call. IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_* code of the builtin. If MAXLEN is not NULL, it is maximum length passed as third argument. */ tree -fold_builtin_memory_chk (tree fndecl, tree arglist, tree maxlen, bool ignore, +fold_builtin_memory_chk (tree fndecl, + tree dest, tree src, tree len, tree size, + tree maxlen, bool ignore, enum built_in_function fcode) { - tree dest, src, len, size, fn; - - if (!validate_arglist (arglist, - POINTER_TYPE, - fcode == BUILT_IN_MEMSET_CHK - ? INTEGER_TYPE : POINTER_TYPE, - INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + tree fn; - dest = TREE_VALUE (arglist); - /* Actually val for __memset_chk, but it doesn't matter. */ - src = TREE_VALUE (TREE_CHAIN (arglist)); - len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); - size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))); + if (!validate_arg (dest, POINTER_TYPE) + || !validate_arg (src, + (fcode == BUILT_IN_MEMSET_CHK + ? INTEGER_TYPE : POINTER_TYPE)) + || !validate_arg (len, INTEGER_TYPE) + || !validate_arg (size, INTEGER_TYPE)) + return NULL_TREE; /* If SRC and DEST are the same (and not volatile), return DEST (resp. DEST+LEN for __mempcpy_chk). */ @@ -11057,7 +11171,7 @@ fold_builtin_memory_chk (tree fndecl, tree arglist, tree maxlen, bool ignore, } if (! host_integerp (size, 1)) - return 0; + return NULL_TREE; if (! integer_all_onesp (size)) { @@ -11074,24 +11188,20 @@ fold_builtin_memory_chk (tree fndecl, tree arglist, tree maxlen, bool ignore, (void) __memcpy_chk (). */ fn = built_in_decls[BUILT_IN_MEMCPY_CHK]; if (!fn) - return 0; + return NULL_TREE; - return build_function_call_expr (fn, arglist); + return build_call_expr (fn, 4, dest, src, len, size); } - return 0; + return NULL_TREE; } } else maxlen = len; if (tree_int_cst_lt (size, maxlen)) - return 0; + return NULL_TREE; } - arglist = build_tree_list (NULL_TREE, len); - arglist = tree_cons (NULL_TREE, src, arglist); - arglist = tree_cons (NULL_TREE, dest, arglist); - fn = NULL_TREE; /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume mem{cpy,pcpy,move,set} is available. */ @@ -11114,36 +11224,35 @@ fold_builtin_memory_chk (tree fndecl, tree arglist, tree maxlen, bool ignore, } if (!fn) - return 0; + return NULL_TREE; - return build_function_call_expr (fn, arglist); + return build_call_expr (fn, 3, dest, src, len); } /* Fold a call to the __st[rp]cpy_chk builtin. - IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_* + DEST, SRC, and SIZE are the arguments to the call. + IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_* code of the builtin. If MAXLEN is not NULL, it is maximum length of strings passed as second argument. */ tree -fold_builtin_stxcpy_chk (tree fndecl, tree arglist, tree maxlen, bool ignore, +fold_builtin_stxcpy_chk (tree fndecl, tree dest, tree src, tree size, + tree maxlen, bool ignore, enum built_in_function fcode) { - tree dest, src, size, len, fn; - - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, - VOID_TYPE)) - return 0; + tree len, fn; - dest = TREE_VALUE (arglist); - src = TREE_VALUE (TREE_CHAIN (arglist)); - size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + if (!validate_arg (dest, POINTER_TYPE) + || !validate_arg (src, POINTER_TYPE) + || !validate_arg (size, INTEGER_TYPE)) + return NULL_TREE; /* If SRC and DEST are the same (and not volatile), return DEST. */ if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0)) return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest); if (! host_integerp (size, 1)) - return 0; + return NULL_TREE; if (! integer_all_onesp (size)) { @@ -11158,73 +11267,66 @@ fold_builtin_stxcpy_chk (tree fndecl, tree arglist, tree maxlen, bool ignore, if (fcode == BUILT_IN_STPCPY_CHK) { if (! ignore) - return 0; + return NULL_TREE; /* If return value of __stpcpy_chk is ignored, optimize into __strcpy_chk. */ fn = built_in_decls[BUILT_IN_STRCPY_CHK]; if (!fn) - return 0; + return NULL_TREE; - return build_function_call_expr (fn, arglist); + return build_call_expr (fn, 3, dest, src, size); } if (! len || TREE_SIDE_EFFECTS (len)) - return 0; + return NULL_TREE; /* If c_strlen returned something, but not a constant, transform __strcpy_chk into __memcpy_chk. */ fn = built_in_decls[BUILT_IN_MEMCPY_CHK]; if (!fn) - return 0; + return NULL_TREE; len = size_binop (PLUS_EXPR, len, ssize_int (1)); - arglist = build_tree_list (NULL_TREE, size); - arglist = tree_cons (NULL_TREE, len, arglist); - arglist = tree_cons (NULL_TREE, src, arglist); - arglist = tree_cons (NULL_TREE, dest, arglist); return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), - build_function_call_expr (fn, arglist)); + build_call_expr (fn, 4, + dest, src, len, size)); } } else maxlen = len; if (! tree_int_cst_lt (maxlen, size)) - return 0; + return NULL_TREE; } - arglist = build_tree_list (NULL_TREE, src); - arglist = tree_cons (NULL_TREE, dest, arglist); - /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */ fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK ? BUILT_IN_STPCPY : BUILT_IN_STRCPY]; if (!fn) - return 0; + return NULL_TREE; - return build_function_call_expr (fn, arglist); + return build_call_expr (fn, 2, dest, src); } -/* Fold a call to the __strncpy_chk builtin. - If MAXLEN is not NULL, it is maximum length passed as third argument. */ +/* Fold a call to the __strncpy_chk builtin. DEST, SRC, LEN, and SIZE + are the arguments to the call. If MAXLEN is not NULL, it is maximum + length passed as third argument. */ tree -fold_builtin_strncpy_chk (tree arglist, tree maxlen) +fold_builtin_strncpy_chk (tree dest, tree src, tree len, tree size, + tree maxlen) { - tree dest, src, size, len, fn; - - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, - INTEGER_TYPE, VOID_TYPE)) - return 0; + tree fn; - dest = TREE_VALUE (arglist); - src = TREE_VALUE (TREE_CHAIN (arglist)); - len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); - size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))); + if (!validate_arg (dest, POINTER_TYPE) + || !validate_arg (src, POINTER_TYPE) + || !validate_arg (len, INTEGER_TYPE) + || !validate_arg (size, INTEGER_TYPE)) + return NULL_TREE; if (! host_integerp (size, 1)) - return 0; + return NULL_TREE; if (! integer_all_onesp (size)) { @@ -11234,42 +11336,36 @@ fold_builtin_strncpy_chk (tree arglist, tree maxlen) For MAXLEN only allow optimizing into non-_ocs function if SIZE is >= MAXLEN, never convert to __ocs_fail (). */ if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1)) - return 0; + return NULL_TREE; } else maxlen = len; if (tree_int_cst_lt (size, maxlen)) - return 0; + return NULL_TREE; } - arglist = build_tree_list (NULL_TREE, len); - arglist = tree_cons (NULL_TREE, src, arglist); - arglist = tree_cons (NULL_TREE, dest, arglist); - /* If __builtin_strncpy_chk is used, assume strncpy is available. */ fn = built_in_decls[BUILT_IN_STRNCPY]; if (!fn) - return 0; + return NULL_TREE; - return build_function_call_expr (fn, arglist); + return build_call_expr (fn, 3, dest, src, len); } -/* Fold a call to the __strcat_chk builtin FNDECL with ARGLIST. */ +/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE + are the arguments to the call. */ static tree -fold_builtin_strcat_chk (tree fndecl, tree arglist) +fold_builtin_strcat_chk (tree fndecl, tree dest, tree src, tree size) { - tree dest, src, size, fn; + tree fn; const char *p; - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, - VOID_TYPE)) - return 0; - - dest = TREE_VALUE (arglist); - src = TREE_VALUE (TREE_CHAIN (arglist)); - size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + if (!validate_arg (dest, POINTER_TYPE) + || !validate_arg (src, POINTER_TYPE) + || !validate_arg (size, INTEGER_TYPE)) + return NULL_TREE; p = c_getstr (src); /* If the SRC parameter is "", return DEST. */ @@ -11277,35 +11373,31 @@ fold_builtin_strcat_chk (tree fndecl, tree arglist) return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src); if (! host_integerp (size, 1) || ! integer_all_onesp (size)) - return 0; - - arglist = build_tree_list (NULL_TREE, src); - arglist = tree_cons (NULL_TREE, dest, arglist); + return NULL_TREE; /* If __builtin_strcat_chk is used, assume strcat is available. */ fn = built_in_decls[BUILT_IN_STRCAT]; if (!fn) - return 0; + return NULL_TREE; - return build_function_call_expr (fn, arglist); + return build_call_expr (fn, 2, dest, src); } -/* Fold a call to the __strncat_chk builtin EXP. */ +/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC, + LEN, and SIZE. */ static tree -fold_builtin_strncat_chk (tree fndecl, tree arglist) +fold_builtin_strncat_chk (tree fndecl, + tree dest, tree src, tree len, tree size) { - tree dest, src, size, len, fn; + tree fn; const char *p; - if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, - INTEGER_TYPE, VOID_TYPE)) - return 0; - - dest = TREE_VALUE (arglist); - src = TREE_VALUE (TREE_CHAIN (arglist)); - len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); - size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))); + if (!validate_arg (dest, POINTER_TYPE) + || !validate_arg (src, POINTER_TYPE) + || !validate_arg (size, INTEGER_TYPE) + || !validate_arg (size, INTEGER_TYPE)) + return NULL_TREE; p = c_getstr (src); /* If the SRC parameter is "" or if LEN is 0, return DEST. */ @@ -11315,7 +11407,7 @@ fold_builtin_strncat_chk (tree fndecl, tree arglist) return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src); if (! host_integerp (size, 1)) - return 0; + return NULL_TREE; if (! integer_all_onesp (size)) { @@ -11328,71 +11420,55 @@ fold_builtin_strncat_chk (tree fndecl, tree arglist) /* If LEN >= strlen (SRC), optimize into __strcat_chk. */ fn = built_in_decls[BUILT_IN_STRCAT_CHK]; if (!fn) - return 0; + return NULL_TREE; - arglist = build_tree_list (NULL_TREE, size); - arglist = tree_cons (NULL_TREE, src, arglist); - arglist = tree_cons (NULL_TREE, dest, arglist); - return build_function_call_expr (fn, arglist); + return build_call_expr (fn, 3, dest, src, size); } - return 0; + return NULL_TREE; } - arglist = build_tree_list (NULL_TREE, len); - arglist = tree_cons (NULL_TREE, src, arglist); - arglist = tree_cons (NULL_TREE, dest, arglist); - /* If __builtin_strncat_chk is used, assume strncat is available. */ fn = built_in_decls[BUILT_IN_STRNCAT]; if (!fn) - return 0; + return NULL_TREE; - return build_function_call_expr (fn, arglist); + return build_call_expr (fn, 3, dest, src, len); } -/* Fold a call to __{,v}sprintf_chk with argument list ARGLIST. Return 0 if +/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if a normal call should be emitted rather than expanding the function inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */ static tree -fold_builtin_sprintf_chk (tree arglist, enum built_in_function fcode) +fold_builtin_sprintf_chk (tree exp, enum built_in_function fcode) { tree dest, size, len, fn, fmt, flag; const char *fmt_str; + int nargs = call_expr_nargs (exp); /* Verify the required arguments in the original call. */ - if (! arglist) - return 0; - dest = TREE_VALUE (arglist); - if (! POINTER_TYPE_P (TREE_TYPE (dest))) - return 0; - arglist = TREE_CHAIN (arglist); - if (! arglist) - return 0; - flag = TREE_VALUE (arglist); - if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE) - return 0; - arglist = TREE_CHAIN (arglist); - if (! arglist) - return 0; - size = TREE_VALUE (arglist); - if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE) - return 0; - arglist = TREE_CHAIN (arglist); - if (! arglist) - return 0; - fmt = TREE_VALUE (arglist); - if (! POINTER_TYPE_P (TREE_TYPE (fmt))) - return 0; - arglist = TREE_CHAIN (arglist); + if (nargs < 4) + return NULL_TREE; + dest = CALL_EXPR_ARG (exp, 0); + if (!validate_arg (dest, POINTER_TYPE)) + return NULL_TREE; + flag = CALL_EXPR_ARG (exp, 1); + if (!validate_arg (flag, INTEGER_TYPE)) + return NULL_TREE; + size = CALL_EXPR_ARG (exp, 2); + if (!validate_arg (size, INTEGER_TYPE)) + return NULL_TREE; + fmt = CALL_EXPR_ARG (exp, 3); + if (!validate_arg (fmt, POINTER_TYPE)) + return NULL_TREE; if (! host_integerp (size, 1)) - return 0; + return NULL_TREE; len = NULL_TREE; if (!init_target_chars ()) - return 0; + return NULL_TREE; /* Check whether the format is a literal string constant. */ fmt_str = c_getstr (fmt); @@ -11401,19 +11477,20 @@ fold_builtin_sprintf_chk (tree arglist, enum built_in_function fcode) /* If the format doesn't contain % args or %%, we know the size. */ if (strchr (fmt_str, target_percent) == 0) { - if (fcode != BUILT_IN_SPRINTF_CHK || arglist == NULL_TREE) + if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4) len = build_int_cstu (size_type_node, strlen (fmt_str)); } /* If the format is "%s" and first ... argument is a string literal, we know the size too. */ - else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0) + else if (fcode == BUILT_IN_SPRINTF_CHK + && strcmp (fmt_str, target_percent_s) == 0) { tree arg; - if (arglist && !TREE_CHAIN (arglist)) + if (nargs == 5) { - arg = TREE_VALUE (arglist); - if (POINTER_TYPE_P (TREE_TYPE (arg))) + arg = CALL_EXPR_ARG (exp, 4); + if (validate_arg (arg, POINTER_TYPE)) { len = c_strlen (arg, 1); if (! len || ! host_integerp (len, 1)) @@ -11426,7 +11503,7 @@ fold_builtin_sprintf_chk (tree arglist, enum built_in_function fcode) if (! integer_all_onesp (size)) { if (! len || ! tree_int_cst_lt (len, size)) - return 0; + return NULL_TREE; } /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0 @@ -11434,70 +11511,55 @@ fold_builtin_sprintf_chk (tree arglist, enum built_in_function fcode) if (! integer_zerop (flag)) { if (fmt_str == NULL) - return 0; - if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s)) - return 0; + return NULL_TREE; + if (strchr (fmt_str, target_percent) != NULL + && strcmp (fmt_str, target_percent_s)) + return NULL_TREE; } - arglist = tree_cons (NULL_TREE, fmt, arglist); - arglist = tree_cons (NULL_TREE, dest, arglist); - /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */ fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF]; if (!fn) - return 0; + return NULL_TREE; - return build_function_call_expr (fn, arglist); + return rewrite_call_expr (exp, 4, fn, 2, dest, fmt); } -/* Fold a call to {,v}snprintf with argument list ARGLIST. Return 0 if +/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if a normal call should be emitted rather than expanding the function inline. FCODE is either BUILT_IN_SNPRINTF_CHK or BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length passed as second argument. */ tree -fold_builtin_snprintf_chk (tree arglist, tree maxlen, +fold_builtin_snprintf_chk (tree exp, tree maxlen, enum built_in_function fcode) { tree dest, size, len, fn, fmt, flag; const char *fmt_str; /* Verify the required arguments in the original call. */ - if (! arglist) - return 0; - dest = TREE_VALUE (arglist); - if (! POINTER_TYPE_P (TREE_TYPE (dest))) - return 0; - arglist = TREE_CHAIN (arglist); - if (! arglist) - return 0; - len = TREE_VALUE (arglist); - if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE) - return 0; - arglist = TREE_CHAIN (arglist); - if (! arglist) - return 0; - flag = TREE_VALUE (arglist); - if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE) - return 0; - arglist = TREE_CHAIN (arglist); - if (! arglist) - return 0; - size = TREE_VALUE (arglist); - if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE) - return 0; - arglist = TREE_CHAIN (arglist); - if (! arglist) - return 0; - fmt = TREE_VALUE (arglist); - if (! POINTER_TYPE_P (TREE_TYPE (fmt))) - return 0; - arglist = TREE_CHAIN (arglist); + if (call_expr_nargs (exp) < 5) + return NULL_TREE; + dest = CALL_EXPR_ARG (exp, 0); + if (!validate_arg (dest, POINTER_TYPE)) + return NULL_TREE; + len = CALL_EXPR_ARG (exp, 1); + if (!validate_arg (len, INTEGER_TYPE)) + return NULL_TREE; + flag = CALL_EXPR_ARG (exp, 2); + if (!validate_arg (flag, INTEGER_TYPE)) + return NULL_TREE; + size = CALL_EXPR_ARG (exp, 3); + if (!validate_arg (size, INTEGER_TYPE)) + return NULL_TREE; + fmt = CALL_EXPR_ARG (exp, 4); + if (!validate_arg (fmt, POINTER_TYPE)) + return NULL_TREE; if (! host_integerp (size, 1)) - return 0; + return NULL_TREE; if (! integer_all_onesp (size)) { @@ -11507,17 +11569,17 @@ fold_builtin_snprintf_chk (tree arglist, tree maxlen, For MAXLEN only allow optimizing into non-_ocs function if SIZE is >= MAXLEN, never convert to __ocs_fail (). */ if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1)) - return 0; + return NULL_TREE; } else maxlen = len; if (tree_int_cst_lt (size, maxlen)) - return 0; + return NULL_TREE; } if (!init_target_chars ()) - return 0; + return NULL_TREE; /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0 or if format doesn't contain % chars or is "%s". */ @@ -11525,62 +11587,44 @@ fold_builtin_snprintf_chk (tree arglist, tree maxlen, { fmt_str = c_getstr (fmt); if (fmt_str == NULL) - return 0; - if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s)) - return 0; + return NULL_TREE; + if (strchr (fmt_str, target_percent) != NULL + && strcmp (fmt_str, target_percent_s)) + return NULL_TREE; } - arglist = tree_cons (NULL_TREE, fmt, arglist); - arglist = tree_cons (NULL_TREE, len, arglist); - arglist = tree_cons (NULL_TREE, dest, arglist); - /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is available. */ fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF]; if (!fn) - return 0; + return NULL_TREE; - return build_function_call_expr (fn, arglist); + return rewrite_call_expr (exp, 5, fn, 3, dest, len, fmt); } /* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins. + FMT and ARG are the arguments to the call; we don't fold cases with + more than 2 arguments, and ARG may be null if this is a 1-argument case. - Return 0 if no simplification was possible, otherwise return the + Return NULL_TREE if no simplification was possible, otherwise return the simplified form of the call as a tree. FCODE is the BUILT_IN_* code of the function to be simplified. */ static tree -fold_builtin_printf (tree fndecl, tree arglist, bool ignore, +fold_builtin_printf (tree fndecl, tree fmt, tree arg, bool ignore, enum built_in_function fcode) { - tree fmt, fn = NULL_TREE, fn_putchar, fn_puts, arg, call; + tree fn_putchar, fn_puts, newarg, call = NULL_TREE; const char *fmt_str = NULL; /* If the return value is used, don't do the transformation. */ if (! ignore) - return 0; + return NULL_TREE; /* Verify the required arguments in the original call. */ - if (fcode == BUILT_IN_PRINTF_CHK || fcode == BUILT_IN_VPRINTF_CHK) - { - tree flag; - - if (! arglist) - return 0; - flag = TREE_VALUE (arglist); - if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE - || TREE_SIDE_EFFECTS (flag)) - return 0; - arglist = TREE_CHAIN (arglist); - } - - if (! arglist) - return 0; - fmt = TREE_VALUE (arglist); - if (! POINTER_TYPE_P (TREE_TYPE (fmt))) - return 0; - arglist = TREE_CHAIN (arglist); + if (!validate_arg (fmt, POINTER_TYPE)) + return NULL_TREE; /* Check whether the format is a literal string constant. */ fmt_str = c_getstr (fmt); @@ -11601,32 +11645,31 @@ fold_builtin_printf (tree fndecl, tree arglist, bool ignore, } if (!init_target_chars ()) - return 0; + return NULL_TREE; - if (strcmp (fmt_str, target_percent_s) == 0 || strchr (fmt_str, target_percent) == NULL) + if (strcmp (fmt_str, target_percent_s) == 0 + || strchr (fmt_str, target_percent) == NULL) { const char *str; if (strcmp (fmt_str, target_percent_s) == 0) { if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK) - return 0; + return NULL_TREE; - if (! arglist - || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist))) - || TREE_CHAIN (arglist)) - return 0; + if (!arg || !validate_arg (arg, POINTER_TYPE)) + return NULL_TREE; - str = c_getstr (TREE_VALUE (arglist)); + str = c_getstr (arg); if (str == NULL) - return 0; + return NULL_TREE; } else { /* The format specifier doesn't contain any '%' characters. */ if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK - && arglist) - return 0; + && arg) + return NULL_TREE; str = fmt_str; } @@ -11640,9 +11683,9 @@ fold_builtin_printf (tree fndecl, tree arglist, bool ignore, /* Given printf("c"), (where c is any one character,) convert "c"[0] to an int and pass that to the replacement function. */ - arg = build_int_cst (NULL_TREE, str[0]); - arglist = build_tree_list (NULL_TREE, arg); - fn = fn_putchar; + newarg = build_int_cst (NULL_TREE, str[0]); + if (fn_putchar) + call = build_call_expr (fn_putchar, 1, newarg); } else { @@ -11656,92 +11699,69 @@ fold_builtin_printf (tree fndecl, tree arglist, bool ignore, memcpy (newstr, str, len - 1); newstr[len - 1] = 0; - arg = build_string_literal (len, newstr); - arglist = build_tree_list (NULL_TREE, arg); - fn = fn_puts; + newarg = build_string_literal (len, newstr); + if (fn_puts) + call = build_call_expr (fn_puts, 1, newarg); } else /* We'd like to arrange to call fputs(string,stdout) here, but we need stdout and don't have a way to get it yet. */ - return 0; + return NULL_TREE; } } /* The other optimizations can be done only on the non-va_list variants. */ else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK) - return 0; + return NULL_TREE; /* If the format specifier was "%s\n", call __builtin_puts(arg). */ else if (strcmp (fmt_str, target_percent_s_newline) == 0) { - if (! arglist - || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist))) - || TREE_CHAIN (arglist)) - return 0; - fn = fn_puts; + if (!arg || !validate_arg (arg, POINTER_TYPE)) + return NULL_TREE; + if (fn_puts) + call = build_call_expr (fn_puts, 1, arg); } /* If the format specifier was "%c", call __builtin_putchar(arg). */ else if (strcmp (fmt_str, target_percent_c) == 0) { - if (! arglist - || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE - || TREE_CHAIN (arglist)) - return 0; - fn = fn_putchar; + if (!arg || !validate_arg (arg, INTEGER_TYPE)) + return NULL_TREE; + if (fn_putchar) + call = build_call_expr (fn_putchar, 1, arg); } - if (!fn) - return 0; + if (!call) + return NULL_TREE; - call = build_function_call_expr (fn, arglist); return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call); } /* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins. + FP, FMT, and ARG are the arguments to the call. We don't fold calls with + more than 3 arguments, and ARG may be null in the 2-argument case. - Return 0 if no simplification was possible, otherwise return the + Return NULL_TREE if no simplification was possible, otherwise return the simplified form of the call as a tree. FCODE is the BUILT_IN_* code of the function to be simplified. */ static tree -fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore, +fold_builtin_fprintf (tree fndecl, tree fp, tree fmt, tree arg, bool ignore, enum built_in_function fcode) { - tree fp, fmt, fn = NULL_TREE, fn_fputc, fn_fputs, arg, call; + tree fn_fputc, fn_fputs, call = NULL_TREE; const char *fmt_str = NULL; /* If the return value is used, don't do the transformation. */ if (! ignore) - return 0; + return NULL_TREE; /* Verify the required arguments in the original call. */ - if (! arglist) - return 0; - fp = TREE_VALUE (arglist); - if (! POINTER_TYPE_P (TREE_TYPE (fp))) - return 0; - arglist = TREE_CHAIN (arglist); - - if (fcode == BUILT_IN_FPRINTF_CHK || fcode == BUILT_IN_VFPRINTF_CHK) - { - tree flag; - - if (! arglist) - return 0; - flag = TREE_VALUE (arglist); - if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE - || TREE_SIDE_EFFECTS (flag)) - return 0; - arglist = TREE_CHAIN (arglist); - } - - if (! arglist) - return 0; - fmt = TREE_VALUE (arglist); - if (! POINTER_TYPE_P (TREE_TYPE (fmt))) - return 0; - arglist = TREE_CHAIN (arglist); + if (!validate_arg (fp, POINTER_TYPE)) + return NULL_TREE; + if (!validate_arg (fmt, POINTER_TYPE)) + return NULL_TREE; /* Check whether the format is a literal string constant. */ fmt_str = c_getstr (fmt); @@ -11762,14 +11782,14 @@ fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore, } if (!init_target_chars ()) - return 0; + return NULL_TREE; /* If the format doesn't contain % args or %%, use strcpy. */ if (strchr (fmt_str, target_percent) == NULL) { if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK - && arglist) - return 0; + && arg) + return NULL_TREE; /* If the format specifier was "", fprintf does nothing. */ if (fmt_str[0] == '\0') @@ -11777,7 +11797,7 @@ fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore, /* If FP has side-effects, just wait until gimplification is done. */ if (TREE_SIDE_EFFECTS (fp)) - return 0; + return NULL_TREE; return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0); } @@ -11785,45 +11805,34 @@ fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore, /* When "string" doesn't contain %, replace all cases of fprintf (fp, string) with fputs (string, fp). The fputs builtin will take care of special cases like length == 1. */ - arglist = build_tree_list (NULL_TREE, fp); - arglist = tree_cons (NULL_TREE, fmt, arglist); - fn = fn_fputs; + if (fn_fputs) + call = build_call_expr (fn_fputs, 2, fmt, fp); } /* The other optimizations can be done only on the non-va_list variants. */ else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK) - return 0; + return NULL_TREE; /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */ else if (strcmp (fmt_str, target_percent_s) == 0) { - if (! arglist - || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist))) - || TREE_CHAIN (arglist)) - return 0; - arg = TREE_VALUE (arglist); - arglist = build_tree_list (NULL_TREE, fp); - arglist = tree_cons (NULL_TREE, arg, arglist); - fn = fn_fputs; + if (!arg || !validate_arg (arg, POINTER_TYPE)) + return NULL_TREE; + if (fn_fputs) + call = build_call_expr (fn_fputs, 2, arg, fp); } /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */ else if (strcmp (fmt_str, target_percent_c) == 0) { - if (! arglist - || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE - || TREE_CHAIN (arglist)) - return 0; - arg = TREE_VALUE (arglist); - arglist = build_tree_list (NULL_TREE, fp); - arglist = tree_cons (NULL_TREE, arg, arglist); - fn = fn_fputc; + if (!arg || !validate_arg (arg, INTEGER_TYPE)) + return NULL_TREE; + if (fn_fputc) + call = build_call_expr (fn_fputc, 2, arg, fp); } - if (!fn) - return 0; - - call = build_function_call_expr (fn, arglist); + if (!call) + return NULL_TREE; return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call); } diff --git a/gcc/c-common.c b/gcc/c-common.c index 0bbb439324b..d9a826d1d96 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -1576,16 +1576,23 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp, /* We need to warn about conflicts among arguments and conflicts between args and the function address. Side effects of the function address, however, are not ordered by the sequence point of the call. */ - tmp_before = tmp_nosp = tmp_list2 = tmp_list3 = 0; - verify_tree (TREE_OPERAND (x, 0), &tmp_before, &tmp_nosp, NULL_TREE); - if (TREE_OPERAND (x, 1)) - verify_tree (TREE_OPERAND (x, 1), &tmp_list2, &tmp_list3, NULL_TREE); - merge_tlist (&tmp_list3, tmp_list2, 0); - add_tlist (&tmp_before, tmp_list3, NULL_TREE, 0); - add_tlist (&tmp_before, tmp_nosp, NULL_TREE, 0); - warn_for_collisions (tmp_before); - add_tlist (pbefore_sp, tmp_before, NULL_TREE, 0); - return; + { + call_expr_arg_iterator iter; + tree arg; + tmp_before = tmp_nosp = 0; + verify_tree (CALL_EXPR_FN (x), &tmp_before, &tmp_nosp, NULL_TREE); + FOR_EACH_CALL_EXPR_ARG (arg, iter, x) + { + tmp_list2 = tmp_list3 = 0; + verify_tree (arg, &tmp_list2, &tmp_list3, NULL_TREE); + merge_tlist (&tmp_list3, tmp_list2, 0); + add_tlist (&tmp_before, tmp_list3, NULL_TREE, 0); + } + add_tlist (&tmp_before, tmp_nosp, NULL_TREE, 0); + warn_for_collisions (tmp_before); + add_tlist (pbefore_sp, tmp_before, NULL_TREE, 0); + return; + } case TREE_LIST: /* Scan all the list, e.g. indices of multi dimensional array. */ @@ -1645,7 +1652,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp, else if (IS_EXPR_CODE_CLASS (cl)) { int lp; - int max = TREE_CODE_LENGTH (TREE_CODE (x)); + int max = TREE_OPERAND_LENGTH (x); for (lp = 0; lp < max; lp++) { tmp_before = tmp_nosp = 0; @@ -5940,7 +5947,7 @@ check_function_arguments_recurse (void (*callback) if (TREE_CODE (param) == CALL_EXPR) { - tree type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (param, 0))); + tree type = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (param))); tree attrs; bool found_format_arg = false; @@ -5953,10 +5960,11 @@ check_function_arguments_recurse (void (*callback) attrs = TREE_CHAIN (attrs)) if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs))) { - tree inner_args; + tree inner_arg; tree format_num_expr; int format_num; int i; + call_expr_arg_iterator iter; /* Extract the argument number, which was previously checked to be valid. */ @@ -5967,14 +5975,13 @@ check_function_arguments_recurse (void (*callback) format_num = TREE_INT_CST_LOW (format_num_expr); - for (inner_args = TREE_OPERAND (param, 1), i = 1; - inner_args != 0; - inner_args = TREE_CHAIN (inner_args), i++) + for (inner_arg = first_call_expr_arg (param, &iter), i = 1; + inner_arg != 0; + inner_arg = next_call_expr_arg (&iter), i++) if (i == format_num) { check_function_arguments_recurse (callback, ctx, - TREE_VALUE (inner_args), - param_num); + inner_arg, param_num); found_format_arg = true; break; } @@ -6191,7 +6198,7 @@ c_warn_unused_result (tree *top_p) ftype = TREE_TYPE (fdecl); else { - ftype = TREE_TYPE (TREE_OPERAND (t, 0)); + ftype = TREE_TYPE (CALL_EXPR_FN (t)); /* Look past pointer-to-function to the function type itself. */ ftype = TREE_TYPE (ftype); } diff --git a/gcc/c-omp.c b/gcc/c-omp.c index 0bae32140d8..115d7811d1e 100644 --- a/gcc/c-omp.c +++ b/gcc/c-omp.c @@ -76,7 +76,7 @@ c_finish_omp_barrier (void) tree x; x = built_in_decls[BUILT_IN_GOMP_BARRIER]; - x = build_function_call_expr (x, NULL); + x = build_call_expr (x, 0); add_stmt (x); } @@ -150,7 +150,7 @@ c_finish_omp_flush (void) tree x; x = built_in_decls[BUILT_IN_SYNCHRONIZE]; - x = build_function_call_expr (x, NULL); + x = build_call_expr (x, 0); add_stmt (x); } diff --git a/gcc/c-pretty-print.c b/gcc/c-pretty-print.c index e7ca1246b35..b69f0da29ff 100644 --- a/gcc/c-pretty-print.c +++ b/gcc/c-pretty-print.c @@ -1270,9 +1270,20 @@ pp_c_postfix_expression (c_pretty_printer *pp, tree e) break; case CALL_EXPR: - pp_postfix_expression (pp, TREE_OPERAND (e, 0)); - pp_c_call_argument_list (pp, TREE_OPERAND (e, 1)); - break; + { + call_expr_arg_iterator iter; + tree arg; + pp_postfix_expression (pp, CALL_EXPR_FN (e)); + pp_c_left_paren (pp); + FOR_EACH_CALL_EXPR_ARG (arg, iter, e) + { + pp_expression (pp, arg); + if (more_call_expr_args_p (&iter)) + pp_separate_with (pp, ','); + } + pp_c_right_paren (pp); + break; + } case UNORDERED_EXPR: pp_c_identifier (pp, flag_isoc99 @@ -1419,7 +1430,8 @@ pp_c_constructor_elts (c_pretty_printer *pp, VEC(constructor_elt,gc) *v) } } -/* Print out an expression-list in parens, as in a function call. */ +/* Print out an expression-list in parens, as if it were the argument + list to a function. */ void pp_c_call_argument_list (c_pretty_printer *pp, tree t) diff --git a/gcc/c-semantics.c b/gcc/c-semantics.c index 2dda9b03a66..7b1f83b358c 100644 --- a/gcc/c-semantics.c +++ b/gcc/c-semantics.c @@ -115,6 +115,9 @@ build_stmt (enum tree_code code, ...) va_list p; bool side_effects; + /* This function cannot be used to construct variably-sized nodes. */ + gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp); + va_start (p, code); ret = make_node (code); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 28ce2baf163..f6ba19e2842 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -2330,17 +2330,17 @@ build_function_call (tree function, tree params) if (require_constant_value) { - result = fold_build3_initializer (CALL_EXPR, TREE_TYPE (fntype), - function, coerced_params, NULL_TREE); - + result = fold_build_call_list_initializer (TREE_TYPE (fntype), + function, + coerced_params); if (TREE_CONSTANT (result) && (name == NULL_TREE || strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0)) pedwarn_init ("initializer element is not constant"); } else - result = fold_build3 (CALL_EXPR, TREE_TYPE (fntype), - function, coerced_params, NULL_TREE); + result = fold_build_call_list (TREE_TYPE (fntype), + function, coerced_params); if (VOID_TYPE_P (TREE_TYPE (result))) return result; diff --git a/gcc/calls.c b/gcc/calls.c index 1f8ed60bf12..d84eb51aa36 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -553,11 +553,10 @@ bool alloca_call_p (tree exp) { if (TREE_CODE (exp) == CALL_EXPR - && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR - && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) - == FUNCTION_DECL) - && (special_function_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), - 0) & ECF_MAY_BE_ALLOCA)) + && TREE_CODE (CALL_EXPR_FN (exp)) == ADDR_EXPR + && (TREE_CODE (TREE_OPERAND (CALL_EXPR_FN (exp), 0)) == FUNCTION_DECL) + && (special_function_p (TREE_OPERAND (CALL_EXPR_FN (exp), 0), 0) + & ECF_MAY_BE_ALLOCA)) return true; return false; } @@ -626,7 +625,7 @@ call_expr_flags (tree t) flags = flags_from_decl_or_type (decl); else { - t = TREE_TYPE (TREE_OPERAND (t, 0)); + t = TREE_TYPE (CALL_EXPR_FN (t)); if (t && TREE_CODE (t) == POINTER_TYPE) flags = flags_from_decl_or_type (TREE_TYPE (t)); else @@ -1280,7 +1279,8 @@ precompute_arguments (int flags, int num_actuals, struct arg_data *args) compute and return the final value for MUST_PREALLOCATE. */ static int -finalize_must_preallocate (int must_preallocate, int num_actuals, struct arg_data *args, struct args_size *args_size) +finalize_must_preallocate (int must_preallocate, int num_actuals, + struct arg_data *args, struct args_size *args_size) { /* See if we have or want to preallocate stack space. @@ -1809,7 +1809,7 @@ shift_return_value (enum machine_mode mode, bool left_p, rtx value) return true; } -/* Generate all the code for a function call +/* Generate all the code for a CALL_EXPR exp and return an rtx for its value. Store the value in TARGET (specified as an rtx) if convenient. If the value is stored in TARGET then TARGET is returned. @@ -1822,7 +1822,8 @@ expand_call (tree exp, rtx target, int ignore) static int currently_expanding_call = 0; /* List of actual parameters. */ - tree actparms = TREE_OPERAND (exp, 1); + /* FIXME: rewrite this so that it doesn't cons up a TREE_LIST. */ + tree actparms = CALL_EXPR_ARGS (exp); /* RTX for the function to be called. */ rtx funexp; /* Sequence of insns to perform a normal "call". */ @@ -1923,8 +1924,8 @@ expand_call (tree exp, rtx target, int ignore) int old_stack_pointer_delta = 0; rtx call_fusage; - tree p = TREE_OPERAND (exp, 0); - tree addr = TREE_OPERAND (exp, 0); + tree p = CALL_EXPR_FN (exp); + tree addr = CALL_EXPR_FN (exp); int i; /* The alignment of the stack, in bits. */ unsigned HOST_WIDE_INT preferred_stack_boundary; @@ -2585,8 +2586,8 @@ expand_call (tree exp, rtx target, int ignore) once we have started filling any specific hard regs. */ precompute_register_parameters (num_actuals, args, ®_parm_seen); - if (TREE_OPERAND (exp, 2)) - static_chain_value = expand_normal (TREE_OPERAND (exp, 2)); + if (CALL_EXPR_STATIC_CHAIN (exp)) + static_chain_value = expand_normal (CALL_EXPR_STATIC_CHAIN (exp)); else static_chain_value = 0; diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c index 9d89aeb8d01..ec4e356c8c2 100644 --- a/gcc/cgraphbuild.c +++ b/gcc/cgraphbuild.c @@ -131,6 +131,8 @@ build_cgraph_edges (void) if (call && (decl = get_callee_fndecl (call))) { + int i; + int n = call_expr_nargs (call); int freq = (!bb->frequency && !entry_freq ? CGRAPH_FREQ_BASE : bb->frequency * CGRAPH_FREQ_BASE / entry_freq); if (freq > CGRAPH_FREQ_MAX) @@ -138,8 +140,9 @@ build_cgraph_edges (void) cgraph_create_edge (node, cgraph_node (decl), stmt, bb->count, freq, bb->loop_depth); - walk_tree (&TREE_OPERAND (call, 1), - record_reference, node, visited_nodes); + for (i = 0; i < n; i++) + walk_tree (&CALL_EXPR_ARG (call, i), + record_reference, node, visited_nodes); if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT) walk_tree (&GIMPLE_STMT_OPERAND (stmt, 0), record_reference, node, visited_nodes); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index f7274ee1fcf..16c34aecfeb 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1402,7 +1402,7 @@ update_call_expr (struct cgraph_node *new_version) for (e = new_version->callers; e; e = e->next_caller) /* Update the call expr on the edges to call the new version. */ - TREE_OPERAND (TREE_OPERAND (get_call_expr_in (e->call_stmt), 0), 0) = new_version->decl; + TREE_OPERAND (CALL_EXPR_FN (get_call_expr_in (e->call_stmt)), 0) = new_version->decl; } diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index b98085716c3..dcaa647047a 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -6500,9 +6500,10 @@ alpha_expand_builtin (tree exp, rtx target, { #define MAX_ARGS 2 - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned int fcode = DECL_FUNCTION_CODE (fndecl); - tree arglist = TREE_OPERAND (exp, 1); + tree arg; + call_expr_arg_iterator iter; enum insn_code icode; rtx op[MAX_ARGS], pat; int arity; @@ -6516,13 +6517,11 @@ alpha_expand_builtin (tree exp, rtx target, nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node; - for (arglist = TREE_OPERAND (exp, 1), arity = 0; - arglist; - arglist = TREE_CHAIN (arglist), arity++) + arity = 0; + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) { const struct insn_operand_data *insn_op; - tree arg = TREE_VALUE (arglist); if (arg == error_mark_node) return NULL_RTX; if (arity > MAX_ARGS) @@ -6534,6 +6533,7 @@ alpha_expand_builtin (tree exp, rtx target, if (!(*insn_op->predicate) (op[arity], insn_op->mode)) op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]); + arity++; } if (nonvoid) diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 78f6d729803..5c47533e6aa 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -13341,11 +13341,11 @@ safe_vector_operand (rtx x, enum machine_mode mode) static rtx arm_expand_binop_builtin (enum insn_code icode, - tree arglist, rtx target) + tree exp, rtx target) { rtx pat; - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); enum machine_mode tmode = insn_data[icode].operand[0].mode; @@ -13380,10 +13380,10 @@ arm_expand_binop_builtin (enum insn_code icode, static rtx arm_expand_unop_builtin (enum insn_code icode, - tree arglist, rtx target, int do_load) + tree exp, rtx target, int do_load) { rtx pat; - tree arg0 = TREE_VALUE (arglist); + tree arg0 = CALL_EXPR_ARG (exp, 0); rtx op0 = expand_normal (arg0); enum machine_mode tmode = insn_data[icode].operand[0].mode; enum machine_mode mode0 = insn_data[icode].operand[1].mode; @@ -13425,8 +13425,7 @@ arm_expand_builtin (tree exp, { const struct builtin_description * d; enum insn_code icode; - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - tree arglist = TREE_OPERAND (exp, 1); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); tree arg0; tree arg1; tree arg2; @@ -13455,8 +13454,8 @@ arm_expand_builtin (tree exp, : fcode == ARM_BUILTIN_TEXTRMUH ? CODE_FOR_iwmmxt_textrmuh : CODE_FOR_iwmmxt_textrmw); - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = expand_normal (arg0); op1 = expand_normal (arg1); tmode = insn_data[icode].operand[0].mode; @@ -13487,9 +13486,9 @@ arm_expand_builtin (tree exp, icode = (fcode == ARM_BUILTIN_TINSRB ? CODE_FOR_iwmmxt_tinsrb : fcode == ARM_BUILTIN_TINSRH ? CODE_FOR_iwmmxt_tinsrh : CODE_FOR_iwmmxt_tinsrw); - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); op0 = expand_normal (arg0); op1 = expand_normal (arg1); op2 = expand_normal (arg2); @@ -13519,15 +13518,15 @@ arm_expand_builtin (tree exp, return target; case ARM_BUILTIN_SETWCX: - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = force_reg (SImode, expand_normal (arg0)); op1 = expand_normal (arg1); emit_insn (gen_iwmmxt_tmcr (op1, op0)); return 0; case ARM_BUILTIN_GETWCX: - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); op0 = expand_normal (arg0); target = gen_reg_rtx (SImode); emit_insn (gen_iwmmxt_tmrc (target, op0)); @@ -13535,8 +13534,8 @@ arm_expand_builtin (tree exp, case ARM_BUILTIN_WSHUFH: icode = CODE_FOR_iwmmxt_wshufh; - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = expand_normal (arg0); op1 = expand_normal (arg1); tmode = insn_data[icode].operand[0].mode; @@ -13562,13 +13561,13 @@ arm_expand_builtin (tree exp, return target; case ARM_BUILTIN_WSADB: - return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadb, arglist, target); + return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadb, exp, target); case ARM_BUILTIN_WSADH: - return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadh, arglist, target); + return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadh, exp, target); case ARM_BUILTIN_WSADBZ: - return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadbz, arglist, target); + return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadbz, exp, target); case ARM_BUILTIN_WSADHZ: - return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadhz, arglist, target); + return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadhz, exp, target); /* Several three-argument builtins. */ case ARM_BUILTIN_WMACS: @@ -13589,9 +13588,9 @@ arm_expand_builtin (tree exp, : fcode == ARM_BUILTIN_TMIATB ? CODE_FOR_iwmmxt_tmiatb : fcode == ARM_BUILTIN_TMIATT ? CODE_FOR_iwmmxt_tmiatt : CODE_FOR_iwmmxt_walign); - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); op0 = expand_normal (arg0); op1 = expand_normal (arg1); op2 = expand_normal (arg2); @@ -13630,11 +13629,11 @@ arm_expand_builtin (tree exp, for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++) if (d->code == (const enum arm_builtins) fcode) - return arm_expand_binop_builtin (d->icode, arglist, target); + return arm_expand_binop_builtin (d->icode, exp, target); for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++) if (d->code == (const enum arm_builtins) fcode) - return arm_expand_unop_builtin (d->icode, arglist, target, 0); + return arm_expand_unop_builtin (d->icode, exp, target, 0); /* @@@ Should really do something sensible here. */ return NULL_RTX; diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 0d46f61f287..7f964638742 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -4617,12 +4617,12 @@ safe_vector_operand (rtx x, enum machine_mode mode) if this is a normal binary op, or one of the MACFLAG_xxx constants. */ static rtx -bfin_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target, +bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target, int macflag) { rtx pat; - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); enum machine_mode op0mode = GET_MODE (op0); @@ -4675,11 +4675,11 @@ bfin_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target, /* Subroutine of bfin_expand_builtin to take care of unop insns. */ static rtx -bfin_expand_unop_builtin (enum insn_code icode, tree arglist, +bfin_expand_unop_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat; - tree arg0 = TREE_VALUE (arglist); + tree arg0 = CALL_EXPR_ARG (exp, 0); rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); enum machine_mode op0mode = GET_MODE (op0); enum machine_mode tmode = insn_data[icode].operand[0].mode; @@ -4725,8 +4725,7 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, size_t i; enum insn_code icode; const struct builtin_description *d; - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - tree arglist = TREE_OPERAND (exp, 1); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned int fcode = DECL_FUNCTION_CODE (fndecl); tree arg0, arg1, arg2; rtx op0, op1, op2, accvec, pat, tmp1, tmp2; @@ -4743,7 +4742,7 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, case BFIN_BUILTIN_DIFFHL_2X16: case BFIN_BUILTIN_DIFFLH_2X16: - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3 : CODE_FOR_sublohiv2hi3); @@ -4768,8 +4767,8 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, return target; case BFIN_BUILTIN_CPLX_MUL_16: - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); accvec = gen_reg_rtx (V2PDImode); @@ -4795,9 +4794,9 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, case BFIN_BUILTIN_CPLX_MAC_16: case BFIN_BUILTIN_CPLX_MSU_16: - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0); @@ -4838,12 +4837,12 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++) if (d->code == fcode) - return bfin_expand_binop_builtin (d->icode, arglist, target, + return bfin_expand_binop_builtin (d->icode, exp, target, d->macflag); for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++) if (d->code == fcode) - return bfin_expand_unop_builtin (d->icode, arglist, target); + return bfin_expand_unop_builtin (d->icode, exp, target); gcc_unreachable (); } diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index 6e831c73923..ce0f706c2a8 100644 --- a/gcc/config/c4x/c4x.c +++ b/gcc/config/c4x/c4x.c @@ -4395,16 +4395,15 @@ c4x_expand_builtin (tree exp, rtx target, enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED) { - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned int fcode = DECL_FUNCTION_CODE (fndecl); - tree arglist = TREE_OPERAND (exp, 1); tree arg0, arg1; rtx r0, r1; switch (fcode) { case C4X_BUILTIN_FIX: - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); r0 = expand_expr (arg0, NULL_RTX, QFmode, 0); if (! target || ! register_operand (target, QImode)) target = gen_reg_rtx (QImode); @@ -4412,7 +4411,7 @@ c4x_expand_builtin (tree exp, rtx target, return target; case C4X_BUILTIN_FIX_ANSI: - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); r0 = expand_expr (arg0, NULL_RTX, QFmode, 0); if (! target || ! register_operand (target, QImode)) target = gen_reg_rtx (QImode); @@ -4422,8 +4421,8 @@ c4x_expand_builtin (tree exp, rtx target, case C4X_BUILTIN_MPYI: if (! TARGET_C3X) break; - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); r0 = expand_expr (arg0, NULL_RTX, QImode, 0); r1 = expand_expr (arg1, NULL_RTX, QImode, 0); if (! target || ! register_operand (target, QImode)) @@ -4434,7 +4433,7 @@ c4x_expand_builtin (tree exp, rtx target, case C4X_BUILTIN_TOIEEE: if (TARGET_C3X) break; - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); r0 = expand_expr (arg0, NULL_RTX, QFmode, 0); if (! target || ! register_operand (target, QFmode)) target = gen_reg_rtx (QFmode); @@ -4444,7 +4443,7 @@ c4x_expand_builtin (tree exp, rtx target, case C4X_BUILTIN_FRIEEE: if (TARGET_C3X) break; - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); r0 = expand_expr (arg0, NULL_RTX, QFmode, 0); if (register_operand (r0, QFmode)) { @@ -4460,7 +4459,7 @@ c4x_expand_builtin (tree exp, rtx target, case C4X_BUILTIN_RCPF: if (TARGET_C3X) break; - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); r0 = expand_expr (arg0, NULL_RTX, QFmode, 0); if (! target || ! register_operand (target, QFmode)) target = gen_reg_rtx (QFmode); diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index 942f3c688ed..b8701a527d7 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -9216,8 +9216,9 @@ frv_expand_builtin (tree exp, enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED) { - tree arglist = TREE_OPERAND (exp, 1); - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + /* FIXME: Pass the CALL_EXPR directly instead of consing up an arglist. */ + tree arglist = CALL_EXPR_ARGS (exp); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned fcode = (unsigned)DECL_FUNCTION_CODE (fndecl); unsigned i; struct builtin_description *d; diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 13419d77cfe..ff5766c84b3 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2695,7 +2695,7 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) func = decl; else { - func = TREE_TYPE (TREE_OPERAND (exp, 0)); + func = TREE_TYPE (CALL_EXPR_FN (exp)); if (POINTER_TYPE_P (func)) func = TREE_TYPE (func); } @@ -2730,7 +2730,7 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) tree type; /* We're looking at the CALL_EXPR, we need the type of the function. */ - type = TREE_OPERAND (exp, 0); /* pointer expression */ + type = CALL_EXPR_FN (exp); /* pointer expression */ type = TREE_TYPE (type); /* pointer type */ type = TREE_TYPE (type); /* function type */ @@ -17254,11 +17254,11 @@ safe_vector_operand (rtx x, enum machine_mode mode) /* Subroutine of ix86_expand_builtin to take care of binop insns. */ static rtx -ix86_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target) +ix86_expand_binop_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat, xops[3]; - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); enum machine_mode tmode = insn_data[icode].operand[0].mode; @@ -17322,11 +17322,11 @@ ix86_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target) /* Subroutine of ix86_expand_builtin to take care of stores. */ static rtx -ix86_expand_store_builtin (enum insn_code icode, tree arglist) +ix86_expand_store_builtin (enum insn_code icode, tree exp) { rtx pat; - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); enum machine_mode mode0 = insn_data[icode].operand[0].mode; @@ -17347,11 +17347,11 @@ ix86_expand_store_builtin (enum insn_code icode, tree arglist) /* Subroutine of ix86_expand_builtin to take care of unop insns. */ static rtx -ix86_expand_unop_builtin (enum insn_code icode, tree arglist, +ix86_expand_unop_builtin (enum insn_code icode, tree exp, rtx target, int do_load) { rtx pat; - tree arg0 = TREE_VALUE (arglist); + tree arg0 = CALL_EXPR_ARG (exp, 0); rtx op0 = expand_normal (arg0); enum machine_mode tmode = insn_data[icode].operand[0].mode; enum machine_mode mode0 = insn_data[icode].operand[1].mode; @@ -17383,10 +17383,10 @@ ix86_expand_unop_builtin (enum insn_code icode, tree arglist, sqrtss, rsqrtss, rcpss. */ static rtx -ix86_expand_unop1_builtin (enum insn_code icode, tree arglist, rtx target) +ix86_expand_unop1_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat; - tree arg0 = TREE_VALUE (arglist); + tree arg0 = CALL_EXPR_ARG (exp, 0); rtx op1, op0 = expand_normal (arg0); enum machine_mode tmode = insn_data[icode].operand[0].mode; enum machine_mode mode0 = insn_data[icode].operand[1].mode; @@ -17417,12 +17417,12 @@ ix86_expand_unop1_builtin (enum insn_code icode, tree arglist, rtx target) /* Subroutine of ix86_expand_builtin to take care of comparison insns. */ static rtx -ix86_expand_sse_compare (const struct builtin_description *d, tree arglist, +ix86_expand_sse_compare (const struct builtin_description *d, tree exp, rtx target) { rtx pat; - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); rtx op2; @@ -17469,12 +17469,12 @@ ix86_expand_sse_compare (const struct builtin_description *d, tree arglist, /* Subroutine of ix86_expand_builtin to take care of comi insns. */ static rtx -ix86_expand_sse_comi (const struct builtin_description *d, tree arglist, +ix86_expand_sse_comi (const struct builtin_description *d, tree exp, rtx target) { rtx pat; - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); rtx op2; @@ -17549,7 +17549,7 @@ get_element_number (tree vec_type, tree arg) these sorts of instructions. */ static rtx -ix86_expand_vec_init_builtin (tree type, tree arglist, rtx target) +ix86_expand_vec_init_builtin (tree type, tree exp, rtx target) { enum machine_mode tmode = TYPE_MODE (type); enum machine_mode inner_mode = GET_MODE_INNER (tmode); @@ -17557,15 +17557,14 @@ ix86_expand_vec_init_builtin (tree type, tree arglist, rtx target) rtvec v = rtvec_alloc (n_elt); gcc_assert (VECTOR_MODE_P (tmode)); + gcc_assert (call_expr_nargs (exp) == n_elt); - for (i = 0; i < n_elt; ++i, arglist = TREE_CHAIN (arglist)) + for (i = 0; i < n_elt; ++i) { - rtx x = expand_normal (TREE_VALUE (arglist)); + rtx x = expand_normal (CALL_EXPR_ARG (exp, i)); RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x); } - gcc_assert (arglist == NULL); - if (!target || !register_operand (target, tmode)) target = gen_reg_rtx (tmode); @@ -17578,15 +17577,15 @@ ix86_expand_vec_init_builtin (tree type, tree arglist, rtx target) had a language-level syntax for referencing vector elements. */ static rtx -ix86_expand_vec_ext_builtin (tree arglist, rtx target) +ix86_expand_vec_ext_builtin (tree exp, rtx target) { enum machine_mode tmode, mode0; tree arg0, arg1; int elt; rtx op0; - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = expand_normal (arg0); elt = get_element_number (TREE_TYPE (arg0), arg1); @@ -17610,16 +17609,16 @@ ix86_expand_vec_ext_builtin (tree arglist, rtx target) a language-level syntax for referencing vector elements. */ static rtx -ix86_expand_vec_set_builtin (tree arglist) +ix86_expand_vec_set_builtin (tree exp) { enum machine_mode tmode, mode1; tree arg0, arg1, arg2; int elt; rtx op0, op1; - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); tmode = TYPE_MODE (TREE_TYPE (arg0)); mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))); @@ -17654,8 +17653,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, const struct builtin_description *d; size_t i; enum insn_code icode; - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - tree arglist = TREE_OPERAND (exp, 1); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); tree arg0, arg1, arg2, arg3; rtx op0, op1, op2, op3, pat; enum machine_mode tmode, mode0, mode1, mode2, mode3, mode4; @@ -17677,9 +17675,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ? CODE_FOR_mmx_maskmovq : CODE_FOR_sse2_maskmovdqu); /* Note the arg order is different from the operand order. */ - arg1 = TREE_VALUE (arglist); - arg2 = TREE_VALUE (TREE_CHAIN (arglist)); - arg0 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg1 = CALL_EXPR_ARG (exp, 0); + arg2 = CALL_EXPR_ARG (exp, 1); + arg0 = CALL_EXPR_ARG (exp, 2); op0 = expand_normal (arg0); op1 = expand_normal (arg1); op2 = expand_normal (arg2); @@ -17703,17 +17701,17 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, return 0; case IX86_BUILTIN_SQRTSS: - return ix86_expand_unop1_builtin (CODE_FOR_sse_vmsqrtv4sf2, arglist, target); + return ix86_expand_unop1_builtin (CODE_FOR_sse_vmsqrtv4sf2, exp, target); case IX86_BUILTIN_RSQRTSS: - return ix86_expand_unop1_builtin (CODE_FOR_sse_vmrsqrtv4sf2, arglist, target); + return ix86_expand_unop1_builtin (CODE_FOR_sse_vmrsqrtv4sf2, exp, target); case IX86_BUILTIN_RCPSS: - return ix86_expand_unop1_builtin (CODE_FOR_sse_vmrcpv4sf2, arglist, target); + return ix86_expand_unop1_builtin (CODE_FOR_sse_vmrcpv4sf2, exp, target); case IX86_BUILTIN_LOADUPS: - return ix86_expand_unop_builtin (CODE_FOR_sse_movups, arglist, target, 1); + return ix86_expand_unop_builtin (CODE_FOR_sse_movups, exp, target, 1); case IX86_BUILTIN_STOREUPS: - return ix86_expand_store_builtin (CODE_FOR_sse_movups, arglist); + return ix86_expand_store_builtin (CODE_FOR_sse_movups, exp); case IX86_BUILTIN_LOADHPS: case IX86_BUILTIN_LOADLPS: @@ -17723,8 +17721,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, : fcode == IX86_BUILTIN_LOADLPS ? CODE_FOR_sse_loadlps : fcode == IX86_BUILTIN_LOADHPD ? CODE_FOR_sse2_loadhpd : CODE_FOR_sse2_loadlpd); - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = expand_normal (arg0); op1 = expand_normal (arg1); tmode = insn_data[icode].operand[0].mode; @@ -17747,8 +17745,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, case IX86_BUILTIN_STORELPS: icode = (fcode == IX86_BUILTIN_STOREHPS ? CODE_FOR_sse_storehps : CODE_FOR_sse_storelps); - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = expand_normal (arg0); op1 = expand_normal (arg1); mode0 = insn_data[icode].operand[0].mode; @@ -17764,12 +17762,12 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, return const0_rtx; case IX86_BUILTIN_MOVNTPS: - return ix86_expand_store_builtin (CODE_FOR_sse_movntv4sf, arglist); + return ix86_expand_store_builtin (CODE_FOR_sse_movntv4sf, exp); case IX86_BUILTIN_MOVNTQ: - return ix86_expand_store_builtin (CODE_FOR_sse_movntdi, arglist); + return ix86_expand_store_builtin (CODE_FOR_sse_movntdi, exp); case IX86_BUILTIN_LDMXCSR: - op0 = expand_normal (TREE_VALUE (arglist)); + op0 = expand_normal (CALL_EXPR_ARG (exp, 0)); target = assign_386_stack_local (SImode, SLOT_TEMP); emit_move_insn (target, op0); emit_insn (gen_sse_ldmxcsr (target)); @@ -17785,9 +17783,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, icode = (fcode == IX86_BUILTIN_SHUFPS ? CODE_FOR_sse_shufps : CODE_FOR_sse2_shufpd); - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); op0 = expand_normal (arg0); op1 = expand_normal (arg1); op2 = expand_normal (arg2); @@ -17825,8 +17823,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, : fcode == IX86_BUILTIN_PSHUFLW ? CODE_FOR_sse2_pshuflw : fcode == IX86_BUILTIN_PSHUFD ? CODE_FOR_sse2_pshufd : CODE_FOR_mmx_pshufw); - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = expand_normal (arg0); op1 = expand_normal (arg1); tmode = insn_data[icode].operand[0].mode; @@ -17855,8 +17853,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, case IX86_BUILTIN_PSRLDQI128: icode = ( fcode == IX86_BUILTIN_PSLLDQI128 ? CODE_FOR_sse2_ashlti3 : CODE_FOR_sse2_lshrti3); - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = expand_normal (arg0); op1 = expand_normal (arg1); tmode = insn_data[icode].operand[0].mode; @@ -17885,86 +17883,86 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, return NULL_RTX; case IX86_BUILTIN_PAVGUSB: - return ix86_expand_binop_builtin (CODE_FOR_mmx_uavgv8qi3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_uavgv8qi3, exp, target); case IX86_BUILTIN_PF2ID: - return ix86_expand_unop_builtin (CODE_FOR_mmx_pf2id, arglist, target, 0); + return ix86_expand_unop_builtin (CODE_FOR_mmx_pf2id, exp, target, 0); case IX86_BUILTIN_PFACC: - return ix86_expand_binop_builtin (CODE_FOR_mmx_haddv2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_haddv2sf3, exp, target); case IX86_BUILTIN_PFADD: - return ix86_expand_binop_builtin (CODE_FOR_mmx_addv2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_addv2sf3, exp, target); case IX86_BUILTIN_PFCMPEQ: - return ix86_expand_binop_builtin (CODE_FOR_mmx_eqv2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_eqv2sf3, exp, target); case IX86_BUILTIN_PFCMPGE: - return ix86_expand_binop_builtin (CODE_FOR_mmx_gev2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_gev2sf3, exp, target); case IX86_BUILTIN_PFCMPGT: - return ix86_expand_binop_builtin (CODE_FOR_mmx_gtv2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_gtv2sf3, exp, target); case IX86_BUILTIN_PFMAX: - return ix86_expand_binop_builtin (CODE_FOR_mmx_smaxv2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_smaxv2sf3, exp, target); case IX86_BUILTIN_PFMIN: - return ix86_expand_binop_builtin (CODE_FOR_mmx_sminv2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_sminv2sf3, exp, target); case IX86_BUILTIN_PFMUL: - return ix86_expand_binop_builtin (CODE_FOR_mmx_mulv2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_mulv2sf3, exp, target); case IX86_BUILTIN_PFRCP: - return ix86_expand_unop_builtin (CODE_FOR_mmx_rcpv2sf2, arglist, target, 0); + return ix86_expand_unop_builtin (CODE_FOR_mmx_rcpv2sf2, exp, target, 0); case IX86_BUILTIN_PFRCPIT1: - return ix86_expand_binop_builtin (CODE_FOR_mmx_rcpit1v2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_rcpit1v2sf3, exp, target); case IX86_BUILTIN_PFRCPIT2: - return ix86_expand_binop_builtin (CODE_FOR_mmx_rcpit2v2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_rcpit2v2sf3, exp, target); case IX86_BUILTIN_PFRSQIT1: - return ix86_expand_binop_builtin (CODE_FOR_mmx_rsqit1v2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_rsqit1v2sf3, exp, target); case IX86_BUILTIN_PFRSQRT: - return ix86_expand_unop_builtin (CODE_FOR_mmx_rsqrtv2sf2, arglist, target, 0); + return ix86_expand_unop_builtin (CODE_FOR_mmx_rsqrtv2sf2, exp, target, 0); case IX86_BUILTIN_PFSUB: - return ix86_expand_binop_builtin (CODE_FOR_mmx_subv2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_subv2sf3, exp, target); case IX86_BUILTIN_PFSUBR: - return ix86_expand_binop_builtin (CODE_FOR_mmx_subrv2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_subrv2sf3, exp, target); case IX86_BUILTIN_PI2FD: - return ix86_expand_unop_builtin (CODE_FOR_mmx_floatv2si2, arglist, target, 0); + return ix86_expand_unop_builtin (CODE_FOR_mmx_floatv2si2, exp, target, 0); case IX86_BUILTIN_PMULHRW: - return ix86_expand_binop_builtin (CODE_FOR_mmx_pmulhrwv4hi3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_pmulhrwv4hi3, exp, target); case IX86_BUILTIN_PF2IW: - return ix86_expand_unop_builtin (CODE_FOR_mmx_pf2iw, arglist, target, 0); + return ix86_expand_unop_builtin (CODE_FOR_mmx_pf2iw, exp, target, 0); case IX86_BUILTIN_PFNACC: - return ix86_expand_binop_builtin (CODE_FOR_mmx_hsubv2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_hsubv2sf3, exp, target); case IX86_BUILTIN_PFPNACC: - return ix86_expand_binop_builtin (CODE_FOR_mmx_addsubv2sf3, arglist, target); + return ix86_expand_binop_builtin (CODE_FOR_mmx_addsubv2sf3, exp, target); case IX86_BUILTIN_PI2FW: - return ix86_expand_unop_builtin (CODE_FOR_mmx_pi2fw, arglist, target, 0); + return ix86_expand_unop_builtin (CODE_FOR_mmx_pi2fw, exp, target, 0); case IX86_BUILTIN_PSWAPDSI: - return ix86_expand_unop_builtin (CODE_FOR_mmx_pswapdv2si2, arglist, target, 0); + return ix86_expand_unop_builtin (CODE_FOR_mmx_pswapdv2si2, exp, target, 0); case IX86_BUILTIN_PSWAPDSF: - return ix86_expand_unop_builtin (CODE_FOR_mmx_pswapdv2sf2, arglist, target, 0); + return ix86_expand_unop_builtin (CODE_FOR_mmx_pswapdv2sf2, exp, target, 0); case IX86_BUILTIN_SQRTSD: - return ix86_expand_unop1_builtin (CODE_FOR_sse2_vmsqrtv2df2, arglist, target); + return ix86_expand_unop1_builtin (CODE_FOR_sse2_vmsqrtv2df2, exp, target); case IX86_BUILTIN_LOADUPD: - return ix86_expand_unop_builtin (CODE_FOR_sse2_movupd, arglist, target, 1); + return ix86_expand_unop_builtin (CODE_FOR_sse2_movupd, exp, target, 1); case IX86_BUILTIN_STOREUPD: - return ix86_expand_store_builtin (CODE_FOR_sse2_movupd, arglist); + return ix86_expand_store_builtin (CODE_FOR_sse2_movupd, exp); case IX86_BUILTIN_MFENCE: emit_insn (gen_sse2_mfence ()); @@ -17974,7 +17972,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, return 0; case IX86_BUILTIN_CLFLUSH: - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); op0 = expand_normal (arg0); icode = CODE_FOR_sse2_clflush; if (! (*insn_data[icode].operand[0].predicate) (op0, Pmode)) @@ -17984,21 +17982,21 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, return 0; case IX86_BUILTIN_MOVNTPD: - return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2df, arglist); + return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2df, exp); case IX86_BUILTIN_MOVNTDQ: - return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2di, arglist); + return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2di, exp); case IX86_BUILTIN_MOVNTI: - return ix86_expand_store_builtin (CODE_FOR_sse2_movntsi, arglist); + return ix86_expand_store_builtin (CODE_FOR_sse2_movntsi, exp); case IX86_BUILTIN_LOADDQU: - return ix86_expand_unop_builtin (CODE_FOR_sse2_movdqu, arglist, target, 1); + return ix86_expand_unop_builtin (CODE_FOR_sse2_movdqu, exp, target, 1); case IX86_BUILTIN_STOREDQU: - return ix86_expand_store_builtin (CODE_FOR_sse2_movdqu, arglist); + return ix86_expand_store_builtin (CODE_FOR_sse2_movdqu, exp); case IX86_BUILTIN_MONITOR: - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); op0 = expand_normal (arg0); op1 = expand_normal (arg1); op2 = expand_normal (arg2); @@ -18015,8 +18013,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, return 0; case IX86_BUILTIN_MWAIT: - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = expand_normal (arg0); op1 = expand_normal (arg1); if (!REG_P (op0)) @@ -18027,7 +18025,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, return 0; case IX86_BUILTIN_LDDQU: - return ix86_expand_unop_builtin (CODE_FOR_sse3_lddqu, arglist, + return ix86_expand_unop_builtin (CODE_FOR_sse3_lddqu, exp, target, 1); case IX86_BUILTIN_PALIGNR: @@ -18042,9 +18040,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, icode = CODE_FOR_ssse3_palignrti; mode = V2DImode; } - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0); @@ -18077,18 +18075,18 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, return target; case IX86_BUILTIN_MOVNTSD: - return ix86_expand_store_builtin (CODE_FOR_sse4a_vmmovntv2df, arglist); + return ix86_expand_store_builtin (CODE_FOR_sse4a_vmmovntv2df, exp); case IX86_BUILTIN_MOVNTSS: - return ix86_expand_store_builtin (CODE_FOR_sse4a_vmmovntv4sf, arglist); + return ix86_expand_store_builtin (CODE_FOR_sse4a_vmmovntv4sf, exp); case IX86_BUILTIN_INSERTQ: case IX86_BUILTIN_EXTRQ: icode = (fcode == IX86_BUILTIN_EXTRQ ? CODE_FOR_sse4a_extrq : CODE_FOR_sse4a_insertq); - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = expand_normal (arg0); op1 = expand_normal (arg1); tmode = insn_data[icode].operand[0].mode; @@ -18110,9 +18108,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, case IX86_BUILTIN_EXTRQI: icode = CODE_FOR_sse4a_extrqi; - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); op0 = expand_normal (arg0); op1 = expand_normal (arg1); op2 = expand_normal (arg2); @@ -18144,10 +18142,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, case IX86_BUILTIN_INSERTQI: icode = CODE_FOR_sse4a_insertqi; - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); - arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); + arg3 = CALL_EXPR_ARG (exp, 3); op0 = expand_normal (arg0); op1 = expand_normal (arg1); op2 = expand_normal (arg2); @@ -18187,7 +18185,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, case IX86_BUILTIN_VEC_INIT_V2SI: case IX86_BUILTIN_VEC_INIT_V4HI: case IX86_BUILTIN_VEC_INIT_V8QI: - return ix86_expand_vec_init_builtin (TREE_TYPE (exp), arglist, target); + return ix86_expand_vec_init_builtin (TREE_TYPE (exp), exp, target); case IX86_BUILTIN_VEC_EXT_V2DF: case IX86_BUILTIN_VEC_EXT_V2DI: @@ -18196,11 +18194,11 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, case IX86_BUILTIN_VEC_EXT_V8HI: case IX86_BUILTIN_VEC_EXT_V2SI: case IX86_BUILTIN_VEC_EXT_V4HI: - return ix86_expand_vec_ext_builtin (arglist, target); + return ix86_expand_vec_ext_builtin (exp, target); case IX86_BUILTIN_VEC_SET_V8HI: case IX86_BUILTIN_VEC_SET_V4HI: - return ix86_expand_vec_set_builtin (arglist); + return ix86_expand_vec_set_builtin (exp); default: break; @@ -18214,18 +18212,18 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, || d->icode == CODE_FOR_sse_vmmaskcmpv4sf3 || d->icode == CODE_FOR_sse2_maskcmpv2df3 || d->icode == CODE_FOR_sse2_vmmaskcmpv2df3) - return ix86_expand_sse_compare (d, arglist, target); + return ix86_expand_sse_compare (d, exp, target); - return ix86_expand_binop_builtin (d->icode, arglist, target); + return ix86_expand_binop_builtin (d->icode, exp, target); } for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++) if (d->code == fcode) - return ix86_expand_unop_builtin (d->icode, arglist, target, 0); + return ix86_expand_unop_builtin (d->icode, exp, target, 0); for (i = 0, d = bdesc_comi; i < ARRAY_SIZE (bdesc_comi); i++, d++) if (d->code == fcode) - return ix86_expand_sse_comi (d, arglist, target); + return ix86_expand_sse_comi (d, exp, target); gcc_unreachable (); } diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c index 42b7c176693..a86dd40e2da 100644 --- a/gcc/config/iq2000/iq2000.c +++ b/gcc/config/iq2000/iq2000.c @@ -2569,11 +2569,11 @@ void_ftype_int_int_int def_builtin ("__builtin_syscall", void_ftype, IQ2000_BUILTIN_SYSCALL); } -/* Builtin for ICODE having ARGCOUNT args in ARGLIST where each arg +/* Builtin for ICODE having ARGCOUNT args in EXP where each arg has an rtx CODE. */ static rtx -expand_one_builtin (enum insn_code icode, rtx target, tree arglist, +expand_one_builtin (enum insn_code icode, rtx target, tree exp, enum rtx_code *code, int argcount) { rtx pat; @@ -2585,8 +2585,7 @@ expand_one_builtin (enum insn_code icode, rtx target, tree arglist, mode[0] = insn_data[icode].operand[0].mode; for (i = 0; i < argcount; i++) { - arg[i] = TREE_VALUE (arglist); - arglist = TREE_CHAIN (arglist); + arg[i] = CALL_EXPR_ARG (exp, i); op[i] = expand_expr (arg[i], NULL_RTX, VOIDmode, 0); mode[i] = insn_data[icode].operand[i].mode; if (code[i] == CONST_INT && GET_CODE (op[i]) != CONST_INT) @@ -2655,8 +2654,7 @@ iq2000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED) { - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - tree arglist = TREE_OPERAND (exp, 1); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); int fcode = DECL_FUNCTION_CODE (fndecl); enum rtx_code code [5]; @@ -2671,162 +2669,162 @@ iq2000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, break; case IQ2000_BUILTIN_ADO16: - return expand_one_builtin (CODE_FOR_ado16, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_ado16, target, exp, code, 2); case IQ2000_BUILTIN_RAM: code[1] = CONST_INT; code[2] = CONST_INT; code[3] = CONST_INT; - return expand_one_builtin (CODE_FOR_ram, target, arglist, code, 4); + return expand_one_builtin (CODE_FOR_ram, target, exp, code, 4); case IQ2000_BUILTIN_CHKHDR: - return expand_one_builtin (CODE_FOR_chkhdr, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_chkhdr, target, exp, code, 2); case IQ2000_BUILTIN_PKRL: - return expand_one_builtin (CODE_FOR_pkrl, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_pkrl, target, exp, code, 2); case IQ2000_BUILTIN_CFC0: code[0] = CONST_INT; - return expand_one_builtin (CODE_FOR_cfc0, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_cfc0, target, exp, code, 1); case IQ2000_BUILTIN_CFC1: code[0] = CONST_INT; - return expand_one_builtin (CODE_FOR_cfc1, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_cfc1, target, exp, code, 1); case IQ2000_BUILTIN_CFC2: code[0] = CONST_INT; - return expand_one_builtin (CODE_FOR_cfc2, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_cfc2, target, exp, code, 1); case IQ2000_BUILTIN_CFC3: code[0] = CONST_INT; - return expand_one_builtin (CODE_FOR_cfc3, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_cfc3, target, exp, code, 1); case IQ2000_BUILTIN_CTC0: code[1] = CONST_INT; - return expand_one_builtin (CODE_FOR_ctc0, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_ctc0, target, exp, code, 2); case IQ2000_BUILTIN_CTC1: code[1] = CONST_INT; - return expand_one_builtin (CODE_FOR_ctc1, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_ctc1, target, exp, code, 2); case IQ2000_BUILTIN_CTC2: code[1] = CONST_INT; - return expand_one_builtin (CODE_FOR_ctc2, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_ctc2, target, exp, code, 2); case IQ2000_BUILTIN_CTC3: code[1] = CONST_INT; - return expand_one_builtin (CODE_FOR_ctc3, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_ctc3, target, exp, code, 2); case IQ2000_BUILTIN_MFC0: code[0] = CONST_INT; - return expand_one_builtin (CODE_FOR_mfc0, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_mfc0, target, exp, code, 1); case IQ2000_BUILTIN_MFC1: code[0] = CONST_INT; - return expand_one_builtin (CODE_FOR_mfc1, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_mfc1, target, exp, code, 1); case IQ2000_BUILTIN_MFC2: code[0] = CONST_INT; - return expand_one_builtin (CODE_FOR_mfc2, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_mfc2, target, exp, code, 1); case IQ2000_BUILTIN_MFC3: code[0] = CONST_INT; - return expand_one_builtin (CODE_FOR_mfc3, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_mfc3, target, exp, code, 1); case IQ2000_BUILTIN_MTC0: code[1] = CONST_INT; - return expand_one_builtin (CODE_FOR_mtc0, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_mtc0, target, exp, code, 2); case IQ2000_BUILTIN_MTC1: code[1] = CONST_INT; - return expand_one_builtin (CODE_FOR_mtc1, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_mtc1, target, exp, code, 2); case IQ2000_BUILTIN_MTC2: code[1] = CONST_INT; - return expand_one_builtin (CODE_FOR_mtc2, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_mtc2, target, exp, code, 2); case IQ2000_BUILTIN_MTC3: code[1] = CONST_INT; - return expand_one_builtin (CODE_FOR_mtc3, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_mtc3, target, exp, code, 2); case IQ2000_BUILTIN_LUR: - return expand_one_builtin (CODE_FOR_lur, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_lur, target, exp, code, 2); case IQ2000_BUILTIN_RB: - return expand_one_builtin (CODE_FOR_rb, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_rb, target, exp, code, 2); case IQ2000_BUILTIN_RX: - return expand_one_builtin (CODE_FOR_rx, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_rx, target, exp, code, 2); case IQ2000_BUILTIN_SRRD: - return expand_one_builtin (CODE_FOR_srrd, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_srrd, target, exp, code, 1); case IQ2000_BUILTIN_SRWR: - return expand_one_builtin (CODE_FOR_srwr, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_srwr, target, exp, code, 2); case IQ2000_BUILTIN_WB: - return expand_one_builtin (CODE_FOR_wb, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_wb, target, exp, code, 2); case IQ2000_BUILTIN_WX: - return expand_one_builtin (CODE_FOR_wx, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_wx, target, exp, code, 2); case IQ2000_BUILTIN_LUC32L: - return expand_one_builtin (CODE_FOR_luc32l, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_luc32l, target, exp, code, 2); case IQ2000_BUILTIN_LUC64: - return expand_one_builtin (CODE_FOR_luc64, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_luc64, target, exp, code, 2); case IQ2000_BUILTIN_LUC64L: - return expand_one_builtin (CODE_FOR_luc64l, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_luc64l, target, exp, code, 2); case IQ2000_BUILTIN_LUK: - return expand_one_builtin (CODE_FOR_luk, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_luk, target, exp, code, 2); case IQ2000_BUILTIN_LULCK: - return expand_one_builtin (CODE_FOR_lulck, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_lulck, target, exp, code, 1); case IQ2000_BUILTIN_LUM32: - return expand_one_builtin (CODE_FOR_lum32, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_lum32, target, exp, code, 2); case IQ2000_BUILTIN_LUM32L: - return expand_one_builtin (CODE_FOR_lum32l, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_lum32l, target, exp, code, 2); case IQ2000_BUILTIN_LUM64: - return expand_one_builtin (CODE_FOR_lum64, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_lum64, target, exp, code, 2); case IQ2000_BUILTIN_LUM64L: - return expand_one_builtin (CODE_FOR_lum64l, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_lum64l, target, exp, code, 2); case IQ2000_BUILTIN_LURL: - return expand_one_builtin (CODE_FOR_lurl, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_lurl, target, exp, code, 2); case IQ2000_BUILTIN_MRGB: code[2] = CONST_INT; - return expand_one_builtin (CODE_FOR_mrgb, target, arglist, code, 3); + return expand_one_builtin (CODE_FOR_mrgb, target, exp, code, 3); case IQ2000_BUILTIN_SRRDL: - return expand_one_builtin (CODE_FOR_srrdl, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_srrdl, target, exp, code, 1); case IQ2000_BUILTIN_SRULCK: - return expand_one_builtin (CODE_FOR_srulck, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_srulck, target, exp, code, 1); case IQ2000_BUILTIN_SRWRU: - return expand_one_builtin (CODE_FOR_srwru, target, arglist, code, 2); + return expand_one_builtin (CODE_FOR_srwru, target, exp, code, 2); case IQ2000_BUILTIN_TRAPQFL: - return expand_one_builtin (CODE_FOR_trapqfl, target, arglist, code, 0); + return expand_one_builtin (CODE_FOR_trapqfl, target, exp, code, 0); case IQ2000_BUILTIN_TRAPQNE: - return expand_one_builtin (CODE_FOR_trapqne, target, arglist, code, 0); + return expand_one_builtin (CODE_FOR_trapqne, target, exp, code, 0); case IQ2000_BUILTIN_TRAPREL: - return expand_one_builtin (CODE_FOR_traprel, target, arglist, code, 1); + return expand_one_builtin (CODE_FOR_traprel, target, exp, code, 1); case IQ2000_BUILTIN_WBU: - return expand_one_builtin (CODE_FOR_wbu, target, arglist, code, 3); + return expand_one_builtin (CODE_FOR_wbu, target, exp, code, 3); case IQ2000_BUILTIN_SYSCALL: - return expand_one_builtin (CODE_FOR_syscall, target, arglist, code, 0); + return expand_one_builtin (CODE_FOR_syscall, target, exp, code, 0); } return NULL_RTX; diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 93c482368ae..7112cc363d2 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -10336,8 +10336,10 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, const struct builtin_description *bdesc; const struct bdesc_map *m; - fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - arglist = TREE_OPERAND (exp, 1); + fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + /* FIXME: Rewrite this to use the CALL_EXPR directly instead of consing + up an arglist. */ + arglist = CALL_EXPR_ARGS (exp); fcode = DECL_FUNCTION_CODE (fndecl); bdesc = NULL; diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index 55c9b7c66b2..1845eda584a 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -2436,7 +2436,8 @@ altivec_build_resolved_builtin (tree *args, int n, tree impl_fndecl = rs6000_builtin_decls[desc->overloaded_code]; tree ret_type = rs6000_builtin_type (desc->ret_type); tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (impl_fndecl)); - tree arglist = NULL_TREE, arg_type[3]; + tree arg_type[3]; + tree call; int i; for (i = 0; i < n; i++) @@ -2463,13 +2464,30 @@ altivec_build_resolved_builtin (tree *args, int n, build_int_cst (NULL_TREE, 2)); } - while (--n >= 0) - arglist = tree_cons (NULL_TREE, - fold_convert (arg_type[n], args[n]), - arglist); - - return fold_convert (ret_type, - build_function_call_expr (impl_fndecl, arglist)); + switch (n) + { + case 0: + call = build_call_expr (impl_fndecl, 0); + break; + case 1: + call = build_call_expr (impl_fndecl, 1, + fold_convert (arg_type[0], args[0])); + break; + case 2: + call = build_call_expr (impl_fndecl, 2, + fold_convert (arg_type[0], args[0]), + fold_convert (arg_type[1], args[1])); + break; + case 3: + call = build_call_expr (impl_fndecl, 3, + fold_convert (arg_type[0], args[0]), + fold_convert (arg_type[1], args[1]), + fold_convert (arg_type[2], args[2])); + break; + default: + gcc_unreachable (); + } + return fold_convert (ret_type, call); } /* Implementation of the resolve_overloaded_builtin target hook, to diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 4ed383f31ab..5389c318cf4 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -6294,12 +6294,8 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) tree tmp = create_tmp_var (type, "va_arg_tmp"); tree dest_addr = build_fold_addr_expr (tmp); - tree copy = build_function_call_expr - (implicit_built_in_decls[BUILT_IN_MEMCPY], - tree_cons (NULL_TREE, dest_addr, - tree_cons (NULL_TREE, addr, - tree_cons (NULL_TREE, size_int (rsize * 4), - NULL_TREE)))); + tree copy = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY], + 3, dest_addr, addr, size_int (rsize * 4)); gimplify_and_add (copy, pre_p); addr = dest_addr; @@ -6934,10 +6930,10 @@ static struct builtin_description bdesc_1arg[] = }; static rtx -rs6000_expand_unop_builtin (enum insn_code icode, tree arglist, rtx target) +rs6000_expand_unop_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat; - tree arg0 = TREE_VALUE (arglist); + tree arg0 = CALL_EXPR_ARG (exp, 0); rtx op0 = expand_normal (arg0); enum machine_mode tmode = insn_data[icode].operand[0].mode; enum machine_mode mode0 = insn_data[icode].operand[1].mode; @@ -6983,10 +6979,10 @@ rs6000_expand_unop_builtin (enum insn_code icode, tree arglist, rtx target) } static rtx -altivec_expand_abs_builtin (enum insn_code icode, tree arglist, rtx target) +altivec_expand_abs_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat, scratch1, scratch2; - tree arg0 = TREE_VALUE (arglist); + tree arg0 = CALL_EXPR_ARG (exp, 0); rtx op0 = expand_normal (arg0); enum machine_mode tmode = insn_data[icode].operand[0].mode; enum machine_mode mode0 = insn_data[icode].operand[1].mode; @@ -7015,11 +7011,11 @@ altivec_expand_abs_builtin (enum insn_code icode, tree arglist, rtx target) } static rtx -rs6000_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target) +rs6000_expand_binop_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat; - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); enum machine_mode tmode = insn_data[icode].operand[0].mode; @@ -7089,12 +7085,12 @@ rs6000_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target) static rtx altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode, - tree arglist, rtx target) + tree exp, rtx target) { rtx pat, scratch; - tree cr6_form = TREE_VALUE (arglist); - tree arg0 = TREE_VALUE (TREE_CHAIN (arglist)); - tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + tree cr6_form = CALL_EXPR_ARG (exp, 0); + tree arg0 = CALL_EXPR_ARG (exp, 1); + tree arg1 = CALL_EXPR_ARG (exp, 2); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); enum machine_mode tmode = SImode; @@ -7165,11 +7161,11 @@ altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode, } static rtx -altivec_expand_lv_builtin (enum insn_code icode, tree arglist, rtx target) +altivec_expand_lv_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat, addr; - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); enum machine_mode tmode = insn_data[icode].operand[0].mode; enum machine_mode mode0 = Pmode; enum machine_mode mode1 = Pmode; @@ -7211,11 +7207,11 @@ altivec_expand_lv_builtin (enum insn_code icode, tree arglist, rtx target) } static rtx -spe_expand_stv_builtin (enum insn_code icode, tree arglist) +spe_expand_stv_builtin (enum insn_code icode, tree exp) { - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + tree arg2 = CALL_EXPR_ARG (exp, 2); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); rtx op2 = expand_normal (arg2); @@ -7244,11 +7240,11 @@ spe_expand_stv_builtin (enum insn_code icode, tree arglist) } static rtx -altivec_expand_stv_builtin (enum insn_code icode, tree arglist) +altivec_expand_stv_builtin (enum insn_code icode, tree exp) { - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + tree arg2 = CALL_EXPR_ARG (exp, 2); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); rtx op2 = expand_normal (arg2); @@ -7285,12 +7281,12 @@ altivec_expand_stv_builtin (enum insn_code icode, tree arglist) } static rtx -rs6000_expand_ternop_builtin (enum insn_code icode, tree arglist, rtx target) +rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat; - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + tree arg2 = CALL_EXPR_ARG (exp, 2); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); rtx op2 = expand_normal (arg2); @@ -7348,8 +7344,7 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree arglist, rtx target) static rtx altivec_expand_ld_builtin (tree exp, rtx target, bool *expandedp) { - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - tree arglist = TREE_OPERAND (exp, 1); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned int fcode = DECL_FUNCTION_CODE (fndecl); tree arg0; enum machine_mode tmode, mode0; @@ -7377,7 +7372,7 @@ altivec_expand_ld_builtin (tree exp, rtx target, bool *expandedp) *expandedp = true; - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); op0 = expand_normal (arg0); tmode = insn_data[icode].operand[0].mode; mode0 = insn_data[icode].operand[1].mode; @@ -7402,8 +7397,7 @@ static rtx altivec_expand_st_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, bool *expandedp) { - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - tree arglist = TREE_OPERAND (exp, 1); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned int fcode = DECL_FUNCTION_CODE (fndecl); tree arg0, arg1; enum machine_mode mode0, mode1; @@ -7429,8 +7423,8 @@ altivec_expand_st_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, return NULL_RTX; } - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = expand_normal (arg0); op1 = expand_normal (arg1); mode0 = insn_data[icode].operand[0].mode; @@ -7454,8 +7448,7 @@ static rtx altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, bool *expandedp) { - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - tree arglist = TREE_OPERAND (exp, 1); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned int fcode = DECL_FUNCTION_CODE (fndecl); tree arg0, arg1, arg2; enum machine_mode mode0, mode1, mode2; @@ -7470,9 +7463,9 @@ altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++) if (d->code == fcode) { - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); op0 = expand_normal (arg0); op1 = expand_normal (arg1); op2 = expand_normal (arg2); @@ -7512,7 +7505,7 @@ altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, /* Expand vec_init builtin. */ static rtx -altivec_expand_vec_init_builtin (tree type, tree arglist, rtx target) +altivec_expand_vec_init_builtin (tree type, tree exp, rtx target) { enum machine_mode tmode = TYPE_MODE (type); enum machine_mode inner_mode = GET_MODE_INNER (tmode); @@ -7520,15 +7513,14 @@ altivec_expand_vec_init_builtin (tree type, tree arglist, rtx target) rtvec v = rtvec_alloc (n_elt); gcc_assert (VECTOR_MODE_P (tmode)); - - for (i = 0; i < n_elt; ++i, arglist = TREE_CHAIN (arglist)) + gcc_assert (n_elt == call_expr_nargs (exp)); + + for (i = 0; i < n_elt; ++i) { - rtx x = expand_normal (TREE_VALUE (arglist)); + rtx x = expand_normal (CALL_EXPR_ARG (exp, i)); RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x); } - gcc_assert (arglist == NULL); - if (!target || !register_operand (target, tmode)) target = gen_reg_rtx (tmode); @@ -7556,16 +7548,16 @@ get_element_number (tree vec_type, tree arg) /* Expand vec_set builtin. */ static rtx -altivec_expand_vec_set_builtin (tree arglist) +altivec_expand_vec_set_builtin (tree exp) { enum machine_mode tmode, mode1; tree arg0, arg1, arg2; int elt; rtx op0, op1; - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); tmode = TYPE_MODE (TREE_TYPE (arg0)); mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))); @@ -7588,15 +7580,15 @@ altivec_expand_vec_set_builtin (tree arglist) /* Expand vec_ext builtin. */ static rtx -altivec_expand_vec_ext_builtin (tree arglist, rtx target) +altivec_expand_vec_ext_builtin (tree exp, rtx target) { enum machine_mode tmode, mode0; tree arg0, arg1; int elt; rtx op0; - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); op0 = expand_normal (arg0); elt = get_element_number (TREE_TYPE (arg0), arg1); @@ -7624,8 +7616,7 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp) struct builtin_description_predicates *dp; size_t i; enum insn_code icode; - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - tree arglist = TREE_OPERAND (exp, 1); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); tree arg0; rtx op0, pat; enum machine_mode tmode, mode0; @@ -7656,15 +7647,15 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp) switch (fcode) { case ALTIVEC_BUILTIN_STVX: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx, arglist); + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx, exp); case ALTIVEC_BUILTIN_STVEBX: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvebx, arglist); + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvebx, exp); case ALTIVEC_BUILTIN_STVEHX: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvehx, arglist); + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvehx, exp); case ALTIVEC_BUILTIN_STVEWX: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvewx, arglist); + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvewx, exp); case ALTIVEC_BUILTIN_STVXL: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl, arglist); + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl, exp); case ALTIVEC_BUILTIN_MFVSCR: icode = CODE_FOR_altivec_mfvscr; @@ -7683,7 +7674,7 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp) case ALTIVEC_BUILTIN_MTVSCR: icode = CODE_FOR_altivec_mtvscr; - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); op0 = expand_normal (arg0); mode0 = insn_data[icode].operand[0].mode; @@ -7705,7 +7696,7 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp) case ALTIVEC_BUILTIN_DSS: icode = CODE_FOR_altivec_dss; - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); STRIP_NOPS (arg0); op0 = expand_normal (arg0); mode0 = insn_data[icode].operand[0].mode; @@ -7731,19 +7722,19 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp) case ALTIVEC_BUILTIN_VEC_INIT_V8HI: case ALTIVEC_BUILTIN_VEC_INIT_V16QI: case ALTIVEC_BUILTIN_VEC_INIT_V4SF: - return altivec_expand_vec_init_builtin (TREE_TYPE (exp), arglist, target); + return altivec_expand_vec_init_builtin (TREE_TYPE (exp), exp, target); case ALTIVEC_BUILTIN_VEC_SET_V4SI: case ALTIVEC_BUILTIN_VEC_SET_V8HI: case ALTIVEC_BUILTIN_VEC_SET_V16QI: case ALTIVEC_BUILTIN_VEC_SET_V4SF: - return altivec_expand_vec_set_builtin (arglist); + return altivec_expand_vec_set_builtin (exp); case ALTIVEC_BUILTIN_VEC_EXT_V4SI: case ALTIVEC_BUILTIN_VEC_EXT_V8HI: case ALTIVEC_BUILTIN_VEC_EXT_V16QI: case ALTIVEC_BUILTIN_VEC_EXT_V4SF: - return altivec_expand_vec_ext_builtin (arglist, target); + return altivec_expand_vec_ext_builtin (exp, target); default: break; @@ -7754,39 +7745,39 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp) d = (struct builtin_description *) bdesc_abs; for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++) if (d->code == fcode) - return altivec_expand_abs_builtin (d->icode, arglist, target); + return altivec_expand_abs_builtin (d->icode, exp, target); /* Expand the AltiVec predicates. */ dp = (struct builtin_description_predicates *) bdesc_altivec_preds; for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++) if (dp->code == fcode) return altivec_expand_predicate_builtin (dp->icode, dp->opcode, - arglist, target); + exp, target); /* LV* are funky. We initialized them differently. */ switch (fcode) { case ALTIVEC_BUILTIN_LVSL: return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsl, - arglist, target); + exp, target); case ALTIVEC_BUILTIN_LVSR: return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsr, - arglist, target); + exp, target); case ALTIVEC_BUILTIN_LVEBX: return altivec_expand_lv_builtin (CODE_FOR_altivec_lvebx, - arglist, target); + exp, target); case ALTIVEC_BUILTIN_LVEHX: return altivec_expand_lv_builtin (CODE_FOR_altivec_lvehx, - arglist, target); + exp, target); case ALTIVEC_BUILTIN_LVEWX: return altivec_expand_lv_builtin (CODE_FOR_altivec_lvewx, - arglist, target); + exp, target); case ALTIVEC_BUILTIN_LVXL: return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl, - arglist, target); + exp, target); case ALTIVEC_BUILTIN_LVX: return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx, - arglist, target); + exp, target); default: break; /* Fall through. */ @@ -7832,8 +7823,7 @@ static struct builtin_description bdesc_2arg_spe[] = static rtx spe_expand_builtin (tree exp, rtx target, bool *expandedp) { - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - tree arglist = TREE_OPERAND (exp, 1); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); tree arg1, arg0; unsigned int fcode = DECL_FUNCTION_CODE (fndecl); enum insn_code icode; @@ -7854,7 +7844,7 @@ spe_expand_builtin (tree exp, rtx target, bool *expandedp) case SPE_BUILTIN_EVSTWHO: case SPE_BUILTIN_EVSTWWE: case SPE_BUILTIN_EVSTWWO: - arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg1 = CALL_EXPR_ARG (exp, 2); if (TREE_CODE (arg1) != INTEGER_CST || TREE_INT_CST_LOW (arg1) & ~0x1f) { @@ -7871,10 +7861,10 @@ spe_expand_builtin (tree exp, rtx target, bool *expandedp) { case SPE_BUILTIN_EVSPLATFI: return rs6000_expand_unop_builtin (CODE_FOR_spe_evsplatfi, - arglist, target); + exp, target); case SPE_BUILTIN_EVSPLATI: return rs6000_expand_unop_builtin (CODE_FOR_spe_evsplati, - arglist, target); + exp, target); default: break; } @@ -7882,48 +7872,48 @@ spe_expand_builtin (tree exp, rtx target, bool *expandedp) d = (struct builtin_description *) bdesc_2arg_spe; for (i = 0; i < ARRAY_SIZE (bdesc_2arg_spe); ++i, ++d) if (d->code == fcode) - return rs6000_expand_binop_builtin (d->icode, arglist, target); + return rs6000_expand_binop_builtin (d->icode, exp, target); d = (struct builtin_description *) bdesc_spe_predicates; for (i = 0; i < ARRAY_SIZE (bdesc_spe_predicates); ++i, ++d) if (d->code == fcode) - return spe_expand_predicate_builtin (d->icode, arglist, target); + return spe_expand_predicate_builtin (d->icode, exp, target); d = (struct builtin_description *) bdesc_spe_evsel; for (i = 0; i < ARRAY_SIZE (bdesc_spe_evsel); ++i, ++d) if (d->code == fcode) - return spe_expand_evsel_builtin (d->icode, arglist, target); + return spe_expand_evsel_builtin (d->icode, exp, target); switch (fcode) { case SPE_BUILTIN_EVSTDDX: - return spe_expand_stv_builtin (CODE_FOR_spe_evstddx, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstddx, exp); case SPE_BUILTIN_EVSTDHX: - return spe_expand_stv_builtin (CODE_FOR_spe_evstdhx, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstdhx, exp); case SPE_BUILTIN_EVSTDWX: - return spe_expand_stv_builtin (CODE_FOR_spe_evstdwx, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstdwx, exp); case SPE_BUILTIN_EVSTWHEX: - return spe_expand_stv_builtin (CODE_FOR_spe_evstwhex, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstwhex, exp); case SPE_BUILTIN_EVSTWHOX: - return spe_expand_stv_builtin (CODE_FOR_spe_evstwhox, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstwhox, exp); case SPE_BUILTIN_EVSTWWEX: - return spe_expand_stv_builtin (CODE_FOR_spe_evstwwex, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstwwex, exp); case SPE_BUILTIN_EVSTWWOX: - return spe_expand_stv_builtin (CODE_FOR_spe_evstwwox, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstwwox, exp); case SPE_BUILTIN_EVSTDD: - return spe_expand_stv_builtin (CODE_FOR_spe_evstdd, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstdd, exp); case SPE_BUILTIN_EVSTDH: - return spe_expand_stv_builtin (CODE_FOR_spe_evstdh, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstdh, exp); case SPE_BUILTIN_EVSTDW: - return spe_expand_stv_builtin (CODE_FOR_spe_evstdw, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstdw, exp); case SPE_BUILTIN_EVSTWHE: - return spe_expand_stv_builtin (CODE_FOR_spe_evstwhe, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstwhe, exp); case SPE_BUILTIN_EVSTWHO: - return spe_expand_stv_builtin (CODE_FOR_spe_evstwho, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstwho, exp); case SPE_BUILTIN_EVSTWWE: - return spe_expand_stv_builtin (CODE_FOR_spe_evstwwe, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstwwe, exp); case SPE_BUILTIN_EVSTWWO: - return spe_expand_stv_builtin (CODE_FOR_spe_evstwwo, arglist); + return spe_expand_stv_builtin (CODE_FOR_spe_evstwwo, exp); case SPE_BUILTIN_MFSPEFSCR: icode = CODE_FOR_spe_mfspefscr; tmode = insn_data[icode].operand[0].mode; @@ -7940,7 +7930,7 @@ spe_expand_builtin (tree exp, rtx target, bool *expandedp) return target; case SPE_BUILTIN_MTSPEFSCR: icode = CODE_FOR_spe_mtspefscr; - arg0 = TREE_VALUE (arglist); + arg0 = CALL_EXPR_ARG (exp, 0); op0 = expand_normal (arg0); mode0 = insn_data[icode].operand[0].mode; @@ -7963,12 +7953,12 @@ spe_expand_builtin (tree exp, rtx target, bool *expandedp) } static rtx -spe_expand_predicate_builtin (enum insn_code icode, tree arglist, rtx target) +spe_expand_predicate_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat, scratch, tmp; - tree form = TREE_VALUE (arglist); - tree arg0 = TREE_VALUE (TREE_CHAIN (arglist)); - tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + tree form = CALL_EXPR_ARG (exp, 0); + tree arg0 = CALL_EXPR_ARG (exp, 1); + tree arg1 = CALL_EXPR_ARG (exp, 2); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); enum machine_mode mode0 = insn_data[icode].operand[1].mode; @@ -8071,13 +8061,13 @@ spe_expand_predicate_builtin (enum insn_code icode, tree arglist, rtx target) */ static rtx -spe_expand_evsel_builtin (enum insn_code icode, tree arglist, rtx target) +spe_expand_evsel_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat, scratch; - tree arg0 = TREE_VALUE (arglist); - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); - tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))); + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + tree arg2 = CALL_EXPR_ARG (exp, 2); + tree arg3 = CALL_EXPR_ARG (exp, 3); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); rtx op2 = expand_normal (arg2); @@ -8131,8 +8121,7 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED) { - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - tree arglist = TREE_OPERAND (exp, 1); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned int fcode = DECL_FUNCTION_CODE (fndecl); struct builtin_description *d; size_t i; @@ -8150,7 +8139,7 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, gcc_assert (TARGET_ALTIVEC); - arg = TREE_VALUE (arglist); + arg = CALL_EXPR_ARG (exp, 0); gcc_assert (TREE_CODE (TREE_TYPE (arg)) == POINTER_TYPE); op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL); addr = memory_address (mode, op); @@ -8178,20 +8167,15 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, return target; } - + + /* FIXME: There's got to be a nicer way to handle this case than + constructing a new CALL_EXPR. */ if (fcode == ALTIVEC_BUILTIN_VCFUX || fcode == ALTIVEC_BUILTIN_VCFSX) { - if (!TREE_CHAIN (arglist)) - { - tree t, arg0; - t = NULL_TREE; - t = tree_cons (NULL_TREE, integer_zero_node, t); - arg0 = TREE_VALUE (arglist); - t = tree_cons (NULL_TREE, arg0, t); - arglist = t; - TREE_OPERAND (exp, 1) = t; - } + if (call_expr_nargs (exp) == 1) + exp = build_call_nary (TREE_TYPE (exp), CALL_EXPR_FN (exp), + 2, CALL_EXPR_ARG (exp, 0), integer_zero_node); } if (TARGET_ALTIVEC) @@ -8215,19 +8199,19 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, d = (struct builtin_description *) bdesc_1arg; for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++) if (d->code == fcode) - return rs6000_expand_unop_builtin (d->icode, arglist, target); + return rs6000_expand_unop_builtin (d->icode, exp, target); /* Handle simple binary operations. */ d = (struct builtin_description *) bdesc_2arg; for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++) if (d->code == fcode) - return rs6000_expand_binop_builtin (d->icode, arglist, target); + return rs6000_expand_binop_builtin (d->icode, exp, target); /* Handle simple ternary operations. */ d = (struct builtin_description *) bdesc_3arg; for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++) if (d->code == fcode) - return rs6000_expand_ternop_builtin (d->icode, arglist, target); + return rs6000_expand_ternop_builtin (d->icode, exp, target); gcc_unreachable (); } diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index af449f8f928..26484664b54 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -8210,13 +8210,14 @@ s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, unsigned int const *code_for_builtin = TARGET_64BIT ? code_for_builtin_64 : code_for_builtin_31; - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned int fcode = DECL_FUNCTION_CODE (fndecl); - tree arglist = TREE_OPERAND (exp, 1); enum insn_code icode; rtx op[MAX_ARGS], pat; int arity; bool nonvoid; + tree arg; + call_expr_arg_iterator iter; if (fcode >= S390_BUILTIN_max) internal_error ("bad builtin fcode"); @@ -8226,13 +8227,11 @@ s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node; - for (arglist = TREE_OPERAND (exp, 1), arity = 0; - arglist; - arglist = TREE_CHAIN (arglist), arity++) + arity = 0; + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) { const struct insn_operand_data *insn_op; - tree arg = TREE_VALUE (arglist); if (arg == error_mark_node) return NULL_RTX; if (arity > MAX_ARGS) @@ -8244,6 +8243,7 @@ s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, if (!(*insn_op->predicate) (op[arity], insn_op->mode)) op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]); + arity++; } if (nonvoid) diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 3e71e115108..96a00f6cc6b 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -9904,8 +9904,7 @@ static rtx sh_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, int ignore) { - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - tree arglist = TREE_OPERAND (exp, 1); + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned int fcode = DECL_FUNCTION_CODE (fndecl); const struct builtin_description *d = &bdesc[fcode]; enum insn_code icode = d->icode; @@ -9938,10 +9937,9 @@ sh_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, if (! signature_args[signature][i]) break; - arg = TREE_VALUE (arglist); + arg = CALL_EXPR_ARG (exp, i - 1); if (arg == error_mark_node) return const0_rtx; - arglist = TREE_CHAIN (arglist); if (signature_args[signature][i] & 8) { opmode = ptr_mode; diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 05390096b7c..45bc9e187e5 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -5701,12 +5701,10 @@ sparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) tree tmp = create_tmp_var (type, "va_arg_tmp"); tree dest_addr = build_fold_addr_expr (tmp); - tree copy = build_function_call_expr - (implicit_built_in_decls[BUILT_IN_MEMCPY], - tree_cons (NULL_TREE, dest_addr, - tree_cons (NULL_TREE, addr, - tree_cons (NULL_TREE, size_int (rsize), - NULL_TREE)))); + tree copy = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY], 3, + dest_addr, + addr, + size_int (rsize)); gimplify_and_add (copy, pre_p); addr = dest_addr; @@ -7985,8 +7983,9 @@ static rtx sparc_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode tmode, int ignore ATTRIBUTE_UNUSED) { - tree arglist; - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + tree arg; + call_expr_arg_iterator iter; + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned int icode = DECL_FUNCTION_CODE (fndecl); rtx pat, op[4]; enum machine_mode mode[4]; @@ -8001,11 +8000,8 @@ sparc_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, else op[arg_count] = target; - for (arglist = TREE_OPERAND (exp, 1); arglist; - arglist = TREE_CHAIN (arglist)) + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) { - tree arg = TREE_VALUE (arglist); - arg_count++; mode[arg_count] = insn_data[icode].operand[arg_count].mode; op[arg_count] = expand_normal (arg); diff --git a/gcc/configure b/gcc/configure index 933bdd9e293..77dfa405ddf 100755 --- a/gcc/configure +++ b/gcc/configure @@ -16014,70 +16014,70 @@ echo "${ECHO_T}$gcc_cv_ld_pie" >&6 echo "$as_me:$LINENO: checking linker EH-compatible garbage collection of sections" >&5 echo $ECHO_N "checking linker EH-compatible garbage collection of sections... $ECHO_C" >&6 gcc_cv_ld_eh_gc_sections=no -if test $in_tree_ld = yes ; then - if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 17 -o "$gcc_cv_gld_major_version" -gt 2 \ - && test $in_tree_ld_is_elf = yes; then - gcc_cv_ld_eh_gc_sections=yes - fi -elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then - cat > conftest.s <<EOF - .section .text -.globl _start - .type _start, @function -_start: - .long foo - .size _start, .-_start - .section .text.foo,"ax",@progbits - .type foo, @function -foo: - .long 0 - .size foo, .-foo - .section .gcc_except_table.foo,"a",@progbits -.L0: - .long 0 - .section .eh_frame,"a",@progbits - .long .L0 -EOF - if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then - if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \ - | grep "gc-sections option ignored" > /dev/null; then - gcc_cv_ld_eh_gc_sections=no - elif $gcc_cv_objdump -h conftest | grep gcc_except_table > /dev/null; then - gcc_cv_ld_eh_gc_sections=yes - # If no COMDAT groups, the compiler will emit .gnu.linkonce.t. sections. - if test x$gcc_cv_as_comdat_group != xyes; then - gcc_cv_ld_eh_gc_sections=no - cat > conftest.s <<EOF - .section .text -.globl _start - .type _start, @function -_start: - .long foo - .size _start, .-_start - .section .gnu.linkonce.t.foo,"ax",@progbits - .type foo, @function -foo: - .long 0 - .size foo, .-foo - .section .gcc_except_table.foo,"a",@progbits -.L0: - .long 0 - .section .eh_frame,"a",@progbits - .long .L0 -EOF - if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then - if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \ - | grep "gc-sections option ignored" > /dev/null; then - gcc_cv_ld_eh_gc_sections=no - elif $gcc_cv_objdump -h conftest | grep gcc_except_table > /dev/null; then - gcc_cv_ld_eh_gc_sections=yes - fi - fi - fi - fi - fi - rm -f conftest.s conftest.o conftest -fi +#if test $in_tree_ld = yes ; then +# if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 17 -o "$gcc_cv_gld_major_version" -gt 2 \ +# && test $in_tree_ld_is_elf = yes; then +# gcc_cv_ld_eh_gc_sections=yes +# fi +#elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then +# cat > conftest.s <<EOF +# .section .text +#.globl _start +# .type _start, @function +#_start: +# .long foo +# .size _start, .-_start +# .section .text.foo,"ax",@progbits +# .type foo, @function +#foo: +# .long 0 +# .size foo, .-foo +# .section .gcc_except_table.foo,"a",@progbits +#.L0: +# .long 0 +# .section .eh_frame,"a",@progbits +# .long .L0 +#EOF +# if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then +# if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \ +# | grep "gc-sections option ignored" > /dev/null; then +# gcc_cv_ld_eh_gc_sections=no +# elif $gcc_cv_objdump -h conftest | grep gcc_except_table > /dev/null; then +# gcc_cv_ld_eh_gc_sections=yes +# # If no COMDAT groups, the compiler will emit .gnu.linkonce.t. sections. +# if test x$gcc_cv_as_comdat_group != xyes; then +# gcc_cv_ld_eh_gc_sections=no +# cat > conftest.s <<EOF +# .section .text +#.globl _start +# .type _start, @function +#_start: +# .long foo +# .size _start, .-_start +# .section .gnu.linkonce.t.foo,"ax",@progbits +# .type foo, @function +#foo: +# .long 0 +# .size foo, .-foo +# .section .gcc_except_table.foo,"a",@progbits +#.L0: +# .long 0 +# .section .eh_frame,"a",@progbits +# .long .L0 +#EOF +# if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then +# if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \ +# | grep "gc-sections option ignored" > /dev/null; then +# gcc_cv_ld_eh_gc_sections=no +# elif $gcc_cv_objdump -h conftest | grep gcc_except_table > /dev/null; then +# gcc_cv_ld_eh_gc_sections=yes +# fi +# fi +# fi +# fi +# fi +# rm -f conftest.s conftest.o conftest +#fi case "$target" in hppa*-*-linux*) # ??? This apparently exposes a binutils bug with PC-relative relocations. diff --git a/gcc/convert.c b/gcc/convert.c index af97d2a7590..b6c6d0fcf75 100644 --- a/gcc/convert.c +++ b/gcc/convert.c @@ -173,7 +173,7 @@ convert_to_real (tree type, tree expr) CASE_MATHFN (Y1) #undef CASE_MATHFN { - tree arg0 = strip_float_extensions (TREE_VALUE (TREE_OPERAND (expr, 1))); + tree arg0 = strip_float_extensions (CALL_EXPR_ARG (expr, 0)); tree newtype = type; /* We have (outertype)sqrt((innertype)x). Choose the wider mode from @@ -188,13 +188,12 @@ convert_to_real (tree type, tree expr) && (TYPE_MODE (newtype) == TYPE_MODE (double_type_node) || TYPE_MODE (newtype) == TYPE_MODE (float_type_node))) { - tree arglist; tree fn = mathfn_built_in (newtype, fcode); if (fn) { - arglist = build_tree_list (NULL_TREE, fold (convert_to_real (newtype, arg0))); - expr = build_function_call_expr (fn, arglist); + tree arg = fold (convert_to_real (newtype, arg0)); + expr = build_call_expr (fn, 1, arg); if (newtype == type) return expr; } @@ -225,18 +224,14 @@ convert_to_real (tree type, tree expr) if (fn) { - tree arg - = strip_float_extensions (TREE_VALUE (TREE_OPERAND (expr, 1))); + tree arg = strip_float_extensions (CALL_EXPR_ARG (expr, 0)); /* Make sure (type)arg0 is an extension, otherwise we could end up changing (float)floor(double d) into floorf((float)d), which is incorrect because (float)d uses round-to-nearest and can round up to the next integer. */ if (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (arg))) - return - build_function_call_expr (fn, - build_tree_list (NULL_TREE, - fold (convert_to_real (type, arg)))); + return build_call_expr (fn, 1, fold (convert_to_real (type, arg))); } } @@ -434,10 +429,7 @@ convert_to_integer (tree type, tree expr) break; CASE_FLT_FN (BUILT_IN_TRUNC): - { - tree arglist = TREE_OPERAND (s_expr, 1); - return convert_to_integer (type, TREE_VALUE (arglist)); - } + return convert_to_integer (type, CALL_EXPR_ARG (s_expr, 0)); default: break; @@ -445,8 +437,7 @@ convert_to_integer (tree type, tree expr) if (fn) { - tree arglist = TREE_OPERAND (s_expr, 1); - tree newexpr = build_function_call_expr (fn, arglist); + tree newexpr = build_call_expr (fn, 1, CALL_EXPR_ARG (s_expr, 0)); return convert_to_integer (type, newexpr); } } diff --git a/gcc/coverage.c b/gcc/coverage.c index ba9f1285fc2..aaec5edf667 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -949,8 +949,7 @@ create_coverage (void) /* Generate a call to __gcov_init(&gcov_info). */ body = NULL; t = build_fold_addr_expr (gcov_info); - t = tree_cons (NULL, t, NULL); - t = build_function_call_expr (gcov_init, t); + t = build_call_expr (gcov_init, 1, t); append_to_statement_list (t, &body); /* Generate a constructor to run it. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index fd068e4155b..16df0f7da4f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,90 @@ +2007-02-15 Sandra Loosemore <sandra@codesourcery.com> + Brooks Moses <brooks.moses@codesourcery.com> + Lee Millward <lee.millward@codesourcery.com> + + * cp-tree.def (AGGR_INIT_EXPR): Adjust documentation. + Change class to tcc_vl_exp. + + * call.c (build_call): Use build_call_list instead + of build3. + (build_over_call): Likewise. + (build_new_method_call): Use build_min_non_dep_call_list + instead of build_min_non_dep. + + * error.c (dump_call_expr_args): New function. + (dump_aggr_init_expr_args): New function. + (dump_expr) <AGGR_INIT_EXPR, CALL_EXPR, INDIRECT_REF>: Use them. + Update to use new CALL_EXPR and AGGR_INIT_EXPR accessor macros. + + * cvt.c (convert_to_void): Use build_call_array instead + of build3; use new AGGR_INIT_EXPR accessor macros. + + * mangle.c (write_expression): Use TREE_OPERAND_LENGTH + instead of TREE_CODE_LENGTH. + + * dump.c (cp_dump_tree) <AGGR_INIT_EXPR>: Update to use new + AGGR_INIT_EXPR accessor macros. + + * cp-gimplify.c (cp_gimplify_init_expr): Use + AGGR_INIT_EXPR_SLOT to set the slot operand. + + * cp-tree.h (AGGR_INIT_EXPR_FN): New macro. + (AGGR_INIT_EXPR_SLOT): New macro. + (AGGR_INIT_EXPR_ARG): New macro. + (aggr_init_expr_nargs): New macro. + (AGGR_INIT_EXPR_ARGP): New macro. + (aggr_init_expr_arg_iterator): New. + (init_aggr_init_expr_arg_iterator): New. + (next_aggr_init_expr_arg): New. + (first_aggr_init_expr_arg): New. + (more_aggr_init_expr_args_p): New. + (FOR_EACH_AGGR_INIT_EXPR_ARG): New. + (stabilize_aggr_init): New declaration. + (build_min_non_dep_call_list): Likewise. + + * tree.c (process_aggr_init_operands): New function. + (build_aggr_init_array) New function. + (build_cplus_new): Update to use new CALL_EXPR and + AGGR_INIT_EXPR accessor macros. Replace use of build3 with + build_aggr_init_array. + (build_min_non_dep_call_list) New function. + (build_min_nt): Assert input code parameter is not a variable + length expression class. + (build_min, build_min_non_dep): Likewise. + (cp_tree_equal) <CALL_EXPR>: Iterate through the arguments + to check for equality instead of recursing. Handle tcc_vl_exp + tree code classes. + (stabilize_call): Update to only handle CALL_EXPRs, not + AGGR_INIT_EXPRs; use new CALL_EXPR accessor macros. + (stabilize_aggr_init): New function. + (stabilize_init): Use it. + + * cxx-pretty-print.c (pp_cxx_postfix_expression) + <AGGR_INIT_EXPR, CALL_EXPR>: Update to use new CALL_EXPR and + AGGR_INIT_EXPR accessor macros and argument iterators. + + * pt.c (tsubst_copy) <CALL_EXPR>: Replace build_nt with + build_vl_exp. Iterate through the operands, recursively + processing each one. + (tsubst_copy_and_build) <CALL_EXPR>: Update to use new + CALL_EXPR accessor macros. + (value_dependent_expression_p) <default>: Handle tcc_vl_exp + tree code classes. Use TREE_OPERAND_LENGTH instead of + TREE_CODE_LENGTH. + + * semantics.c (finish_call_expr): Use build_nt_call_list + instead of build_nt. + (simplify_aggr_init_expr): Update to use new AGGR_INIT_EXPR + accessor macros. Use build_call_array to construct the + CALL_EXPR node instead of build3 + + * decl2.c (build_offset_ref_call_from_tree): Use + build_nt_call_list and build_min_non_dep_call_list instead + of build_min_nt and build_min_non_dep. + + * parser.c (cp_parser_postfix_expression) <CPP_OPEN_PAREN>: + Use build_nt_call_list instead of build_min_nt. + 2007-02-15 Manuel Lopez-Ibanez <manu@gcc.gnu.org> PR c++/28943 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 6690fa2a389..b1b5a8e8277 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -336,7 +336,7 @@ build_call (tree function, tree parms) TREE_VALUE (tmp), t); } - function = build3 (CALL_EXPR, result_type, function, parms, NULL_TREE); + function = build_call_list (result_type, function, parms); TREE_HAS_CONSTRUCTOR (function) = is_constructor; TREE_NOTHROW (function) = nothrow; @@ -4740,7 +4740,7 @@ build_over_call (struct z_candidate *cand, int flags) tree expr; tree return_type; return_type = TREE_TYPE (TREE_TYPE (fn)); - expr = build3 (CALL_EXPR, return_type, fn, args, NULL_TREE); + expr = build_call_list (return_type, fn, args); if (TREE_THIS_VOLATILE (fn) && cfun) current_function_returns_abnormally = 1; if (!VOID_TYPE_P (return_type)) @@ -5122,7 +5122,7 @@ build_java_interface_fn_ref (tree fn, tree instance) lookup_fn = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (java_iface_lookup_fn)), java_iface_lookup_fn); - return build3 (CALL_EXPR, ptr_type_node, lookup_fn, lookup_args, NULL_TREE); + return build_call_list (ptr_type_node, lookup_fn, lookup_args); } /* Returns the value to use for the in-charge parameter when making a @@ -5533,10 +5533,10 @@ build_new_method_call (tree instance, tree fns, tree args, } if (processing_template_decl && call != error_mark_node) - call = (build_min_non_dep - (CALL_EXPR, call, + call = (build_min_non_dep_call_list + (call, build_min_nt (COMPONENT_REF, orig_instance, orig_fns, NULL_TREE), - orig_args, NULL_TREE)); + orig_args)); /* Free all the conversions we allocated. */ obstack_free (&conversion_obstack, p); diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 6a427c695db..aa1b0ed73c9 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -410,7 +410,7 @@ cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p) if (TREE_CODE (sub) == AGGR_INIT_EXPR) { gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue); - TREE_OPERAND (sub, 2) = to; + AGGR_INIT_EXPR_SLOT (sub) = to; *expr_p = from; /* The initialization is now a side-effect, so the container can diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 090f91f40c5..bcc6b54223c 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -74,10 +74,12 @@ DEFTREECODE (MEMBER_REF, "member_ref", tcc_reference, 2) operator converts to. Operand is expression to be converted. */ DEFTREECODE (TYPE_EXPR, "type_expr", tcc_expression, 1) -/* For AGGR_INIT_EXPR, operand 0 is function which performs initialization, - operand 1 is argument list to initialization function, - and operand 2 is the slot which was allocated for this expression. */ -DEFTREECODE (AGGR_INIT_EXPR, "aggr_init_expr", tcc_expression, 3) +/* AGGR_INIT_EXPRs have a variably-sized representation similar to + that of CALL_EXPRs. Operand 0 is an INTEGER_CST node containing the + operand count, operand 1 is the function which performs initialization, + operand 2 is the slot which was allocated for this expression, and + the remaining operands are the arguments to the initialization function. */ +DEFTREECODE (AGGR_INIT_EXPR, "aggr_init_expr", tcc_vl_exp, 3) /* A throw expression. operand 0 is the expression, if there was one, else it is NULL_TREE. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4de73ff9c00..b3857815c2a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2331,6 +2331,85 @@ extern void decl_shadowed_for_var_insert (tree, tree); #define AGGR_INIT_VIA_CTOR_P(NODE) \ TREE_LANG_FLAG_0 (AGGR_INIT_EXPR_CHECK (NODE)) +/* AGGR_INIT_EXPR accessors. These are equivalent to the CALL_EXPR + accessors, except for AGGR_INIT_EXPR_SLOT (which takes the place of + CALL_EXPR_STATIC_CHAIN). */ + +#define AGGR_INIT_EXPR_FN(NODE) TREE_OPERAND (AGGR_INIT_EXPR_CHECK (NODE), 1) +#define AGGR_INIT_EXPR_SLOT(NODE) \ + TREE_OPERAND (AGGR_INIT_EXPR_CHECK (NODE), 2) +#define AGGR_INIT_EXPR_ARG(NODE, I) \ + TREE_OPERAND (AGGR_INIT_EXPR_CHECK (NODE), (I) + 3) +#define aggr_init_expr_nargs(NODE) (VL_EXP_OPERAND_LENGTH(NODE) - 3) + +/* AGGR_INIT_EXPR_ARGP returns a pointer to the argument vector for NODE. + We can't use &AGGR_INIT_EXPR_ARG (NODE, 0) because that will complain if + the argument count is zero when checking is enabled. Instead, do + the pointer arithmetic to advance past the 3 fixed operands in a + AGGR_INIT_EXPR. That produces a valid pointer to just past the end of + the operand array, even if it's not valid to dereference it. */ +#define AGGR_INIT_EXPR_ARGP(NODE) \ + (&(TREE_OPERAND (AGGR_INIT_EXPR_CHECK (NODE), 0)) + 3) + +/* Abstract iterators for AGGR_INIT_EXPRs. */ + +/* Structure containing iterator state. */ +typedef struct aggr_init_expr_arg_iterator_d GTY (()) +{ + tree t; /* the aggr_init_expr */ + int n; /* argument count */ + int i; /* next argument index */ +} aggr_init_expr_arg_iterator; + +/* Initialize the abstract argument list iterator object ITER with the + arguments from AGGR_INIT_EXPR node EXP. */ +static inline void +init_aggr_init_expr_arg_iterator (tree exp, + aggr_init_expr_arg_iterator *iter) +{ + iter->t = exp; + iter->n = aggr_init_expr_nargs (exp); + iter->i = 0; +} + +/* Return the next argument from abstract argument list iterator object ITER, + and advance its state. Return NULL_TREE if there are no more arguments. */ +static inline tree +next_aggr_init_expr_arg (aggr_init_expr_arg_iterator *iter) +{ + tree result; + if (iter->i >= iter->n) + return NULL_TREE; + result = AGGR_INIT_EXPR_ARG (iter->t, iter->i); + iter->i++; + return result; +} + +/* Initialize the abstract argument list iterator object ITER, then advance + past and return the first argument. Useful in for expressions, e.g. + for (arg = first_aggr_init_expr_arg (exp, &iter); arg; + arg = next_aggr_init_expr_arg (&iter)) */ +static inline tree +first_aggr_init_expr_arg (tree exp, aggr_init_expr_arg_iterator *iter) +{ + init_aggr_init_expr_arg_iterator (exp, iter); + return next_aggr_init_expr_arg (iter); +} + +/* Test whether there are more arguments in abstract argument list iterator + ITER, without changing its state. */ +static inline bool +more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) +{ + return (iter->i < iter->n); +} + +/* Iterate through each argument ARG of AGGR_INIT_EXPR CALL, using variable + ITER (of type aggr_init_expr_arg_iterator) to hold the iteration state. */ +#define FOR_EACH_AGGR_INIT_EXPR_ARG(arg, iter, call) \ + for ((arg) = first_aggr_init_expr_arg ((call), &(iter)); (arg); \ + (arg) = next_aggr_init_expr_arg (&(iter))) + /* The TYPE_MAIN_DECL for a class template type is a TYPE_DECL, not a TEMPLATE_DECL. This macro determines whether or not a given class type is really a template type, as opposed to an instantiation or @@ -4375,6 +4454,7 @@ extern void lang_check_failed (const char *, int, const char *) ATTRIBUTE_NORETURN; extern tree stabilize_expr (tree, tree *); extern void stabilize_call (tree, tree *); +extern void stabilize_aggr_init (tree, tree *); extern bool stabilize_init (tree, tree *); extern tree add_stmt_to_compound (tree, tree); extern tree cxx_maybe_build_cleanup (tree); @@ -4390,6 +4470,7 @@ extern bool builtin_valid_in_constant_expr_p (tree); extern tree build_min (enum tree_code, tree, ...); extern tree build_min_nt (enum tree_code, ...); extern tree build_min_non_dep (enum tree_code, tree, ...); +extern tree build_min_non_dep_call_list (tree, tree, tree); extern tree build_cplus_new (tree, tree); extern tree get_target_expr (tree); extern tree build_cplus_array_type (tree, tree); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 220edddb535..497179b3bbc 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -902,9 +902,11 @@ convert_to_void (tree expr, const char *implicit) if (TREE_CODE (init) == AGGR_INIT_EXPR && !AGGR_INIT_VIA_CTOR_P (init)) { - tree fn = TREE_OPERAND (init, 0); - expr = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), - fn, TREE_OPERAND (init, 1), NULL_TREE); + tree fn = AGGR_INIT_EXPR_FN (init); + expr = build_call_array (TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), + fn, + aggr_init_expr_nargs (init), + AGGR_INIT_EXPR_ARGP (init)); } } break; diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index 4f2bf86ed51..5c13362df95 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -412,9 +412,11 @@ pp_cxx_postfix_expression (cxx_pretty_printer *pp, tree t) case AGGR_INIT_EXPR: case CALL_EXPR: { - tree fun = TREE_OPERAND (t, 0); - tree args = TREE_OPERAND (t, 1); + tree fun = (code == AGGR_INIT_EXPR ? AGGR_INIT_EXPR_FN (t) + : CALL_EXPR_FN (t)); tree saved_scope = pp->enclosing_scope; + bool skipfirst = false; + tree arg; if (TREE_CODE (fun) == ADDR_EXPR) fun = TREE_OPERAND (fun, 0); @@ -427,9 +429,11 @@ pp_cxx_postfix_expression (cxx_pretty_printer *pp, tree t) ; else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)) { - tree object = code == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P (t) - ? TREE_OPERAND (t, 2) - : TREE_VALUE (args); + tree object = (code == AGGR_INIT_EXPR + ? (AGGR_INIT_VIA_CTOR_P (t) + ? AGGR_INIT_EXPR_SLOT (t) + : AGGR_INIT_EXPR_ARG (t, 0)) + : CALL_EXPR_ARG (t, 0)); while (TREE_CODE (object) == NOP_EXPR) object = TREE_OPERAND (object, 0); @@ -447,18 +451,49 @@ pp_cxx_postfix_expression (cxx_pretty_printer *pp, tree t) pp_cxx_postfix_expression (pp, object); pp_cxx_arrow (pp); } - args = TREE_CHAIN (args); + skipfirst = true; pp->enclosing_scope = strip_pointer_operator (TREE_TYPE (object)); } pp_cxx_postfix_expression (pp, fun); pp->enclosing_scope = saved_scope; - pp_cxx_call_argument_list (pp, args); + pp_cxx_left_paren (pp); + if (code == AGGR_INIT_EXPR) + { + aggr_init_expr_arg_iterator iter; + FOR_EACH_AGGR_INIT_EXPR_ARG (arg, iter, t) + { + if (skipfirst) + skipfirst = false; + else + { + pp_cxx_expression (pp, arg); + if (more_aggr_init_expr_args_p (&iter)) + pp_cxx_separate_with (pp, ','); + } + } + } + else + { + call_expr_arg_iterator iter; + FOR_EACH_CALL_EXPR_ARG (arg, iter, t) + { + if (skipfirst) + skipfirst = false; + else + { + pp_cxx_expression (pp, arg); + if (more_call_expr_args_p (&iter)) + pp_cxx_separate_with (pp, ','); + } + } + } + pp_cxx_right_paren (pp); } if (code == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P (t)) { pp_cxx_separate_with (pp, ','); - pp_cxx_postfix_expression (pp, TREE_OPERAND (t, 2)); + pp_cxx_postfix_expression (pp, AGGR_INIT_EXPR_SLOT (t)); } break; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 4e4f6a5642b..68917b68bd9 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3401,7 +3401,7 @@ build_offset_ref_call_from_tree (tree fn, tree args) || TREE_CODE (fn) == MEMBER_REF); if (type_dependent_expression_p (fn) || any_type_dependent_arguments_p (args)) - return build_min_nt (CALL_EXPR, fn, args, NULL_TREE); + return build_nt_call_list (fn, args); /* Transform the arguments and add the implicit "this" parameter. That must be done before the FN is transformed @@ -3431,7 +3431,7 @@ build_offset_ref_call_from_tree (tree fn, tree args) expr = build_function_call (fn, args); if (processing_template_decl && expr != error_mark_node) - return build_min_non_dep (CALL_EXPR, expr, orig_fn, orig_args, NULL_TREE); + return build_min_non_dep_call_list (expr, orig_fn, orig_args); return expr; } diff --git a/gcc/cp/dump.c b/gcc/cp/dump.c index c63cfe2bd89..de569f2d894 100644 --- a/gcc/cp/dump.c +++ b/gcc/cp/dump.c @@ -388,10 +388,21 @@ cp_dump_tree (void* dump_info, tree t) break; case AGGR_INIT_EXPR: - dump_int (di, "ctor", AGGR_INIT_VIA_CTOR_P (t)); - dump_child ("fn", TREE_OPERAND (t, 0)); - dump_child ("args", TREE_OPERAND (t, 1)); - dump_child ("decl", TREE_OPERAND (t, 2)); + { + int i = 0; + tree arg; + aggr_init_expr_arg_iterator iter; + dump_int (di, "ctor", AGGR_INIT_VIA_CTOR_P (t)); + dump_child ("fn", AGGR_INIT_EXPR_FN (t)); + FOR_EACH_AGGR_INIT_EXPR_ARG (arg, iter, t) + { + char buffer[32]; + sprintf (buffer, "%u", i); + dump_child (buffer, arg); + i++; + } + dump_child ("decl", AGGR_INIT_EXPR_SLOT (t)); + } break; case HANDLER: diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 00f07677454..6a0eed5e16b 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -66,6 +66,8 @@ static void dump_aggr_type (tree, int); static void dump_type_prefix (tree, int); static void dump_type_suffix (tree, int); static void dump_function_name (tree, int); +static void dump_call_expr_args (tree, int, bool); +static void dump_aggr_init_expr_args (tree, int, bool); static void dump_expr_list (tree, int); static void dump_global_iord (tree); static void dump_parameters (tree, int); @@ -1265,6 +1267,55 @@ dump_template_parms (tree info, int primary, int flags) pp_cxx_end_template_argument_list (cxx_pp); } +/* Print out the arguments of CALL_EXPR T as a parenthesized list using + flags FLAGS. Skip over the first argument if SKIPFIRST is true. */ + +static void +dump_call_expr_args (tree t, int flags, bool skipfirst) +{ + tree arg; + call_expr_arg_iterator iter; + + pp_cxx_left_paren (cxx_pp); + FOR_EACH_CALL_EXPR_ARG (arg, iter, t) + { + if (skipfirst) + skipfirst = false; + else + { + dump_expr (arg, flags | TFF_EXPR_IN_PARENS); + if (more_call_expr_args_p (&iter)) + pp_separate_with_comma (cxx_pp); + } + } + pp_cxx_right_paren (cxx_pp); +} + +/* Print out the arguments of AGGR_INIT_EXPR T as a parenthesized list + using flags FLAGS. Skip over the first argument if SKIPFIRST is + true. */ + +static void +dump_aggr_init_expr_args (tree t, int flags, bool skipfirst) +{ + tree arg; + aggr_init_expr_arg_iterator iter; + + pp_cxx_left_paren (cxx_pp); + FOR_EACH_AGGR_INIT_EXPR_ARG (arg, iter, t) + { + if (skipfirst) + skipfirst = false; + else + { + dump_expr (arg, flags | TFF_EXPR_IN_PARENS); + if (more_aggr_init_expr_args_p (&iter)) + pp_separate_with_comma (cxx_pp); + } + } + pp_cxx_right_paren (cxx_pp); +} + /* Print out a list of initializers (subr of dump_expr). */ static void @@ -1387,8 +1438,8 @@ dump_expr (tree t, int flags) { tree fn = NULL_TREE; - if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR) - fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0); + if (TREE_CODE (AGGR_INIT_EXPR_FN (t)) == ADDR_EXPR) + fn = TREE_OPERAND (AGGR_INIT_EXPR_FN (t), 0); if (fn && TREE_CODE (fn) == FUNCTION_DECL) { @@ -1398,18 +1449,15 @@ dump_expr (tree t, int flags) dump_decl (fn, 0); } else - dump_expr (TREE_OPERAND (t, 0), 0); + dump_expr (AGGR_INIT_EXPR_FN (t), 0); } - pp_cxx_left_paren (cxx_pp); - if (TREE_OPERAND (t, 1)) - dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags); - pp_cxx_right_paren (cxx_pp); + dump_aggr_init_expr_args (t, flags, false); break; case CALL_EXPR: { - tree fn = TREE_OPERAND (t, 0); - tree args = TREE_OPERAND (t, 1); + tree fn = CALL_EXPR_FN (t); + bool skipfirst = false; if (TREE_CODE (fn) == ADDR_EXPR) fn = TREE_OPERAND (fn, 0); @@ -1420,7 +1468,7 @@ dump_expr (tree t, int flags) if (TREE_TYPE (fn) != NULL_TREE && NEXT_CODE (fn) == METHOD_TYPE) { - tree ob = TREE_VALUE (args); + tree ob = CALL_EXPR_ARG (t, 0); if (TREE_CODE (ob) == ADDR_EXPR) { dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS); @@ -1432,12 +1480,10 @@ dump_expr (tree t, int flags) dump_expr (ob, flags | TFF_EXPR_IN_PARENS); pp_arrow (cxx_pp); } - args = TREE_CHAIN (args); + skipfirst = true; } dump_expr (fn, flags | TFF_EXPR_IN_PARENS); - pp_cxx_left_paren (cxx_pp); - dump_expr_list (args, flags); - pp_cxx_right_paren (cxx_pp); + dump_call_expr_args (t, flags, skipfirst); } break; @@ -1581,10 +1627,8 @@ dump_expr (tree t, int flags) { t = TREE_OPERAND (t, 0); gcc_assert (TREE_CODE (t) == CALL_EXPR); - dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); - pp_cxx_left_paren (cxx_pp); - dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags); - pp_cxx_right_paren (cxx_pp); + dump_expr (CALL_EXPR_FN (t), flags | TFF_EXPR_IN_PARENS); + dump_call_expr_args (t, flags, true); } else { diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 5b8d338e910..94d7ed5e92c 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -2206,7 +2206,7 @@ write_expression (tree expr) break; default: - for (i = 0; i < TREE_CODE_LENGTH (code); ++i) + for (i = 0; i < TREE_OPERAND_LENGTH (expr); ++i) { tree operand = TREE_OPERAND (expr, i); /* As a GNU extension, the middle operand of a diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 328add29594..b8af4d288bd 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -4443,8 +4443,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) || any_type_dependent_arguments_p (args))) { postfix_expression - = build_min_nt (CALL_EXPR, postfix_expression, - args, NULL_TREE); + = build_nt_call_list (postfix_expression, args); break; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ee8db6dee25..31ad46c5052 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8350,12 +8350,15 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) NULL_TREE, NULL_TREE); case CALL_EXPR: - return build_nt (code, - tsubst_copy (TREE_OPERAND (t, 0), args, - complain, in_decl), - tsubst_copy (TREE_OPERAND (t, 1), args, complain, - in_decl), - NULL_TREE); + { + int n = VL_EXP_OPERAND_LENGTH (t); + tree result = build_vl_exp (CALL_EXPR, n); + int i; + for (i = 0; i < n; i++) + TREE_OPERAND (t, i) = tsubst_copy (TREE_OPERAND (t, i), args, + complain, in_decl); + return result; + } case COND_EXPR: case MODOP_EXPR: @@ -9271,7 +9274,7 @@ tsubst_copy_and_build (tree t, bool qualified_p; bool koenig_p; - function = TREE_OPERAND (t, 0); + function = CALL_EXPR_FN (t); /* When we parsed the expression, we determined whether or not Koenig lookup should be performed. */ koenig_p = KOENIG_LOOKUP_P (t); @@ -9304,7 +9307,8 @@ tsubst_copy_and_build (tree t, qualified_p = true; } - call_args = RECUR (TREE_OPERAND (t, 1)); + /* FIXME: Rewrite this so as not to construct an arglist. */ + call_args = RECUR (CALL_EXPR_ARGS (t)); /* We do not perform argument-dependent lookup if normal lookup finds a non-function, in accordance with the @@ -13064,9 +13068,10 @@ value_dependent_expression_p (tree expression) (TREE_OPERAND (expression, 1)))); case tcc_expression: + case tcc_vl_exp: { int i; - for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (expression)); ++i) + for (i = 0; i < TREE_OPERAND_LENGTH (expression); ++i) /* In some cases, some of the operands may be missing. (For example, in the case of PREDECREMENT_EXPR, the amount to increment by may be missing.) That doesn't diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 326bcfb4d5a..3df045e733d 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1789,7 +1789,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) if (type_dependent_expression_p (fn) || any_type_dependent_arguments_p (args)) { - result = build_nt (CALL_EXPR, fn, args, NULL_TREE); + result = build_nt_call_list (fn, args); KOENIG_LOOKUP_P (result) = koenig_p; return result; } @@ -1846,7 +1846,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) if (processing_template_decl) { if (type_dependent_expression_p (object)) - return build_nt (CALL_EXPR, orig_fn, orig_args, NULL_TREE); + return build_nt_call_list (orig_fn, orig_args); object = build_non_dependent_expr (object); } @@ -1890,8 +1890,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) if (processing_template_decl) { - result = build3 (CALL_EXPR, TREE_TYPE (result), orig_fn, - orig_args, NULL_TREE); + result = build_call_list (TREE_TYPE (result), orig_fn, orig_args); KOENIG_LOOKUP_P (result) = koenig_p; } return result; @@ -2975,9 +2974,8 @@ simplify_aggr_init_expr (tree *tp) tree aggr_init_expr = *tp; /* Form an appropriate CALL_EXPR. */ - tree fn = TREE_OPERAND (aggr_init_expr, 0); - tree args = TREE_OPERAND (aggr_init_expr, 1); - tree slot = TREE_OPERAND (aggr_init_expr, 2); + tree fn = AGGR_INIT_EXPR_FN (aggr_init_expr); + tree slot = AGGR_INIT_EXPR_SLOT (aggr_init_expr); tree type = TREE_TYPE (slot); tree call_expr; @@ -2995,23 +2993,20 @@ simplify_aggr_init_expr (tree *tp) style = arg; } + call_expr = build_call_array (TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), + fn, + aggr_init_expr_nargs (aggr_init_expr), + AGGR_INIT_EXPR_ARGP (aggr_init_expr)); + if (style == ctor) { /* Replace the first argument to the ctor with the address of the slot. */ - tree addr; - - args = TREE_CHAIN (args); cxx_mark_addressable (slot); - addr = build1 (ADDR_EXPR, build_pointer_type (type), slot); - args = tree_cons (NULL_TREE, addr, args); + CALL_EXPR_ARG (call_expr, 0) = + build1 (ADDR_EXPR, build_pointer_type (type), slot); } - - call_expr = build3 (CALL_EXPR, - TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), - fn, args, NULL_TREE); - - if (style == arg) + else if (style == arg) { /* Just mark it addressable here, and leave the rest to expand_call{,_inline}. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index a3d11a334d9..7c5a4dc5bdd 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -261,8 +261,55 @@ build_local_temp (tree type) return slot; } -/* INIT is a CALL_EXPR which needs info about its target. - TYPE is the type that this initialization should appear to have. +/* Set various status flags when building an AGGR_INIT_EXPR object T. */ + +static void +process_aggr_init_operands (tree t) +{ + bool side_effects; + + side_effects = TREE_SIDE_EFFECTS (t); + if (!side_effects) + { + int i, n; + n = TREE_OPERAND_LENGTH (t); + for (i = 1; i < n; i++) + { + tree op = TREE_OPERAND (t, i); + if (op && TREE_SIDE_EFFECTS (op)) + { + side_effects = 1; + break; + } + } + } + TREE_SIDE_EFFECTS (t) = side_effects; +} + +/* Build an AGGR_INIT_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE, + FN, and SLOT. NARGS is the number of call arguments which are specified + as a tree array ARGS. */ + +static tree +build_aggr_init_array (tree return_type, tree fn, tree slot, int nargs, + tree *args) +{ + tree t; + int i; + + t = build_vl_exp (AGGR_INIT_EXPR, nargs + 3); + TREE_TYPE (t) = return_type; + AGGR_INIT_EXPR_FN (t) = fn; + AGGR_INIT_EXPR_SLOT (t) = slot; + for (i = 0; i < nargs; i++) + AGGR_INIT_EXPR_ARG (t, i) = args[i]; + process_aggr_init_operands (t); + return t; +} + +/* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its + target. TYPE is the type that this initialization should appear to + have. Build an encapsulation of the initialization to perform and return it so that it can be processed by language-independent @@ -280,10 +327,13 @@ build_cplus_new (tree type, tree init) abstract class. */ abstract_virtuals_error (NULL_TREE, type); - if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR) + if (TREE_CODE (init) == CALL_EXPR) + fn = CALL_EXPR_FN (init); + else if (TREE_CODE (init) == AGGR_INIT_EXPR) + fn = AGGR_INIT_EXPR_FN (init); + else return convert (type, init); - fn = TREE_OPERAND (init, 0); is_ctor = (TREE_CODE (fn) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0))); @@ -303,8 +353,14 @@ build_cplus_new (tree type, tree init) type, don't mess with AGGR_INIT_EXPR. */ if (is_ctor || TREE_ADDRESSABLE (type)) { - rval = build3 (AGGR_INIT_EXPR, void_type_node, fn, - TREE_OPERAND (init, 1), slot); + if (TREE_CODE(init) == CALL_EXPR) + rval = build_aggr_init_array (void_type_node, fn, slot, + call_expr_nargs (init), + CALL_EXPR_ARGP (init)); + else + rval = build_aggr_init_array (void_type_node, fn, slot, + aggr_init_expr_nargs (init), + AGGR_INIT_EXPR_ARGP (init)); TREE_SIDE_EFFECTS (rval) = 1; AGGR_INIT_VIA_CTOR_P (rval) = is_ctor; } @@ -1420,6 +1476,8 @@ build_min_nt (enum tree_code code, ...) int i; va_list p; + gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp); + va_start (p, code); t = make_node (code); @@ -1435,6 +1493,7 @@ build_min_nt (enum tree_code code, ...) return t; } + /* Similar to `build', but for template definitions. */ tree @@ -1445,6 +1504,8 @@ build_min (enum tree_code code, tree tt, ...) int i; va_list p; + gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp); + va_start (p, tt); t = make_node (code); @@ -1475,6 +1536,8 @@ build_min_non_dep (enum tree_code code, tree non_dep, ...) int i; va_list p; + gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp); + va_start (p, non_dep); t = make_node (code); @@ -1497,6 +1560,19 @@ build_min_non_dep (enum tree_code code, tree non_dep, ...) return t; } +/* Similar to `build_call_list', but for template definitions of non-dependent + expressions. NON_DEP is the non-dependent expression that has been + built. */ + +tree +build_min_non_dep_call_list (tree non_dep, tree fn, tree arglist) +{ + tree t = build_nt_call_list (fn, arglist); + TREE_TYPE (t) = TREE_TYPE (non_dep); + TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep); + return t; +} + tree get_type_decl (tree t) { @@ -1615,9 +1691,20 @@ cp_tree_equal (tree t1, tree t2) return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); case CALL_EXPR: - if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0))) - return false; - return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)); + { + tree arg1, arg2; + call_expr_arg_iterator iter1, iter2; + if (!cp_tree_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2))) + return false; + for (arg1 = first_call_expr_arg (t1, &iter1), + arg2 = first_call_expr_arg (t2, &iter2); + arg1 && arg2; + arg1 = next_call_expr_arg (&iter1), + arg2 = next_call_expr_arg (&iter2)) + if (!cp_tree_equal (arg1, arg2)) + return false; + return (arg1 || arg2); + } case TARGET_EXPR: { @@ -1747,12 +1834,18 @@ cp_tree_equal (tree t1, tree t2) case tcc_binary: case tcc_comparison: case tcc_expression: + case tcc_vl_exp: case tcc_reference: case tcc_statement: { - int i; + int i, n; + + n = TREE_OPERAND_LENGTH (t1); + if (TREE_CODE_CLASS (code1) == tcc_vl_exp + && n != TREE_OPERAND_LENGTH (t2)) + return false; - for (i = 0; i < TREE_CODE_LENGTH (code1); ++i) + for (i = 0; i < n; ++i) if (!cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i))) return false; @@ -2438,21 +2531,49 @@ void stabilize_call (tree call, tree *initp) { tree inits = NULL_TREE; - tree t; + int i; + int nargs = call_expr_nargs (call); if (call == error_mark_node) return; - gcc_assert (TREE_CODE (call) == CALL_EXPR - || TREE_CODE (call) == AGGR_INIT_EXPR); + gcc_assert (TREE_CODE (call) == CALL_EXPR); - for (t = TREE_OPERAND (call, 1); t; t = TREE_CHAIN (t)) - if (TREE_SIDE_EFFECTS (TREE_VALUE (t))) - { - tree init; - TREE_VALUE (t) = stabilize_expr (TREE_VALUE (t), &init); - inits = add_stmt_to_compound (inits, init); - } + for (i = 0; i < nargs; i++) + { + tree init; + CALL_EXPR_ARG (call, i) = + stabilize_expr (CALL_EXPR_ARG (call, i), &init); + inits = add_stmt_to_compound (inits, init); + } + + *initp = inits; +} + +/* Like stabilize_expr, but for an AGGR_INIT_EXPR whose arguments we want + to pre-evaluate. CALL is modified in place to use the pre-evaluated + arguments, while, upon return, *INITP contains an expression to + compute the arguments. */ + +void +stabilize_aggr_init (tree call, tree *initp) +{ + tree inits = NULL_TREE; + int i; + int nargs = aggr_init_expr_nargs (call); + + if (call == error_mark_node) + return; + + gcc_assert (TREE_CODE (call) == AGGR_INIT_EXPR); + + for (i = 0; i < nargs; i++) + { + tree init; + AGGR_INIT_EXPR_ARG (call, i) = + stabilize_expr (AGGR_INIT_EXPR_ARG (call, i), &init); + inits = add_stmt_to_compound (inits, init); + } *initp = inits; } @@ -2499,13 +2620,18 @@ stabilize_init (tree init, tree *initp) if (TREE_CODE (t) == COND_EXPR) return false; - if (TREE_CODE (t) == CALL_EXPR - || TREE_CODE (t) == AGGR_INIT_EXPR) + if (TREE_CODE (t) == CALL_EXPR) { stabilize_call (t, initp); return true; } + if (TREE_CODE (t) == AGGR_INIT_EXPR) + { + stabilize_aggr_init (t, initp); + return true; + } + /* The initialization is being performed via a bitwise copy -- and the item copied may have side effects. */ return TREE_SIDE_EFFECTS (init); diff --git a/gcc/doc/c-tree.texi b/gcc/doc/c-tree.texi index 46af3abff9f..4bf09057124 100644 --- a/gcc/doc/c-tree.texi +++ b/gcc/doc/c-tree.texi @@ -2474,19 +2474,39 @@ argument does cause side-effects. @item CALL_EXPR These nodes are used to represent calls to functions, including -non-static member functions. The first operand is a pointer to the +non-static member functions. @code{CALL_EXPR}s are implemented as +expression nodes with a variable number of operands. Rather than using +@code{TREE_OPERAND} to extract them, it is preferable to use the +specialized accessor macros and functions that operate specifically on +@code{CALL_EXPR} nodes. + +@code{CALL_EXPR_FN} returns a pointer to the function to call; it is always an expression whose type is a -@code{POINTER_TYPE}. The second argument is a @code{TREE_LIST}. The -arguments to the call appear left-to-right in the list. The -@code{TREE_VALUE} of each list node contains the expression -corresponding to that argument. (The value of @code{TREE_PURPOSE} for -these nodes is unspecified, and should be ignored.) For non-static +@code{POINTER_TYPE}. + +The number of arguments to the call is returned by @code{call_expr_nargs}, +while the arguments themselves can be accessed with the @code{CALL_EXPR_ARG} +macro. The arguments are zero-indexed and numbered left-to-right. +You can iterate over the arguments using @code{FOR_EACH_CALL_EXPR_ARG}, as in: + +@smallexample +tree call, arg; +call_expr_arg_iterator iter; +FOR_EACH_CALL_EXPR_ARG (arg, iter, call) + /* arg is bound to successive arguments of call. */ + ...; +@end smallexample + +For non-static member functions, there will be an operand corresponding to the @code{this} pointer. There will always be expressions corresponding to all of the arguments, even if the function is declared with default arguments and some arguments are not explicitly provided at the call sites. +@code{CALL_EXPR}s also have a @code{CALL_EXPR_STATIC_CHAIN} operand that +is used to implement nested functions. This operand is otherwise null. + @item STMT_EXPR These nodes are used to represent GCC's statement-expression extension. The statement-expression extension allows code like this: @@ -2613,15 +2633,14 @@ cleanups. An @code{AGGR_INIT_EXPR} represents the initialization as the return value of a function call, or as the result of a constructor. An @code{AGGR_INIT_EXPR} will only appear as a full-expression, or as the -second operand of a @code{TARGET_EXPR}. The first operand to the -@code{AGGR_INIT_EXPR} is the address of a function to call, just as in -a @code{CALL_EXPR}. The second operand are the arguments to pass that -function, as a @code{TREE_LIST}, again in a manner similar to that of -a @code{CALL_EXPR}. +second operand of a @code{TARGET_EXPR}. @code{AGGR_INIT_EXPR}s have +a representation similar to that of @code{CALL_EXPR}s. You can use +the @code{AGGR_INIT_EXPR_FN} and @code{AGGR_INIT_EXPR_ARG} macros to access +the function to call and the arguments to pass. If @code{AGGR_INIT_VIA_CTOR_P} holds of the @code{AGGR_INIT_EXPR}, then -the initialization is via a constructor call. The address of the third -operand of the @code{AGGR_INIT_EXPR}, which is always a @code{VAR_DECL}, +the initialization is via a constructor call. The address of the +@code{AGGR_INIT_EXPR_SLOT} operand, which is always a @code{VAR_DECL}, is taken, and this value replaces the first argument in the argument list. diff --git a/gcc/except.c b/gcc/except.c index dc510794d50..915059c3971 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -2867,9 +2867,9 @@ expand_builtin_unwind_init (void) } rtx -expand_builtin_eh_return_data_regno (tree arglist) +expand_builtin_eh_return_data_regno (tree exp) { - tree which = TREE_VALUE (arglist); + tree which = CALL_EXPR_ARG (exp, 0); unsigned HOST_WIDE_INT iwhich; if (TREE_CODE (which) != INTEGER_CST) diff --git a/gcc/expr.c b/gcc/expr.c index 42cb253e72e..1c2ff13fa17 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -1355,7 +1355,7 @@ rtx emit_block_move_via_libcall (rtx dst, rtx src, rtx size, bool tailcall) { rtx dst_addr, src_addr; - tree call_expr, arg_list, fn, src_tree, dst_tree, size_tree; + tree call_expr, fn, src_tree, dst_tree, size_tree; enum machine_mode size_mode; rtx retval; @@ -1386,14 +1386,7 @@ emit_block_move_via_libcall (rtx dst, rtx src, rtx size, bool tailcall) size_tree = make_tree (sizetype, size); fn = emit_block_move_libcall_fn (true); - arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE); - arg_list = tree_cons (NULL_TREE, src_tree, arg_list); - arg_list = tree_cons (NULL_TREE, dst_tree, arg_list); - - /* Now we have to build up the CALL_EXPR itself. */ - call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); - call_expr = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), - call_expr, arg_list, NULL_TREE); + call_expr = build_call_expr (fn, 3, dst_tree, src_tree, size_tree); CALL_EXPR_TAILCALL (call_expr) = tailcall; retval = expand_normal (call_expr); @@ -2576,7 +2569,7 @@ clear_storage (rtx object, rtx size, enum block_op_methods method) rtx set_storage_via_libcall (rtx object, rtx size, rtx val, bool tailcall) { - tree call_expr, arg_list, fn, object_tree, size_tree, val_tree; + tree call_expr, fn, object_tree, size_tree, val_tree; enum machine_mode size_mode; rtx retval; @@ -2602,14 +2595,8 @@ set_storage_via_libcall (rtx object, rtx size, rtx val, bool tailcall) val_tree = make_tree (integer_type_node, val); fn = clear_storage_libcall_fn (true); - arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE); - arg_list = tree_cons (NULL_TREE, val_tree, arg_list); - arg_list = tree_cons (NULL_TREE, object_tree, arg_list); - - /* Now we have to build up the CALL_EXPR itself. */ - call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); - call_expr = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), - call_expr, arg_list, NULL_TREE); + call_expr = build_call_expr (fn, 3, + object_tree, integer_zero_node, size_tree); CALL_EXPR_TAILCALL (call_expr) = tailcall; retval = expand_normal (call_expr); @@ -6225,6 +6212,7 @@ safe_from_p (rtx x, tree exp, int top_p) case tcc_expression: case tcc_reference: + case tcc_vl_exp: /* Now do code-specific tests. EXP_RTL is set to any rtx we find in the expression. If it is set, we conflict iff we are that rtx or both are in memory. Otherwise, we check all operands of the @@ -6287,7 +6275,7 @@ safe_from_p (rtx x, tree exp, int top_p) if (exp_rtl) break; - nops = TREE_CODE_LENGTH (TREE_CODE (exp)); + nops = TREE_OPERAND_LENGTH (exp); for (i = 0; i < nops; i++) if (TREE_OPERAND (exp, i) != 0 && ! safe_from_p (x, TREE_OPERAND (exp, i), 0)) @@ -7769,12 +7757,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, case CALL_EXPR: /* Check for a built-in function. */ - if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR - && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) + if (TREE_CODE (CALL_EXPR_FN (exp)) == ADDR_EXPR + && (TREE_CODE (TREE_OPERAND (CALL_EXPR_FN (exp), 0)) == FUNCTION_DECL) - && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) + && DECL_BUILT_IN (TREE_OPERAND (CALL_EXPR_FN (exp), 0))) { - if (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) + if (DECL_BUILT_IN_CLASS (TREE_OPERAND (CALL_EXPR_FN (exp), 0)) == BUILT_IN_FRONTEND) return lang_hooks.expand_expr (exp, original_target, tmode, modifier, diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 7d66736b13b..0aca93c386a 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -1195,7 +1195,7 @@ negate_expr_p (tree t) case CALL_EXPR: /* Negate -f(x) as f(-x). */ if (negate_mathfn_p (builtin_mathfn_code (t))) - return negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1))); + return negate_expr_p (CALL_EXPR_ARG (t, 0)); break; case RSHIFT_EXPR: @@ -1382,14 +1382,13 @@ fold_negate_expr (tree t) case CALL_EXPR: /* Negate -f(x) as f(-x). */ if (negate_mathfn_p (builtin_mathfn_code (t)) - && negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1)))) + && negate_expr_p (CALL_EXPR_ARG (t, 0))) { - tree fndecl, arg, arglist; + tree fndecl, arg; fndecl = get_callee_fndecl (t); - arg = negate_expr (TREE_VALUE (TREE_OPERAND (t, 1))); - arglist = build_tree_list (NULL_TREE, arg); - return build_function_call_expr (fndecl, arglist); + arg = negate_expr (CALL_EXPR_ARG (t, 0)); + return build_call_expr (fndecl, 1, arg); } break; @@ -2929,10 +2928,18 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags) && operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 0), flags)); + default: + return 0; + } + + case tcc_vl_exp: + switch (TREE_CODE (arg0)) + { case CALL_EXPR: /* If the CALL_EXPRs call different functions, then they clearly can not be equal. */ - if (!OP_SAME (0)) + if (! operand_equal_p (CALL_EXPR_FN (arg0), CALL_EXPR_FN (arg1), + flags)) return 0; { @@ -2945,25 +2952,22 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags) return 0; } - /* Now see if all the arguments are the same. operand_equal_p - does not handle TREE_LIST, so we walk the operands here - feeding them to operand_equal_p. */ - arg0 = TREE_OPERAND (arg0, 1); - arg1 = TREE_OPERAND (arg1, 1); - while (arg0 && arg1) - { - if (! operand_equal_p (TREE_VALUE (arg0), TREE_VALUE (arg1), - flags)) + /* Now see if all the arguments are the same. */ + { + call_expr_arg_iterator iter0, iter1; + tree a0, a1; + for (a0 = first_call_expr_arg (arg0, &iter0), + a1 = first_call_expr_arg (arg1, &iter1); + a0 && a1; + a0 = next_call_expr_arg (&iter0), + a1 = next_call_expr_arg (&iter1)) + if (! operand_equal_p (a0, a1, flags)) return 0; - arg0 = TREE_CHAIN (arg0); - arg1 = TREE_CHAIN (arg1); - } - - /* If we get here and both argument lists are exhausted - then the CALL_EXPRs are equal. */ - return ! (arg0 || arg1); - + /* If we get here and both argument lists are exhausted + then the CALL_EXPRs are equal. */ + return ! (a0 || a1); + } default: return 0; } @@ -4035,7 +4039,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh, if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))) { - if (TREE_CODE_LENGTH (code) > 0) + if (TREE_OPERAND_LENGTH (exp) > 0) arg0 = TREE_OPERAND (exp, 0); if (TREE_CODE_CLASS (code) == tcc_comparison || TREE_CODE_CLASS (code) == tcc_unary @@ -4044,7 +4048,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh, if (TREE_CODE_CLASS (code) == tcc_binary || TREE_CODE_CLASS (code) == tcc_comparison || (TREE_CODE_CLASS (code) == tcc_expression - && TREE_CODE_LENGTH (code) > 1)) + && TREE_OPERAND_LENGTH (exp) > 1)) arg1 = TREE_OPERAND (exp, 1); } @@ -5677,6 +5681,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type, if ((COMPARISON_CLASS_P (op0) || UNARY_CLASS_P (op0) || BINARY_CLASS_P (op0) + || VL_EXP_CLASS_P (op0) || EXPRESSION_CLASS_P (op0)) /* ... and is unsigned, and its type is smaller than ctype, then we cannot pass through as widening. */ @@ -6151,7 +6156,7 @@ fold_mathfn_compare (enum built_in_function fcode, enum tree_code code, if (BUILTIN_SQRT_P (fcode)) { - tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1)); + tree arg = CALL_EXPR_ARG (arg0, 0); enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg0)); c = TREE_REAL_CST (arg1); @@ -7970,8 +7975,7 @@ fold_unary (enum tree_code code, tree type, tree op0) CASE_FLT_FN (BUILT_IN_CEXPI): fn = mathfn_built_in (type, BUILT_IN_COS); if (fn) - return build_function_call_expr (fn, - TREE_OPERAND (arg0, 1)); + return build_call_expr (fn, 1, CALL_EXPR_ARG (arg0, 0)); break; default: @@ -8013,8 +8017,7 @@ fold_unary (enum tree_code code, tree type, tree op0) CASE_FLT_FN (BUILT_IN_CEXPI): fn = mathfn_built_in (type, BUILT_IN_SIN); if (fn) - return build_function_call_expr (fn, - TREE_OPERAND (arg0, 1)); + return build_call_expr (fn, 1, CALL_EXPR_ARG (arg0, 0)); break; default: @@ -9807,9 +9810,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) /* Optimizations of root(...)*root(...). */ if (fcode0 == fcode1 && BUILTIN_ROOT_P (fcode0)) { - tree rootfn, arg, arglist; - tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1)); - tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1)); + tree rootfn, arg; + tree arg00 = CALL_EXPR_ARG (arg0, 0); + tree arg10 = CALL_EXPR_ARG (arg1, 0); /* Optimize sqrt(x)*sqrt(x) as x. */ if (BUILTIN_SQRT_P (fcode0) @@ -9818,21 +9821,19 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) return arg00; /* Optimize root(x)*root(y) as root(x*y). */ - rootfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); + rootfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); arg = fold_build2 (MULT_EXPR, type, arg00, arg10); - arglist = build_tree_list (NULL_TREE, arg); - return build_function_call_expr (rootfn, arglist); + return build_call_expr (rootfn, 1, arg); } /* Optimize expN(x)*expN(y) as expN(x+y). */ if (fcode0 == fcode1 && BUILTIN_EXPONENT_P (fcode0)) { - tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); + tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); tree arg = fold_build2 (PLUS_EXPR, type, - TREE_VALUE (TREE_OPERAND (arg0, 1)), - TREE_VALUE (TREE_OPERAND (arg1, 1))); - tree arglist = build_tree_list (NULL_TREE, arg); - return build_function_call_expr (expfn, arglist); + CALL_EXPR_ARG (arg0, 0), + CALL_EXPR_ARG (arg1, 0)); + return build_call_expr (expfn, 1, arg); } /* Optimizations of pow(...)*pow(...). */ @@ -9840,33 +9841,25 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) || (fcode0 == BUILT_IN_POWF && fcode1 == BUILT_IN_POWF) || (fcode0 == BUILT_IN_POWL && fcode1 == BUILT_IN_POWL)) { - tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1)); - tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, - 1))); - tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1)); - tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1, - 1))); + tree arg00 = CALL_EXPR_ARG (arg0, 0); + tree arg01 = CALL_EXPR_ARG (arg0, 1); + tree arg10 = CALL_EXPR_ARG (arg1, 0); + tree arg11 = CALL_EXPR_ARG (arg1, 1); /* Optimize pow(x,y)*pow(z,y) as pow(x*z,y). */ if (operand_equal_p (arg01, arg11, 0)) { - tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); + tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); tree arg = fold_build2 (MULT_EXPR, type, arg00, arg10); - tree arglist = tree_cons (NULL_TREE, arg, - build_tree_list (NULL_TREE, - arg01)); - return build_function_call_expr (powfn, arglist); + return build_call_expr (powfn, 2, arg, arg01); } /* Optimize pow(x,y)*pow(x,z) as pow(x,y+z). */ if (operand_equal_p (arg00, arg10, 0)) { - tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); + tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); tree arg = fold_build2 (PLUS_EXPR, type, arg01, arg11); - tree arglist = tree_cons (NULL_TREE, arg00, - build_tree_list (NULL_TREE, - arg)); - return build_function_call_expr (powfn, arglist); + return build_call_expr (powfn, 2, arg00, arg); } } @@ -9877,14 +9870,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) || (fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_TAN) || (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_TANF) || (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_TANL)) - && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)), - TREE_VALUE (TREE_OPERAND (arg1, 1)), 0)) + && operand_equal_p (CALL_EXPR_ARG (arg0, 0), + CALL_EXPR_ARG (arg1, 0), 0)) { tree sinfn = mathfn_built_in (type, BUILT_IN_SIN); if (sinfn != NULL_TREE) - return build_function_call_expr (sinfn, - TREE_OPERAND (arg0, 1)); + return build_call_expr (sinfn, 1, CALL_EXPR_ARG (arg0, 0)); } /* Optimize x*pow(x,c) as pow(x,c+1). */ @@ -9892,23 +9884,20 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) || fcode1 == BUILT_IN_POWF || fcode1 == BUILT_IN_POWL) { - tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1)); - tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1, - 1))); + tree arg10 = CALL_EXPR_ARG (arg1, 0); + tree arg11 = CALL_EXPR_ARG (arg1, 1); if (TREE_CODE (arg11) == REAL_CST && !TREE_OVERFLOW (arg11) && operand_equal_p (arg0, arg10, 0)) { - tree powfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0); + tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0); REAL_VALUE_TYPE c; - tree arg, arglist; + tree arg; c = TREE_REAL_CST (arg11); real_arithmetic (&c, PLUS_EXPR, &c, &dconst1); arg = build_real (type, c); - arglist = build_tree_list (NULL_TREE, arg); - arglist = tree_cons (NULL_TREE, arg0, arglist); - return build_function_call_expr (powfn, arglist); + return build_call_expr (powfn, 2, arg0, arg); } } @@ -9917,23 +9906,20 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) || fcode0 == BUILT_IN_POWF || fcode0 == BUILT_IN_POWL) { - tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1)); - tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, - 1))); + tree arg00 = CALL_EXPR_ARG (arg0, 0); + tree arg01 = CALL_EXPR_ARG (arg0, 1); if (TREE_CODE (arg01) == REAL_CST && !TREE_OVERFLOW (arg01) && operand_equal_p (arg1, arg00, 0)) { - tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); + tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); REAL_VALUE_TYPE c; - tree arg, arglist; + tree arg; c = TREE_REAL_CST (arg01); real_arithmetic (&c, PLUS_EXPR, &c, &dconst1); arg = build_real (type, c); - arglist = build_tree_list (NULL_TREE, arg); - arglist = tree_cons (NULL_TREE, arg1, arglist); - return build_function_call_expr (powfn, arglist); + return build_call_expr (powfn, 2, arg1, arg); } } @@ -9946,9 +9932,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) if (powfn) { tree arg = build_real (type, dconst2); - tree arglist = build_tree_list (NULL_TREE, arg); - arglist = tree_cons (NULL_TREE, arg0, arglist); - return build_function_call_expr (powfn, arglist); + return build_call_expr (powfn, 2, arg0, arg); } } } @@ -10480,29 +10464,27 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_COS) || (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_COSF) || (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_COSL)) - && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)), - TREE_VALUE (TREE_OPERAND (arg1, 1)), 0)) + && operand_equal_p (CALL_EXPR_ARG (arg0, 0), + CALL_EXPR_ARG (arg1, 0), 0)) { tree tanfn = mathfn_built_in (type, BUILT_IN_TAN); if (tanfn != NULL_TREE) - return build_function_call_expr (tanfn, - TREE_OPERAND (arg0, 1)); + return build_call_expr (tanfn, 1, CALL_EXPR_ARG (arg0, 0)); } /* Optimize cos(x)/sin(x) as 1.0/tan(x). */ if (((fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_SIN) || (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_SINF) || (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_SINL)) - && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)), - TREE_VALUE (TREE_OPERAND (arg1, 1)), 0)) + && operand_equal_p (CALL_EXPR_ARG (arg0, 0), + CALL_EXPR_ARG (arg1, 0), 0)) { tree tanfn = mathfn_built_in (type, BUILT_IN_TAN); if (tanfn != NULL_TREE) { - tree tmp = TREE_OPERAND (arg0, 1); - tmp = build_function_call_expr (tanfn, tmp); + tree tmp = build_call_expr (tanfn, 1, CALL_EXPR_ARG (arg0, 0)); return fold_build2 (RDIV_EXPR, type, build_real (type, dconst1), tmp); } @@ -10514,8 +10496,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) || (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_TANF) || (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_TANL))) { - tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1)); - tree arg01 = TREE_VALUE (TREE_OPERAND (arg1, 1)); + tree arg00 = CALL_EXPR_ARG (arg0, 0); + tree arg01 = CALL_EXPR_ARG (arg1, 0); if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00))) && ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg00))) @@ -10524,8 +10506,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) tree cosfn = mathfn_built_in (type, BUILT_IN_COS); if (cosfn != NULL_TREE) - return build_function_call_expr (cosfn, - TREE_OPERAND (arg0, 1)); + return build_call_expr (cosfn, 1, arg00); } } @@ -10535,8 +10516,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) || (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_SINF) || (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_SINL))) { - tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1)); - tree arg01 = TREE_VALUE (TREE_OPERAND (arg1, 1)); + tree arg00 = CALL_EXPR_ARG (arg0, 0); + tree arg01 = CALL_EXPR_ARG (arg1, 0); if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00))) && ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg00))) @@ -10546,8 +10527,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) if (cosfn != NULL_TREE) { - tree tmp = TREE_OPERAND (arg0, 1); - tmp = build_function_call_expr (cosfn, tmp); + tree tmp = build_call_expr (cosfn, 1, arg00); return fold_build2 (RDIV_EXPR, type, build_real (type, dconst1), tmp); @@ -10560,33 +10540,29 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) || fcode0 == BUILT_IN_POWF || fcode0 == BUILT_IN_POWL) { - tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1)); - tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1))); + tree arg00 = CALL_EXPR_ARG (arg0, 0); + tree arg01 = CALL_EXPR_ARG (arg0, 1); if (TREE_CODE (arg01) == REAL_CST && !TREE_OVERFLOW (arg01) && operand_equal_p (arg1, arg00, 0)) { - tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); + tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); REAL_VALUE_TYPE c; - tree arg, arglist; + tree arg; c = TREE_REAL_CST (arg01); real_arithmetic (&c, MINUS_EXPR, &c, &dconst1); arg = build_real (type, c); - arglist = build_tree_list (NULL_TREE, arg); - arglist = tree_cons (NULL_TREE, arg1, arglist); - return build_function_call_expr (powfn, arglist); + return build_call_expr (powfn, 2, arg1, arg); } } /* Optimize x/expN(y) into x*expN(-y). */ if (BUILTIN_EXPONENT_P (fcode1)) { - tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0); - tree arg = negate_expr (TREE_VALUE (TREE_OPERAND (arg1, 1))); - tree arglist = build_tree_list (NULL_TREE, - fold_convert (type, arg)); - arg1 = build_function_call_expr (expfn, arglist); + tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0); + tree arg = negate_expr (CALL_EXPR_ARG (arg1, 0)); + arg1 = build_call_expr (expfn, 1, fold_convert (type, arg)); return fold_build2 (MULT_EXPR, type, arg0, arg1); } @@ -10595,13 +10571,11 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) || fcode1 == BUILT_IN_POWF || fcode1 == BUILT_IN_POWL) { - tree powfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0); - tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1)); - tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1, 1))); + tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0); + tree arg10 = CALL_EXPR_ARG (arg1, 0); + tree arg11 = CALL_EXPR_ARG (arg1, 1); tree neg11 = fold_convert (type, negate_expr (arg11)); - tree arglist = tree_cons (NULL_TREE, arg10, - build_tree_list (NULL_TREE, neg11)); - arg1 = build_function_call_expr (powfn, arglist); + arg1 = build_call_expr (powfn, 2, arg10, neg11); return fold_build2 (MULT_EXPR, type, arg0, arg1); } } @@ -11386,16 +11360,14 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) && integer_zerop (arg1)) { tree fndecl = get_callee_fndecl (arg0); - tree arglist; if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN - && (arglist = TREE_OPERAND (arg0, 1)) - && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE - && ! TREE_CHAIN (arglist)) + && call_expr_nargs (arg0) == 1 + && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (arg0, 0))) == POINTER_TYPE) { - tree iref = build_fold_indirect_ref (TREE_VALUE (arglist)); + tree iref = build_fold_indirect_ref (CALL_EXPR_ARG (arg0, 0)); return fold_build2 (code, type, iref, build_int_cst (TREE_TYPE (iref), 0)); } @@ -12376,12 +12348,9 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2) return NULL_TREE; case CALL_EXPR: - /* Check for a built-in function. */ - if (TREE_CODE (op0) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (op0, 0)) == FUNCTION_DECL - && DECL_BUILT_IN (TREE_OPERAND (op0, 0))) - return fold_builtin (TREE_OPERAND (op0, 0), op1, false); - return NULL_TREE; + /* CALL_EXPRs used to be ternary exprs. Catch any mistaken uses + of fold_ternary on them. */ + gcc_unreachable (); case BIT_FIELD_REF: if (TREE_CODE (arg0) == VECTOR_CST @@ -12439,6 +12408,18 @@ fold (tree expr) if (kind == tcc_constant) return t; + /* CALL_EXPR-like objects with variable numbers of operands are + treated specially. */ + if (kind == tcc_vl_exp) + { + if (code == CALL_EXPR) + { + tem = fold_call_expr (expr, false); + return tem ? tem : expr; + } + return expr; + } + if (IS_EXPR_CODE_CLASS (kind) || IS_GIMPLE_STMT_CODE_CLASS (kind)) { @@ -12632,7 +12613,8 @@ recursive_label: case tcc_unary: case tcc_binary: case tcc_statement: - len = TREE_CODE_LENGTH (code); + case tcc_vl_exp: + len = TREE_OPERAND_LENGTH (expr); for (i = 0; i < len; ++i) fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht); break; @@ -12811,7 +12793,8 @@ fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2 md5_finish_ctx (&ctx, checksum_before_op2); htab_empty (ht); #endif - + + gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp); tem = fold_ternary (code, type, op0, op1, op2); if (!tem) tem = build3_stat (code, type, op0, op1, op2 PASS_MEM_STAT); @@ -12844,6 +12827,57 @@ fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2 return tem; } +/* Fold a CALL_EXPR expression of type TYPE with operands FN and ARGLIST + and a null static chain. + Return a folded expression if successful. Otherwise, return a CALL_EXPR + of type TYPE from the given operands as constructed by build_call_list. */ + +tree +fold_build_call_list (tree type, tree fn, tree arglist) +{ + tree tem; +#ifdef ENABLE_FOLD_CHECKING + unsigned char checksum_before_fn[16], + checksum_before_arglist[16], + checksum_after_fn[16], + checksum_after_arglist[16]; + struct md5_ctx ctx; + htab_t ht; + + ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL); + md5_init_ctx (&ctx); + fold_checksum_tree (fn, &ctx, ht); + md5_finish_ctx (&ctx, checksum_before_fn); + htab_empty (ht); + + md5_init_ctx (&ctx); + fold_checksum_tree (arglist, &ctx, ht); + md5_finish_ctx (&ctx, checksum_before_arglist); + htab_empty (ht); +#endif + + tem = fold_builtin_call_list (type, fn, arglist); + +#ifdef ENABLE_FOLD_CHECKING + md5_init_ctx (&ctx); + fold_checksum_tree (fn, &ctx, ht); + md5_finish_ctx (&ctx, checksum_after_fn); + htab_empty (ht); + + if (memcmp (checksum_before_fn, checksum_after_fn, 16)) + fold_check_failed (fn, tem); + + md5_init_ctx (&ctx); + fold_checksum_tree (arglist, &ctx, ht); + md5_finish_ctx (&ctx, checksum_after_arglist); + htab_delete (ht); + + if (memcmp (checksum_before_arglist, checksum_after_arglist, 16)) + fold_check_failed (arglist, tem); +#endif + return tem; +} + /* Perform constant folding and related simplification of initializer expression EXPR. These behave identically to "fold_buildN" but ignore potential run-time traps and exceptions that fold must preserve. */ @@ -12904,6 +12938,18 @@ fold_build3_initializer (enum tree_code code, tree type, tree op0, tree op1, return result; } +tree +fold_build_call_list_initializer (tree type, tree fn, tree arglist) +{ + tree result; + START_FOLD_INIT; + + result = fold_build_call_list (type, fn, arglist); + + END_FOLD_INIT; + return result; +} + #undef START_FOLD_INIT #undef END_FOLD_INIT @@ -13223,7 +13269,6 @@ tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p) case CALL_EXPR: { tree fndecl = get_callee_fndecl (t); - tree arglist = TREE_OPERAND (t, 1); if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) switch (DECL_FUNCTION_CODE (fndecl)) { @@ -13251,7 +13296,7 @@ tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p) /* sqrt(-0.0) is -0.0. */ if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (t)))) return true; - return tree_expr_nonnegative_warnv_p (TREE_VALUE (arglist), + return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0), strict_overflow_p); CASE_FLT_FN (BUILT_IN_ASINH): @@ -13282,52 +13327,49 @@ tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p) CASE_FLT_FN (BUILT_IN_TANH): CASE_FLT_FN (BUILT_IN_TRUNC): /* True if the 1st argument is nonnegative. */ - return tree_expr_nonnegative_warnv_p (TREE_VALUE (arglist), + return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0), strict_overflow_p); CASE_FLT_FN (BUILT_IN_FMAX): /* True if the 1st OR 2nd arguments are nonnegative. */ - return (tree_expr_nonnegative_warnv_p (TREE_VALUE (arglist), + return (tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0), strict_overflow_p) - || (tree_expr_nonnegative_warnv_p - (TREE_VALUE (TREE_CHAIN (arglist)), - strict_overflow_p))); + || (tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 1), + strict_overflow_p))); CASE_FLT_FN (BUILT_IN_FMIN): /* True if the 1st AND 2nd arguments are nonnegative. */ - return (tree_expr_nonnegative_warnv_p (TREE_VALUE (arglist), + return (tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0), strict_overflow_p) - && (tree_expr_nonnegative_warnv_p - (TREE_VALUE (TREE_CHAIN (arglist)), - strict_overflow_p))); + && (tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 1), + strict_overflow_p))); CASE_FLT_FN (BUILT_IN_COPYSIGN): /* True if the 2nd argument is nonnegative. */ - return (tree_expr_nonnegative_warnv_p - (TREE_VALUE (TREE_CHAIN (arglist)), - strict_overflow_p)); + return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 1), + strict_overflow_p); CASE_FLT_FN (BUILT_IN_POWI): /* True if the 1st argument is nonnegative or the second argument is an even integer. */ - if (TREE_CODE (TREE_VALUE (TREE_CHAIN (arglist))) == INTEGER_CST) + if (TREE_CODE (CALL_EXPR_ARG (t, 1)) == INTEGER_CST) { - tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + tree arg1 = CALL_EXPR_ARG (t, 1); if ((TREE_INT_CST_LOW (arg1) & 1) == 0) return true; } - return tree_expr_nonnegative_warnv_p (TREE_VALUE (arglist), + return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0), strict_overflow_p); CASE_FLT_FN (BUILT_IN_POW): /* True if the 1st argument is nonnegative or the second argument is an even integer valued real. */ - if (TREE_CODE (TREE_VALUE (TREE_CHAIN (arglist))) == REAL_CST) + if (TREE_CODE (CALL_EXPR_ARG (t, 1)) == REAL_CST) { REAL_VALUE_TYPE c; HOST_WIDE_INT n; - c = TREE_REAL_CST (TREE_VALUE (TREE_CHAIN (arglist))); + c = TREE_REAL_CST (CALL_EXPR_ARG (t, 1)); n = real_to_integer (&c); if ((n & 1) == 0) { @@ -13338,7 +13380,7 @@ tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p) return true; } } - return tree_expr_nonnegative_warnv_p (TREE_VALUE (arglist), + return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0), strict_overflow_p); default: @@ -14336,19 +14378,17 @@ fold_strip_sign_ops (tree exp) { CASE_FLT_FN (BUILT_IN_COPYSIGN): /* Strip copysign function call, return the 1st argument. */ - arg0 = TREE_VALUE (TREE_OPERAND (exp, 1)); - arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (exp, 1))); + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); return omit_one_operand (TREE_TYPE (exp), arg0, arg1); default: /* Strip sign ops from the argument of "odd" math functions. */ if (negate_mathfn_p (fcode)) { - arg0 = fold_strip_sign_ops (TREE_VALUE (TREE_OPERAND (exp, 1))); + arg0 = fold_strip_sign_ops (CALL_EXPR_ARG (exp, 0)); if (arg0) - return build_function_call_expr (get_callee_fndecl (exp), - build_tree_list (NULL_TREE, - arg0)); + return build_call_expr (get_callee_fndecl (exp), 1, arg0); } break; } diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index bf9fe04d748..796c8b9a06b 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,68 @@ +2007-02-15 Sandra Loosemore <sandra@codesourcery.com> + Brooks Moses <brooks.moses@codesourcery.com> + Lee Millward <lee.millward@codesourcery.com> + + * trans-expr.c (gfc_conv_power_op): Use build_call_expr. + (gfc_conv_string_tmp): Likewise. + (gfc_conv_concat_op): Likewise. + (gfc_build_compare_string): Likewise. + (gfc_conv_function_call): Use build_call_list instead of build3. + + * trans-array.c (gfc_trans_allocate_array_storage): Use + build_call_expr. + (gfc_grow_array): Likewise. + (gfc_trans_array_ctor_element): Likewise. + (gfc_trans_array_constructor_value): Likewise. + (gfc_array_allocate): Likewise. + (gfc_array_deallocate): Likewise. + (gfc_trans_auto_array_allocation): Likewise. + (gfc_trans_dummy_array_bias): Likewise. + (gfc_conv_array_parameter): Likewise. + (gfc_trans_dealloc_allocated): Likewise. + (gfc_duplicate_allocatable): Likewise. + + * trans-openmp.c (gfc_trans_omp_barrier): Use build_call_expr. + (gfc_trans_omp_flush): Likewise. + + * trans-stmt.c (gfc_conv_elementel_dependencies): Use build_call_expr. + (gfc_trans_pause): Likewise. + (gfc_trans_stop): Likewise. + (gfc_trans_character_select): Likewise. + (gfc_do_allocate): Likewise. + (gfc_trans_assign_need_temp): Likewise. + (gfc_trans_pointer_assign_need_temp): Likewise. + (gfc_trans_forall_1): Likewise. + (gfc_trans_where_2): Likewise. + (gfc_trans_allocate): Likewise. + (gfc_trans_deallocate): Likewise. + + * trans.c (gfc_trans_runtime_check): Use build_call_expr. + + * trans-io.c (gfc_trans_open): Use build_call_expr. + (gfc_trans_close): Likewise. + (build_filepos): Likewise. + (gfc_trans_inquire): Likewise. + (NML_FIRST_ARG): Delete. + (NML_ADD_ARG): Delete. + (transfer_namelist_element): Use build_call_expr. + (build_dt): Likewise. + (gfc_trans_dt_end): Likewise. + (transfer_expr): Likewise. + (transfer_array-desc): Likewise. + + * trans-decl.c (gfc_generate_function_code): Use build_call_expr. + (gfc_generate_constructors): Likewise. + + * trans-intrinsic.c (gfc_conv_intrinsic_ctime): Use build_call_expr. + (gfc_conv_intrinsic_fdate): Likewise. + (gfc_conv_intrinsic_ttynam): Likewise. + (gfc_conv_intrinsic_array_transfer): Likewise. + (gfc_conv_associated): Likewise. + (gfc_conv_intrinsic_si_kind): Likewise. + (gfc_conv_intrinsic_trim): Likewise. + (gfc_conv_intrinsic_repeat: Likewise. + (gfc_conv_intrinsic_iargc): Likewise. + 2007-02-14 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR fortran/30779 diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 1c899759fad..64ea9d6f436 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -501,7 +501,6 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post, bool dynamic, bool dealloc) { tree tmp; - tree args; tree desc; bool onstack; @@ -534,15 +533,13 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post, else { /* Allocate memory to hold the data. */ - args = gfc_chainon_list (NULL_TREE, size); - if (gfc_index_integer_kind == 4) tmp = gfor_fndecl_internal_malloc; else if (gfc_index_integer_kind == 8) tmp = gfor_fndecl_internal_malloc64; else gcc_unreachable (); - tmp = build_function_call_expr (tmp, args); + tmp = build_call_expr (tmp, 1, size); tmp = gfc_evaluate_now (tmp, pre); gfc_conv_descriptor_data_set (pre, desc, tmp); } @@ -559,8 +556,7 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post, /* Free the temporary. */ tmp = gfc_conv_descriptor_data_get (desc); tmp = fold_convert (pvoid_type_node, tmp); - tmp = gfc_chainon_list (NULL_TREE, tmp); - tmp = build_function_call_expr (gfor_fndecl_internal_free, tmp); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmp); gfc_add_expr_to_block (post, tmp); } } @@ -829,7 +825,7 @@ gfc_get_iteration_count (tree start, tree end, tree step) static void gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra) { - tree args; + tree arg0, arg1; tree tmp; tree size; tree ubound; @@ -844,14 +840,12 @@ gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra) gfc_add_modify_expr (pblock, ubound, tmp); /* Get the value of the current data pointer. */ - tmp = gfc_conv_descriptor_data_get (desc); - args = gfc_chainon_list (NULL_TREE, tmp); + arg0 = gfc_conv_descriptor_data_get (desc); /* Calculate the new array size. */ size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc))); tmp = build2 (PLUS_EXPR, gfc_array_index_type, ubound, gfc_index_one_node); - tmp = build2 (MULT_EXPR, gfc_array_index_type, tmp, size); - args = gfc_chainon_list (args, tmp); + arg1 = build2 (MULT_EXPR, gfc_array_index_type, tmp, size); /* Pick the appropriate realloc function. */ if (gfc_index_integer_kind == 4) @@ -862,7 +856,7 @@ gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra) gcc_unreachable (); /* Set the new data pointer. */ - tmp = build_function_call_expr (tmp, args); + tmp = build_call_expr (tmp, 2, arg0, arg1); gfc_conv_descriptor_data_set (pblock, desc, tmp); } @@ -971,7 +965,6 @@ gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc, tree offset, gfc_se * se, gfc_expr * expr) { tree tmp; - tree args; gfc_conv_expr (se, expr); @@ -993,11 +986,8 @@ gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc, tmp = gfc_build_addr_expr (pchar_type_node, tmp); /* We know the temporary and the value will be the same length, so can use memcpy. */ - args = gfc_chainon_list (NULL_TREE, tmp); - args = gfc_chainon_list (args, se->expr); - args = gfc_chainon_list (args, se->string_length); - tmp = built_in_decls[BUILT_IN_MEMCPY]; - tmp = build_function_call_expr (tmp, args); + tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3, + tmp, se->expr, se->string_length); gfc_add_expr_to_block (&se->pre, tmp); } } @@ -1206,11 +1196,8 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type, size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)); bound = build_int_cst (NULL_TREE, n * size); - tmp = gfc_chainon_list (NULL_TREE, tmp); - tmp = gfc_chainon_list (tmp, init); - tmp = gfc_chainon_list (tmp, bound); - tmp = build_function_call_expr (built_in_decls[BUILT_IN_MEMCPY], - tmp); + tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3, + tmp, init, bound); gfc_add_expr_to_block (&body, tmp); *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type, @@ -3491,13 +3478,11 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat) else gcc_unreachable (); - tmp = NULL_TREE; /* The allocate_array variants take the old pointer as first argument. */ if (allocatable_array) - tmp = gfc_chainon_list (tmp, pointer); - tmp = gfc_chainon_list (tmp, size); - tmp = gfc_chainon_list (tmp, pstat); - tmp = build_function_call_expr (allocate, tmp); + tmp = build_call_expr (allocate, 3, pointer, size, pstat); + else + tmp = build_call_expr (allocate, 2, size, pstat); tmp = build2 (MODIFY_EXPR, void_type_node, pointer, tmp); gfc_add_expr_to_block (&se->pre, tmp); @@ -3533,9 +3518,7 @@ gfc_array_deallocate (tree descriptor, tree pstat) STRIP_NOPS (var); /* Parameter is the address of the data component. */ - tmp = gfc_chainon_list (NULL_TREE, var); - tmp = gfc_chainon_list (tmp, pstat); - tmp = build_function_call_expr (gfor_fndecl_deallocate, tmp); + tmp = build_call_expr (gfor_fndecl_deallocate, 2, var, pstat); gfc_add_expr_to_block (&block, tmp); /* Zero the data pointer. */ @@ -3826,15 +3809,13 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody) size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp); /* Allocate memory to hold the data. */ - tmp = gfc_chainon_list (NULL_TREE, size); - if (gfc_index_integer_kind == 4) fndecl = gfor_fndecl_internal_malloc; else if (gfc_index_integer_kind == 8) fndecl = gfor_fndecl_internal_malloc64; else gcc_unreachable (); - tmp = build_function_call_expr (fndecl, tmp); + tmp = build_call_expr (fndecl, 1, size); tmp = fold (convert (TREE_TYPE (decl), tmp)); gfc_add_modify_expr (&block, decl, tmp); @@ -3850,8 +3831,7 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody) /* Free the temporary. */ tmp = convert (pvoid_type_node, decl); - tmp = gfc_chainon_list (NULL_TREE, tmp); - tmp = build_function_call_expr (gfor_fndecl_internal_free, tmp); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmp); gfc_add_expr_to_block (&block, tmp); return gfc_finish_block (&block); @@ -4020,8 +4000,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body) gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0))); /* A library call to repack the array if necessary. */ tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc); - tmp = gfc_chainon_list (NULL_TREE, tmp); - stmt_unpacked = build_function_call_expr (gfor_fndecl_in_pack, tmp); + stmt_unpacked = build_call_expr (gfor_fndecl_in_pack, 1, tmp); stride = gfc_index_one_node; } @@ -4203,15 +4182,12 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body) if (sym->attr.intent != INTENT_IN) { /* Copy the data back. */ - tmp = gfc_chainon_list (NULL_TREE, dumdesc); - tmp = gfc_chainon_list (tmp, tmpdesc); - tmp = build_function_call_expr (gfor_fndecl_in_unpack, tmp); + tmp = build_call_expr (gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc); gfc_add_expr_to_block (&cleanup, tmp); } /* Free the temporary. */ - tmp = gfc_chainon_list (NULL_TREE, tmpdesc); - tmp = build_function_call_expr (gfor_fndecl_internal_free, tmp); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmpdesc); gfc_add_expr_to_block (&cleanup, tmp); stmt = gfc_finish_block (&cleanup); @@ -4778,23 +4754,19 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77) { desc = se->expr; /* Repack the array. */ - tmp = gfc_chainon_list (NULL_TREE, desc); - ptr = build_function_call_expr (gfor_fndecl_in_pack, tmp); + ptr = build_call_expr (gfor_fndecl_in_pack, 1, desc); ptr = gfc_evaluate_now (ptr, &se->pre); se->expr = ptr; gfc_start_block (&block); /* Copy the data back. */ - tmp = gfc_chainon_list (NULL_TREE, desc); - tmp = gfc_chainon_list (tmp, ptr); - tmp = build_function_call_expr (gfor_fndecl_in_unpack, tmp); + tmp = build_call_expr (gfor_fndecl_in_unpack, 2, desc, ptr); gfc_add_expr_to_block (&block, tmp); /* Free the temporary. */ tmp = convert (pvoid_type_node, ptr); - tmp = gfc_chainon_list (NULL_TREE, tmp); - tmp = build_function_call_expr (gfor_fndecl_internal_free, tmp); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmp); gfc_add_expr_to_block (&block, tmp); stmt = gfc_finish_block (&block); @@ -4836,9 +4808,7 @@ gfc_trans_dealloc_allocated (tree descriptor) /* Call array_deallocate with an int* present in the second argument. Although it is ignored here, it's presence ensures that arrays that are already deallocated are ignored. */ - tmp = gfc_chainon_list (NULL_TREE, var); - tmp = gfc_chainon_list (tmp, ptr); - tmp = build_function_call_expr (gfor_fndecl_deallocate, tmp); + tmp = build_call_expr (gfor_fndecl_deallocate, 2, var, ptr); gfc_add_expr_to_block (&block, tmp); /* Zero the data pointer. */ @@ -4880,7 +4850,6 @@ gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank) tree tmp; tree size; tree nelems; - tree args; tree null_cond; tree null_data; stmtblock_t block; @@ -4897,11 +4866,10 @@ gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank) TYPE_SIZE_UNIT (gfc_get_element_type (type))); /* Allocate memory to the destination. */ - tmp = gfc_chainon_list (NULL_TREE, size); if (gfc_index_integer_kind == 4) - tmp = build_function_call_expr (gfor_fndecl_internal_malloc, tmp); + tmp = build_call_expr (gfor_fndecl_internal_malloc, 1, size); else if (gfc_index_integer_kind == 8) - tmp = build_function_call_expr (gfor_fndecl_internal_malloc64, tmp); + tmp = build_call_expr (gfor_fndecl_internal_malloc64, 1, size); else gcc_unreachable (); tmp = fold (convert (TREE_TYPE (gfc_conv_descriptor_data_get (src)), @@ -4910,13 +4878,9 @@ gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank) /* We know the temporary and the value will be the same length, so can use memcpy. */ - tmp = gfc_conv_descriptor_data_get (dest); - args = gfc_chainon_list (NULL_TREE, tmp); - tmp = gfc_conv_descriptor_data_get (src); - args = gfc_chainon_list (args, tmp); - args = gfc_chainon_list (args, size); tmp = built_in_decls[BUILT_IN_MEMCPY]; - tmp = build_function_call_expr (tmp, args); + tmp = build_call_expr (tmp, 3, gfc_conv_descriptor_data_get (dest), + gfc_conv_descriptor_data_get (src), size); gfc_add_expr_to_block (&block, tmp); tmp = gfc_finish_block (&block); diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 1bf11e30c29..d001ad9eba6 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -3135,23 +3135,16 @@ gfc_generate_function_code (gfc_namespace * ns) if (sym->attr.is_main_program) { - tree arglist, gfc_int4_type_node; - - gfc_int4_type_node = gfc_get_int_type (4); - arglist = gfc_chainon_list (NULL_TREE, - build_int_cst (gfc_int4_type_node, - gfc_option.warn_std)); - arglist = gfc_chainon_list (arglist, - build_int_cst (gfc_int4_type_node, - gfc_option.allow_std)); - arglist = gfc_chainon_list (arglist, - build_int_cst (gfc_int4_type_node, - pedantic)); - arglist = gfc_chainon_list (arglist, - build_int_cst (gfc_int4_type_node, - gfc_option.flag_dump_core)); - - tmp = build_function_call_expr (gfor_fndecl_set_std, arglist); + tree gfc_int4_type_node = gfc_get_int_type (4); + tmp = build_call_expr (gfor_fndecl_set_std, 3, + build_int_cst (gfc_int4_type_node, + gfc_option.warn_std), + build_int_cst (gfc_int4_type_node, + gfc_option.allow_std), + build_int_cst (gfc_int4_type_node, + pedantic), + build_int_cst (gfc_int4_type_node, + gfc_option.flag_dump_core)); gfc_add_expr_to_block (&body, tmp); } @@ -3160,13 +3153,10 @@ gfc_generate_function_code (gfc_namespace * ns) needed. */ if (sym->attr.is_main_program && gfc_option.fpe != 0) { - tree arglist, gfc_c_int_type_node; - - gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind); - arglist = gfc_chainon_list (NULL_TREE, - build_int_cst (gfc_c_int_type_node, - gfc_option.fpe)); - tmp = build_function_call_expr (gfor_fndecl_set_fpe, arglist); + tree gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind); + tmp = build_call_expr (gfor_fndecl_set_fpe, 1, + build_int_cst (gfc_c_int_type_node, + gfc_option.fpe)); gfc_add_expr_to_block (&body, tmp); } @@ -3175,13 +3165,10 @@ gfc_generate_function_code (gfc_namespace * ns) if (sym->attr.is_main_program && gfc_option.convert != CONVERT_NATIVE) { - tree arglist, gfc_c_int_type_node; - - gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind); - arglist = gfc_chainon_list (NULL_TREE, - build_int_cst (gfc_c_int_type_node, - gfc_option.convert)); - tmp = build_function_call_expr (gfor_fndecl_set_convert, arglist); + tree gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind); + tmp = build_call_expr (gfor_fndecl_set_convert, 1, + build_int_cst (gfc_c_int_type_node, + gfc_option.convert)); gfc_add_expr_to_block (&body, tmp); } @@ -3190,26 +3177,22 @@ gfc_generate_function_code (gfc_namespace * ns) if (sym->attr.is_main_program && gfc_option.record_marker != 0) { - tree arglist, gfc_c_int_type_node; - - gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind); - arglist = gfc_chainon_list (NULL_TREE, - build_int_cst (gfc_c_int_type_node, - gfc_option.record_marker)); - tmp = build_function_call_expr (gfor_fndecl_set_record_marker, arglist); + tree gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind); + tmp = build_call_expr (gfor_fndecl_set_record_marker, 1, + build_int_cst (gfc_c_int_type_node, + gfc_option.record_marker)); gfc_add_expr_to_block (&body, tmp); - } if (sym->attr.is_main_program && gfc_option.max_subrecord_length != 0) { - tree arglist, gfc_c_int_type_node; + tree gfc_c_int_type_node; gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind); - arglist = gfc_chainon_list (NULL_TREE, - build_int_cst (gfc_c_int_type_node, - gfc_option.max_subrecord_length)); - tmp = build_function_call_expr (gfor_fndecl_set_max_subrecord_length, arglist); + tmp = build_call_expr (gfor_fndecl_set_max_subrecord_length, + 1, + build_int_cst (gfc_c_int_type_node, + gfc_option.max_subrecord_length)); gfc_add_expr_to_block (&body, tmp); } @@ -3374,8 +3357,7 @@ gfc_generate_constructors (void) for (; gfc_static_ctors; gfc_static_ctors = TREE_CHAIN (gfc_static_ctors)) { - tmp = - build_function_call_expr (TREE_VALUE (gfc_static_ctors), NULL_TREE); + tmp = build_call_expr (TREE_VALUE (gfc_static_ctors), 0); DECL_SAVED_TREE (fndecl) = build_stmt (EXPR_STMT, tmp); } diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 1a97e317622..839d768318e 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -748,7 +748,6 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr) gfc_se lse; gfc_se rse; tree fndecl; - tree tmp; gfc_init_se (&lse, se); gfc_conv_expr_val (&lse, expr->value.op.op1); @@ -887,9 +886,7 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr) break; } - tmp = gfc_chainon_list (NULL_TREE, lse.expr); - tmp = gfc_chainon_list (tmp, rse.expr); - se->expr = build_function_call_expr (fndecl, tmp); + se->expr = build_call_expr (fndecl, 2, lse.expr, rse.expr); } @@ -900,7 +897,6 @@ gfc_conv_string_tmp (gfc_se * se, tree type, tree len) { tree var; tree tmp; - tree args; gcc_assert (TREE_TYPE (len) == gfc_charlen_type_node); @@ -918,15 +914,13 @@ gfc_conv_string_tmp (gfc_se * se, tree type, tree len) { /* Allocate a temporary to hold the result. */ var = gfc_create_var (type, "pstr"); - args = gfc_chainon_list (NULL_TREE, len); - tmp = build_function_call_expr (gfor_fndecl_internal_malloc, args); + tmp = build_call_expr (gfor_fndecl_internal_malloc, 1, len); tmp = convert (type, tmp); gfc_add_modify_expr (&se->pre, var, tmp); /* Free the temporary afterwards. */ tmp = convert (pvoid_type_node, var); - args = gfc_chainon_list (NULL_TREE, tmp); - tmp = build_function_call_expr (gfor_fndecl_internal_free, args); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmp); gfc_add_expr_to_block (&se->post, tmp); } @@ -945,7 +939,6 @@ gfc_conv_concat_op (gfc_se * se, gfc_expr * expr) tree len; tree type; tree var; - tree args; tree tmp; gcc_assert (expr->value.op.op1->ts.type == BT_CHARACTER @@ -974,14 +967,10 @@ gfc_conv_concat_op (gfc_se * se, gfc_expr * expr) var = gfc_conv_string_tmp (se, type, len); /* Do the actual concatenation. */ - args = NULL_TREE; - args = gfc_chainon_list (args, len); - args = gfc_chainon_list (args, var); - args = gfc_chainon_list (args, lse.string_length); - args = gfc_chainon_list (args, lse.expr); - args = gfc_chainon_list (args, rse.string_length); - args = gfc_chainon_list (args, rse.expr); - tmp = build_function_call_expr (gfor_fndecl_concat_string, args); + tmp = build_call_expr (gfor_fndecl_concat_string, 6, + len, var, + lse.string_length, lse.expr, + rse.string_length, rse.expr); gfc_add_expr_to_block (&se->pre, tmp); /* Add the cleanup for the operands. */ @@ -1205,17 +1194,9 @@ gfc_build_compare_string (tree len1, tree str1, tree len2, tree str2) tmp = fold_build2 (MINUS_EXPR, type, sc1, sc2); } else - { - tmp = NULL_TREE; - tmp = gfc_chainon_list (tmp, len1); - tmp = gfc_chainon_list (tmp, str1); - tmp = gfc_chainon_list (tmp, len2); - tmp = gfc_chainon_list (tmp, str2); - - /* Build a call for the comparison. */ - tmp = build_function_call_expr (gfor_fndecl_compare_string, tmp); - } - + /* Build a call for the comparison. */ + tmp = build_call_expr (gfor_fndecl_compare_string, 4, + len1, str1, len2, str2); return tmp; } @@ -1281,7 +1262,7 @@ gfc_conv_operator_assign (gfc_se *lse, gfc_se *rse, gfc_symbol *sym) gfc_init_se (&se, NULL); gfc_conv_function_val (&se, sym); tmp = TREE_TYPE (TREE_TYPE (TREE_TYPE (se.expr))); - tmp = build3 (CALL_EXPR, tmp, se.expr, args, NULL_TREE); + tmp = build_call_list (tmp, se.expr, args); gfc_add_expr_to_block (&block, tmp); gfc_add_block_to_block (&block, &lse->post); @@ -2407,8 +2388,7 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, } fntype = TREE_TYPE (TREE_TYPE (se->expr)); - se->expr = build3 (CALL_EXPR, TREE_TYPE (fntype), se->expr, - arglist, NULL_TREE); + se->expr = build_call_list (TREE_TYPE (fntype), se->expr, arglist); /* If we have a pointer function, but we don't want a pointer, e.g. something like @@ -2542,26 +2522,21 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest, /* Truncate string if source is too long. */ cond2 = fold_build2 (GE_EXPR, boolean_type_node, slen, dlen); - tmp2 = gfc_chainon_list (NULL_TREE, dest); - tmp2 = gfc_chainon_list (tmp2, src); - tmp2 = gfc_chainon_list (tmp2, dlen); - tmp2 = build_function_call_expr (built_in_decls[BUILT_IN_MEMMOVE], tmp2); + tmp2 = build_call_expr (built_in_decls[BUILT_IN_MEMMOVE], + 3, dest, src, dlen); /* Else copy and pad with spaces. */ - tmp3 = gfc_chainon_list (NULL_TREE, dest); - tmp3 = gfc_chainon_list (tmp3, src); - tmp3 = gfc_chainon_list (tmp3, slen); - tmp3 = build_function_call_expr (built_in_decls[BUILT_IN_MEMMOVE], tmp3); + tmp3 = build_call_expr (built_in_decls[BUILT_IN_MEMMOVE], + 3, dest, src, slen); tmp4 = fold_build2 (PLUS_EXPR, pchar_type_node, dest, fold_convert (pchar_type_node, slen)); - tmp4 = gfc_chainon_list (NULL_TREE, tmp4); - tmp4 = gfc_chainon_list (tmp4, build_int_cst - (gfc_get_int_type (gfc_c_int_kind), - lang_hooks.to_target_charset (' '))); - tmp4 = gfc_chainon_list (tmp4, fold_build2 (MINUS_EXPR, TREE_TYPE(dlen), - dlen, slen)); - tmp4 = build_function_call_expr (built_in_decls[BUILT_IN_MEMSET], tmp4); + tmp4 = build_call_expr (built_in_decls[BUILT_IN_MEMSET], 3, + tmp4, + build_int_cst (gfc_get_int_type (gfc_c_int_kind), + lang_hooks.to_target_charset (' ')), + fold_build2 (MINUS_EXPR, TREE_TYPE(dlen), + dlen, slen)); gfc_init_block (&tempblock); gfc_add_expr_to_block (&tempblock, tmp3); @@ -3585,7 +3560,7 @@ static tree gfc_trans_zero_assign (gfc_expr * expr) { tree dest, len, type; - tree tmp, args; + tree tmp; gfc_symbol *sym; sym = expr->symtree->n.sym; @@ -3613,10 +3588,8 @@ gfc_trans_zero_assign (gfc_expr * expr) len = fold_convert (size_type_node, len); /* Construct call to __builtin_memset. */ - args = build_tree_list (NULL_TREE, len); - args = tree_cons (NULL_TREE, integer_zero_node, args); - args = tree_cons (NULL_TREE, dest, args); - tmp = build_function_call_expr (built_in_decls[BUILT_IN_MEMSET], args); + tmp = build_call_expr (built_in_decls[BUILT_IN_MEMSET], + 3, dest, integer_zero_node, len); return fold_convert (void_type_node, tmp); } @@ -3627,7 +3600,7 @@ gfc_trans_zero_assign (gfc_expr * expr) static tree gfc_build_memcpy_call (tree dst, tree src, tree len) { - tree tmp, args; + tree tmp; /* Convert arguments to the correct types. */ if (!POINTER_TYPE_P (TREE_TYPE (dst))) @@ -3643,10 +3616,7 @@ gfc_build_memcpy_call (tree dst, tree src, tree len) len = fold_convert (size_type_node, len); /* Construct call to __builtin_memcpy. */ - args = build_tree_list (NULL_TREE, len); - args = tree_cons (NULL_TREE, src, args); - args = tree_cons (NULL_TREE, dst, args); - tmp = build_function_call_expr (built_in_decls[BUILT_IN_MEMCPY], args); + tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3, dst, src, len); return fold_convert (void_type_node, tmp); } diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 1bce128d976..e6bc46f228d 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -164,6 +164,8 @@ real_compnt_info; enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR }; /* Evaluate the arguments to an intrinsic function. */ +/* FIXME: This function and its callers should be rewritten so that it's + not necessary to cons up a list to hold the arguments. */ static tree gfc_conv_intrinsic_function_args (gfc_se * se, gfc_expr * expr) @@ -1273,8 +1275,7 @@ gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr) /* Free the temporary afterwards, if necessary. */ cond = build2 (GT_EXPR, boolean_type_node, len, build_int_cst (TREE_TYPE (len), 0)); - arglist = gfc_chainon_list (NULL_TREE, var); - tmp = build_function_call_expr (gfor_fndecl_internal_free, arglist); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, var); tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ()); gfc_add_expr_to_block (&se->post, tmp); @@ -1309,8 +1310,7 @@ gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr) /* Free the temporary afterwards, if necessary. */ cond = build2 (GT_EXPR, boolean_type_node, len, build_int_cst (TREE_TYPE (len), 0)); - arglist = gfc_chainon_list (NULL_TREE, var); - tmp = build_function_call_expr (gfor_fndecl_internal_free, arglist); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, var); tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ()); gfc_add_expr_to_block (&se->post, tmp); @@ -1347,8 +1347,7 @@ gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr) /* Free the temporary afterwards, if necessary. */ cond = build2 (GT_EXPR, boolean_type_node, len, build_int_cst (TREE_TYPE (len), 0)); - arglist = gfc_chainon_list (NULL_TREE, var); - tmp = build_function_call_expr (gfor_fndecl_internal_free, arglist); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, var); tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ()); gfc_add_expr_to_block (&se->post, tmp); @@ -2809,7 +2808,6 @@ gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr) tree lower; tree stride; tree stmt; - tree args; gfc_actual_arglist *arg; gfc_se argse; gfc_ss *ss; @@ -2850,15 +2848,13 @@ gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr) && arg->expr->ref->u.ar.type == AR_FULL)) { tmp = build_fold_addr_expr (argse.expr); - tmp = gfc_chainon_list (NULL_TREE, tmp); - source = build_function_call_expr (gfor_fndecl_in_pack, tmp); + source = build_call_expr (gfor_fndecl_in_pack, 1, tmp); source = gfc_evaluate_now (source, &argse.pre); /* Free the temporary. */ gfc_start_block (&block); tmp = convert (pvoid_type_node, source); - tmp = gfc_chainon_list (NULL_TREE, tmp); - tmp = build_function_call_expr (gfor_fndecl_internal_free, tmp); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmp); gfc_add_expr_to_block (&block, tmp); stmt = gfc_finish_block (&block); @@ -2998,13 +2994,11 @@ gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr) info, tmp, false, true, false); /* Use memcpy to do the transfer. */ - tmp = gfc_conv_descriptor_data_get (info->descriptor); - args = gfc_chainon_list (NULL_TREE, tmp); - tmp = fold_convert (pvoid_type_node, source); - args = gfc_chainon_list (args, source); - args = gfc_chainon_list (args, size_bytes); - tmp = built_in_decls[BUILT_IN_MEMCPY]; - tmp = build_function_call_expr (tmp, args); + tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], + 3, + gfc_conv_descriptor_data_get (info->descriptor), + fold_convert (pvoid_type_node, source), + size_bytes); gfc_add_expr_to_block (&se->pre, tmp); se->expr = info->descriptor; @@ -3024,7 +3018,7 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) tree type; tree ptr; gfc_ss *ss; - tree tmpdecl, tmp, args; + tree tmpdecl, tmp; /* Get a pointer to the source. */ arg = expr->value.function.actual; @@ -3059,13 +3053,10 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) /* Use memcpy to do the transfer. */ tmp = build1 (ADDR_EXPR, build_pointer_type (type), tmpdecl); - tmp = fold_convert (pvoid_type_node, tmp); - args = gfc_chainon_list (NULL_TREE, tmp); - tmp = fold_convert (pvoid_type_node, ptr); - args = gfc_chainon_list (args, tmp); - args = gfc_chainon_list (args, moldsize); - tmp = built_in_decls[BUILT_IN_MEMCPY]; - tmp = build_function_call_expr (tmp, args); + tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3, + fold_convert (pvoid_type_node, tmp), + fold_convert (pvoid_type_node, ptr), + moldsize); gfc_add_expr_to_block (&se->pre, tmp); se->expr = tmpdecl; @@ -3112,7 +3103,7 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr) gfc_se arg2se; tree tmp2; tree tmp; - tree args, fndecl; + tree fndecl; tree nonzero_charlen; tree nonzero_arraylen; gfc_ss *ss1, *ss2; @@ -3185,18 +3176,15 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr) /* A pointer to an array, call library function _gfor_associated. */ gcc_assert (ss2 != gfc_ss_terminator); - args = NULL_TREE; arg1se.want_pointer = 1; gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1); - args = gfc_chainon_list (args, arg1se.expr); arg2se.want_pointer = 1; gfc_conv_expr_descriptor (&arg2se, arg2->expr, ss2); gfc_add_block_to_block (&se->pre, &arg2se.pre); gfc_add_block_to_block (&se->post, &arg2se.post); - args = gfc_chainon_list (args, arg2se.expr); fndecl = gfor_fndecl_associated; - se->expr = build_function_call_expr (fndecl, args); + se->expr = build_call_expr (fndecl, 2, arg1se.expr, arg2se.expr); se->expr = build2 (TRUTH_AND_EXPR, boolean_type_node, se->expr, nonzero_arraylen); @@ -3287,8 +3275,7 @@ gfc_conv_intrinsic_si_kind (gfc_se * se, gfc_expr * expr) args = gfc_conv_intrinsic_function_args (se, expr); args = TREE_VALUE (args); args = build_fold_addr_expr (args); - args = tree_cons (NULL_TREE, args, NULL_TREE); - se->expr = build_function_call_expr (gfor_fndecl_si_kind, args); + se->expr = build_call_expr (gfor_fndecl_si_kind, 1, args); } /* Generate code for SELECTED_REAL_KIND (P, R) intrinsic function. */ @@ -3351,8 +3338,7 @@ gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr) /* Free the temporary afterwards, if necessary. */ cond = build2 (GT_EXPR, boolean_type_node, len, build_int_cst (TREE_TYPE (len), 0)); - arglist = gfc_chainon_list (NULL_TREE, var); - tmp = build_function_call_expr (gfor_fndecl_internal_free, arglist); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, var); tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ()); gfc_add_expr_to_block (&se->post, tmp); @@ -3370,7 +3356,6 @@ gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr) tree tmp; tree len; tree args; - tree arglist; tree ncopies; tree var; tree type; @@ -3395,12 +3380,9 @@ gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr) var = gfc_conv_string_tmp (se, build_pointer_type (type), len); /* Create the argument list and generate the function call. */ - arglist = NULL_TREE; - arglist = gfc_chainon_list (arglist, var); - arglist = gfc_chainon_list (arglist, TREE_VALUE (args)); - arglist = gfc_chainon_list (arglist, TREE_VALUE (TREE_CHAIN (args))); - arglist = gfc_chainon_list (arglist, ncopies); - tmp = build_function_call_expr (gfor_fndecl_string_repeat, arglist); + tmp = build_call_expr (gfor_fndecl_string_repeat, 4, var, + TREE_VALUE (args), + TREE_VALUE (TREE_CHAIN (args)), ncopies); gfc_add_expr_to_block (&se->pre, tmp); se->expr = var; @@ -3419,7 +3401,7 @@ gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr) /* Call the library function. This always returns an INTEGER(4). */ fndecl = gfor_fndecl_iargc; - tmp = build_function_call_expr (fndecl, NULL_TREE); + tmp = build_call_expr (fndecl, 0); /* Convert it to the required type. */ type = gfc_typenode_for_spec (&expr->ts); diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c index 9865f44c331..951d4651869 100644 --- a/gcc/fortran/trans-io.c +++ b/gcc/fortran/trans-io.c @@ -835,8 +835,7 @@ gfc_trans_open (gfc_code * code) set_parameter_const (&block, var, IOPARM_common_flags, mask); tmp = build_fold_addr_expr (var); - tmp = gfc_chainon_list (NULL_TREE, tmp); - tmp = build_function_call_expr (iocall[IOCALL_OPEN], tmp); + tmp = build_call_expr (iocall[IOCALL_OPEN], 1, tmp); gfc_add_expr_to_block (&block, tmp); gfc_add_block_to_block (&block, &post_block); @@ -888,8 +887,7 @@ gfc_trans_close (gfc_code * code) set_parameter_const (&block, var, IOPARM_common_flags, mask); tmp = build_fold_addr_expr (var); - tmp = gfc_chainon_list (NULL_TREE, tmp); - tmp = build_function_call_expr (iocall[IOCALL_CLOSE], tmp); + tmp = build_call_expr (iocall[IOCALL_CLOSE], 1, tmp); gfc_add_expr_to_block (&block, tmp); gfc_add_block_to_block (&block, &post_block); @@ -939,8 +937,7 @@ build_filepos (tree function, gfc_code * code) set_parameter_const (&block, var, IOPARM_common_flags, mask); tmp = build_fold_addr_expr (var); - tmp = gfc_chainon_list (NULL_TREE, tmp); - tmp = build_function_call_expr (function, tmp); + tmp = build_call_expr (function, 1, tmp); gfc_add_expr_to_block (&block, tmp); gfc_add_block_to_block (&block, &post_block); @@ -1125,8 +1122,7 @@ gfc_trans_inquire (gfc_code * code) set_parameter_const (&block, var, IOPARM_common_flags, mask); tmp = build_fold_addr_expr (var); - tmp = gfc_chainon_list (NULL_TREE, tmp); - tmp = build_function_call_expr (iocall[IOCALL_INQUIRE], tmp); + tmp = build_call_expr (iocall[IOCALL_INQUIRE], 1, tmp); gfc_add_expr_to_block (&block, tmp); gfc_add_block_to_block (&block, &post_block); @@ -1248,8 +1244,6 @@ nml_get_addr_expr (gfc_symbol * sym, gfc_component * c, call to iocall[IOCALL_SET_NML_VAL]. For derived type variable, recursively generate calls to iocall[IOCALL_SET_NML_VAL] for each component. */ -#define NML_FIRST_ARG(a) args = gfc_chainon_list (NULL_TREE, a) -#define NML_ADD_ARG(a) args = gfc_chainon_list (args, a) #define IARG(i) build_int_cst (gfc_array_index_type, i) static void @@ -1263,7 +1257,6 @@ transfer_namelist_element (stmtblock_t * block, const char * var_name, tree dt = NULL; tree string; tree tmp; - tree args; tree dtype; tree dt_parm_addr; int n_dim; @@ -1329,18 +1322,14 @@ transfer_namelist_element (stmtblock_t * block, const char * var_name, (address, name, type, kind or string_length, dtype) */ dt_parm_addr = build_fold_addr_expr (dt_parm); - NML_FIRST_ARG (dt_parm_addr); - NML_ADD_ARG (addr_expr); - NML_ADD_ARG (string); - NML_ADD_ARG (IARG (ts->kind)); if (ts->type == BT_CHARACTER) - NML_ADD_ARG (ts->cl->backend_decl); + tmp = ts->cl->backend_decl; else - NML_ADD_ARG (build_int_cst (gfc_charlen_type_node, 0)); - - NML_ADD_ARG (dtype); - tmp = build_function_call_expr (iocall[IOCALL_SET_NML_VAL], args); + tmp = build_int_cst (gfc_charlen_type_node, 0); + tmp = build_call_expr (iocall[IOCALL_SET_NML_VAL], 6, + dt_parm_addr, addr_expr, string, + IARG (ts->kind), tmp, dtype); gfc_add_expr_to_block (block, tmp); /* If the object is an array, transfer rank times: @@ -1348,12 +1337,12 @@ transfer_namelist_element (stmtblock_t * block, const char * var_name, for ( n_dim = 0 ; n_dim < rank ; n_dim++ ) { - NML_FIRST_ARG (dt_parm_addr); - NML_ADD_ARG (IARG (n_dim)); - NML_ADD_ARG (GFC_TYPE_ARRAY_STRIDE (dt, n_dim)); - NML_ADD_ARG (GFC_TYPE_ARRAY_LBOUND (dt, n_dim)); - NML_ADD_ARG (GFC_TYPE_ARRAY_UBOUND (dt, n_dim)); - tmp = build_function_call_expr (iocall[IOCALL_SET_NML_VAL_DIM], args); + tmp = build_call_expr (iocall[IOCALL_SET_NML_VAL_DIM], 5, + dt_parm_addr, + IARG (n_dim), + GFC_TYPE_ARRAY_STRIDE (dt, n_dim), + GFC_TYPE_ARRAY_LBOUND (dt, n_dim), + GFC_TYPE_ARRAY_UBOUND (dt, n_dim)); gfc_add_expr_to_block (block, tmp); } @@ -1377,8 +1366,6 @@ transfer_namelist_element (stmtblock_t * block, const char * var_name, } #undef IARG -#undef NML_ADD_ARG -#undef NML_FIRST_ARG /* Create a data transfer statement. Not all of the fields are valid for both reading and writing, but improper use has been filtered @@ -1509,8 +1496,7 @@ build_dt (tree function, gfc_code * code) set_parameter_const (&block, var, IOPARM_common_flags, mask); tmp = build_fold_addr_expr (var); - tmp = gfc_chainon_list (NULL_TREE, tmp); - tmp = build_function_call_expr (function, tmp); + tmp = build_call_expr (function, 1, tmp); gfc_add_expr_to_block (&block, tmp); gfc_add_block_to_block (&block, &post_block); @@ -1590,8 +1576,7 @@ gfc_trans_dt_end (gfc_code * code) } tmp = build_fold_addr_expr (dt_parm); - tmp = gfc_chainon_list (NULL_TREE, tmp); - tmp = build_function_call_expr (function, tmp); + tmp = build_call_expr (function, 1, tmp); gfc_add_expr_to_block (&block, tmp); gfc_add_block_to_block (&block, dt_post_end_block); gfc_init_block (dt_post_end_block); @@ -1702,7 +1687,7 @@ transfer_array_component (tree expr, gfc_component * cm) static void transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr) { - tree args, tmp, function, arg2, field, expr; + tree tmp, function, arg2, field, expr; gfc_component *c; int kind; @@ -1777,11 +1762,7 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr) } tmp = build_fold_addr_expr (dt_parm); - args = gfc_chainon_list (NULL_TREE, tmp); - args = gfc_chainon_list (args, addr_expr); - args = gfc_chainon_list (args, arg2); - - tmp = build_function_call_expr (function, args); + tmp = build_call_expr (function, 3, tmp, addr_expr, arg2); gfc_add_expr_to_block (&se->pre, tmp); gfc_add_block_to_block (&se->pre, &se->post); @@ -1794,7 +1775,7 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr) static void transfer_array_desc (gfc_se * se, gfc_typespec * ts, tree addr_expr) { - tree args, tmp, charlen_arg, kind_arg; + tree tmp, charlen_arg, kind_arg; if (ts->type == BT_CHARACTER) charlen_arg = se->string_length; @@ -1804,11 +1785,8 @@ transfer_array_desc (gfc_se * se, gfc_typespec * ts, tree addr_expr) kind_arg = build_int_cst (NULL_TREE, ts->kind); tmp = build_fold_addr_expr (dt_parm); - args = gfc_chainon_list (NULL_TREE, tmp); - args = gfc_chainon_list (args, addr_expr); - args = gfc_chainon_list (args, kind_arg); - args = gfc_chainon_list (args, charlen_arg); - tmp = build_function_call_expr (iocall[IOCALL_X_ARRAY], args); + tmp = build_call_expr (iocall[IOCALL_X_ARRAY], 4, + tmp, addr_expr, kind_arg, charlen_arg); gfc_add_expr_to_block (&se->pre, tmp); gfc_add_block_to_block (&se->pre, &se->post); } diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index 82763161277..49368661591 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -875,7 +875,7 @@ static tree gfc_trans_omp_barrier (void) { tree decl = built_in_decls [BUILT_IN_GOMP_BARRIER]; - return build_function_call_expr (decl, NULL); + return build_call_expr (decl, 0); } static tree @@ -1054,7 +1054,7 @@ static tree gfc_trans_omp_flush (void) { tree decl = built_in_decls [BUILT_IN_SYNCHRONIZE]; - return build_function_call_expr (decl, NULL); + return build_call_expr (decl, 0); } static tree diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index 6b8a9a0b3be..cdc8dc6c669 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -295,9 +295,7 @@ gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse, gfc_add_modify_expr (&se->pre, info->offset, offset); /* Copy the result back using unpack. */ - tmp = gfc_chainon_list (NULL_TREE, parmse.expr); - tmp = gfc_chainon_list (tmp, data); - tmp = build_function_call_expr (gfor_fndecl_in_unpack, tmp); + tmp = build_call_expr (gfor_fndecl_in_unpack, 2, parmse.expr, data); gfc_add_expr_to_block (&se->post, tmp); gfc_add_block_to_block (&se->post, &parmse.post); @@ -470,9 +468,7 @@ gfc_trans_pause (gfc_code * code) { tree gfc_int4_type_node = gfc_get_int_type (4); gfc_se se; - tree args; tree tmp; - tree fndecl; /* Start a new block for this statement. */ gfc_init_se (&se, NULL); @@ -482,18 +478,15 @@ gfc_trans_pause (gfc_code * code) if (code->expr == NULL) { tmp = build_int_cst (gfc_int4_type_node, code->ext.stop_code); - args = gfc_chainon_list (NULL_TREE, tmp); - fndecl = gfor_fndecl_pause_numeric; + tmp = build_call_expr (gfor_fndecl_pause_numeric, 1, tmp); } else { gfc_conv_expr_reference (&se, code->expr); - args = gfc_chainon_list (NULL_TREE, se.expr); - args = gfc_chainon_list (args, se.string_length); - fndecl = gfor_fndecl_pause_string; + tmp = build_call_expr (gfor_fndecl_pause_string, 2, + se.expr, se.string_length); } - tmp = build_function_call_expr (fndecl, args); gfc_add_expr_to_block (&se.pre, tmp); gfc_add_block_to_block (&se.pre, &se.post); @@ -510,9 +503,7 @@ gfc_trans_stop (gfc_code * code) { tree gfc_int4_type_node = gfc_get_int_type (4); gfc_se se; - tree args; tree tmp; - tree fndecl; /* Start a new block for this statement. */ gfc_init_se (&se, NULL); @@ -522,18 +513,15 @@ gfc_trans_stop (gfc_code * code) if (code->expr == NULL) { tmp = build_int_cst (gfc_int4_type_node, code->ext.stop_code); - args = gfc_chainon_list (NULL_TREE, tmp); - fndecl = gfor_fndecl_stop_numeric; + tmp = build_call_expr (gfor_fndecl_stop_numeric, 1, tmp); } else { gfc_conv_expr_reference (&se, code->expr); - args = gfc_chainon_list (NULL_TREE, se.expr); - args = gfc_chainon_list (args, se.string_length); - fndecl = gfor_fndecl_stop_string; + tmp = build_call_expr (gfor_fndecl_stop_string, 2, + se.expr, se.string_length); } - tmp = build_function_call_expr (fndecl, args); gfc_add_expr_to_block (&se.pre, tmp); gfc_add_block_to_block (&se.pre, &se.post); @@ -1308,7 +1296,7 @@ gfc_trans_logical_select (gfc_code * code) static tree gfc_trans_character_select (gfc_code *code) { - tree init, node, end_label, tmp, type, args, *labels; + tree init, node, end_label, tmp, type, *labels; tree case_label; stmtblock_t block, body; gfc_case *cp, *d; @@ -1449,25 +1437,19 @@ gfc_trans_character_select (gfc_code *code) DECL_INITIAL (tmp) = init; init = tmp; - /* Build an argument list for the library call */ + /* Build the library call */ init = gfc_build_addr_expr (pvoid_type_node, init); - args = gfc_chainon_list (NULL_TREE, init); - - tmp = build_int_cst (NULL_TREE, n); - args = gfc_chainon_list (args, tmp); - tmp = gfc_build_addr_expr (pvoid_type_node, end_label); - args = gfc_chainon_list (args, tmp); gfc_init_se (&se, NULL); gfc_conv_expr_reference (&se, code->expr); - args = gfc_chainon_list (args, se.expr); - args = gfc_chainon_list (args, se.string_length); - gfc_add_block_to_block (&block, &se.pre); - tmp = build_function_call_expr (gfor_fndecl_select_string, args); + tmp = build_call_expr (gfor_fndecl_select_string, 5, + init, build_int_cst (NULL_TREE, n), + tmp, se.expr, se.string_length); + case_label = gfc_create_var (TREE_TYPE (tmp), "case_label"); gfc_add_modify_expr (&block, case_label, tmp); @@ -1687,7 +1669,6 @@ gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock, tree tmpvar; tree type; tree tmp; - tree args; if (INTEGER_CST_P (size)) { @@ -1710,14 +1691,13 @@ gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock, tmpvar = gfc_create_var (build_pointer_type (type), "temp"); *pdata = convert (pvoid_type_node, tmpvar); - args = gfc_chainon_list (NULL_TREE, bytesize); if (gfc_index_integer_kind == 4) tmp = gfor_fndecl_internal_malloc; else if (gfc_index_integer_kind == 8) tmp = gfor_fndecl_internal_malloc64; else gcc_unreachable (); - tmp = build_function_call_expr (tmp, args); + tmp = build_call_expr (tmp, 1, bytesize); tmp = convert (TREE_TYPE (tmpvar), tmp); gfc_add_modify_expr (pblock, tmpvar, tmp); } @@ -2229,8 +2209,7 @@ gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2, if (ptemp1) { /* Free the temporary. */ - tmp = gfc_chainon_list (NULL_TREE, ptemp1); - tmp = build_function_call_expr (gfor_fndecl_internal_free, tmp); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, ptemp1); gfc_add_expr_to_block (block, tmp); } } @@ -2388,8 +2367,7 @@ gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2, /* Free the temporary. */ if (ptemp1) { - tmp = gfc_chainon_list (NULL_TREE, ptemp1); - tmp = build_function_call_expr (gfor_fndecl_internal_free, tmp); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, ptemp1); gfc_add_expr_to_block (block, tmp); } } @@ -2724,8 +2702,7 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) if (pmask) { /* Free the temporary for the mask. */ - tmp = gfc_chainon_list (NULL_TREE, pmask); - tmp = build_function_call_expr (gfor_fndecl_internal_free, tmp); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, pmask); gfc_add_expr_to_block (&block, tmp); } if (maskindex) @@ -3322,16 +3299,14 @@ gfc_trans_where_2 (gfc_code * code, tree mask, bool invert, /* If we allocated a pending mask array, deallocate it now. */ if (ppmask) { - tree args = gfc_chainon_list (NULL_TREE, ppmask); - tmp = build_function_call_expr (gfor_fndecl_internal_free, args); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, ppmask); gfc_add_expr_to_block (block, tmp); } /* If we allocated a current mask array, deallocate it now. */ if (pcmask) { - tree args = gfc_chainon_list (NULL_TREE, pcmask); - tmp = build_function_call_expr (gfor_fndecl_internal_free, args); + tmp = build_call_expr (gfor_fndecl_internal_free, 1, pcmask); gfc_add_expr_to_block (block, tmp); } } @@ -3617,9 +3592,7 @@ gfc_trans_allocate (gfc_code * code) if (expr->ts.type == BT_CHARACTER && tmp == NULL_TREE) tmp = se.string_length; - parm = gfc_chainon_list (NULL_TREE, tmp); - parm = gfc_chainon_list (parm, pstat); - tmp = build_function_call_expr (gfor_fndecl_allocate, parm); + tmp = build_call_expr (gfor_fndecl_allocate, 2, tmp, pstat); tmp = build2 (MODIFY_EXPR, void_type_node, se.expr, tmp); gfc_add_expr_to_block (&se.pre, tmp); @@ -3685,7 +3658,7 @@ gfc_trans_deallocate (gfc_code * code) gfc_se se; gfc_alloc *al; gfc_expr *expr; - tree apstat, astat, parm, pstat, stat, tmp; + tree apstat, astat, pstat, stat, tmp; stmtblock_t block; gfc_start_block (&block); @@ -3748,9 +3721,7 @@ gfc_trans_deallocate (gfc_code * code) tmp = gfc_array_deallocate (se.expr, pstat); else { - parm = gfc_chainon_list (NULL_TREE, se.expr); - parm = gfc_chainon_list (parm, pstat); - tmp = build_function_call_expr (gfor_fndecl_deallocate, parm); + tmp = build_call_expr (gfor_fndecl_deallocate, 2, se.expr, pstat); gfc_add_expr_to_block (&se.pre, tmp); tmp = build2 (MODIFY_EXPR, void_type_node, diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index d942ebd6fc3..59b2dec335e 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -318,7 +318,7 @@ gfc_trans_runtime_check (tree cond, const char * msgid, stmtblock_t * pblock, stmtblock_t block; tree body; tree tmp; - tree args; + tree arg; char * message; int line; @@ -342,11 +342,10 @@ gfc_trans_runtime_check (tree cond, const char * msgid, stmtblock_t * pblock, asprintf (&message, "%s (in file '%s', around line %d)", _(msgid), gfc_source_file, input_line + 1); - tmp = gfc_build_addr_expr (pchar_type_node, gfc_build_cstring_const(message)); + arg = gfc_build_addr_expr (pchar_type_node, gfc_build_cstring_const(message)); gfc_free(message); - args = gfc_chainon_list (NULL_TREE, tmp); - tmp = build_function_call_expr (gfor_fndecl_runtime_error, args); + tmp = build_call_expr (gfor_fndecl_runtime_error, 1, arg); gfc_add_expr_to_block (&block, tmp); body = gfc_finish_block (&block); @@ -359,9 +358,8 @@ gfc_trans_runtime_check (tree cond, const char * msgid, stmtblock_t * pblock, { /* Tell the compiler that this isn't likely. */ cond = fold_convert (long_integer_type_node, cond); - tmp = gfc_chainon_list (NULL_TREE, cond); - tmp = gfc_chainon_list (tmp, build_int_cst (long_integer_type_node, 0)); - cond = build_function_call_expr (built_in_decls[BUILT_IN_EXPECT], tmp); + tmp = build_int_cst (long_integer_type_node, 0); + cond = build_call_expr (built_in_decls[BUILT_IN_EXPECT], 2, cond, tmp); cond = fold_convert (boolean_type_node, cond); tmp = build3_v (COND_EXPR, cond, body, build_empty_stmt ()); diff --git a/gcc/function.c b/gcc/function.c index b667a177560..57911bebdc2 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3203,16 +3203,15 @@ gimplify_parameters (void) } else { - tree ptr_type, addr, args; + tree ptr_type, addr; ptr_type = build_pointer_type (type); addr = create_tmp_var (ptr_type, get_name (parm)); DECL_IGNORED_P (addr) = 0; local = build_fold_indirect_ref (addr); - args = tree_cons (NULL, DECL_SIZE_UNIT (parm), NULL); t = built_in_decls[BUILT_IN_ALLOCA]; - t = build_function_call_expr (t, args); + t = build_call_expr (t, 1, DECL_SIZE_UNIT (parm)); t = fold_convert (ptr_type, t); t = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t); gimplify_and_add (t, &stmts); diff --git a/gcc/gengtype.c b/gcc/gengtype.c index 515c31c4695..09d8ada4719 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -719,7 +719,7 @@ adjust_field_tree_exp (type_p t, options_p opt ATTRIBUTE_UNUSED) flds = create_field (NULL, t, ""); flds->opt = create_option (nodot, "length", - "TREE_CODE_LENGTH (TREE_CODE ((tree) &%0))"); + "TREE_OPERAND_LENGTH ((tree) &%0)"); flds->opt = create_option (flds->opt, "default", ""); return new_structure ("tree_exp_subunion", 1, &lexer_line, flds, nodot); @@ -1746,16 +1746,27 @@ walk_type (type_p t, struct walk_type_data *d) if (t->u.a.p->kind == TYPE_SCALAR) break; + /* When walking an array, compute the length and store it in a + local variable before walking the array elements, instead of + recomputing the length expression each time through the loop. + This is necessary to handle tcc_vl_exp objects like CALL_EXPR, + where the length is stored in the first array element, + because otherwise that operand can get overwritten on the + first iteration. */ oprintf (d->of, "%*s{\n", d->indent, ""); d->indent += 2; oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter); - oprintf (d->of, "%*sfor (i%d = 0; i%d != (size_t)(", d->indent, "", - loopcounter, loopcounter); + oprintf (d->of, "%*ssize_t l%d = (size_t)(", + d->indent, "", loopcounter); if (length) output_escaped_param (d, length, "length"); else oprintf (d->of, "%s", t->u.a.len); - oprintf (d->of, "); i%d++) {\n", loopcounter); + oprintf (d->of, ");\n"); + + oprintf (d->of, "%*sfor (i%d = 0; i%d != l%d; i%d++) {\n", + d->indent, "", + loopcounter, loopcounter, loopcounter, loopcounter); d->indent += 2; d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter); d->used_length = 1; diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index 9c68447206c..ac5266a3334 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -134,10 +134,9 @@ lower_function_body (void) /* Build 'DISP_VAR = __builtin_setjmp_dispatcher (DISP_LABEL);' and insert. */ disp_var = create_tmp_var (ptr_type_node, "setjmpvar"); - t = build_addr (disp_label, current_function_decl); - arg = tree_cons (NULL, t, NULL); + arg = build_addr (disp_label, current_function_decl); t = implicit_built_in_decls[BUILT_IN_SETJMP_DISPATCHER]; - t = build_function_call_expr (t,arg); + t = build_call_expr (t, 1, arg); x = build2 (GIMPLE_MODIFY_STMT, void_type_node, disp_var, t); /* Build 'goto DISP_VAR;' and insert. */ @@ -663,12 +662,9 @@ lower_builtin_setjmp (tree_stmt_iterator *tsi) dest = NULL_TREE; /* Build '__builtin_setjmp_setup (BUF, NEXT_LABEL)' and insert. */ - t = build_addr (next_label, current_function_decl); - arg = tree_cons (NULL, t, NULL); - t = TREE_VALUE (GENERIC_TREE_OPERAND (stmt, 1)); - arg = tree_cons (NULL, t, arg); + arg = build_addr (next_label, current_function_decl); t = implicit_built_in_decls[BUILT_IN_SETJMP_SETUP]; - t = build_function_call_expr (t, arg); + t = build_call_expr (t, 2, CALL_EXPR_ARG (stmt, 0), arg); SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt)); tsi_link_before (tsi, t, TSI_SAME_STMT); @@ -689,10 +685,9 @@ lower_builtin_setjmp (tree_stmt_iterator *tsi) tsi_link_before (tsi, t, TSI_SAME_STMT); /* Build '__builtin_setjmp_receiver (NEXT_LABEL)' and insert. */ - t = build_addr (next_label, current_function_decl); - arg = tree_cons (NULL, t, NULL); + arg = build_addr (next_label, current_function_decl); t = implicit_built_in_decls[BUILT_IN_SETJMP_RECEIVER]; - t = build_function_call_expr (t, arg); + t = build_call_expr (t, 1, arg); SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt)); tsi_link_before (tsi, t, TSI_SAME_STMT); diff --git a/gcc/gimplify.c b/gcc/gimplify.c index d615aa3bbad..2d02617ccb4 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1040,14 +1040,13 @@ build_stack_save_restore (tree *save, tree *restore) tree save_call, tmp_var; save_call = - build_function_call_expr (implicit_built_in_decls[BUILT_IN_STACK_SAVE], - NULL_TREE); + build_call_expr (implicit_built_in_decls[BUILT_IN_STACK_SAVE], 0); tmp_var = create_tmp_var (ptr_type_node, "saved_stack"); *save = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, tmp_var, save_call); *restore = - build_function_call_expr (implicit_built_in_decls[BUILT_IN_STACK_RESTORE], - tree_cons (NULL_TREE, tmp_var, NULL_TREE)); + build_call_expr (implicit_built_in_decls[BUILT_IN_STACK_RESTORE], + 1, tmp_var); } /* Gimplify a BIND_EXPR. Just voidify and recurse. */ @@ -1233,7 +1232,7 @@ gimplify_decl_expr (tree *stmt_p) /* This is a variable-sized decl. Simplify its size and mark it for deferred expansion. Note that mudflap depends on the format of the emitted code: see mx_register_decls(). */ - tree t, args, addr, ptr_type; + tree t, addr, ptr_type; gimplify_one_sizepos (&DECL_SIZE (decl), stmt_p); gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p); @@ -1250,9 +1249,8 @@ gimplify_decl_expr (tree *stmt_p) SET_DECL_VALUE_EXPR (decl, t); DECL_HAS_VALUE_EXPR_P (decl) = 1; - args = tree_cons (NULL, DECL_SIZE_UNIT (decl), NULL); t = built_in_decls[BUILT_IN_ALLOCA]; - t = build_function_call_expr (t, args); + t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl)); t = fold_convert (ptr_type, t); t = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t); @@ -2031,8 +2029,8 @@ static enum gimplify_status gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value) { tree decl; - tree arglist; enum gimplify_status ret; + int i, nargs; gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR); @@ -2056,8 +2054,7 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value) decl = get_callee_fndecl (*expr_p); if (decl && DECL_BUILT_IN (decl)) { - tree arglist = TREE_OPERAND (*expr_p, 1); - tree new = fold_builtin (decl, arglist, !want_value); + tree new = fold_call_expr (*expr_p, !want_value); if (new && new != *expr_p) { @@ -2071,62 +2068,56 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value) if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL && DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_START) { - if (!arglist || !TREE_CHAIN (arglist)) + if (call_expr_nargs (*expr_p) < 2) { error ("too few arguments to function %<va_start%>"); *expr_p = build_empty_stmt (); return GS_OK; } - if (fold_builtin_next_arg (TREE_CHAIN (arglist))) + if (fold_builtin_next_arg (*expr_p, true)) { *expr_p = build_empty_stmt (); return GS_OK; } /* Avoid gimplifying the second argument to va_start, which needs to be the plain PARM_DECL. */ - return gimplify_arg (&TREE_VALUE (TREE_OPERAND (*expr_p, 1)), pre_p); + return gimplify_arg (&CALL_EXPR_ARG (*expr_p, 0), pre_p); } } /* There is a sequence point before the call, so any side effects in the calling expression must occur before the actual call. Force gimplify_expr to use an internal post queue. */ - ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, NULL, + ret = gimplify_expr (&CALL_EXPR_FN (*expr_p), pre_p, NULL, is_gimple_call_addr, fb_rvalue); - if (PUSH_ARGS_REVERSED) - TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1)); - for (arglist = TREE_OPERAND (*expr_p, 1); arglist; - arglist = TREE_CHAIN (arglist)) + nargs = call_expr_nargs (*expr_p); + + for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0); + PUSH_ARGS_REVERSED ? i >= 0 : i < nargs; + PUSH_ARGS_REVERSED ? i-- : i++) { enum gimplify_status t; - t = gimplify_arg (&TREE_VALUE (arglist), pre_p); + t = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p); if (t == GS_ERROR) ret = GS_ERROR; } - if (PUSH_ARGS_REVERSED) - TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1)); /* Try this again in case gimplification exposed something. */ if (ret != GS_ERROR) { - decl = get_callee_fndecl (*expr_p); - if (decl && DECL_BUILT_IN (decl)) - { - tree arglist = TREE_OPERAND (*expr_p, 1); - tree new = fold_builtin (decl, arglist, !want_value); + tree new = fold_call_expr (*expr_p, !want_value); - if (new && new != *expr_p) - { - /* There was a transformation of this call which computes the - same value, but in a more efficient way. Return and try - again. */ - *expr_p = new; - return GS_OK; - } + if (new && new != *expr_p) + { + /* There was a transformation of this call which computes the + same value, but in a more efficient way. Return and try + again. */ + *expr_p = new; + return GS_OK; } } @@ -2561,20 +2552,16 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, fallback_t fallback) static enum gimplify_status gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value) { - tree args, t, to, to_ptr, from; + tree t, to, to_ptr, from, from_ptr; to = GENERIC_TREE_OPERAND (*expr_p, 0); from = GENERIC_TREE_OPERAND (*expr_p, 1); - args = tree_cons (NULL, size, NULL); - - t = build_fold_addr_expr (from); - args = tree_cons (NULL, t, args); + from_ptr = build_fold_addr_expr (from); to_ptr = build_fold_addr_expr (to); - args = tree_cons (NULL, to_ptr, args); t = implicit_built_in_decls[BUILT_IN_MEMCPY]; - t = build_function_call_expr (t, args); + t = build_call_expr (t, 3, to_ptr, from_ptr, size); if (want_value) { @@ -2593,18 +2580,13 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value) static enum gimplify_status gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value) { - tree args, t, to, to_ptr; + tree t, to, to_ptr; to = GENERIC_TREE_OPERAND (*expr_p, 0); - args = tree_cons (NULL, size, NULL); - - args = tree_cons (NULL, integer_zero_node, args); - to_ptr = build_fold_addr_expr (to); - args = tree_cons (NULL, to_ptr, args); t = implicit_built_in_decls[BUILT_IN_MEMSET]; - t = build_function_call_expr (t, args); + t = build_call_expr (t, 3, to_ptr, integer_zero_node, size); if (want_value) { @@ -3687,18 +3669,15 @@ gimplify_variable_sized_compare (tree *expr_p) { tree op0 = TREE_OPERAND (*expr_p, 0); tree op1 = TREE_OPERAND (*expr_p, 1); - tree args, t, dest; - - t = TYPE_SIZE_UNIT (TREE_TYPE (op0)); - t = unshare_expr (t); - t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, op0); - args = tree_cons (NULL, t, NULL); - t = build_fold_addr_expr (op1); - args = tree_cons (NULL, t, args); + tree t, arg, dest, src; + + arg = TYPE_SIZE_UNIT (TREE_TYPE (op0)); + arg = unshare_expr (arg); + arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0); + src = build_fold_addr_expr (op1); dest = build_fold_addr_expr (op0); - args = tree_cons (NULL, dest, args); t = implicit_built_in_decls[BUILT_IN_MEMCMP]; - t = build_function_call_expr (t, args); + t = build_call_expr (t, 3, dest, src, arg); *expr_p = build2 (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node); @@ -5122,7 +5101,7 @@ static enum gimplify_status gimplify_omp_atomic_fetch_op (tree *expr_p, tree addr, tree rhs, int index) { enum built_in_function base; - tree decl, args, itype; + tree decl, itype; enum insn_code *optab; /* Check for one of the supported fetch-op operations. */ @@ -5167,9 +5146,7 @@ gimplify_omp_atomic_fetch_op (tree *expr_p, tree addr, tree rhs, int index) if (optab[TYPE_MODE (itype)] == CODE_FOR_nothing) return GS_UNHANDLED; - args = tree_cons (NULL, fold_convert (itype, rhs), NULL); - args = tree_cons (NULL, addr, args); - *expr_p = build_function_call_expr (decl, args); + *expr_p = build_call_expr (decl, 2, addr, fold_convert (itype, rhs)); return GS_OK; } @@ -5234,7 +5211,7 @@ gimplify_omp_atomic_pipeline (tree *expr_p, tree *pre_p, tree addr, tree rhs, int index) { tree oldval, oldival, oldival2, newval, newival, label; - tree type, itype, cmpxchg, args, x, iaddr; + tree type, itype, cmpxchg, x, iaddr; cmpxchg = built_in_decls[BUILT_IN_VAL_COMPARE_AND_SWAP_N + index + 1]; type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr))); @@ -5295,10 +5272,8 @@ gimplify_omp_atomic_pipeline (tree *expr_p, tree *pre_p, tree addr, fold_convert (itype, oldival)); gimplify_and_add (x, pre_p); - args = tree_cons (NULL, fold_convert (itype, newival), NULL); - args = tree_cons (NULL, fold_convert (itype, oldival), args); - args = tree_cons (NULL, iaddr, args); - x = build_function_call_expr (cmpxchg, args); + x = build_call_expr (cmpxchg, 3, iaddr, fold_convert (itype, oldival), + fold_convert (itype, newival)); if (oldval == oldival) x = fold_convert (type, x); x = build2 (GIMPLE_MODIFY_STMT, void_type_node, oldival, x); @@ -5342,7 +5317,7 @@ gimplify_omp_atomic_mutex (tree *expr_p, tree *pre_p, tree addr, tree rhs) tree t; t = built_in_decls[BUILT_IN_GOMP_ATOMIC_START]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (t, 0); gimplify_and_add (t, pre_p); t = build_fold_indirect_ref (addr); @@ -5350,7 +5325,7 @@ gimplify_omp_atomic_mutex (tree *expr_p, tree *pre_p, tree addr, tree rhs) gimplify_and_add (t, pre_p); t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (t, 0); gimplify_and_add (t, pre_p); *expr_p = NULL; @@ -6458,13 +6433,13 @@ gimplify_function_tree (tree fndecl) x = DECL_SAVED_TREE (fndecl); append_to_statement_list (x, &TREE_OPERAND (tf, 0)); x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT]; - x = build_function_call_expr (x, NULL); + x = build_call_expr (x, 0); append_to_statement_list (x, &TREE_OPERAND (tf, 1)); bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); TREE_SIDE_EFFECTS (bind) = 1; x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER]; - x = build_function_call_expr (x, NULL); + x = build_call_expr (x, 0); append_to_statement_list (x, &BIND_EXPR_BODY (bind)); append_to_statement_list (tf, &BIND_EXPR_BODY (bind)); diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index f2e97732320..6d3d9e89dc6 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -925,8 +925,8 @@ ipcp_update_callgraph (void) if (ipcp_redirect (cs)) { cgraph_redirect_edge_callee (cs, orig_callee); - TREE_OPERAND (TREE_OPERAND - (get_call_expr_in (cs->call_stmt), 0), 0) = + TREE_OPERAND (CALL_EXPR_FN (get_call_expr_in (cs->call_stmt)), + 0) = orig_callee->decl; } } diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 55ff37c2691..c5643142b70 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -419,15 +419,11 @@ void ipa_callsite_compute_count (struct cgraph_edge *cs) { tree call_tree; - tree arg; int arg_num; call_tree = get_call_expr_in (ipa_callsite_tree (cs)); gcc_assert (TREE_CODE (call_tree) == CALL_EXPR); - arg = TREE_OPERAND (call_tree, 1); - arg_num = 0; - for (; arg != NULL_TREE; arg = TREE_CHAIN (arg)) - arg_num++; + arg_num = call_expr_nargs (call_tree); ipa_callsite_param_count_set (cs, arg_num); } @@ -445,38 +441,35 @@ ipa_callsite_compute_param (struct cgraph_edge *cs) struct cgraph_node *mt; tree parm_decl; struct function *curr_cfun; + call_expr_arg_iterator iter; if (ipa_callsite_param_count (cs) == 0) return; ipa_callsite_param_map_create (cs); call_tree = get_call_expr_in (ipa_callsite_tree (cs)); gcc_assert (TREE_CODE (call_tree) == CALL_EXPR); - arg = TREE_OPERAND (call_tree, 1); arg_num = 0; - for (; arg != NULL_TREE; arg = TREE_CHAIN (arg)) + FOR_EACH_CALL_EXPR_ARG (arg, iter, call_tree) { /* If the formal parameter was passed as argument, we store FORMAL_IPATYPE and its index in the caller as the jump function of this argument. */ - if ((TREE_CODE (TREE_VALUE (arg)) == SSA_NAME - && TREE_CODE (SSA_NAME_VAR (TREE_VALUE (arg))) == PARM_DECL) - || TREE_CODE (TREE_VALUE (arg)) == PARM_DECL) + if ((TREE_CODE (arg) == SSA_NAME + && TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL) + || TREE_CODE (arg) == PARM_DECL) { mt = ipa_callsite_caller (cs); - parm_decl = - TREE_CODE (TREE_VALUE (arg)) == - PARM_DECL ? TREE_VALUE (arg) : SSA_NAME_VAR (TREE_VALUE (arg)); + parm_decl = TREE_CODE (arg) == PARM_DECL ? arg : SSA_NAME_VAR (arg); i = ipa_method_tree_map (mt, parm_decl); - if (TREE_CODE (TREE_VALUE (arg)) == SSA_NAME - && IS_VALID_TREE_MAP_INDEX (i)) + if (TREE_CODE (arg) == SSA_NAME && IS_VALID_TREE_MAP_INDEX (i)) { - curr_cfun = DECL_STRUCT_FUNCTION (mt->decl); + curr_cfun = DECL_STRUCT_FUNCTION (mt->decl); if (!gimple_default_def (curr_cfun, parm_decl) - || gimple_default_def (curr_cfun, parm_decl) != TREE_VALUE (arg)) + || gimple_default_def (curr_cfun, parm_decl) != arg) ipa_method_modify_set (mt, i, true); - } + } if (!IS_VALID_TREE_MAP_INDEX (i) || ipa_method_is_modified (mt, i)) ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE); else @@ -488,22 +481,20 @@ ipa_callsite_compute_param (struct cgraph_edge *cs) /* If a constant value was passed as argument, we store CONST_IPATYPE and its value as the jump function of this argument. */ - else if (TREE_CODE (TREE_VALUE (arg)) == INTEGER_CST - || TREE_CODE (TREE_VALUE (arg)) == REAL_CST) + else if (TREE_CODE (arg) == INTEGER_CST + || TREE_CODE (arg) == REAL_CST) { ipa_callsite_param_set_type (cs, arg_num, CONST_IPATYPE); - ipa_callsite_param_set_info_type (cs, arg_num, - TREE_VALUE (arg)); + ipa_callsite_param_set_info_type (cs, arg_num, arg); } /* This is for the case of Fortran. If the address of a const_decl was passed as argument then we store CONST_IPATYPE_REF/CONST_IPATYPE_REF and the constant value as the jump function corresponding to this argument. */ - else if (TREE_CODE (TREE_VALUE (arg)) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (TREE_VALUE (arg), 0)) == - CONST_DECL) + else if (TREE_CODE (arg) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (arg, 0)) == CONST_DECL) { - cst_decl = TREE_OPERAND (TREE_VALUE (arg), 0); + cst_decl = TREE_OPERAND (arg, 0); if (TREE_CODE (DECL_INITIAL (cst_decl)) == INTEGER_CST || TREE_CODE (DECL_INITIAL (cst_decl)) == REAL_CST) { diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index 5f19af8c61e..1be8ef1a1c3 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -316,20 +316,15 @@ get_asm_expr_operands (funct_state local, tree stmt) static void check_call (funct_state local, tree call_expr) { - int flags = call_expr_flags(call_expr); - tree operand_list = TREE_OPERAND (call_expr, 1); + int flags = call_expr_flags (call_expr); tree operand; + call_expr_arg_iterator iter; tree callee_t = get_callee_fndecl (call_expr); struct cgraph_node* callee; enum availability avail = AVAIL_NOT_AVAILABLE; - for (operand = operand_list; - operand != NULL_TREE; - operand = TREE_CHAIN (operand)) - { - tree argument = TREE_VALUE (operand); - check_rhs_var (local, argument); - } + FOR_EACH_CALL_EXPR_ARG (operand, iter, call_expr) + check_rhs_var (local, operand); /* The const and pure flags are set by a variety of places in the compiler (including here). If someone has already set the flags @@ -452,7 +447,14 @@ scan_function (tree *tp, case ADDR_EXPR: check_rhs_var (local, rhs); break; - case CALL_EXPR: + default: + break; + } + break; + case tcc_vl_exp: + switch (TREE_CODE (rhs)) + { + case CALL_EXPR: check_call (local, rhs); break; default: diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c index b1ff849082e..af6dac7c9db 100644 --- a/gcc/ipa-reference.c +++ b/gcc/ipa-reference.c @@ -436,18 +436,13 @@ static void check_call (ipa_reference_local_vars_info_t local, tree call_expr) { int flags = call_expr_flags (call_expr); - tree operand_list = TREE_OPERAND (call_expr, 1); tree operand; tree callee_t = get_callee_fndecl (call_expr); enum availability avail = AVAIL_NOT_AVAILABLE; + call_expr_arg_iterator iter; - for (operand = operand_list; - operand != NULL_TREE; - operand = TREE_CHAIN (operand)) - { - tree argument = TREE_VALUE (operand); - check_rhs_var (local, argument); - } + FOR_EACH_CALL_EXPR_ARG (operand, iter, call_expr) + check_rhs_var (local, operand); if (callee_t) { @@ -534,7 +529,14 @@ scan_for_static_refs (tree *tp, case ADDR_EXPR: check_rhs_var (local, rhs); break; - case CALL_EXPR: + default: + break; + } + break; + case tcc_vl_exp: + switch (TREE_CODE (rhs)) + { + case CALL_EXPR: check_call (local, rhs); break; default: diff --git a/gcc/ipa-type-escape.c b/gcc/ipa-type-escape.c index ccb60109ee0..8c7253e6f01 100644 --- a/gcc/ipa-type-escape.c +++ b/gcc/ipa-type-escape.c @@ -1011,20 +1011,14 @@ static bool check_call (tree call_expr) { int flags = call_expr_flags(call_expr); - tree operand_list = TREE_OPERAND (call_expr, 1); tree operand; tree callee_t = get_callee_fndecl (call_expr); - tree argument; struct cgraph_node* callee; enum availability avail = AVAIL_NOT_AVAILABLE; + call_expr_arg_iterator iter; - for (operand = operand_list; - operand != NULL_TREE; - operand = TREE_CHAIN (operand)) - { - tree argument = TREE_VALUE (operand); - check_rhs_var (argument); - } + FOR_EACH_CALL_EXPR_ARG (operand, iter, call_expr) + check_rhs_var (operand); if (callee_t) { @@ -1037,17 +1031,16 @@ check_call (tree call_expr) parameters. */ if (TYPE_ARG_TYPES (TREE_TYPE (callee_t))) { - operand = operand_list; - for (arg_type = TYPE_ARG_TYPES (TREE_TYPE (callee_t)); + for (arg_type = TYPE_ARG_TYPES (TREE_TYPE (callee_t)), + operand = first_call_expr_arg (call_expr, &iter); arg_type && TREE_VALUE (arg_type) != void_type_node; - arg_type = TREE_CHAIN (arg_type)) + arg_type = TREE_CHAIN (arg_type), + operand = next_call_expr_arg (&iter)) { if (operand) { - argument = TREE_VALUE (operand); last_arg_type = TREE_VALUE(arg_type); - check_cast (last_arg_type, argument); - operand = TREE_CHAIN (operand); + check_cast (last_arg_type, operand); } else /* The code reaches here for some unfortunate @@ -1061,17 +1054,16 @@ check_call (tree call_expr) /* FIXME - According to Geoff Keating, we should never have to do this; the front ends should always process the arg list from the TYPE_ARG_LIST. */ - operand = operand_list; - for (arg_type = DECL_ARGUMENTS (callee_t); + for (arg_type = DECL_ARGUMENTS (callee_t), + operand = first_call_expr_arg (call_expr, &iter); arg_type; - arg_type = TREE_CHAIN (arg_type)) + arg_type = TREE_CHAIN (arg_type), + operand = next_call_expr_arg (&iter)) { if (operand) { - argument = TREE_VALUE (operand); last_arg_type = TREE_TYPE(arg_type); - check_cast (last_arg_type, argument); - operand = TREE_CHAIN (operand); + check_cast (last_arg_type, operand); } else /* The code reaches here for some unfortunate @@ -1086,11 +1078,10 @@ check_call (tree call_expr) arg_type = last_arg_type; for (; operand != NULL_TREE; - operand = TREE_CHAIN (operand)) + operand = next_call_expr_arg (&iter)) { - argument = TREE_VALUE (operand); if (arg_type) - check_cast (arg_type, argument); + check_cast (arg_type, operand); else { /* The code reaches here for some unfortunate @@ -1098,7 +1089,7 @@ check_call (tree call_expr) argument types. Most of these functions have been marked as having their parameters not escape, but for the rest, the type is doomed. */ - tree type = get_canon_type (TREE_TYPE (argument), false, false); + tree type = get_canon_type (TREE_TYPE (operand), false, false); mark_interesting_type (type, FULL_ESCAPE); } } @@ -1114,12 +1105,9 @@ check_call (tree call_expr) { /* If this is a direct call to an external function, mark all of the parameter and return types. */ - for (operand = operand_list; - operand != NULL_TREE; - operand = TREE_CHAIN (operand)) + FOR_EACH_CALL_EXPR_ARG (operand, iter, call_expr) { - tree type = - get_canon_type (TREE_TYPE (TREE_VALUE (operand)), false, false); + tree type = get_canon_type (TREE_TYPE (operand), false, false); mark_interesting_type (type, EXPOSED_PARAMETER); } @@ -1257,7 +1245,14 @@ scan_for_refs (tree *tp, int *walk_subtrees, void *data) look_for_casts (lhs, TREE_OPERAND (rhs, 0)); check_rhs_var (rhs); break; - case CALL_EXPR: + default: + break; + } + break; + case tcc_vl_exp: + switch (TREE_CODE (rhs)) + { + case CALL_EXPR: /* If this is a call to malloc, squirrel away the result so we do mark the resulting cast as being bad. */ diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index f9ef73fb28e..39fe758bf48 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,70 @@ +2007-02-15 Sandra Loosemore <sandra@codesourcery.com> + Brooks Moses <brooks.moses@codesourcery.com> + Lee Millward <lee.millward@codesourcery.com> + + * java-tree.h (BUILD_MONITOR_ENTER): Use build_call_nary instead + of build3. + (BUILD_MONITOR_EXIT): Likewise. + + * java-gimplify.c (java_gimplify_component_ref): Use build_call_expr. + (java_gimplify_modify_expr): Likewise. + + * class.c (cache_this_class_ref): Use build_call_expr. + (build_static_field_ref): Likewise. + (emit_indirect_register_classes): Likewise. + (emit_register_classes): Likewise. + + * resource.c (write_resource_constructor): Use build_call_expr. + + * builtins.c (builtin_creator_function): Change interpretation of + the second parameter to be the whole CALL_EXPR instead of the arglist. + (max_builtin): Tweak parameter list. Use new CALL_EXPR accessors. + (min_builtin): Likewise. + (abs_builtin): Likewise. + (java_build_function_call_expr): Likewise. + (convert_real): Likewise. + (UNMARSHAL3): Likewise. + (UNMARSHAL4): Likewise. + (UNMARSHAL5): Likewise. + (build_arglist_for_builtin): Delete. Fix callers to use + build_call_expr instead. + (putObject_builtin): Tweak parameter list. Use new CALL_EXPR + accessors. + (compareAndSwapInt_builtin): Likewise. + (compareAndSwapLong_builtin): Likewise. + (compareAndSwapObject_builtin): Likewise. + (putVolatile_builtin): Likewise. + (getVolatile_builtin): Likewise. + (VMSupportsCS8_builtin): Likewise. + (check_for_builtin): Pass entire CALL_EXPR to builtin expander + instead of arglist. + + * expr.c (build_java_athrow): Use build_call_nary instead of build3. + (build_java_throw_out_of_bounds_exception): Likewise. + (java_check_reference): Likewise. + (build_java_arraystore_check): Likewise. + (build_newarray): Likewise. + (build_anewarray): Likewise. + (expand_java_multinewarray): Use build_call_list instead of build3. + (build_java_monitor): Use build_call_nary instead of build3. + (java_create_object): Likewise. + (expand_java_NEW): Likewise. + (build_instanceof): Likewise. + (expand_java_CHECKCAST): Likewise. + (build_java_soft_divmod): Likewise. + (build_java_binop): Likewise. + (build_field_ref): Likewise. + (build_class_init): Likewise. + (rewrite_arglist_getcaller): Use build_call_expr. + (build_invokeinterface): Use build_call_nary instead of build3. + (expand_invoke): Use build_call_list instead of build3. + (build_jni_stub): Use build_call_nary, build_call_list, or + build_call_expr instead of build3. + (expand_java_field_op): Use build_call_expr instead of build3. + (force_evaluation_order): Use new CALL_EXPR accessors. + + * lang.c (java_get_callee_fndecl): Use new CALL_EXPR accessors. + 2007-02-15 David Daney <ddaney@avtrex.com> * Make-lang.in (JAVA_MANFILES): Add doc/gc-analyze.1. diff --git a/gcc/java/builtins.c b/gcc/java/builtins.c index ef8854ae2e6..cfbab665192 100644 --- a/gcc/java/builtins.c +++ b/gcc/java/builtins.c @@ -60,7 +60,8 @@ static tree VMSupportsCS8_builtin (tree, tree); /* Functions of this type are used to inline a given call. Such a function should either return an expression, if the call is to be inlined, or NULL_TREE if a real call should be emitted. Arguments - are method return type and arguments to call. */ + are method return type and the original CALL_EXPR containing the + arguments to the call. */ typedef tree builtin_creator_function (tree, tree); /* Hold a char*, before initialization, or a tree, after @@ -130,50 +131,73 @@ static GTY(()) struct builtin_record java_builtins[] = /* Internal functions which implement various builtin conversions. */ static tree -max_builtin (tree method_return_type, tree method_arguments) +max_builtin (tree method_return_type, tree orig_call) { /* MAX_EXPR does not handle -0.0 in the Java style. */ if (TREE_CODE (method_return_type) == REAL_TYPE) return NULL_TREE; return fold_build2 (MAX_EXPR, method_return_type, - TREE_VALUE (method_arguments), - TREE_VALUE (TREE_CHAIN (method_arguments))); + CALL_EXPR_ARG (orig_call, 0), + CALL_EXPR_ARG (orig_call, 1)); } static tree -min_builtin (tree method_return_type, tree method_arguments) +min_builtin (tree method_return_type, tree orig_call) { /* MIN_EXPR does not handle -0.0 in the Java style. */ if (TREE_CODE (method_return_type) == REAL_TYPE) return NULL_TREE; return fold_build2 (MIN_EXPR, method_return_type, - TREE_VALUE (method_arguments), - TREE_VALUE (TREE_CHAIN (method_arguments))); + CALL_EXPR_ARG (orig_call, 0), + CALL_EXPR_ARG (orig_call, 1)); } static tree -abs_builtin (tree method_return_type, tree method_arguments) +abs_builtin (tree method_return_type, tree orig_call) { return fold_build1 (ABS_EXPR, method_return_type, - TREE_VALUE (method_arguments)); + CALL_EXPR_ARG (orig_call, 0)); } -/* Mostly copied from ../builtins.c. */ +/* Construct a new call to FN using the arguments from ORIG_CALL. */ + static tree -java_build_function_call_expr (tree fn, tree arglist) +java_build_function_call_expr (tree fn, tree orig_call) { - tree call_expr; - - call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); - return fold_build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), - call_expr, arglist, NULL_TREE); + int nargs = call_expr_nargs (orig_call); + switch (nargs) + { + /* Although we could handle the 0-3 argument cases using the general + logic in the default case, splitting them out permits folding to + be performed without constructing a temporary CALL_EXPR. */ + case 0: + return build_call_expr (fn, 0); + case 1: + return build_call_expr (fn, 1, CALL_EXPR_ARG (orig_call, 0)); + case 2: + return build_call_expr (fn, 2, + CALL_EXPR_ARG (orig_call, 0), + CALL_EXPR_ARG (orig_call, 1)); + case 3: + return build_call_expr (fn, 3, + CALL_EXPR_ARG (orig_call, 0), + CALL_EXPR_ARG (orig_call, 1), + CALL_EXPR_ARG (orig_call, 2)); + default: + { + tree fntype = TREE_TYPE (fn); + fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fn); + return fold (build_call_array (TREE_TYPE (fntype), + fn, nargs, CALL_EXPR_ARGP (orig_call))); + } + } } static tree -convert_real (tree method_return_type, tree method_arguments) +convert_real (tree method_return_type, tree orig_call) { return build1 (VIEW_CONVERT_EXPR, method_return_type, - TREE_VALUE (method_arguments)); + CALL_EXPR_ARG (orig_call, 0)); } @@ -191,76 +215,51 @@ convert_real (tree method_return_type, tree method_arguments) */ -/* Macros to unmarshal arguments from a TREE_LIST into a few +/* Macros to unmarshal arguments from a CALL_EXPR into a few variables. We also convert the offset arg from a long to an integer that is the same size as a pointer. */ -#define UNMARSHAL3(METHOD_ARGUMENTS) \ +#define UNMARSHAL3(METHOD_CALL) \ tree this_arg, obj_arg, offset_arg; \ do \ { \ - tree chain = METHOD_ARGUMENTS; \ - this_arg = TREE_VALUE (chain); \ - chain = TREE_CHAIN (chain); \ - obj_arg = TREE_VALUE (chain); \ - chain = TREE_CHAIN (chain); \ + tree orig_method_call = METHOD_CALL; \ + this_arg = CALL_EXPR_ARG (orig_method_call, 0); \ + obj_arg = CALL_EXPR_ARG (orig_method_call, 1); \ offset_arg = fold_convert (java_type_for_size (POINTER_SIZE, 0), \ - TREE_VALUE (chain)); \ + CALL_EXPR_ARG (orig_method_call, 2)); \ } \ while (0) -#define UNMARSHAL4(METHOD_ARGUMENTS) \ +#define UNMARSHAL4(METHOD_CALL) \ tree value_type, this_arg, obj_arg, offset_arg, value_arg; \ do \ { \ - tree chain = METHOD_ARGUMENTS; \ - this_arg = TREE_VALUE (chain); \ - chain = TREE_CHAIN (chain); \ - obj_arg = TREE_VALUE (chain); \ - chain = TREE_CHAIN (chain); \ + tree orig_method_call = METHOD_CALL; \ + this_arg = CALL_EXPR_ARG (orig_method_call, 0); \ + obj_arg = CALL_EXPR_ARG (orig_method_call, 1); \ offset_arg = fold_convert (java_type_for_size (POINTER_SIZE, 0), \ - TREE_VALUE (chain)); \ - chain = TREE_CHAIN (chain); \ - value_arg = TREE_VALUE (chain); \ + CALL_EXPR_ARG (orig_method_call, 2)); \ + value_arg = CALL_EXPR_ARG (orig_method_call, 3); \ value_type = TREE_TYPE (value_arg); \ } \ while (0) -#define UNMARSHAL5(METHOD_ARGUMENTS) \ +#define UNMARSHAL5(METHOD_CALL) \ tree value_type, this_arg, obj_arg, offset_arg, expected_arg, value_arg; \ do \ { \ - tree chain = METHOD_ARGUMENTS; \ - this_arg = TREE_VALUE (chain); \ - chain = TREE_CHAIN (chain); \ - obj_arg = TREE_VALUE (chain); \ - chain = TREE_CHAIN (chain); \ + tree orig_method_call = METHOD_CALL; \ + this_arg = CALL_EXPR_ARG (orig_method_call, 0); \ + obj_arg = CALL_EXPR_ARG (orig_method_call, 1); \ offset_arg = fold_convert (java_type_for_size (POINTER_SIZE, 0), \ - TREE_VALUE (chain)); \ - chain = TREE_CHAIN (chain); \ - expected_arg = TREE_VALUE (chain); \ - chain = TREE_CHAIN (chain); \ - value_arg = TREE_VALUE (chain); \ + CALL_EXPR_ARG (orig_method_call, 2)); \ + expected_arg = CALL_EXPR_ARG (orig_method_call, 3); \ + value_arg = CALL_EXPR_ARG (orig_method_call, 4); \ value_type = TREE_TYPE (value_arg); \ } \ while (0) -/* Construct an arglist from a call. */ - -static tree -build_arglist_for_builtin (tree arg, ...) -{ - va_list ap; - tree nextarg; - tree newarglist = build_tree_list (NULL_TREE, arg); - - va_start(ap, arg); - while ((nextarg = va_arg(ap, tree))) - newarglist = tree_cons (NULL_TREE, nextarg, newarglist); - - return nreverse (newarglist); -} - /* Add an address to an offset, forming a sum. */ static tree @@ -286,10 +285,10 @@ build_check_this (tree stmt, tree this_arg) static tree putObject_builtin (tree method_return_type ATTRIBUTE_UNUSED, - tree method_arguments) + tree orig_call) { tree addr, stmt; - UNMARSHAL4 (method_arguments); + UNMARSHAL4 (orig_call); addr = build_addr_sum (value_type, obj_arg, offset_arg); stmt = fold_build2 (MODIFY_EXPR, value_type, @@ -302,22 +301,18 @@ putObject_builtin (tree method_return_type ATTRIBUTE_UNUSED, static tree compareAndSwapInt_builtin (tree method_return_type ATTRIBUTE_UNUSED, - tree method_arguments) + tree orig_call) { enum machine_mode mode = TYPE_MODE (int_type_node); if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing || sync_compare_and_swap[mode] != CODE_FOR_nothing) { - tree newarglist, addr, stmt; - UNMARSHAL5 (method_arguments); + tree addr, stmt; + UNMARSHAL5 (orig_call); addr = build_addr_sum (int_type_node, obj_arg, offset_arg); - - newarglist - = build_arglist_for_builtin (addr, expected_arg, value_arg, NULL_TREE); - stmt = (build_function_call_expr - (built_in_decls[BUILT_IN_BOOL_COMPARE_AND_SWAP_4], - newarglist)); + stmt = build_call_expr (built_in_decls[BUILT_IN_BOOL_COMPARE_AND_SWAP_4], + 3, addr, expected_arg, value_arg); return build_check_this (stmt, this_arg); } @@ -326,22 +321,18 @@ compareAndSwapInt_builtin (tree method_return_type ATTRIBUTE_UNUSED, static tree compareAndSwapLong_builtin (tree method_return_type ATTRIBUTE_UNUSED, - tree method_arguments) + tree orig_call) { enum machine_mode mode = TYPE_MODE (long_type_node); if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing || sync_compare_and_swap[mode] != CODE_FOR_nothing) { - tree newarglist, addr, stmt; - UNMARSHAL5 (method_arguments); + tree addr, stmt; + UNMARSHAL5 (orig_call); addr = build_addr_sum (long_type_node, obj_arg, offset_arg); - - newarglist - = build_arglist_for_builtin (addr, expected_arg, value_arg, NULL_TREE); - stmt = (build_function_call_expr - (built_in_decls[BUILT_IN_BOOL_COMPARE_AND_SWAP_8], - newarglist)); + stmt = build_call_expr (built_in_decls[BUILT_IN_BOOL_COMPARE_AND_SWAP_8], + 3, addr, expected_arg, value_arg); return build_check_this (stmt, this_arg); } @@ -349,27 +340,23 @@ compareAndSwapLong_builtin (tree method_return_type ATTRIBUTE_UNUSED, } static tree compareAndSwapObject_builtin (tree method_return_type ATTRIBUTE_UNUSED, - tree method_arguments) + tree orig_call) { enum machine_mode mode = TYPE_MODE (ptr_type_node); if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing || sync_compare_and_swap[mode] != CODE_FOR_nothing) { - tree newarglist, addr, stmt; + tree addr, stmt; int builtin; - UNMARSHAL5 (method_arguments); + UNMARSHAL5 (orig_call); builtin = (POINTER_SIZE == 32 ? BUILT_IN_BOOL_COMPARE_AND_SWAP_4 : BUILT_IN_BOOL_COMPARE_AND_SWAP_8); addr = build_addr_sum (value_type, obj_arg, offset_arg); - - newarglist - = build_arglist_for_builtin (addr, expected_arg, value_arg, NULL_TREE); - stmt = (build_function_call_expr - (built_in_decls[builtin], - newarglist)); + stmt = build_call_expr (built_in_decls[builtin], + 3, addr, expected_arg, value_arg); return build_check_this (stmt, this_arg); } @@ -378,20 +365,17 @@ compareAndSwapObject_builtin (tree method_return_type ATTRIBUTE_UNUSED, static tree putVolatile_builtin (tree method_return_type ATTRIBUTE_UNUSED, - tree method_arguments) + tree orig_call) { - tree newarglist, addr, stmt, modify_stmt; - UNMARSHAL4 (method_arguments); + tree addr, stmt, modify_stmt; + UNMARSHAL4 (orig_call); addr = build_addr_sum (value_type, obj_arg, offset_arg); addr = fold_convert (build_pointer_type (build_type_variant (value_type, 0, 1)), addr); - newarglist = NULL_TREE; - stmt = (build_function_call_expr - (built_in_decls[BUILT_IN_SYNCHRONIZE], - newarglist)); + stmt = build_call_expr (built_in_decls[BUILT_IN_SYNCHRONIZE], 0); modify_stmt = fold_build2 (MODIFY_EXPR, value_type, build_java_indirect_ref (value_type, addr, flag_check_references), @@ -404,20 +388,17 @@ putVolatile_builtin (tree method_return_type ATTRIBUTE_UNUSED, static tree getVolatile_builtin (tree method_return_type ATTRIBUTE_UNUSED, - tree method_arguments) + tree orig_call) { - tree newarglist, addr, stmt, modify_stmt, tmp; - UNMARSHAL3 (method_arguments); + tree addr, stmt, modify_stmt, tmp; + UNMARSHAL3 (orig_call); addr = build_addr_sum (method_return_type, obj_arg, offset_arg); addr = fold_convert (build_pointer_type (build_type_variant (method_return_type, 0, 1)), addr); - newarglist = NULL_TREE; - stmt = (build_function_call_expr - (built_in_decls[BUILT_IN_SYNCHRONIZE], - newarglist)); + stmt = build_call_expr (built_in_decls[BUILT_IN_SYNCHRONIZE], 0); tmp = build_decl (VAR_DECL, NULL, method_return_type); DECL_IGNORED_P (tmp) = 1; @@ -437,7 +418,7 @@ getVolatile_builtin (tree method_return_type ATTRIBUTE_UNUSED, static tree VMSupportsCS8_builtin (tree method_return_type, - tree method_arguments ATTRIBUTE_UNUSED) + tree orig_call ATTRIBUTE_UNUSED) { enum machine_mode mode = TYPE_MODE (long_type_node); gcc_assert (method_return_type == boolean_type_node); @@ -596,7 +577,6 @@ check_for_builtin (tree method, tree call) if (optimize && TREE_CODE (call) == CALL_EXPR) { int i; - tree method_arguments = TREE_OPERAND (call, 1); tree method_class = DECL_NAME (TYPE_NAME (DECL_CONTEXT (method))); tree method_name = DECL_NAME (method); tree method_return_type = TREE_TYPE (TREE_TYPE (method)); @@ -611,8 +591,7 @@ check_for_builtin (tree method, tree call) if (java_builtins[i].creator != NULL) { tree result - = (*java_builtins[i].creator) (method_return_type, - method_arguments); + = (*java_builtins[i].creator) (method_return_type, call); return result == NULL_TREE ? call : result; } @@ -623,7 +602,7 @@ check_for_builtin (tree method, tree call) fn = built_in_decls[java_builtins[i].builtin_code]; if (fn == NULL_TREE) return call; - return java_build_function_call_expr (fn, method_arguments); + return java_build_function_call_expr (fn, call); } } } diff --git a/gcc/java/class.c b/gcc/java/class.c index 804c239fcfa..85cdeb49e1e 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -1039,10 +1039,8 @@ cache_this_class_ref (tree fndecl) && ! DECL_CLINIT_P (fndecl) && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (fndecl)))) { - tree init = build3 (CALL_EXPR, void_type_node, - build_address_of (soft_initclass_node), - build_tree_list (NULL_TREE, this_classdollar), - NULL_TREE); + tree init = build_call_expr (soft_initclass_node, 1, + this_classdollar); java_add_stmt (init); } } @@ -1177,20 +1175,16 @@ build_static_field_ref (tree fdecl) int cpool_index = alloc_constant_fieldref (output_class, fdecl); tree cache_entry = build_fieldref_cache_entry (cpool_index, fdecl); - tree test - = build3 (CALL_EXPR, boolean_type_node, - build_address_of (built_in_decls[BUILT_IN_EXPECT]), - tree_cons (NULL_TREE, build2 (EQ_EXPR, boolean_type_node, - cache_entry, null_pointer_node), - build_tree_list (NULL_TREE, boolean_false_node)), - NULL_TREE); + tree test + = build_call_expr (built_in_decls[BUILT_IN_EXPECT], 2, + build2 (EQ_EXPR, boolean_type_node, + cache_entry, null_pointer_node), + boolean_false_node); tree cpool_index_cst = build_int_cst (NULL_TREE, cpool_index); tree init - = build3 (CALL_EXPR, ptr_type_node, - build_address_of (soft_resolvepoolentry_node), - tree_cons (NULL_TREE, build_class_ref (output_class), - build_tree_list (NULL_TREE, cpool_index_cst)), - NULL_TREE); + = build_call_expr (soft_resolvepoolentry_node, 2, + build_class_ref (output_class), + cpool_index_cst); init = build2 (MODIFY_EXPR, ptr_type_node, cache_entry, init); init = build3 (COND_EXPR, ptr_type_node, test, init, cache_entry); init = fold_convert (build_pointer_type (TREE_TYPE (fdecl)), init); @@ -2693,8 +2687,7 @@ emit_indirect_register_classes (tree *list_p) TREE_PUBLIC (t) = 1; DECL_EXTERNAL (t) = 1; register_class_fn = t; - t = tree_cons (NULL, reg_class_list, NULL); - t = build_function_call_expr (register_class_fn, t); + t = build_call_expr (register_class_fn, 1, reg_class_list); append_to_statement_list (t, list_p); } @@ -2759,8 +2752,7 @@ emit_register_classes (tree *list_p) for (i = 0; VEC_iterate (tree, registered_class, i, klass); ++i) { t = build_fold_addr_expr (klass); - t = tree_cons (NULL, t, NULL); - t = build_function_call_expr (register_class_fn, t); + t = build_call_expr (register_class_fn, 1, t); append_to_statement_list (t, list_p); } } diff --git a/gcc/java/expr.c b/gcc/java/expr.c index ed5103f5988..46300efd07a 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -716,11 +716,9 @@ build_java_athrow (tree node) { tree call; - call = build3 (CALL_EXPR, - void_type_node, - build_address_of (throw_node), - build_tree_list (NULL_TREE, node), - NULL_TREE); + call = build_call_nary (void_type_node, + build_address_of (throw_node), + 1, node); TREE_SIDE_EFFECTS (call) = 1; java_add_stmt (call); java_stack_pop (stack_pointer); @@ -799,9 +797,9 @@ encode_newarray_type (tree type) static tree build_java_throw_out_of_bounds_exception (tree index) { - tree node = build3 (CALL_EXPR, int_type_node, - build_address_of (soft_badarrayindex_node), - build_tree_list (NULL_TREE, index), NULL_TREE); + tree node = build_call_nary (int_type_node, + build_address_of (soft_badarrayindex_node), + 1, index); TREE_SIDE_EFFECTS (node) = 1; /* Allows expansion within ANDIF */ return (node); } @@ -850,9 +848,9 @@ java_check_reference (tree expr, int check) expr = build3 (COND_EXPR, TREE_TYPE (expr), build2 (EQ_EXPR, boolean_type_node, expr, null_pointer_node), - build3 (CALL_EXPR, void_type_node, - build_address_of (soft_nullpointer_node), - NULL_TREE, NULL_TREE), + build_call_nary (void_type_node, + build_address_of (soft_nullpointer_node), + 0), expr); } @@ -1014,11 +1012,9 @@ build_java_arraystore_check (tree array, tree object) } /* Build an invocation of _Jv_CheckArrayStore */ - check = build3 (CALL_EXPR, void_type_node, - build_address_of (soft_checkarraystore_node), - tree_cons (NULL_TREE, array, - build_tree_list (NULL_TREE, object)), - NULL_TREE); + check = build_call_nary (void_type_node, + build_address_of (soft_checkarraystore_node), + 2, array, object); TREE_SIDE_EFFECTS (check) = 1; return check; @@ -1060,12 +1056,9 @@ build_newarray (int atype_value, tree length) some work. */ type_arg = build_class_ref (prim_type); - return build3 (CALL_EXPR, promote_type (type), - build_address_of (soft_newarray_node), - tree_cons (NULL_TREE, - type_arg, - build_tree_list (NULL_TREE, length)), - NULL_TREE); + return build_call_nary (promote_type (type), + build_address_of (soft_newarray_node), + 2, type_arg, length); } /* Generates anewarray from a given CLASS_TYPE. Gets from the stack the size @@ -1079,13 +1072,12 @@ build_anewarray (tree class_type, tree length) host_integerp (length, 0) ? tree_low_cst (length, 0) : -1); - return build3 (CALL_EXPR, promote_type (type), - build_address_of (soft_anewarray_node), - tree_cons (NULL_TREE, length, - tree_cons (NULL_TREE, build_class_ref (class_type), - build_tree_list (NULL_TREE, - null_pointer_node))), - NULL_TREE); + return build_call_nary (promote_type (type), + build_address_of (soft_anewarray_node), + 3, + length, + build_class_ref (class_type), + null_pointer_node); } /* Return a node the evaluates 'new TYPE[LENGTH]'. */ @@ -1112,14 +1104,15 @@ expand_java_multianewarray (tree class_type, int ndim) for( i = 0; i < ndim; i++ ) args = tree_cons (NULL_TREE, pop_value (int_type_node), args); - push_value (build3 (CALL_EXPR, - promote_type (class_type), - build_address_of (soft_multianewarray_node), - tree_cons (NULL_TREE, build_class_ref (class_type), - tree_cons (NULL_TREE, - build_int_cst (NULL_TREE, ndim), - args)), - NULL_TREE)); + args = tree_cons (NULL_TREE, + build_class_ref (class_type), + tree_cons (NULL_TREE, + build_int_cst (NULL_TREE, ndim), + args)); + + push_value (build_call_list (promote_type (class_type), + build_address_of (soft_multianewarray_node), + args)); } /* ARRAY[INDEX] <- RHS. build_java_check_indexed_type makes sure that @@ -1246,11 +1239,9 @@ expand_java_array_length (void) static tree build_java_monitor (tree call, tree object) { - return build3 (CALL_EXPR, - void_type_node, - build_address_of (call), - build_tree_list (NULL_TREE, object), - NULL_TREE); + return build_call_nary (void_type_node, + build_address_of (call), + 1, object); } /* Emit code for one of the PUSHC instructions. */ @@ -1347,10 +1338,9 @@ java_create_object (tree type) ? alloc_object_node : alloc_no_finalizer_node); - return build3 (CALL_EXPR, promote_type (type), - build_address_of (alloc_node), - build_tree_list (NULL_TREE, build_class_ref (type)), - NULL_TREE); + return build_call_nary (promote_type (type), + build_address_of (alloc_node), + 1, build_class_ref (type)); } static void @@ -1363,10 +1353,9 @@ expand_java_NEW (tree type) if (! CLASS_LOADED_P (type)) load_class (type, 1); safe_layout_class (type); - push_value (build3 (CALL_EXPR, promote_type (type), - build_address_of (alloc_node), - build_tree_list (NULL_TREE, build_class_ref (type)), - NULL_TREE)); + push_value (build_call_nary (promote_type (type), + build_address_of (alloc_node), + 1, build_class_ref (type))); } /* This returns an expression which will extract the class of an @@ -1445,12 +1434,9 @@ build_instanceof (tree value, tree type) } else { - expr = build3 (CALL_EXPR, itype, - build_address_of (soft_instanceof_node), - tree_cons (NULL_TREE, value, - build_tree_list (NULL_TREE, - build_class_ref (type))), - NULL_TREE); + expr = build_call_nary (itype, + build_address_of (soft_instanceof_node), + 2, value, build_class_ref (type)); } TREE_SIDE_EFFECTS (expr) = TREE_SIDE_EFFECTS (value); return expr; @@ -1468,11 +1454,9 @@ static void expand_java_CHECKCAST (tree type) { tree value = pop_value (ptr_type_node); - value = build3 (CALL_EXPR, promote_type (type), - build_address_of (soft_checkcast_node), - tree_cons (NULL_TREE, build_class_ref (type), - build_tree_list (NULL_TREE, value)), - NULL_TREE); + value = build_call_nary (promote_type (type), + build_address_of (soft_checkcast_node), + 2, build_class_ref (type), value); push_value (value); } @@ -1527,12 +1511,7 @@ build_java_soft_divmod (enum tree_code op, tree type, tree op1, tree op2) } gcc_assert (call); - call = build3 (CALL_EXPR, type, - build_address_of (call), - tree_cons (NULL_TREE, arg1, - build_tree_list (NULL_TREE, arg2)), - NULL_TREE); - + call = build_call_nary (type, build_address_of (call), 2, arg1, arg2); return call; } @@ -1595,11 +1574,9 @@ build_java_binop (enum tree_code op, tree type, tree arg1, tree arg2) arg1 = convert (double_type_node, arg1); arg2 = convert (double_type_node, arg2); } - call = build3 (CALL_EXPR, double_type_node, - build_address_of (soft_fmod_node), - tree_cons (NULL_TREE, arg1, - build_tree_list (NULL_TREE, arg2)), - NULL_TREE); + call = build_call_nary (double_type_node, + build_address_of (soft_fmod_node), + 2, arg1, arg2); if (type != double_type_node) call = convert (type, call); return call; @@ -1759,10 +1736,9 @@ build_field_ref (tree self_value, tree self_class, tree name) = build3 (COND_EXPR, TREE_TYPE (field_offset), build2 (EQ_EXPR, boolean_type_node, field_offset, integer_zero_node), - build3 (CALL_EXPR, void_type_node, - build_address_of (soft_nosuchfield_node), - build_tree_list (NULL_TREE, otable_index), - NULL_TREE), + build_call_nary (void_type_node, + build_address_of (soft_nosuchfield_node), + 1, otable_index), field_offset); field_offset = fold (convert (sizetype, field_offset)); @@ -1998,10 +1974,9 @@ build_class_init (tree clas, tree expr) if (always_initialize_class_p) { - init = build3 (CALL_EXPR, void_type_node, - build_address_of (soft_initclass_node), - build_tree_list (NULL_TREE, build_class_ref (clas)), - NULL_TREE); + init = build_call_nary (void_type_node, + build_address_of (soft_initclass_node), + 1, build_class_ref (clas)); TREE_SIDE_EFFECTS (init) = 1; } else @@ -2031,10 +2006,9 @@ build_class_init (tree clas, tree expr) *init_test_decl = decl; } - init = build3 (CALL_EXPR, void_type_node, - build_address_of (soft_initclass_node), - build_tree_list (NULL_TREE, build_class_ref (clas)), - NULL_TREE); + init = build_call_nary (void_type_node, + build_address_of (soft_initclass_node), + 1, build_class_ref (clas)); TREE_SIDE_EFFECTS (init) = 1; init = build3 (COND_EXPR, void_type_node, build2 (EQ_EXPR, boolean_type_node, @@ -2084,9 +2058,8 @@ static tree rewrite_arglist_getcaller (tree arglist) { tree retaddr - = (build_function_call_expr - (built_in_decls[BUILT_IN_RETURN_ADDRESS], - build_tree_list (NULL_TREE, integer_zero_node))); + = build_call_expr (built_in_decls[BUILT_IN_RETURN_ADDRESS], + 1, integer_zero_node); DECL_INLINE (current_function_decl) = 0; @@ -2356,7 +2329,6 @@ static GTY(()) tree class_ident; tree build_invokeinterface (tree dtable, tree method) { - tree lookup_arg; tree interface; tree idx; @@ -2401,13 +2373,9 @@ build_invokeinterface (tree dtable, tree method) interface = build_class_ref (interface); } - lookup_arg = tree_cons (NULL_TREE, dtable, - tree_cons (NULL_TREE, interface, - build_tree_list (NULL_TREE, idx))); - - return build3 (CALL_EXPR, ptr_type_node, - build_address_of (soft_lookupinterfacemethod_node), - lookup_arg, NULL_TREE); + return build_call_nary (ptr_type_node, + build_address_of (soft_lookupinterfacemethod_node), + 3, dtable, interface, idx); } /* Expand one of the invoke_* opcodes. @@ -2590,8 +2558,7 @@ expand_invoke (int opcode, int method_ref_index, int nargs ATTRIBUTE_UNUSED) else func = build1 (NOP_EXPR, build_pointer_type (method_type), func); - call = build3 (CALL_EXPR, TREE_TYPE (method_type), - func, arg_list, NULL_TREE); + call = build_call_list (TREE_TYPE (method_type), func, arg_list); TREE_SIDE_EFFECTS (call) = 1; call = check_for_builtin (method, call); @@ -2616,7 +2583,8 @@ expand_invoke (int opcode, int method_ref_index, int nargs ATTRIBUTE_UNUSED) tree build_jni_stub (tree method) { - tree jnifunc, call, args, body, lookup_arg, method_sig, arg_types; + tree jnifunc, call, args, body, method_sig, arg_types; + tree jniarg0, jniarg1, jniarg2, jniarg3; tree jni_func_type, tem; tree env_var, res_var = NULL_TREE, block; tree method_args, res_type; @@ -2671,10 +2639,9 @@ build_jni_stub (tree method) /* Compute the local `env' by calling _Jv_GetJNIEnvNewFrame. */ body = build2 (MODIFY_EXPR, ptr_type_node, env_var, - build3 (CALL_EXPR, ptr_type_node, - build_address_of (soft_getjnienvnewframe_node), - build_tree_list (NULL_TREE, klass), - NULL_TREE)); + build_call_nary (ptr_type_node, + build_address_of (soft_getjnienvnewframe_node), + 1, klass)); CAN_COMPLETE_NORMALLY (body) = 1; /* All the arguments to this method become arguments to the @@ -2713,18 +2680,14 @@ build_jni_stub (tree method) /* We call _Jv_LookupJNIMethod to find the actual underlying function pointer. _Jv_LookupJNIMethod will throw the appropriate exception if this function is not found at runtime. */ - tem = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, args_size)); method_sig = build_java_signature (TREE_TYPE (method)); - lookup_arg = tree_cons (NULL_TREE, - build_utf8_ref (unmangle_classname - (IDENTIFIER_POINTER (method_sig), - IDENTIFIER_LENGTH (method_sig))), - tem); - tem = DECL_NAME (method); - lookup_arg - = tree_cons (NULL_TREE, klass, - tree_cons (NULL_TREE, build_utf8_ref (tem), lookup_arg)); - + jniarg0 = klass; + jniarg1 = build_utf8_ref (DECL_NAME (method)); + jniarg2 = build_utf8_ref (unmangle_classname + (IDENTIFIER_POINTER (method_sig), + IDENTIFIER_LENGTH (method_sig))); + jniarg3 = build_int_cst (NULL_TREE, args_size); + tem = build_function_type (TREE_TYPE (TREE_TYPE (method)), arg_types); #ifdef MODIFY_JNI_METHOD_CALL @@ -2736,16 +2699,18 @@ build_jni_stub (tree method) jnifunc = build3 (COND_EXPR, ptr_type_node, meth_var, meth_var, build2 (MODIFY_EXPR, ptr_type_node, meth_var, - build3 (CALL_EXPR, ptr_type_node, - build_address_of - (soft_lookupjnimethod_node), - lookup_arg, NULL_TREE))); + build_call_nary (ptr_type_node, + build_address_of + (soft_lookupjnimethod_node), + 4, + jniarg0, jniarg1, + jniarg2, jniarg3))); /* Now we make the actual JNI call via the resulting function pointer. */ - call = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (method)), - build1 (NOP_EXPR, jni_func_type, jnifunc), - args, NULL_TREE); + call = build_call_list (TREE_TYPE (TREE_TYPE (method)), + build1 (NOP_EXPR, jni_func_type, jnifunc), + args); /* If the JNI call returned a result, capture it here. If we had to unwrap JNI object results, we would do that here. */ @@ -2754,10 +2719,9 @@ build_jni_stub (tree method) /* If the call returns an object, it may return a JNI weak reference, in which case we must unwrap it. */ if (! JPRIMITIVE_TYPE_P (TREE_TYPE (TREE_TYPE (method)))) - call = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (method)), - build_address_of (soft_unwrapjni_node), - build_tree_list (NULL_TREE, call), - NULL_TREE); + call = build_call_nary (TREE_TYPE (TREE_TYPE (method)), + build_address_of (soft_unwrapjni_node), + 1, call); call = build2 (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (method)), res_var, call); } @@ -2769,10 +2733,9 @@ build_jni_stub (tree method) TREE_SIDE_EFFECTS (body) = 1; /* Now free the environment we allocated. */ - call = build3 (CALL_EXPR, ptr_type_node, - build_address_of (soft_jnipopsystemframe_node), - build_tree_list (NULL_TREE, env_var), - NULL_TREE); + call = build_call_nary (ptr_type_node, + build_address_of (soft_jnipopsystemframe_node), + 1, env_var); TREE_SIDE_EFFECTS (call) = 1; CAN_COMPLETE_NORMALLY (call) = 1; body = build2 (COMPOUND_EXPR, void_type_node, body, call); @@ -2805,11 +2768,8 @@ build_jni_stub (tree method) && (! METHOD_PRIVATE (method) || INNER_CLASS_P (DECL_CONTEXT (method)))) { - tree init = build3 (CALL_EXPR, void_type_node, - build_address_of (soft_initclass_node), - build_tree_list (NULL_TREE, - klass), - NULL_TREE); + tree init = build_call_expr (soft_initclass_node, 1, + klass); body = build2 (COMPOUND_EXPR, void_type_node, init, body); TREE_SIDE_EFFECTS (body) = 1; } @@ -2943,11 +2903,8 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index) field_ref, new_value); if (TREE_THIS_VOLATILE (field_decl)) - java_add_stmt - (build3 - (CALL_EXPR, void_type_node, - build_address_of (built_in_decls[BUILT_IN_SYNCHRONIZE]), - NULL_TREE, NULL_TREE)); + java_add_stmt + (build_call_expr (built_in_decls[BUILT_IN_SYNCHRONIZE], 0)); java_add_stmt (modify_expr); } @@ -2965,10 +2922,7 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index) if (TREE_THIS_VOLATILE (field_decl)) java_add_stmt - (build3 - (CALL_EXPR, void_type_node, - build_address_of (built_in_decls[BUILT_IN_SYNCHRONIZE]), - NULL_TREE, NULL_TREE)); + (build_call_expr (built_in_decls[BUILT_IN_SYNCHRONIZE], 0)); push_value (temp); } @@ -3725,40 +3679,36 @@ force_evaluation_order (tree node) && TREE_CODE (TREE_OPERAND (node, 0)) == CALL_EXPR && TREE_CODE (TREE_OPERAND (node, 1)) == SAVE_EXPR)) { - tree arg, cmp; + tree call, cmp; + int i, nargs; - arg = node; - - /* Position arg properly, account for wrapped around ctors. */ + /* Account for wrapped around ctors. */ if (TREE_CODE (node) == COMPOUND_EXPR) - arg = TREE_OPERAND (node, 0); - - arg = TREE_OPERAND (arg, 1); - - /* An empty argument list is ok, just ignore it. */ - if (!arg) - return node; + call = TREE_OPERAND (node, 0); + else + call = node; - /* Not having a list of arguments here is an error. */ - gcc_assert (TREE_CODE (arg) == TREE_LIST); + nargs = call_expr_nargs (call); /* This reverses the evaluation order. This is a desired effect. */ - for (cmp = NULL_TREE; arg; arg = TREE_CHAIN (arg)) + for (i = 0, cmp = NULL_TREE; i < nargs; i++) { + tree arg = CALL_EXPR_ARG (call, i); /* Promote types smaller than integer. This is required by some ABIs. */ - tree type = TREE_TYPE (TREE_VALUE (arg)); + tree type = TREE_TYPE (arg); tree saved; if (targetm.calls.promote_prototypes (type) && INTEGRAL_TYPE_P (type) && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), TYPE_SIZE (integer_type_node))) - TREE_VALUE (arg) = fold_convert (integer_type_node, TREE_VALUE (arg)); + arg = fold_convert (integer_type_node, arg); - saved = save_expr (force_evaluation_order (TREE_VALUE (arg))); + saved = save_expr (force_evaluation_order (arg)); cmp = (cmp == NULL_TREE ? saved : build2 (COMPOUND_EXPR, void_type_node, cmp, saved)); - TREE_VALUE (arg) = saved; + + CALL_EXPR_ARG (call, i) = saved; } if (cmp && TREE_CODE (cmp) == COMPOUND_EXPR) diff --git a/gcc/java/java-gimplify.c b/gcc/java/java-gimplify.c index 96e900934e3..eeda04c3363 100644 --- a/gcc/java/java-gimplify.c +++ b/gcc/java/java-gimplify.c @@ -212,10 +212,7 @@ java_gimplify_component_ref (tree *expr_p, tree *pre_p, tree *post_p) if (stat == GS_ERROR) return stat; - sync_expr - = build3 (CALL_EXPR, void_type_node, - build_address_of (built_in_decls[BUILT_IN_SYNCHRONIZE]), - NULL_TREE, NULL_TREE); + sync_expr = build_call_expr (built_in_decls[BUILT_IN_SYNCHRONIZE], 0); TREE_SIDE_EFFECTS (sync_expr) = 1; *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p), sync_expr, *expr_p); @@ -255,10 +252,8 @@ java_gimplify_modify_expr (tree *modify_expr_p, tree *pre_p, tree *post_p) */ enum gimplify_status stat; - tree sync_expr - = build3 (CALL_EXPR, void_type_node, - build_address_of (built_in_decls[BUILT_IN_SYNCHRONIZE]), - NULL_TREE, NULL_TREE); + tree sync_expr = + build_call_expr (built_in_decls[BUILT_IN_SYNCHRONIZE], 0); TREE_SIDE_EFFECTS (sync_expr) = 1; stat = gimplify_expr (&rhs, pre_p, post_p, diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 732e0cde115..4a413712fe2 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -1626,20 +1626,18 @@ extern tree *type_map; #define BUILD_MONITOR_ENTER(WHERE, ARG) \ { \ - (WHERE) = build3 (CALL_EXPR, int_type_node, \ - build_address_of (soft_monitorenter_node), \ - build_tree_list (NULL_TREE, (ARG)), \ - NULL_TREE); \ + (WHERE) = build_call_nary (int_type_node, \ + build_address_of (soft_monitorenter_node), \ + 1, (ARG)); \ TREE_SIDE_EFFECTS (WHERE) = 1; \ } -#define BUILD_MONITOR_EXIT(WHERE, ARG) \ - { \ - (WHERE) = build3 (CALL_EXPR, int_type_node, \ - build_address_of (soft_monitorexit_node), \ - build_tree_list (NULL_TREE, (ARG)), \ - NULL_TREE); \ - TREE_SIDE_EFFECTS (WHERE) = 1; \ +#define BUILD_MONITOR_EXIT(WHERE, ARG) \ + { \ + (WHERE) = build_call_nary (int_type_node, \ + build_address_of (soft_monitorexit_node), \ + 1, (ARG)); \ + TREE_SIDE_EFFECTS (WHERE) = 1; \ } /* True when we can perform static class initialization optimization */ diff --git a/gcc/java/lang.c b/gcc/java/lang.c index 51459c53dd7..b1912cc1128 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -989,7 +989,7 @@ java_get_callee_fndecl (tree call_expr) if (TREE_CODE (call_expr) != CALL_EXPR) return NULL; - method = TREE_OPERAND (call_expr, 0); + method = CALL_EXPR_FN (call_expr); STRIP_NOPS (method); if (TREE_CODE (method) != ARRAY_REF) return NULL; diff --git a/gcc/java/resource.c b/gcc/java/resource.c index b0b941cc8dc..91bbdc5c30d 100644 --- a/gcc/java/resource.c +++ b/gcc/java/resource.c @@ -116,8 +116,7 @@ write_resource_constructor (tree *list_p) for (iter = nreverse (resources); iter ; iter = TREE_CHAIN (iter)) { t = build_fold_addr_expr (TREE_VALUE (iter)); - t = tree_cons (NULL, t, NULL); - t = build_function_call_expr (register_resource_fn, t); + t = build_call_expr (register_resource_fn, 1, t); append_to_statement_list (t, list_p); } } diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 033ba3eeb11..0341c5f358b 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,10 @@ +2007-02-15 Sandra Loosemore <sandra@codesourcery.com> + Brooks Moses <brooks.moses@codesourcery.com> + Lee Millward <lee.millward@codesourcery.com> + + * objc-act.c (receiver_is_class_object): Use new CALL_EXPR accessors. + (objc_get_callee_fndecl): Likewise. + 2007-01-23 Andrew Pinski <pinskia@gmail.com> PR objc/27438 diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index b94bc0a3f0d..6dd6a464ce0 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -6131,7 +6131,7 @@ receiver_is_class_object (tree receiver, int self, int super) /* The receiver is a function call that returns an id. Check if it is a call to objc_getClass, if so, pick up the class name. */ if (TREE_CODE (receiver) == CALL_EXPR - && (exp = TREE_OPERAND (receiver, 0)) + && (exp = CALL_EXPR_FN (receiver)) && TREE_CODE (exp) == ADDR_EXPR && (exp = TREE_OPERAND (exp, 0)) && TREE_CODE (exp) == FUNCTION_DECL @@ -6141,9 +6141,7 @@ receiver_is_class_object (tree receiver, int self, int super) && TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl) && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS) /* We have a call to objc_get_class/objc_getClass! */ - && (arg = TREE_OPERAND (receiver, 1)) - && TREE_CODE (arg) == TREE_LIST - && (arg = TREE_VALUE (arg))) + && (arg = CALL_EXPR_ARG (receiver, 0))) { STRIP_NOPS (arg); if (TREE_CODE (arg) == ADDR_EXPR @@ -9517,7 +9515,7 @@ objc_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) tree objc_get_callee_fndecl (tree call_expr) { - tree addr = TREE_OPERAND (call_expr, 0); + tree addr = CALL_EXPR_FN (call_expr); if (TREE_CODE (addr) != OBJ_TYPE_REF) return 0; diff --git a/gcc/omp-low.c b/gcc/omp-low.c index e5a320db09d..bb7ecc0e9b3 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -1427,10 +1427,7 @@ scan_omp (tree *stmt_p, omp_context *ctx) static void build_omp_barrier (tree *stmt_list) { - tree t; - - t = built_in_decls[BUILT_IN_GOMP_BARRIER]; - t = build_function_call_expr (t, NULL); + tree t = build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0); gimplify_and_add (t, stmt_list); } @@ -1604,7 +1601,7 @@ lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist, omp_context *ctx) { tree_stmt_iterator diter; - tree c, dtor, copyin_seq, x, args, ptr; + tree c, dtor, copyin_seq, x, ptr; bool copyin_by_ref = false; bool lastprivate_firstprivate = false; int pass; @@ -1676,9 +1673,7 @@ lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist, gcc_assert (DECL_P (ptr)); x = TYPE_SIZE_UNIT (TREE_TYPE (new_var)); - args = tree_cons (NULL, x, NULL); - x = built_in_decls[BUILT_IN_ALLOCA]; - x = build_function_call_expr (x, args); + x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x); x = fold_convert (TREE_TYPE (ptr), x); x = build2 (GIMPLE_MODIFY_STMT, void_type_node, ptr, x); gimplify_and_add (x, ilist); @@ -1710,9 +1705,7 @@ lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist, } else { - args = tree_cons (NULL, x, NULL); - x = built_in_decls[BUILT_IN_ALLOCA]; - x = build_function_call_expr (x, args); + x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x); x = fold_convert (TREE_TYPE (new_var), x); } @@ -1815,8 +1808,7 @@ lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist, but it certainly is to C++ operator=. */ if (copyin_seq) { - x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM]; - x = build_function_call_expr (x, NULL); + x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0); x = build2 (NE_EXPR, boolean_type_node, x, build_int_cst (TREE_TYPE (x), 0)); x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL); @@ -1969,14 +1961,12 @@ lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx) } } - x = built_in_decls[BUILT_IN_GOMP_ATOMIC_START]; - x = build_function_call_expr (x, NULL); + x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0); gimplify_and_add (x, stmt_list); gimplify_and_add (sub_list, stmt_list); - x = built_in_decls[BUILT_IN_GOMP_ATOMIC_END]; - x = build_function_call_expr (x, NULL); + x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0); gimplify_and_add (x, stmt_list); } @@ -2155,7 +2145,7 @@ static void expand_parallel_call (struct omp_region *region, basic_block bb, tree entry_stmt, tree ws_args) { - tree t, args, val, cond, c, list, clauses; + tree t, t1, t2, val, cond, c, list, clauses; block_stmt_iterator si; int start_ix; @@ -2261,21 +2251,23 @@ expand_parallel_call (struct omp_region *region, basic_block bb, } list = NULL_TREE; - args = tree_cons (NULL, val, NULL); t = OMP_PARALLEL_DATA_ARG (entry_stmt); if (t == NULL) - t = null_pointer_node; + t1 = null_pointer_node; else - t = build_fold_addr_expr (t); - args = tree_cons (NULL, t, args); - t = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt)); - args = tree_cons (NULL, t, args); + t1 = build_fold_addr_expr (t); + t2 = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt)); if (ws_args) - args = chainon (args, ws_args); + { + tree args = tree_cons (NULL, t2, + tree_cons (NULL, t1, + tree_cons (NULL, val, ws_args))); + t = build_function_call_expr (built_in_decls[start_ix], args); + } + else + t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val); - t = built_in_decls[start_ix]; - t = build_function_call_expr (t, args); gimplify_and_add (t, &list); t = OMP_PARALLEL_DATA_ARG (entry_stmt); @@ -2283,12 +2275,10 @@ expand_parallel_call (struct omp_region *region, basic_block bb, t = null_pointer_node; else t = build_fold_addr_expr (t); - args = tree_cons (NULL, t, NULL); - t = build_function_call_expr (OMP_PARALLEL_FN (entry_stmt), args); + t = build_call_expr (OMP_PARALLEL_FN (entry_stmt), 1, t); gimplify_and_add (t, &list); - t = built_in_decls[BUILT_IN_GOMP_PARALLEL_END]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0); gimplify_and_add (t, &list); si = bsi_last (bb); @@ -2313,10 +2303,7 @@ maybe_catch_exception (tree *stmt_p) if (lang_protect_cleanup_actions) t = lang_protect_cleanup_actions (); else - { - t = built_in_decls[BUILT_IN_TRAP]; - t = build_function_call_expr (t, NULL); - } + t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0); f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL); EH_FILTER_MUST_NOT_THROW (f) = 1; gimplify_and_add (t, &EH_FILTER_FAILURE (f)); @@ -2583,7 +2570,7 @@ expand_omp_for_generic (struct omp_region *region, { tree l0, l1, l2 = NULL, l3 = NULL; tree type, istart0, iend0, iend; - tree t, args, list; + tree t, list; basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb; basic_block l2_bb = NULL, l3_bb = NULL; block_stmt_iterator si; @@ -2621,25 +2608,24 @@ expand_omp_for_generic (struct omp_region *region, gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR); if (!in_combined_parallel) { + tree t0, t1, t2, t3, t4; /* If this is not a combined parallel loop, emit a call to GOMP_loop_foo_start in ENTRY_BB. */ list = alloc_stmt_list (); - t = build_fold_addr_expr (iend0); - args = tree_cons (NULL, t, NULL); - t = build_fold_addr_expr (istart0); - args = tree_cons (NULL, t, args); + t4 = build_fold_addr_expr (iend0); + t3 = build_fold_addr_expr (istart0); + t2 = fold_convert (long_integer_type_node, fd->step); + t1 = fold_convert (long_integer_type_node, fd->n2); + t0 = fold_convert (long_integer_type_node, fd->n1); if (fd->chunk_size) { t = fold_convert (long_integer_type_node, fd->chunk_size); - args = tree_cons (NULL, t, args); + t = build_call_expr (built_in_decls[start_fn], 6, + t0, t1, t2, t, t3, t4); } - t = fold_convert (long_integer_type_node, fd->step); - args = tree_cons (NULL, t, args); - t = fold_convert (long_integer_type_node, fd->n2); - args = tree_cons (NULL, t, args); - t = fold_convert (long_integer_type_node, fd->n1); - args = tree_cons (NULL, t, args); - t = build_function_call_expr (built_in_decls[start_fn], args); + else + t = build_call_expr (built_in_decls[start_fn], 5, + t0, t1, t2, t3, t4); t = get_formal_tmp_var (t, &list); if (cont_bb) { @@ -2697,11 +2683,9 @@ expand_omp_for_generic (struct omp_region *region, /* Emit code to get the next parallel iteration in L2_BB. */ list = alloc_stmt_list (); - t = build_fold_addr_expr (iend0); - args = tree_cons (NULL, t, NULL); - t = build_fold_addr_expr (istart0); - args = tree_cons (NULL, t, args); - t = build_function_call_expr (built_in_decls[next_fn], args); + t = build_call_expr (built_in_decls[next_fn], 2, + build_fold_addr_expr (istart0), + build_fold_addr_expr (iend0)); t = get_formal_tmp_var (t, &list); t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0), build_and_jump (&l3)); @@ -2716,7 +2700,7 @@ expand_omp_for_generic (struct omp_region *region, t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT]; else t = built_in_decls[BUILT_IN_GOMP_LOOP_END]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (t, 0); bsi_insert_after (&si, t, BSI_SAME_STMT); bsi_remove (&si, true); @@ -2795,13 +2779,11 @@ expand_omp_for_static_nochunk (struct omp_region *region, /* Iteration space partitioning goes in ENTRY_BB. */ list = alloc_stmt_list (); - t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0); t = fold_convert (type, t); nthreads = get_formal_tmp_var (t, &list); - t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0); t = fold_convert (type, t); threadid = get_formal_tmp_var (t, &list); @@ -2972,13 +2954,11 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd) /* Trip and adjustment setup goes in ENTRY_BB. */ list = alloc_stmt_list (); - t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0); t = fold_convert (type, t); nthreads = get_formal_tmp_var (t, &list); - t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0); t = fold_convert (type, t); threadid = get_formal_tmp_var (t, &list); @@ -3224,9 +3204,8 @@ expand_omp_sections (struct omp_region *region) /* If we are not inside a combined parallel+sections region, call GOMP_sections_start. */ t = build_int_cst (unsigned_type_node, len); - t = tree_cons (NULL, t, NULL); u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START]; - t = build_function_call_expr (u, t); + t = build_call_expr (u, 1, t); t = build2 (GIMPLE_MODIFY_STMT, void_type_node, v, t); bsi_insert_after (&si, t, BSI_SAME_STMT); } @@ -3284,8 +3263,7 @@ expand_omp_sections (struct omp_region *region) make_edge (l0_bb, default_bb, 0); si = bsi_start (default_bb); - t = built_in_decls[BUILT_IN_TRAP]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0); bsi_insert_after (&si, t, BSI_CONTINUE_LINKING); /* Code to get the next section goes in L1_BB. */ @@ -3294,8 +3272,7 @@ expand_omp_sections (struct omp_region *region) si = bsi_last (l1_bb); gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE); - t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0); t = build2 (GIMPLE_MODIFY_STMT, void_type_node, v, t); bsi_insert_after (&si, t, BSI_SAME_STMT); bsi_remove (&si, true); @@ -3309,7 +3286,7 @@ expand_omp_sections (struct omp_region *region) t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT]; else t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (t, 0); bsi_insert_after (&si, t, BSI_SAME_STMT); bsi_remove (&si, true); } @@ -3680,8 +3657,7 @@ lower_omp_single_simple (tree single_stmt, tree *pre_p) { tree t; - t = built_in_decls[BUILT_IN_GOMP_SINGLE_START]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_START], 0); t = build3 (COND_EXPR, void_type_node, t, OMP_SINGLE_BODY (single_stmt), NULL); gimplify_and_add (t, pre_p); @@ -3720,7 +3696,7 @@ lower_omp_single_simple (tree single_stmt, tree *pre_p) static void lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx) { - tree ptr_type, t, args, l0, l1, l2, copyin_seq; + tree ptr_type, t, l0, l1, l2, copyin_seq; ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o"); @@ -3731,8 +3707,7 @@ lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx) l1 = create_artificial_label (); l2 = create_artificial_label (); - t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START]; - t = build_function_call_expr (t, NULL); + t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0); t = fold_convert (ptr_type, t); t = build2 (GIMPLE_MODIFY_STMT, void_type_node, ctx->receiver_decl, t); gimplify_and_add (t, pre_p); @@ -3753,9 +3728,7 @@ lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx) ©in_seq, ctx); t = build_fold_addr_expr (ctx->sender_decl); - args = tree_cons (NULL, t, NULL); - t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END]; - t = build_function_call_expr (t, args); + t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t); gimplify_and_add (t, pre_p); t = build_and_jump (&l2); @@ -3828,8 +3801,7 @@ lower_omp_master (tree *stmt_p, omp_context *ctx) append_to_statement_list (stmt, &BIND_EXPR_BODY (bind)); - x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM]; - x = build_function_call_expr (x, NULL); + x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0); x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node); x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab)); gimplify_and_add (x, &BIND_EXPR_BODY (bind)); @@ -3868,8 +3840,7 @@ lower_omp_ordered (tree *stmt_p, omp_context *ctx) append_to_statement_list (stmt, &BIND_EXPR_BODY (bind)); - x = built_in_decls[BUILT_IN_GOMP_ORDERED_START]; - x = build_function_call_expr (x, NULL); + x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0); gimplify_and_add (x, &BIND_EXPR_BODY (bind)); lower_omp (&OMP_ORDERED_BODY (stmt), ctx); @@ -3877,8 +3848,7 @@ lower_omp_ordered (tree *stmt_p, omp_context *ctx) append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind)); OMP_ORDERED_BODY (stmt) = NULL; - x = built_in_decls[BUILT_IN_GOMP_ORDERED_END]; - x = build_function_call_expr (x, NULL); + x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0); gimplify_and_add (x, &BIND_EXPR_BODY (bind)); x = make_node (OMP_RETURN); @@ -3909,7 +3879,7 @@ lower_omp_critical (tree *stmt_p, omp_context *ctx) name = OMP_CRITICAL_NAME (stmt); if (name) { - tree decl, args; + tree decl; splay_tree_node n; if (!critical_name_mutexes) @@ -3939,21 +3909,19 @@ lower_omp_critical (tree *stmt_p, omp_context *ctx) else decl = (tree) n->value; - args = tree_cons (NULL, build_fold_addr_expr (decl), NULL); lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START]; - lock = build_function_call_expr (lock, args); + lock = build_call_expr (lock, 1, build_fold_addr_expr (decl)); - args = tree_cons (NULL, build_fold_addr_expr (decl), NULL); unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END]; - unlock = build_function_call_expr (unlock, args); + unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl)); } else { lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START]; - lock = build_function_call_expr (lock, NULL); + lock = build_call_expr (lock, 0); unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END]; - unlock = build_function_call_expr (unlock, NULL); + unlock = build_call_expr (unlock, 0); } push_gimplify_context (); diff --git a/gcc/optabs.c b/gcc/optabs.c index c8ec9ef05a5..6a78b3785ac 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -410,7 +410,7 @@ expand_widen_pattern_expr (tree exp, rtx op0, rtx op1, rtx wide_op, rtx target, rtx temp; rtx pat; rtx xop0, xop1, wxop; - int nops = TREE_CODE_LENGTH (TREE_CODE (exp)); + int nops = TREE_OPERAND_LENGTH (exp); oprnd0 = TREE_OPERAND (exp, 0); tmode0 = TYPE_MODE (TREE_TYPE (oprnd0)); diff --git a/gcc/predict.c b/gcc/predict.c index 39de19b21aa..df5d3105953 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -913,16 +913,14 @@ expr_expected_value (tree expr, bitmap visited) if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL && DECL_FUNCTION_CODE (decl) == BUILT_IN_EXPECT) { - tree arglist = TREE_OPERAND (expr, 1); tree val; - if (arglist == NULL_TREE - || TREE_CHAIN (arglist) == NULL_TREE) - return NULL; - val = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (expr, 1))); + if (call_expr_nargs (expr) != 2) + return NULL; + val = CALL_EXPR_ARG (expr, 0); if (TREE_CONSTANT (val)) return val; - return TREE_VALUE (TREE_CHAIN (TREE_OPERAND (expr, 1))); + return CALL_EXPR_ARG (expr, 1); } } if (BINARY_CLASS_P (expr) || COMPARISON_CLASS_P (expr)) @@ -965,17 +963,17 @@ strip_builtin_expect (void) { tree stmt = bsi_stmt (bi); tree fndecl; - tree arglist; + tree call; if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT - && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == CALL_EXPR - && (fndecl = get_callee_fndecl (GIMPLE_STMT_OPERAND (stmt, 1))) + && (call = GIMPLE_STMT_OPERAND (stmt, 1)) + && TREE_CODE (call) == CALL_EXPR + && (fndecl = get_callee_fndecl (call)) && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT - && (arglist = TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt, 1), 1)) - && TREE_CHAIN (arglist)) + && call_expr_nargs (call) == 2) { - GIMPLE_STMT_OPERAND (stmt, 1) = TREE_VALUE (arglist); + GIMPLE_STMT_OPERAND (stmt, 1) = CALL_EXPR_ARG (call, 0); update_stmt (stmt); } } diff --git a/gcc/print-tree.c b/gcc/print-tree.c index ab4ae608209..7eef3a386d2 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -661,6 +661,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent) case tcc_binary: case tcc_reference: case tcc_statement: + case tcc_vl_exp: if (TREE_CODE (node) == BIT_FIELD_REF && BIT_FIELD_REF_UNSIGNED (node)) fputs (" unsigned", file); if (TREE_CODE (node) == BIND_EXPR) @@ -670,17 +671,34 @@ print_node (FILE *file, const char *prefix, tree node, int indent) print_node (file, "block", TREE_OPERAND (node, 2), indent + 4); break; } - - len = TREE_CODE_LENGTH (TREE_CODE (node)); - - for (i = 0; i < len; i++) + if (TREE_CODE (node) == CALL_EXPR) { - char temp[10]; - - sprintf (temp, "arg %d", i); - print_node (file, temp, TREE_OPERAND (node, i), indent + 4); + call_expr_arg_iterator iter; + tree arg; + print_node (file, "fn", CALL_EXPR_FN (node), indent + 4); + print_node (file, "static_chain", CALL_EXPR_STATIC_CHAIN (node), + indent + 4); + i = 0; + FOR_EACH_CALL_EXPR_ARG (arg, iter, node) + { + char temp[10]; + sprintf (temp, "arg %d", i); + print_node (file, temp, arg, indent + 4); + i++; + } } + else + { + len = TREE_OPERAND_LENGTH (node); + for (i = 0; i < len; i++) + { + char temp[10]; + + sprintf (temp, "arg %d", i); + print_node (file, temp, TREE_OPERAND (node, i), indent + 4); + } + } print_node (file, "chain", TREE_CHAIN (node), indent + 4); break; diff --git a/gcc/stmt.c b/gcc/stmt.c index 819d9be85b6..9578293d7ae 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -1477,7 +1477,7 @@ warn_if_unused_value (tree exp, location_t locus) /* If this is an expression which has no operands, there is no value to be unused. There are no such language-independent codes, but front ends may define such. */ - if (EXPRESSION_CLASS_P (exp) && TREE_CODE_LENGTH (TREE_CODE (exp)) == 0) + if (EXPRESSION_CLASS_P (exp) && TREE_OPERAND_LENGTH (exp) == 0) return 0; warn: diff --git a/gcc/targhooks.c b/gcc/targhooks.c index fe0007905bf..982fcdb188e 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -432,7 +432,7 @@ default_external_stack_protect_fail (void) stack_chk_fail_decl = t; } - return build_function_call_expr (t, NULL_TREE); + return build_call_expr (t, 0); } tree @@ -465,7 +465,7 @@ default_hidden_stack_protect_fail (void) stack_chk_fail_decl = t; } - return build_function_call_expr (t, NULL_TREE); + return build_call_expr (t, 0); #endif } diff --git a/gcc/tree-browser.c b/gcc/tree-browser.c index 0c3eba0b631..51f8200f313 100644 --- a/gcc/tree-browser.c +++ b/gcc/tree-browser.c @@ -730,45 +730,16 @@ store_child_info (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, node = *tp; /* 'node' is the parent of 'TREE_OPERAND (node, *)'. */ - if (EXPRESSION_CLASS_P (node)) + if (EXPR_P (node)) { - -#define STORE_CHILD(N) do { \ - tree op = TREE_OPERAND (node, N); \ - slot = htab_find_slot (TB_up_ht, op, INSERT); \ - *slot = (void *) node; \ -} while (0) - - switch (TREE_CODE_LENGTH (TREE_CODE (node))) + int n = TREE_OPERAND_LENGTH (node); + int i; + for (i = 0; i < n; i++) { - case 4: - STORE_CHILD (0); - STORE_CHILD (1); - STORE_CHILD (2); - STORE_CHILD (3); - break; - - case 3: - STORE_CHILD (0); - STORE_CHILD (1); - STORE_CHILD (2); - break; - - case 2: - STORE_CHILD (0); - STORE_CHILD (1); - break; - - case 1: - STORE_CHILD (0); - break; - - case 0: - default: - /* No children: nothing to do. */ - break; + tree op = TREE_OPERAND (node, i); + slot = htab_find_slot (TB_up_ht, op, INSERT); + *slot = (void *) node; } -#undef STORE_CHILD } /* Never stop walk_tree. */ @@ -787,46 +758,14 @@ TB_parent_eq (const void *p1, const void *p2) if (p1 == NULL || p2 == NULL) return 0; - if (EXPRESSION_CLASS_P (parent)) + if (EXPR_P (parent)) { - -#define TEST_CHILD(N) do { \ - if (node == TREE_OPERAND (parent, N)) \ - return 1; \ -} while (0) - - switch (TREE_CODE_LENGTH (TREE_CODE (parent))) - { - case 4: - TEST_CHILD (0); - TEST_CHILD (1); - TEST_CHILD (2); - TEST_CHILD (3); - break; - - case 3: - TEST_CHILD (0); - TEST_CHILD (1); - TEST_CHILD (2); - break; - - case 2: - TEST_CHILD (0); - TEST_CHILD (1); - break; - - case 1: - TEST_CHILD (0); - break; - - case 0: - default: - /* No children: nothing to do. */ - break; - } -#undef TEST_CHILD + int n = TREE_OPERAND_LENGTH (parent); + int i; + for (i = 0; i < n; i++) + if (node == TREE_OPERAND (parent, i)) + return 1; } - return 0; } diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c index ae95fc8c496..119a35b97c2 100644 --- a/gcc/tree-chrec.c +++ b/gcc/tree-chrec.c @@ -860,6 +860,8 @@ is_multivariate_chrec (tree chrec) bool chrec_contains_symbols (tree chrec) { + int i, n; + if (chrec == NULL_TREE) return false; @@ -871,24 +873,12 @@ chrec_contains_symbols (tree chrec) || TREE_CODE (chrec) == RESULT_DECL || TREE_CODE (chrec) == FIELD_DECL) return true; - - switch (TREE_CODE_LENGTH (TREE_CODE (chrec))) - { - case 3: - if (chrec_contains_symbols (TREE_OPERAND (chrec, 2))) - return true; - - case 2: - if (chrec_contains_symbols (TREE_OPERAND (chrec, 1))) - return true; - - case 1: - if (chrec_contains_symbols (TREE_OPERAND (chrec, 0))) - return true; - - default: - return false; - } + + n = TREE_OPERAND_LENGTH (chrec); + for (i = 0; i < n; i++) + if (chrec_contains_symbols (TREE_OPERAND (chrec, i))) + return true; + return false; } /* Determines whether the chrec contains undetermined coefficients. */ @@ -896,28 +886,18 @@ chrec_contains_symbols (tree chrec) bool chrec_contains_undetermined (tree chrec) { + int i, n; + if (chrec == chrec_dont_know || chrec == chrec_not_analyzed_yet || chrec == NULL_TREE) return true; - - switch (TREE_CODE_LENGTH (TREE_CODE (chrec))) - { - case 3: - if (chrec_contains_undetermined (TREE_OPERAND (chrec, 2))) - return true; - - case 2: - if (chrec_contains_undetermined (TREE_OPERAND (chrec, 1))) - return true; - - case 1: - if (chrec_contains_undetermined (TREE_OPERAND (chrec, 0))) - return true; - - default: - return false; - } + + n = TREE_OPERAND_LENGTH (chrec); + for (i = 0; i < n; i++) + if (chrec_contains_undetermined (TREE_OPERAND (chrec, i))) + return true; + return false; } /* Determines whether the tree EXPR contains chrecs, and increment @@ -927,6 +907,8 @@ chrec_contains_undetermined (tree chrec) bool tree_contains_chrecs (tree expr, int *size) { + int i, n; + if (expr == NULL_TREE) return false; @@ -936,23 +918,11 @@ tree_contains_chrecs (tree expr, int *size) if (tree_is_chrec (expr)) return true; - switch (TREE_CODE_LENGTH (TREE_CODE (expr))) - { - case 3: - if (tree_contains_chrecs (TREE_OPERAND (expr, 2), size)) - return true; - - case 2: - if (tree_contains_chrecs (TREE_OPERAND (expr, 1), size)) - return true; - - case 1: - if (tree_contains_chrecs (TREE_OPERAND (expr, 0), size)) - return true; - - default: - return false; - } + n = TREE_OPERAND_LENGTH (expr); + for (i = 0; i < n; i++) + if (tree_contains_chrecs (TREE_OPERAND (expr, i), size)) + return true; + return false; } /* Recursive helper function. */ @@ -978,7 +948,7 @@ evolution_function_is_invariant_rec_p (tree chrec, int loopnum) return true; } - switch (TREE_CODE_LENGTH (TREE_CODE (chrec))) + switch (TREE_OPERAND_LENGTH (chrec)) { case 2: if (!evolution_function_is_invariant_rec_p (TREE_OPERAND (chrec, 1), diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c index f985503a835..fce124eb595 100644 --- a/gcc/tree-complex.c +++ b/gcc/tree-complex.c @@ -885,12 +885,7 @@ expand_complex_libcall (block_stmt_iterator *bsi, tree ar, tree ai, { enum machine_mode mode; enum built_in_function bcode; - tree args, fn, stmt, type; - - args = tree_cons (NULL, bi, NULL); - args = tree_cons (NULL, br, args); - args = tree_cons (NULL, ai, args); - args = tree_cons (NULL, ar, args); + tree fn, stmt, type; stmt = bsi_stmt (*bsi); type = TREE_TYPE (GIMPLE_STMT_OPERAND (stmt, 1)); @@ -905,8 +900,7 @@ expand_complex_libcall (block_stmt_iterator *bsi, tree ar, tree ai, gcc_unreachable (); fn = built_in_decls[bcode]; - GIMPLE_STMT_OPERAND (stmt, 1) - = build3 (CALL_EXPR, type, build_fold_addr_expr (fn), args, NULL); + GIMPLE_STMT_OPERAND (stmt, 1) = build_call_expr (fn, 4, ar, ai, br, bi); update_stmt (stmt); if (gimple_in_ssa_p (cfun)) diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index d49d68220c0..b84f36be660 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -4249,7 +4249,8 @@ get_references_in_stmt (tree stmt, VEC (data_ref_loc, heap) **references) { bool clobbers_memory = false; data_ref_loc *ref; - tree *op0, *op1, args, call; + tree *op0, *op1, arg, call; + call_expr_arg_iterator iter; *references = NULL; @@ -4290,9 +4291,9 @@ get_references_in_stmt (tree stmt, VEC (data_ref_loc, heap) **references) if (call) { - for (args = TREE_OPERAND (call, 1); args; args = TREE_CHAIN (args)) + FOR_EACH_CALL_EXPR_ARG (arg, iter, call) { - op0 = &TREE_VALUE (args); + op0 = &arg; if (DECL_P (*op0) || REFERENCE_CLASS_P (*op0)) { diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c index c5a87da343d..73edcc891cf 100644 --- a/gcc/tree-dump.c +++ b/gcc/tree-dump.c @@ -607,8 +607,19 @@ dequeue_and_dump (dump_info_p di) break; case CALL_EXPR: - dump_child ("fn", TREE_OPERAND (t, 0)); - dump_child ("args", TREE_OPERAND (t, 1)); + { + int i = 0; + tree arg; + call_expr_arg_iterator iter; + dump_child ("fn", CALL_EXPR_FN (t)); + FOR_EACH_CALL_EXPR_ARG (arg, iter, t) + { + char buffer[32]; + sprintf (buffer, "%u", i); + dump_child (buffer, arg); + i++; + } + } break; case CONSTRUCTOR: diff --git a/gcc/tree-gimple.c b/gcc/tree-gimple.c index abef0e20539..5530afb231d 100644 --- a/gcc/tree-gimple.c +++ b/gcc/tree-gimple.c @@ -420,7 +420,7 @@ is_gimple_cast (tree t) || TREE_CODE (t) == FIX_TRUNC_EXPR); } -/* Return true if T is a valid op0 of a CALL_EXPR. */ +/* Return true if T is a valid function operand of a CALL_EXPR. */ bool is_gimple_call_addr (tree t) @@ -474,7 +474,7 @@ void recalculate_side_effects (tree t) { enum tree_code code = TREE_CODE (t); - int len = TREE_CODE_LENGTH (code); + int len = TREE_OPERAND_LENGTH (t); int i; switch (TREE_CODE_CLASS (code)) @@ -502,6 +502,7 @@ recalculate_side_effects (tree t) case tcc_unary: /* a unary arithmetic expression */ case tcc_binary: /* a binary arithmetic expression */ case tcc_reference: /* a reference */ + case tcc_vl_exp: /* a function call */ TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t); for (i = 0; i < len; ++i) { diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index d2d9487d367..4e6e3dee5ff 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1430,10 +1430,10 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn, } /* Generate code to initialize the parameters of the function at the - top of the stack in ID from the ARGS (presented as a TREE_LIST). */ + top of the stack in ID from the CALL_EXPR EXP. */ static void -initialize_inlined_parameters (copy_body_data *id, tree args, tree static_chain, +initialize_inlined_parameters (copy_body_data *id, tree exp, tree fn, basic_block bb) { tree parms; @@ -1441,14 +1441,16 @@ initialize_inlined_parameters (copy_body_data *id, tree args, tree static_chain, tree p; tree vars = NULL_TREE; int argnum = 0; + call_expr_arg_iterator iter; + tree static_chain = CALL_EXPR_STATIC_CHAIN (exp); /* Figure out what the parameters are. */ parms = DECL_ARGUMENTS (fn); /* Loop through the parameter declarations, replacing each with an equivalent VAR_DECL, appropriately initialized. */ - for (p = parms, a = args; p; - a = a ? TREE_CHAIN (a) : a, p = TREE_CHAIN (p)) + for (p = parms, a = first_call_expr_arg (exp, &iter); p; + a = next_call_expr_arg (&iter), p = TREE_CHAIN (p)) { tree value; @@ -1456,7 +1458,7 @@ initialize_inlined_parameters (copy_body_data *id, tree args, tree static_chain, /* Find the initializer. */ value = lang_hooks.tree_inlining.convert_parm_for_inlining - (p, a ? TREE_VALUE (a) : NULL_TREE, fn, argnum); + (p, a, fn, argnum); setup_one_parameter (id, p, value, fn, bb, &vars); } @@ -2172,7 +2174,6 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) case CALL_EXPR: { tree decl = get_callee_fndecl (x); - tree arg; cost = d->weights->call_cost; if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) @@ -2195,11 +2196,14 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) that does use function declaration to figure out the arguments. */ if (!decl) { - for (arg = TREE_OPERAND (x, 1); arg; arg = TREE_CHAIN (arg)) - d->count += estimate_move_cost (TREE_TYPE (TREE_VALUE (arg))); + tree a; + call_expr_arg_iterator iter; + FOR_EACH_CALL_EXPR_ARG (a, iter, x) + d->count += estimate_move_cost (TREE_TYPE (a)); } else { + tree arg; for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) d->count += estimate_move_cost (TREE_TYPE (arg)); } @@ -2337,7 +2341,6 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data) tree use_retvar; tree fn; splay_tree st; - tree args; tree return_slot; tree modify_dest; location_t saved_location; @@ -2495,15 +2498,12 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data) id->decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL); - /* Initialize the parameters. */ - args = TREE_OPERAND (t, 1); - /* Record the function we are about to inline. */ id->src_fn = fn; id->src_node = cg_edge->callee; id->src_cfun = DECL_STRUCT_FUNCTION (fn); - initialize_inlined_parameters (id, args, TREE_OPERAND (t, 2), fn, bb); + initialize_inlined_parameters (id, t, fn, bb); if (DECL_INITIAL (fn)) add_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id)); diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c index 4d80c19d385..e6b64687858 100644 --- a/gcc/tree-mudflap.c +++ b/gcc/tree-mudflap.c @@ -656,20 +656,13 @@ mf_build_check_statement_for (tree base, tree limit, refresh *_l vars. This is the body of the conditional. */ - - u = tree_cons (NULL_TREE, - mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION - : *locus), - NULL_TREE); - u = tree_cons (NULL_TREE, dirflag, u); + + u = mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION : *locus); /* NB: we pass the overall [base..limit] range to mf_check. */ - u = tree_cons (NULL_TREE, - fold_build2 (PLUS_EXPR, integer_type_node, - fold_build2 (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base), - integer_one_node), - u); - u = tree_cons (NULL_TREE, mf_base, u); - t = build_function_call_expr (mf_check_fndecl, u); + v = fold_build2 (PLUS_EXPR, integer_type_node, + fold_build2 (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base), + integer_one_node); + t = build_call_expr (mf_check_fndecl, 4, mf_base, v, dirflag, u); gimplify_to_stmt_list (&t); head = tsi_start (t); tsi = tsi_last (t); @@ -996,48 +989,38 @@ mx_register_decls (tree decl, tree *stmt_list) && ! TREE_STATIC (decl)) { tree size = NULL_TREE, variable_name; - tree unregister_fncall, unregister_fncall_params; - tree register_fncall, register_fncall_params; + tree unregister_fncall, unregister_fncall_param; + tree register_fncall, register_fncall_param; size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl))); - /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */ - unregister_fncall_params = - tree_cons (NULL_TREE, - convert (ptr_type_node, - mf_mark (build1 (ADDR_EXPR, - build_pointer_type (TREE_TYPE (decl)), - decl))), - tree_cons (NULL_TREE, - size, - tree_cons (NULL_TREE, - /* __MF_TYPE_STACK */ - build_int_cst (NULL_TREE, 3), - NULL_TREE))); - /* __mf_unregister (...) */ - unregister_fncall = build_function_call_expr (mf_unregister_fndecl, - unregister_fncall_params); - - /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */ + + unregister_fncall_param = + convert (ptr_type_node, + mf_mark (build1 (ADDR_EXPR, + build_pointer_type (TREE_TYPE (decl)), + decl))); + /* __mf_unregister (&VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */ + unregister_fncall = build_call_expr (mf_unregister_fndecl, 3, + unregister_fncall_param, + size, + build_int_cst (NULL_TREE, 3)); + + variable_name = mf_varname_tree (decl); - register_fncall_params = - tree_cons (NULL_TREE, - convert (ptr_type_node, - mf_mark (build1 (ADDR_EXPR, - build_pointer_type (TREE_TYPE (decl)), - decl))), - tree_cons (NULL_TREE, - size, - tree_cons (NULL_TREE, - /* __MF_TYPE_STACK */ - build_int_cst (NULL_TREE, 3), - tree_cons (NULL_TREE, - variable_name, - NULL_TREE)))); - - /* __mf_register (...) */ - register_fncall = build_function_call_expr (mf_register_fndecl, - register_fncall_params); + register_fncall_param = + convert (ptr_type_node, + mf_mark (build1 (ADDR_EXPR, + build_pointer_type (TREE_TYPE (decl)), + decl))); + /* __mf_register (&VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, + "name") */ + register_fncall = build_call_expr (mf_register_fndecl, 4, + register_fncall_param, + size, + build_int_cst (NULL_TREE, 3), + variable_name); + /* Accumulate the two calls. */ /* ??? Set EXPR_LOCATION. */ @@ -1172,21 +1155,17 @@ static GTY (()) tree enqueued_call_stmt_chain; static void mudflap_register_call (tree obj, tree object_size, tree varname) { - tree arg, args, call_stmt; - - args = tree_cons (NULL_TREE, varname, NULL_TREE); - - arg = build_int_cst (NULL_TREE, 4); /* __MF_TYPE_STATIC */ - args = tree_cons (NULL_TREE, arg, args); - - arg = convert (size_type_node, object_size); - args = tree_cons (NULL_TREE, arg, args); + tree arg, call_stmt; arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj); arg = convert (ptr_type_node, arg); - args = tree_cons (NULL_TREE, arg, args); - call_stmt = build_function_call_expr (mf_register_fndecl, args); + call_stmt = build_call_expr (mf_register_fndecl, 4, + arg, + convert (size_type_node, object_size), + /* __MF_TYPE_STATIC */ + build_int_cst (NULL_TREE, 4), + varname); append_to_statement_list (call_stmt, &enqueued_call_stmt_chain); } @@ -1243,16 +1222,15 @@ mudflap_finish_file (void) /* Insert a call to __mf_init. */ { - tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE); + tree call2_stmt = build_call_expr (mf_init_fndecl, 0); append_to_statement_list (call2_stmt, &ctor_statements); } /* If appropriate, call __mf_set_options to pass along read-ignore mode. */ if (flag_mudflap_ignore_reads) { - tree arg = tree_cons (NULL_TREE, - mf_build_string ("-ignore-reads"), NULL_TREE); - tree call_stmt = build_function_call_expr (mf_set_options_fndecl, arg); + tree arg = mf_build_string ("-ignore-reads"); + tree call_stmt = build_call_expr (mf_set_options_fndecl, 1, arg); append_to_statement_list (call_stmt, &ctor_statements); } diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index a3ea11432d0..0713773f761 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -1437,7 +1437,7 @@ convert_nl_goto_reference (tree *tp, int *walk_subtrees, void *data) { struct walk_stmt_info *wi = (struct walk_stmt_info *) data; struct nesting_info *info = wi->info, *i; - tree t = *tp, label, new_label, target_context, x, arg, field; + tree t = *tp, label, new_label, target_context, x, field; void **slot; *walk_subtrees = 0; @@ -1475,11 +1475,8 @@ convert_nl_goto_reference (tree *tp, int *walk_subtrees, void *data) x = get_frame_field (info, target_context, field, &wi->tsi); x = build_addr (x, target_context); x = tsi_gimplify_val (info, x, &wi->tsi); - arg = tree_cons (NULL, x, NULL); - x = build_addr (new_label, target_context); - arg = tree_cons (NULL, x, arg); - x = implicit_built_in_decls[BUILT_IN_NONLOCAL_GOTO]; - x = build_function_call_expr (x, arg); + x = build_call_expr (implicit_built_in_decls[BUILT_IN_NONLOCAL_GOTO], 2, + build_addr (new_label, target_context), x); SET_EXPR_LOCUS (x, EXPR_LOCUS (tsi_stmt (wi->tsi))); *tsi_stmt_ptr (wi->tsi) = x; @@ -1537,7 +1534,7 @@ convert_tramp_reference (tree *tp, int *walk_subtrees, void *data) { struct walk_stmt_info *wi = (struct walk_stmt_info *) data; struct nesting_info *info = wi->info, *i; - tree t = *tp, decl, target_context, x, arg; + tree t = *tp, decl, target_context, x; *walk_subtrees = 0; switch (TREE_CODE (t)) @@ -1573,12 +1570,11 @@ convert_tramp_reference (tree *tp, int *walk_subtrees, void *data) x = get_frame_field (info, target_context, x, &wi->tsi); x = build_addr (x, target_context); x = tsi_gimplify_val (info, x, &wi->tsi); - arg = tree_cons (NULL, x, NULL); /* Do machine-specific ugliness. Normally this will involve computing extra alignment, but it can really be anything. */ - x = implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE]; - x = build_function_call_expr (x, arg); + x = build_call_expr (implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE], + 1, x); x = init_tmp_var (info, x, &wi->tsi); /* Cast back to the proper function type. */ @@ -1591,7 +1587,12 @@ convert_tramp_reference (tree *tp, int *walk_subtrees, void *data) case CALL_EXPR: /* Only walk call arguments, lest we generate trampolines for direct calls. */ - walk_tree (&TREE_OPERAND (t, 1), convert_tramp_reference, wi, NULL); + { + int nargs = call_expr_nargs (t); + int i; + for (i = 0; i < nargs; i++) + walk_tree (&CALL_EXPR_ARG (t, i), convert_tramp_reference, wi, NULL); + } break; default: @@ -1626,7 +1627,7 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data) target_context = decl_function_context (decl); if (target_context && !DECL_NO_STATIC_CHAIN (decl)) { - TREE_OPERAND (t, 2) + CALL_EXPR_STATIC_CHAIN (t) = get_static_chain (info, target_context, &wi->tsi); info->static_chain_added |= (1 << (info->context != target_context)); @@ -1777,29 +1778,25 @@ finalize_nesting_tree_1 (struct nesting_info *root) struct nesting_info *i; for (i = root->inner; i ; i = i->next) { - tree arg, x, field; + tree arg1, arg2, arg3, x, field; field = lookup_tramp_for_decl (root, i->context, NO_INSERT); if (!field) continue; if (DECL_NO_STATIC_CHAIN (i->context)) - x = null_pointer_node; + arg3 = null_pointer_node; else - x = build_addr (root->frame_decl, context); - arg = tree_cons (NULL, x, NULL); + arg3 = build_addr (root->frame_decl, context); - x = build_addr (i->context, context); - arg = tree_cons (NULL, x, arg); + arg2 = build_addr (i->context, context); x = build3 (COMPONENT_REF, TREE_TYPE (field), root->frame_decl, field, NULL_TREE); - x = build_addr (x, context); - arg = tree_cons (NULL, x, arg); + arg1 = build_addr (x, context); x = implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE]; - x = build_function_call_expr (x, arg); - + x = build_call_expr (x, 3, arg1, arg2, arg3); append_to_statement_list (x, &stmt_list); } } diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index a93464b22fa..f1852ca5a7b 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -228,49 +228,41 @@ addr_object_size (tree ptr, int object_size_type) static unsigned HOST_WIDE_INT alloc_object_size (tree call, int object_size_type) { - tree callee, arglist, a, bytes = NULL_TREE; - unsigned int arg_mask = 0; + tree callee, bytes = NULL_TREE; gcc_assert (TREE_CODE (call) == CALL_EXPR); callee = get_callee_fndecl (call); - arglist = TREE_OPERAND (call, 1); if (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) switch (DECL_FUNCTION_CODE (callee)) { case BUILT_IN_MALLOC: case BUILT_IN_ALLOCA: - arg_mask = 1; + if (call_expr_nargs (call) == 1 + && TREE_CODE (CALL_EXPR_ARG (call, 0)) == INTEGER_CST) + bytes = fold_convert (sizetype, CALL_EXPR_ARG (call, 0)); break; /* case BUILT_IN_REALLOC: - arg_mask = 2; + if (call_expr_nargs (call) == 2 + && TREE_CODE (CALL_EXPR_ARG (call, 1)) == INTEGER_CST) + bytes = fold_convert (sizetype, CALL_EXPR_ARG (call, 1)); break; */ case BUILT_IN_CALLOC: - arg_mask = 3; + if (call_expr_nargs (call) == 2 + && TREE_CODE (CALL_EXPR_ARG (call, 0)) == INTEGER_CST + && TREE_CODE (CALL_EXPR_ARG (call, 1)) == INTEGER_CST) + bytes = size_binop (MULT_EXPR, + fold_convert (sizetype, CALL_EXPR_ARG (call, 0)), + fold_convert (sizetype, CALL_EXPR_ARG (call, 1))); break; default: break; } - for (a = arglist; arg_mask && a; arg_mask >>= 1, a = TREE_CHAIN (a)) - if (arg_mask & 1) - { - tree arg = TREE_VALUE (a); - - if (TREE_CODE (arg) != INTEGER_CST) - break; - - if (! bytes) - bytes = fold_convert (sizetype, arg); - else - bytes = size_binop (MULT_EXPR, bytes, - fold_convert (sizetype, arg)); - } - - if (! arg_mask && bytes && host_integerp (bytes, 1)) + if (bytes && host_integerp (bytes, 1)) return tree_low_cst (bytes, 1); return unknown[object_size_type]; @@ -285,7 +277,6 @@ static tree pass_through_call (tree call) { tree callee = get_callee_fndecl (call); - tree arglist = TREE_OPERAND (call, 1); if (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) @@ -305,8 +296,8 @@ pass_through_call (tree call) case BUILT_IN_STRNCPY_CHK: case BUILT_IN_STRCAT_CHK: case BUILT_IN_STRNCAT_CHK: - if (arglist) - return TREE_VALUE (arglist); + if (call_expr_nargs (call) >= 1) + return CALL_EXPR_ARG (call, 0); break; default: break; @@ -1043,17 +1034,13 @@ compute_object_sizes (void) continue; init_object_sizes (); - result = fold_builtin (callee, TREE_OPERAND (call, 1), false); + result = fold_call_expr (call, false); if (!result) { - tree arglist = TREE_OPERAND (call, 1); - - if (arglist != NULL - && POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist))) - && TREE_CHAIN (arglist) != NULL - && TREE_CHAIN (TREE_CHAIN (arglist)) == NULL) + if (call_expr_nargs (call) == 2 + && POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (call, 0)))) { - tree ost = TREE_VALUE (TREE_CHAIN (arglist)); + tree ost = CALL_EXPR_ARG (call, 1); if (host_integerp (ost, 1)) { diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index a942edc8412..8d5ca276ae8 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -74,7 +74,7 @@ do_niy (pretty_printer *buffer, tree node) if (EXPR_P (node)) { - len = TREE_CODE_LENGTH (TREE_CODE (node)); + len = TREE_OPERAND_LENGTH (node); for (i = 0; i < len; ++i) { newline_and_indent (buffer, 2); @@ -1173,12 +1173,22 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, /* Print parameters. */ pp_space (buffer); pp_character (buffer, '('); - op1 = TREE_OPERAND (node, 1); - if (op1) - dump_generic_node (buffer, op1, spc, flags, false); + { + tree arg; + call_expr_arg_iterator iter; + FOR_EACH_CALL_EXPR_ARG (arg, iter, node) + { + dump_generic_node (buffer, arg, spc, flags, false); + if (more_call_expr_args_p (&iter)) + { + pp_character (buffer, ','); + pp_space (buffer); + } + } + } pp_character (buffer, ')'); - op1 = TREE_OPERAND (node, 2); + op1 = CALL_EXPR_STATIC_CHAIN (node); if (op1) { pp_string (buffer, " [static-chain: "); @@ -2528,7 +2538,7 @@ print_call_name (pretty_printer *buffer, tree node) gcc_assert (TREE_CODE (node) == CALL_EXPR); - op0 = TREE_OPERAND (node, 0); + op0 = CALL_EXPR_FN (node); if (TREE_CODE (op0) == NON_LVALUE_EXPR) op0 = TREE_OPERAND (op0, 0); diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index bd7556a074a..b8e54d468e2 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -203,7 +203,7 @@ tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base) tree stmt = value->hvalue.stmt; block_stmt_iterator bsi = bsi_for_stmt (stmt); tree ref = tree_coverage_counter_ref (tag, base), ref_ptr; - tree args, call, val; + tree call, val; tree start = build_int_cst_type (integer_type_node, value->hdata.intvl.int_start); tree steps = build_int_cst_type (unsigned_type_node, value->hdata.intvl.steps); @@ -211,12 +211,8 @@ tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base) build_addr (ref, current_function_decl), true, NULL_TREE); val = prepare_instrumented_value (&bsi, value); - args = tree_cons (NULL_TREE, ref_ptr, - tree_cons (NULL_TREE, val, - tree_cons (NULL_TREE, start, - tree_cons (NULL_TREE, steps, - NULL_TREE)))); - call = build_function_call_expr (tree_interval_profiler_fn, args); + call = build_call_expr (tree_interval_profiler_fn, 4, + ref_ptr, val, start, steps); bsi_insert_before (&bsi, call, BSI_SAME_STMT); } @@ -230,16 +226,13 @@ tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base) tree stmt = value->hvalue.stmt; block_stmt_iterator bsi = bsi_for_stmt (stmt); tree ref = tree_coverage_counter_ref (tag, base), ref_ptr; - tree args, call, val; + tree call, val; ref_ptr = force_gimple_operand_bsi (&bsi, build_addr (ref, current_function_decl), true, NULL_TREE); val = prepare_instrumented_value (&bsi, value); - args = tree_cons (NULL_TREE, ref_ptr, - tree_cons (NULL_TREE, val, - NULL_TREE)); - call = build_function_call_expr (tree_pow2_profiler_fn, args); + call = build_call_expr (tree_pow2_profiler_fn, 2, ref_ptr, val); bsi_insert_before (&bsi, call, BSI_SAME_STMT); } @@ -253,16 +246,13 @@ tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base) tree stmt = value->hvalue.stmt; block_stmt_iterator bsi = bsi_for_stmt (stmt); tree ref = tree_coverage_counter_ref (tag, base), ref_ptr; - tree args, call, val; + tree call, val; ref_ptr = force_gimple_operand_bsi (&bsi, build_addr (ref, current_function_decl), true, NULL_TREE); val = prepare_instrumented_value (&bsi, value); - args = tree_cons (NULL_TREE, ref_ptr, - tree_cons (NULL_TREE, val, - NULL_TREE)); - call = build_function_call_expr (tree_one_value_profiler_fn, args); + call = build_call_expr (tree_one_value_profiler_fn, 2, ref_ptr, val); bsi_insert_before (&bsi, call, BSI_SAME_STMT); } @@ -320,7 +310,7 @@ tree_gen_ic_func_profiler (void) basic_block bb; edge_iterator ei; tree stmt1; - tree args, tree_uid, cur_func; + tree tree_uid, cur_func; if (flag_unit_at_a_time) { @@ -339,13 +329,11 @@ tree_gen_ic_func_profiler (void) current_function_decl), true, NULL_TREE); tree_uid = build_int_cst (gcov_type_node, c_node->pid); - args = tree_cons (NULL_TREE, ic_gcov_type_ptr_var, - tree_cons (NULL_TREE, tree_uid, - tree_cons (NULL_TREE, cur_func, - tree_cons (NULL_TREE, - ic_void_ptr_var, - NULL_TREE)))); - stmt1 = build_function_call_expr (tree_indirect_call_profiler_fn, args); + stmt1 = build_call_expr (tree_indirect_call_profiler_fn, 4, + ic_gcov_type_ptr_var, + tree_uid, + cur_func, + ic_void_ptr_var); bsi_insert_after (&bsi, stmt1, BSI_SAME_STMT); } } @@ -377,14 +365,13 @@ tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base) tree stmt = value->hvalue.stmt; block_stmt_iterator bsi = bsi_for_stmt (stmt); tree ref = tree_coverage_counter_ref (tag, base), ref_ptr; - tree args, call, val; + tree call, val; ref_ptr = force_gimple_operand_bsi (&bsi, build_addr (ref, current_function_decl), true, NULL_TREE); val = prepare_instrumented_value (&bsi, value); - args = tree_cons (NULL_TREE, ref_ptr, tree_cons (NULL_TREE, val, NULL_TREE)); - call = build_function_call_expr (tree_average_profiler_fn, args); + call = build_call_expr (tree_average_profiler_fn, 2, ref_ptr, val); bsi_insert_before (&bsi, call, BSI_SAME_STMT); } @@ -398,14 +385,13 @@ tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base) tree stmt = value->hvalue.stmt; block_stmt_iterator bsi = bsi_for_stmt (stmt); tree ref = tree_coverage_counter_ref (tag, base), ref_ptr; - tree args, call, val; + tree call, val; ref_ptr = force_gimple_operand_bsi (&bsi, build_addr (ref, current_function_decl), true, NULL_TREE); val = prepare_instrumented_value (&bsi, value); - args = tree_cons (NULL_TREE, ref_ptr, tree_cons (NULL_TREE, val, NULL_TREE)); - call = build_function_call_expr (tree_ior_profiler_fn, args); + call = build_call_expr (tree_ior_profiler_fn, 2, ref_ptr, val); bsi_insert_before (&bsi, call, BSI_SAME_STMT); } diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index 43a5e27ddba..9b0df6fb380 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -357,6 +357,8 @@ find_var_scev_info (tree var) bool chrec_contains_symbols_defined_in_loop (tree chrec, unsigned loop_nb) { + int i, n; + if (chrec == NULL_TREE) return false; @@ -386,26 +388,12 @@ chrec_contains_symbols_defined_in_loop (tree chrec, unsigned loop_nb) return false; } - switch (TREE_CODE_LENGTH (TREE_CODE (chrec))) - { - case 3: - if (chrec_contains_symbols_defined_in_loop (TREE_OPERAND (chrec, 2), - loop_nb)) - return true; - - case 2: - if (chrec_contains_symbols_defined_in_loop (TREE_OPERAND (chrec, 1), - loop_nb)) - return true; - - case 1: - if (chrec_contains_symbols_defined_in_loop (TREE_OPERAND (chrec, 0), - loop_nb)) - return true; - - default: - return false; - } + n = TREE_OPERAND_LENGTH (chrec); + for (i = 0; i < n; i++) + if (chrec_contains_symbols_defined_in_loop (TREE_OPERAND (chrec, i), + loop_nb)) + return true; + return false; } /* Return true when PHI is a loop-phi-node. */ @@ -2317,6 +2305,7 @@ instantiate_parameters_1 (struct loop *loop, tree chrec, int flags, htab_t cache break; } + gcc_assert (!VL_EXP_CLASS_P (chrec)); switch (TREE_CODE_LENGTH (TREE_CODE (chrec))) { case 3: diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 364c76370b7..1ecbb3994aa 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -867,7 +867,10 @@ static void sra_walk_call_expr (tree expr, block_stmt_iterator *bsi, const struct sra_walk_fns *fns) { - sra_walk_tree_list (TREE_OPERAND (expr, 1), bsi, false, fns); + int i; + int nargs = call_expr_nargs (expr); + for (i = 0; i < nargs; i++) + sra_walk_expr (&CALL_EXPR_ARG (expr, i), bsi, false, fns); } /* Walk the inputs and outputs of an ASM_EXPR looking for scalarizable diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 5ed2d13adab..e3cdaf9d590 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -3080,11 +3080,13 @@ find_used_portions (tree *tp, int *walk_subtrees, void *lhs_p) break; case CALL_EXPR: { - tree *arg; - for (arg = &TREE_OPERAND (*tp, 1); *arg; arg = &TREE_CHAIN (*arg)) + int i; + int nargs = call_expr_nargs (*tp); + for (i = 0; i < nargs; i++) { - if (TREE_CODE (TREE_VALUE (*arg)) != ADDR_EXPR) - find_used_portions (&TREE_VALUE (*arg), walk_subtrees, NULL); + tree *arg = &CALL_EXPR_ARG (*tp, i); + if (TREE_CODE (*arg) != ADDR_EXPR) + find_used_portions (arg, walk_subtrees, NULL); } *walk_subtrees = 0; return NULL_TREE; diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 459894b24f0..673415c1ca0 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -939,15 +939,13 @@ ccp_fold (tree stmt) /* We may be able to fold away calls to builtin functions if their arguments are constants. */ else if (code == CALL_EXPR - && TREE_CODE (TREE_OPERAND (rhs, 0)) == ADDR_EXPR - && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0)) - == FUNCTION_DECL) - && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0))) + && TREE_CODE (CALL_EXPR_FN (rhs)) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (CALL_EXPR_FN (rhs), 0)) == FUNCTION_DECL + && DECL_BUILT_IN (TREE_OPERAND (CALL_EXPR_FN (rhs), 0))) { if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_USE)) { tree *orig, var; - tree fndecl, arglist; size_t i = 0; ssa_op_iter iter; use_operand_p var_p; @@ -959,9 +957,7 @@ ccp_fold (tree stmt) /* Substitute operands with their values and try to fold. */ replace_uses_in (stmt, NULL, const_val); - fndecl = get_callee_fndecl (rhs); - arglist = TREE_OPERAND (rhs, 1); - retval = fold_builtin (fndecl, arglist, false); + retval = fold_call_expr (rhs, false); /* Restore operands to their original form. */ i = 0; @@ -2219,18 +2215,18 @@ static tree ccp_fold_builtin (tree stmt, tree fn) { tree result, val[3]; - tree callee, arglist, a; + tree callee, a; int arg_mask, i, type; bitmap visited; bool ignore; + call_expr_arg_iterator iter; + int nargs; ignore = TREE_CODE (stmt) != GIMPLE_MODIFY_STMT; /* First try the generic builtin folder. If that succeeds, return the result directly. */ - callee = get_callee_fndecl (fn); - arglist = TREE_OPERAND (fn, 1); - result = fold_builtin (callee, arglist, ignore); + result = fold_call_expr (fn, ignore); if (result) { if (ignore) @@ -2239,12 +2235,14 @@ ccp_fold_builtin (tree stmt, tree fn) } /* Ignore MD builtins. */ + callee = get_callee_fndecl (fn); if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD) return NULL_TREE; /* If the builtin could not be folded, and it has no argument list, we're done. */ - if (!arglist) + nargs = call_expr_nargs (fn); + if (nargs == 0) return NULL_TREE; /* Limit the work only for builtins we know how to simplify. */ @@ -2287,15 +2285,17 @@ ccp_fold_builtin (tree stmt, tree fn) visited = BITMAP_ALLOC (NULL); memset (val, 0, sizeof (val)); - for (i = 0, a = arglist; - arg_mask; - i++, arg_mask >>= 1, a = TREE_CHAIN (a)) - if (arg_mask & 1) - { - bitmap_clear (visited); - if (!get_maxval_strlen (TREE_VALUE (a), &val[i], visited, type)) - val[i] = NULL_TREE; - } + init_call_expr_arg_iterator (fn, &iter); + for (i = 0; arg_mask; i++, arg_mask >>= 1) + { + a = next_call_expr_arg (&iter); + if (arg_mask & 1) + { + bitmap_clear (visited); + if (!get_maxval_strlen (a, &val[i], visited, type)) + val[i] = NULL_TREE; + } + } BITMAP_FREE (visited); @@ -2317,23 +2317,32 @@ ccp_fold_builtin (tree stmt, tree fn) break; case BUILT_IN_STRCPY: - if (val[1] && is_gimple_val (val[1])) - result = fold_builtin_strcpy (callee, arglist, val[1]); + if (val[1] && is_gimple_val (val[1]) && nargs == 2) + result = fold_builtin_strcpy (callee, + CALL_EXPR_ARG (fn, 0), + CALL_EXPR_ARG (fn, 1), + val[1]); break; case BUILT_IN_STRNCPY: - if (val[1] && is_gimple_val (val[1])) - result = fold_builtin_strncpy (callee, arglist, val[1]); + if (val[1] && is_gimple_val (val[1]) && nargs == 3) + result = fold_builtin_strncpy (callee, + CALL_EXPR_ARG (fn, 0), + CALL_EXPR_ARG (fn, 1), + CALL_EXPR_ARG (fn, 2), + val[1]); break; case BUILT_IN_FPUTS: - result = fold_builtin_fputs (arglist, + result = fold_builtin_fputs (CALL_EXPR_ARG (fn, 0), + CALL_EXPR_ARG (fn, 1), TREE_CODE (stmt) != GIMPLE_MODIFY_STMT, 0, val[0]); break; case BUILT_IN_FPUTS_UNLOCKED: - result = fold_builtin_fputs (arglist, + result = fold_builtin_fputs (CALL_EXPR_ARG (fn, 0), + CALL_EXPR_ARG (fn, 1), TREE_CODE (stmt) != GIMPLE_MODIFY_STMT, 1, val[0]); break; @@ -2343,26 +2352,39 @@ ccp_fold_builtin (tree stmt, tree fn) case BUILT_IN_MEMMOVE_CHK: case BUILT_IN_MEMSET_CHK: if (val[2] && is_gimple_val (val[2])) - result = fold_builtin_memory_chk (callee, arglist, val[2], ignore, + result = fold_builtin_memory_chk (callee, + CALL_EXPR_ARG (fn, 0), + CALL_EXPR_ARG (fn, 1), + CALL_EXPR_ARG (fn, 2), + CALL_EXPR_ARG (fn, 3), + val[2], ignore, DECL_FUNCTION_CODE (callee)); break; case BUILT_IN_STRCPY_CHK: case BUILT_IN_STPCPY_CHK: if (val[1] && is_gimple_val (val[1])) - result = fold_builtin_stxcpy_chk (callee, arglist, val[1], ignore, + result = fold_builtin_stxcpy_chk (callee, + CALL_EXPR_ARG (fn, 0), + CALL_EXPR_ARG (fn, 1), + CALL_EXPR_ARG (fn, 2), + val[1], ignore, DECL_FUNCTION_CODE (callee)); break; case BUILT_IN_STRNCPY_CHK: if (val[2] && is_gimple_val (val[2])) - result = fold_builtin_strncpy_chk (arglist, val[2]); + result = fold_builtin_strncpy_chk (CALL_EXPR_ARG (fn, 0), + CALL_EXPR_ARG (fn, 1), + CALL_EXPR_ARG (fn, 2), + CALL_EXPR_ARG (fn, 3), + val[2]); break; case BUILT_IN_SNPRINTF_CHK: case BUILT_IN_VSNPRINTF_CHK: if (val[1] && is_gimple_val (val[1])) - result = fold_builtin_snprintf_chk (arglist, val[1], + result = fold_builtin_snprintf_chk (fn, val[1], DECL_FUNCTION_CODE (callee)); break; @@ -2398,9 +2420,7 @@ fold_stmt (tree *stmt_p) then we may need to fold instances of *&VAR into VAR, etc. */ if (walk_tree (stmt_p, fold_stmt_r, &fold_stmt_r_data, NULL)) { - *stmt_p - = build_function_call_expr (implicit_built_in_decls[BUILT_IN_TRAP], - NULL); + *stmt_p = build_call_expr (implicit_built_in_decls[BUILT_IN_TRAP], 0); return true; } @@ -2428,8 +2448,8 @@ fold_stmt (tree *stmt_p) copying EH region info to the new node. Easier to just do it here where we can just smash the call operand. Also CALL_EXPR_RETURN_SLOT_OPT needs to be handled correctly and - copied, fold_ternary does not have not information. */ - callee = TREE_OPERAND (rhs, 0); + copied, fold_call_expr does not have not information. */ + callee = CALL_EXPR_FN (rhs); if (TREE_CODE (callee) == OBJ_TYPE_REF && lang_hooks.fold_obj_type_ref && TREE_CODE (OBJ_TYPE_REF_OBJECT (callee)) == ADDR_EXPR @@ -2447,7 +2467,7 @@ fold_stmt (tree *stmt_p) t = lang_hooks.fold_obj_type_ref (callee, t); if (t) { - TREE_OPERAND (rhs, 0) = t; + CALL_EXPR_FN (rhs) = t; changed = true; } } diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 04cb28725dc..f1db0376fd1 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -342,10 +342,11 @@ outermost_invariant_loop_expr (tree expr, struct loop *loop) if (class != tcc_unary && class != tcc_binary && class != tcc_expression + && class != tcc_vl_exp && class != tcc_comparison) return NULL; - nops = TREE_CODE_LENGTH (TREE_CODE (expr)); + nops = TREE_OPERAND_LENGTH (expr); for (i = 0; i < nops; i++) { aloop = outermost_invariant_loop_expr (TREE_OPERAND (expr, i), loop); @@ -817,10 +818,11 @@ force_move_till_expr (tree expr, struct loop *orig_loop, struct loop *loop) if (class != tcc_unary && class != tcc_binary && class != tcc_expression + && class != tcc_vl_exp && class != tcc_comparison) return; - nops = TREE_CODE_LENGTH (TREE_CODE (expr)); + nops = TREE_OPERAND_LENGTH (expr); for (i = 0; i < nops; i++) force_move_till_expr (TREE_OPERAND (expr, i), orig_loop, loop); } diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 5982b3d3f62..8ca7e51122f 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -1272,7 +1272,7 @@ expr_invariant_in_loop_p (struct loop *loop, tree expr) if (!EXPR_P (expr) && !GIMPLE_STMT_P (expr)) return false; - len = TREE_CODE_LENGTH (TREE_CODE (expr)); + len = TREE_OPERAND_LENGTH (expr); for (i = 0; i < len; i++) if (!expr_invariant_in_loop_p (loop, TREE_OPERAND (expr, i))) return false; diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 95a9e46c4a8..47267ac594e 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -655,7 +655,7 @@ simplify_replace_tree (tree expr, tree old, tree new) if (!EXPR_P (expr) && !GIMPLE_STMT_P (expr)) return expr; - n = TREE_CODE_LENGTH (TREE_CODE (expr)); + n = TREE_OPERAND_LENGTH (expr); for (i = 0; i < n; i++) { e = TREE_OPERAND (expr, i); @@ -691,7 +691,7 @@ expand_simple_operations (tree expr) code = TREE_CODE (expr); if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))) { - n = TREE_CODE_LENGTH (code); + n = TREE_OPERAND_LENGTH (expr); for (i = 0; i < n; i++) { e = TREE_OPERAND (expr, i); @@ -1882,11 +1882,12 @@ infer_loop_bounds_from_array (struct loop *loop, tree stmt) call = get_call_expr_in (stmt); if (call) { - tree args; + tree arg; + call_expr_arg_iterator iter; - for (args = TREE_OPERAND (call, 1); args; args = TREE_CHAIN (args)) - if (REFERENCE_CLASS_P (TREE_VALUE (args))) - infer_loop_bounds_from_ref (loop, stmt, TREE_VALUE (args)); + FOR_EACH_CALL_EXPR_ARG (arg, iter, call) + if (REFERENCE_CLASS_P (arg)) + infer_loop_bounds_from_ref (loop, stmt, arg); } } diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c index 02093d40d2d..e0612b9a56e 100644 --- a/gcc/tree-ssa-loop-prefetch.c +++ b/gcc/tree-ssa-loop-prefetch.c @@ -815,7 +815,7 @@ static void issue_prefetch_ref (struct mem_ref *ref, unsigned unroll_factor, unsigned ahead) { HOST_WIDE_INT delta; - tree addr, addr_base, prefetch, params, write_p; + tree addr, addr_base, prefetch, write_p; block_stmt_iterator bsi; unsigned n_prefetches, ap; @@ -839,11 +839,8 @@ issue_prefetch_ref (struct mem_ref *ref, unsigned unroll_factor, unsigned ahead) addr = force_gimple_operand_bsi (&bsi, unshare_expr (addr), true, NULL); /* Create the prefetch instruction. */ - params = tree_cons (NULL_TREE, addr, - tree_cons (NULL_TREE, write_p, NULL_TREE)); - - prefetch = build_function_call_expr (built_in_decls[BUILT_IN_PREFETCH], - params); + prefetch = build_call_expr (built_in_decls[BUILT_IN_PREFETCH], + 2, addr, write_p); bsi_insert_before (&bsi, prefetch, BSI_SAME_STMT); } } diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index bb51c3186e6..1861f3e298c 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -606,7 +606,7 @@ execute_cse_sincos_1 (tree name) if (!fndecl) return; res = make_rename_temp (TREE_TYPE (TREE_TYPE (fndecl)), "sincostmp"); - call = build_function_call_expr (fndecl, build_tree_list (NULL_TREE, name)); + call = build_call_expr (fndecl, 1, name); stmt = build2 (GIMPLE_MODIFY_STMT, NULL_TREE, res, call); def_stmt = SSA_NAME_DEF_STMT (name); if (bb_for_stmt (def_stmt) == top_bb @@ -684,7 +684,7 @@ execute_cse_sincos (void) CASE_FLT_FN (BUILT_IN_SIN): CASE_FLT_FN (BUILT_IN_CEXPI): arg = GIMPLE_STMT_OPERAND (stmt, 1); - arg = TREE_VALUE (TREE_OPERAND (arg, 1)); + arg = CALL_EXPR_ARG (arg, 0); if (TREE_CODE (arg) == SSA_NAME) execute_cse_sincos_1 (arg); break; diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index c702ed454db..be9cd6b9a24 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -1871,8 +1871,8 @@ add_call_read_ops (tree stmt, tree callee) static void get_call_expr_operands (tree stmt, tree expr) { - tree op; int call_flags = call_expr_flags (expr); + int i, nargs; stmt_ann_t ann = stmt_ann (stmt); ann->references_memory = true; @@ -1894,12 +1894,12 @@ get_call_expr_operands (tree stmt, tree expr) } /* Find uses in the called function. */ - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_use); - - for (op = TREE_OPERAND (expr, 1); op; op = TREE_CHAIN (op)) - get_expr_operands (stmt, &TREE_VALUE (op), opf_use); + get_expr_operands (stmt, &CALL_EXPR_FN (expr), opf_use); + nargs = call_expr_nargs (expr); + for (i = 0; i < nargs; i++) + get_expr_operands (stmt, &CALL_EXPR_ARG (expr, i), opf_use); - get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_use); + get_expr_operands (stmt, &CALL_EXPR_STATIC_CHAIN (expr), opf_use); } diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 72af16d2caa..b39c9e8e9f3 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -38,6 +38,7 @@ Boston, MA 02110-1301, USA. */ #include "tree-iterator.h" #include "real.h" #include "alloc-pool.h" +#include "obstack.h" #include "tree-pass.h" #include "flags.h" #include "bitmap.h" @@ -387,11 +388,15 @@ static alloc_pool binary_node_pool; static alloc_pool unary_node_pool; static alloc_pool reference_node_pool; static alloc_pool comparison_node_pool; -static alloc_pool expression_node_pool; -static alloc_pool list_node_pool; static alloc_pool modify_expr_node_pool; static bitmap_obstack grand_bitmap_obstack; +/* We can't use allocation pools to hold temporary CALL_EXPR objects, since + they are not of fixed size. Instead, use an obstack. */ + +static struct obstack temp_call_expr_obstack; + + /* To avoid adding 300 temporary variables when we only need one, we only create one temporary variable, on demand, and build ssa names off that. We do have to change the variable if the types don't @@ -881,32 +886,12 @@ fully_constant_expression (tree t) return t; } -/* Return a copy of a chain of nodes, chained through the TREE_CHAIN field. - For example, this can copy a list made of TREE_LIST nodes. - Allocates the nodes in list_node_pool*/ +/* Make a temporary copy of a CALL_EXPR object NODE. */ static tree -pool_copy_list (tree list) +temp_copy_call_expr (tree node) { - tree head; - tree prev, next; - - if (list == 0) - return 0; - head = (tree) pool_alloc (list_node_pool); - - memcpy (head, list, tree_size (list)); - prev = head; - - next = TREE_CHAIN (list); - while (next) - { - TREE_CHAIN (prev) = (tree) pool_alloc (list_node_pool); - memcpy (TREE_CHAIN (prev), next, tree_size (next)); - prev = TREE_CHAIN (prev); - next = TREE_CHAIN (next); - } - return head; + return (tree) obstack_copy (&temp_call_expr_obstack, node, tree_size (node)); } /* Translate the vuses in the VUSES vector backwards through phi nodes @@ -1005,60 +990,52 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2, switch (TREE_CODE_CLASS (TREE_CODE (expr))) { case tcc_expression: + return NULL; + + case tcc_vl_exp: { if (TREE_CODE (expr) != CALL_EXPR) return NULL; else { - tree oldop0 = TREE_OPERAND (expr, 0); - tree oldval0 = oldop0; - tree oldarglist = TREE_OPERAND (expr, 1); - tree oldop2 = TREE_OPERAND (expr, 2); - tree oldval2 = oldop2; - tree newop0; - tree newarglist; - tree newop2 = NULL; - tree oldwalker; - tree newwalker; - tree newexpr; + tree oldfn = CALL_EXPR_FN (expr); + tree oldsc = CALL_EXPR_STATIC_CHAIN (expr); + tree newfn, newsc = NULL; + tree newexpr = NULL_TREE; tree vh = get_value_handle (expr); - bool listchanged = false; bool invariantarg = false; + int i, nargs; VEC (tree, gc) *vuses = VALUE_HANDLE_VUSES (vh); VEC (tree, gc) *tvuses; - /* Call expressions are kind of weird because they have an - argument list. We don't want to value number the list - as one value number, because that doesn't make much - sense, and just breaks the support functions we call, - which expect TREE_OPERAND (call_expr, 2) to be a - TREE_LIST. */ - oldval0 = find_leader_in_sets (oldop0, set1, set2); - newop0 = phi_translate (oldval0, set1, set2, pred, phiblock); - if (newop0 == NULL) + newfn = phi_translate (find_leader_in_sets (oldfn, set1, set2), + set1, set2, pred, phiblock); + if (newfn == NULL) return NULL; - if (oldop2) + if (newfn != oldfn) { - oldop2 = find_leader_in_sets (oldop2, set1, set2); - newop2 = phi_translate (oldop2, set1, set2, pred, phiblock); - if (newop2 == NULL) + newexpr = temp_copy_call_expr (expr); + CALL_EXPR_FN (newexpr) = get_value_handle (newfn); + } + if (oldsc) + { + newsc = phi_translate (find_leader_in_sets (oldsc, set1, set2), + set1, set2, pred, phiblock); + if (newsc == NULL) return NULL; + if (newsc != oldsc) + { + if (!newexpr) + newexpr = temp_copy_call_expr (expr); + CALL_EXPR_STATIC_CHAIN (newexpr) = get_value_handle (newsc); + } } - /* phi translate the argument list piece by piece. - - We could actually build the list piece by piece here, - but it's likely to not be worth the memory we will save, - unless you have millions of call arguments. */ - - newarglist = pool_copy_list (oldarglist); - for (oldwalker = oldarglist, newwalker = newarglist; - oldwalker && newwalker; - oldwalker = TREE_CHAIN (oldwalker), - newwalker = TREE_CHAIN (newwalker)) + /* phi translate the argument list piece by piece. */ + nargs = call_expr_nargs (expr); + for (i = 0; i < nargs; i++) { - - tree oldval = TREE_VALUE (oldwalker); + tree oldval = CALL_EXPR_ARG (expr, i); tree newval; if (oldval) { @@ -1081,40 +1058,36 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2, return NULL; if (newval != oldval) { - listchanged = true; invariantarg |= is_gimple_min_invariant (newval); - TREE_VALUE (newwalker) = get_value_handle (newval); + if (!newexpr) + newexpr = temp_copy_call_expr (expr); + CALL_EXPR_ARG (newexpr, i) = get_value_handle (newval); } } } /* In case of new invariant args we might try to fold the call again. */ - if (invariantarg) + if (invariantarg && !newsc) { - tree tmp = fold_ternary (CALL_EXPR, TREE_TYPE (expr), - newop0, newarglist, newop2); - if (tmp) + tree tmp1 = build_call_array (TREE_TYPE (expr), + newfn, call_expr_nargs (newexpr), + CALL_EXPR_ARGP (newexpr)); + tree tmp2 = fold (tmp1); + if (tmp2 != tmp1) { - STRIP_TYPE_NOPS (tmp); - if (is_gimple_min_invariant (tmp)) - return tmp; + STRIP_TYPE_NOPS (tmp2); + if (is_gimple_min_invariant (tmp2)) + return tmp2; } } - if (listchanged) - vn_lookup_or_add (newarglist, NULL); - tvuses = translate_vuses_through_block (vuses, phiblock, pred); + if (vuses != tvuses && ! newexpr) + newexpr = temp_copy_call_expr (expr); - if (listchanged || (newop0 != oldop0) || (oldop2 != newop2) - || vuses != tvuses) + if (newexpr) { - newexpr = (tree) pool_alloc (expression_node_pool); - memcpy (newexpr, expr, tree_size (expr)); - TREE_OPERAND (newexpr, 0) = newop0 == oldop0 ? oldval0 : get_value_handle (newop0); - TREE_OPERAND (newexpr, 1) = listchanged ? newarglist : oldarglist; - TREE_OPERAND (newexpr, 2) = newop2 == oldop2 ? oldval2 : get_value_handle (newop2); newexpr->base.ann = NULL; vn_lookup_or_add_with_vuses (newexpr, tvuses); expr = newexpr; @@ -1498,22 +1471,25 @@ valid_in_sets (bitmap_set_t set1, bitmap_set_t set2, tree expr, } case tcc_expression: + return false; + + case tcc_vl_exp: { if (TREE_CODE (expr) == CALL_EXPR) { - tree op0 = TREE_OPERAND (expr, 0); - tree arglist = TREE_OPERAND (expr, 1); - tree op2 = TREE_OPERAND (expr, 2); - - /* Check the non-list operands first. */ - if (!union_contains_value (set1, set2, op0) - || (op2 && !union_contains_value (set1, set2, op2))) + tree fn = CALL_EXPR_FN (expr); + tree sc = CALL_EXPR_STATIC_CHAIN (expr); + tree arg; + call_expr_arg_iterator iter; + + /* Check the non-argument operands first. */ + if (!union_contains_value (set1, set2, fn) + || (sc && !union_contains_value (set1, set2, sc))) return false; /* Now check the operands. */ - for (; arglist; arglist = TREE_CHAIN (arglist)) + FOR_EACH_CALL_EXPR_ARG (arg, iter, expr) { - tree arg = TREE_VALUE (arglist); if (!union_contains_value (set1, set2, arg)) return false; } @@ -2512,39 +2488,35 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts) switch (TREE_CODE_CLASS (TREE_CODE (expr))) { - case tcc_expression: + case tcc_vl_exp: { - tree op0, op2; - tree arglist; - tree genop0, genop2; - tree genarglist; - tree walker, genwalker; + tree fn, sc; + tree genfn; + int i, nargs; + tree *buffer; gcc_assert (TREE_CODE (expr) == CALL_EXPR); - genop2 = NULL; - op0 = TREE_OPERAND (expr, 0); - arglist = TREE_OPERAND (expr, 1); - op2 = TREE_OPERAND (expr, 2); + fn = CALL_EXPR_FN (expr); + sc = CALL_EXPR_STATIC_CHAIN (expr); + + genfn = find_or_generate_expression (block, fn, stmts); - genop0 = find_or_generate_expression (block, op0, stmts); - genarglist = copy_list (arglist); - for (walker = arglist, genwalker = genarglist; - genwalker && walker; - genwalker = TREE_CHAIN (genwalker), walker = TREE_CHAIN (walker)) + nargs = call_expr_nargs (expr); + buffer = alloca (nargs * sizeof (tree)); + + for (i = 0; i < nargs; i++) { - TREE_VALUE (genwalker) - = find_or_generate_expression (block, TREE_VALUE (walker), - stmts); + tree arg = CALL_EXPR_ARG (expr, i); + buffer[i] = find_or_generate_expression (block, arg, stmts); } - if (op2) - genop2 = find_or_generate_expression (block, op2, stmts); - folded = fold_build3 (TREE_CODE (expr), TREE_TYPE (expr), - genop0, genarglist, genop2); + folded = build_call_array (TREE_TYPE (expr), genfn, nargs, buffer); + if (sc) + CALL_EXPR_STATIC_CHAIN (folded) = + find_or_generate_expression (block, sc, stmts); + folded = fold (folded); break; - - } break; case tcc_reference: @@ -3236,6 +3208,7 @@ create_value_expr_from (tree expr, basic_block block, tree stmt) || TREE_CODE_CLASS (code) == tcc_comparison || TREE_CODE_CLASS (code) == tcc_reference || TREE_CODE_CLASS (code) == tcc_expression + || TREE_CODE_CLASS (code) == tcc_vl_exp || TREE_CODE_CLASS (code) == tcc_exceptional || TREE_CODE_CLASS (code) == tcc_declaration); @@ -3247,64 +3220,18 @@ create_value_expr_from (tree expr, basic_block block, tree stmt) pool = binary_node_pool; else if (TREE_CODE_CLASS (code) == tcc_comparison) pool = comparison_node_pool; - else if (TREE_CODE_CLASS (code) == tcc_exceptional) - { - gcc_assert (code == TREE_LIST); - pool = list_node_pool; - } else - { - gcc_assert (code == CALL_EXPR); - pool = expression_node_pool; - } + gcc_assert (code == CALL_EXPR); - vexpr = (tree) pool_alloc (pool); - memcpy (vexpr, expr, tree_size (expr)); - - /* This case is only for TREE_LIST's that appear as part of - CALL_EXPR's. Anything else is a bug, but we can't easily verify - this, hence this comment. TREE_LIST is not handled by the - general case below because they don't have a fixed length, or - operands, so you can't access purpose/value/chain through - TREE_OPERAND macros. */ - - if (code == TREE_LIST) + if (code == CALL_EXPR) + vexpr = temp_copy_call_expr (expr); + else { - tree op = NULL_TREE; - tree temp = NULL_TREE; - if (TREE_CHAIN (vexpr)) - temp = create_value_expr_from (TREE_CHAIN (vexpr), block, stmt); - TREE_CHAIN (vexpr) = temp ? temp : TREE_CHAIN (vexpr); - - - /* Recursively value-numberize reference ops. */ - if (REFERENCE_CLASS_P (TREE_VALUE (vexpr))) - { - tree tempop; - op = TREE_VALUE (vexpr); - tempop = create_value_expr_from (op, block, stmt); - op = tempop ? tempop : op; - - TREE_VALUE (vexpr) = vn_lookup_or_add (op, stmt); - } - else - { - op = TREE_VALUE (vexpr); - TREE_VALUE (vexpr) = vn_lookup_or_add (TREE_VALUE (vexpr), NULL); - } - /* This is the equivalent of inserting op into EXP_GEN like we - do below */ - if (!is_undefined_value (op)) - bitmap_value_insert_into_set (EXP_GEN (block), op); - - efi = find_existing_value_expr (vexpr, stmt); - if (efi) - return efi; - get_or_alloc_expression_id (vexpr); - return vexpr; + vexpr = (tree) pool_alloc (pool); + memcpy (vexpr, expr, tree_size (expr)); } - for (i = 0; i < TREE_CODE_LENGTH (code); i++) + for (i = 0; i < TREE_OPERAND_LENGTH (expr); i++) { tree val, op; @@ -3319,20 +3246,6 @@ create_value_expr_from (tree expr, basic_block block, tree stmt) op = tempop ? tempop : op; val = vn_lookup_or_add (op, stmt); } - else if (TREE_CODE (op) == TREE_LIST) - { - tree tempop; - - gcc_assert (TREE_CODE (expr) == CALL_EXPR); - tempop = create_value_expr_from (op, block, stmt); - - op = tempop ? tempop : op; - vn_lookup_or_add (op, NULL); - /* Unlike everywhere else, we do *not* want to replace the - TREE_LIST itself with a value number, because support - functions we call will blow up. */ - val = op; - } else /* Create a value handle for OP and add it to VEXPR. */ val = vn_lookup_or_add (op, NULL); @@ -4100,15 +4013,12 @@ init_pre (bool do_fre) tree_code_size (NEGATE_EXPR), 30); reference_node_pool = create_alloc_pool ("Reference tree nodes", tree_code_size (ARRAY_REF), 30); - expression_node_pool = create_alloc_pool ("Expression tree nodes", - tree_code_size (CALL_EXPR), 30); - list_node_pool = create_alloc_pool ("List tree nodes", - tree_code_size (TREE_LIST), 30); comparison_node_pool = create_alloc_pool ("Comparison tree nodes", tree_code_size (EQ_EXPR), 30); modify_expr_node_pool = create_alloc_pool ("GIMPLE_MODIFY_STMT nodes", tree_code_size (GIMPLE_MODIFY_STMT), - 30); + 30); + obstack_init (&temp_call_expr_obstack); modify_expr_template = NULL; FOR_ALL_BB (bb) @@ -4140,8 +4050,6 @@ fini_pre (bool do_fre) free_alloc_pool (binary_node_pool); free_alloc_pool (reference_node_pool); free_alloc_pool (unary_node_pool); - free_alloc_pool (list_node_pool); - free_alloc_pool (expression_node_pool); free_alloc_pool (comparison_node_pool); free_alloc_pool (modify_expr_node_pool); htab_delete (phi_translate_table); diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index e216f996637..32a66eb0015 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -233,6 +233,7 @@ get_rank (tree e) tree rhs; long rank, maxrank; int i; + int n; if (TREE_CODE (SSA_NAME_VAR (e)) == PARM_DECL && SSA_NAME_IS_DEFAULT_DEF (e)) @@ -256,12 +257,13 @@ get_rank (tree e) rank = 0; maxrank = bb_rank[bb_for_stmt(stmt)->index]; rhs = GIMPLE_STMT_OPERAND (stmt, 1); - if (TREE_CODE_LENGTH (TREE_CODE (rhs)) == 0) + n = TREE_OPERAND_LENGTH (rhs); + if (n == 0) rank = MAX (rank, get_rank (rhs)); else { for (i = 0; - i < TREE_CODE_LENGTH (TREE_CODE (rhs)) + i < n && TREE_OPERAND (rhs, i) && rank != maxrank; i++) diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index e884a658fe8..a6a2a68c3ca 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -2512,6 +2512,7 @@ get_constraint_for (tree t, VEC (ce_s, heap) **results) switch (TREE_CODE_CLASS (TREE_CODE (t))) { case tcc_expression: + case tcc_vl_exp: { switch (TREE_CODE (t)) { @@ -3339,7 +3340,8 @@ find_func_aliases (tree origt) { tree lhsop; tree rhsop; - tree arglist; + tree arg; + call_expr_arg_iterator iter; varinfo_t fi; int i = 1; tree decl; @@ -3364,17 +3366,15 @@ find_func_aliases (tree origt) } else { - decl = TREE_OPERAND (rhsop, 0); + decl = CALL_EXPR_FN (rhsop); fi = get_vi_for_tree (decl); } /* Assign all the passed arguments to the appropriate incoming parameters of the function. */ - arglist = TREE_OPERAND (rhsop, 1); - for (;arglist; arglist = TREE_CHAIN (arglist)) - { - tree arg = TREE_VALUE (arglist); + FOR_EACH_CALL_EXPR_ARG (arg, iter, rhsop) + { struct constraint_expr lhs ; struct constraint_expr *rhsp; @@ -3455,6 +3455,7 @@ find_func_aliases (tree origt) case tcc_constant: case tcc_exceptional: case tcc_expression: + case tcc_vl_exp: case tcc_unary: { unsigned int j; @@ -3488,7 +3489,7 @@ find_func_aliases (tree origt) to process expressions other than simple operands (e.g. INDIRECT_REF, ADDR_EXPR, CALL_EXPR). */ default: - for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (rhsop)); i++) + for (i = 0; i < TREE_OPERAND_LENGTH (rhsop); i++) { tree op = TREE_OPERAND (rhsop, i); unsigned int j; diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 060f57d9a64..e7cd4a17c2e 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -935,10 +935,12 @@ tree_ssa_useless_type_conversion (tree expr) if (TREE_CODE (expr) == NOP_EXPR || TREE_CODE (expr) == CONVERT_EXPR || TREE_CODE (expr) == VIEW_CONVERT_EXPR || TREE_CODE (expr) == NON_LVALUE_EXPR) - return tree_ssa_useless_type_conversion_1 (TREE_TYPE (expr), - TREE_TYPE (TREE_OPERAND (expr, - 0))); - + /* FIXME: Use of GENERIC_TREE_TYPE here is a temporary measure to work + around known bugs with GIMPLE_MODIFY_STMTs appearing in places + they shouldn't. See PR 30391. */ + return tree_ssa_useless_type_conversion_1 + (TREE_TYPE (expr), + GENERIC_TREE_TYPE (TREE_OPERAND (expr, 0))); return false; } diff --git a/gcc/tree-stdarg.c b/gcc/tree-stdarg.c index bc72c17baea..44227e8b0f9 100644 --- a/gcc/tree-stdarg.c +++ b/gcc/tree-stdarg.c @@ -660,7 +660,7 @@ execute_optimize_stdarg (void) } si.va_start_count++; - ap = TREE_VALUE (TREE_OPERAND (call, 1)); + ap = CALL_EXPR_ARG (call, 0); if (TREE_CODE (ap) != ADDR_EXPR) { diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c index c1ca78a3f00..7889cbb8644 100644 --- a/gcc/tree-tailcall.c +++ b/gcc/tree-tailcall.c @@ -374,7 +374,7 @@ propagate_through_phis (tree var, edge e) static void find_tail_calls (basic_block bb, struct tailcall **ret) { - tree ass_var, ret_var, stmt, func, param, args, call = NULL_TREE; + tree ass_var, ret_var, stmt, func, param, call = NULL_TREE; block_stmt_iterator bsi, absi; bool tail_recursion; struct tailcall *nw; @@ -433,11 +433,13 @@ find_tail_calls (basic_block bb, struct tailcall **ret) func = get_callee_fndecl (call); if (func == current_function_decl) { - for (param = DECL_ARGUMENTS (func), args = TREE_OPERAND (call, 1); - param && args; - param = TREE_CHAIN (param), args = TREE_CHAIN (args)) + call_expr_arg_iterator iter; + tree arg; + for (param = DECL_ARGUMENTS (func), + arg = first_call_expr_arg (call, &iter); + param && arg; + param = TREE_CHAIN (param), arg = next_call_expr_arg (&iter)) { - tree arg = TREE_VALUE (args); if (param != arg) { /* Make sure there are no problems with copying. The parameter @@ -460,7 +462,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret) break; } } - if (!args && !param) + if (!arg && !param) tail_recursion = true; } @@ -714,7 +716,9 @@ arg_needs_copy_p (tree param) static void eliminate_tail_call (struct tailcall *t) { - tree param, stmt, args, rslt, call; + tree param, stmt, rslt, call; + tree arg; + call_expr_arg_iterator iter; basic_block bb, first; edge e; tree phi; @@ -769,17 +773,16 @@ eliminate_tail_call (struct tailcall *t) /* Add phi node entries for arguments. The ordering of the phi nodes should be the same as the ordering of the arguments. */ for (param = DECL_ARGUMENTS (current_function_decl), - args = TREE_OPERAND (stmt, 1), - phi = phi_nodes (first); + arg = first_call_expr_arg (stmt, &iter), + phi = phi_nodes (first); param; - param = TREE_CHAIN (param), - args = TREE_CHAIN (args)) + param = TREE_CHAIN (param), arg = next_call_expr_arg (&iter)) { if (!arg_needs_copy_p (param)) continue; gcc_assert (param == SSA_NAME_VAR (PHI_RESULT (phi))); - add_phi_arg (phi, TREE_VALUE (args), e); + add_phi_arg (phi, arg, e); phi = PHI_CHAIN (phi); } diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 9fac417d0d0..30741952b7f 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -434,7 +434,7 @@ vect_recog_pow_pattern (tree last_stmt, tree *type_in, tree *type_out) { tree expr; tree type; - tree fn, arglist, base, exp; + tree fn, base, exp; if (TREE_CODE (last_stmt) != GIMPLE_MODIFY_STMT) return NULL; @@ -446,15 +446,14 @@ vect_recog_pow_pattern (tree last_stmt, tree *type_in, tree *type_out) return NULL_TREE; fn = get_callee_fndecl (expr); - arglist = TREE_OPERAND (expr, 1); switch (DECL_FUNCTION_CODE (fn)) { case BUILT_IN_POWIF: case BUILT_IN_POWI: case BUILT_IN_POWF: case BUILT_IN_POW: - base = TREE_VALUE (arglist); - exp = TREE_VALUE (TREE_CHAIN (arglist)); + base = CALL_EXPR_ARG (expr, 0); + exp = CALL_EXPR_ARG (expr, 1); if (TREE_CODE (exp) != REAL_CST && TREE_CODE (exp) != INTEGER_CST) return NULL_TREE; @@ -484,11 +483,10 @@ vect_recog_pow_pattern (tree last_stmt, tree *type_in, tree *type_out) && REAL_VALUES_EQUAL (TREE_REAL_CST (exp), dconsthalf)) { tree newfn = mathfn_built_in (TREE_TYPE (base), BUILT_IN_SQRT); - tree newarglist = build_tree_list (NULL_TREE, base); *type_in = get_vectype_for_scalar_type (TREE_TYPE (base)); if (*type_in) { - newfn = build_function_call_expr (newfn, newarglist); + newfn = build_call_expr (newfn, 1, base); if (vectorizable_function (newfn, *type_in, *type_in) != NULL_TREE) return newfn; } diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index e901d00dc98..bcb248d1d33 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -1143,7 +1143,7 @@ vect_create_epilog_for_reduction (tree vect_def, tree stmt, tree operation = GIMPLE_STMT_OPERAND (stmt, 1); int op_type; - op_type = TREE_CODE_LENGTH (TREE_CODE (operation)); + op_type = TREE_OPERAND_LENGTH (operation); reduction_op = TREE_OPERAND (operation, op_type-1); vectype = get_vectype_for_scalar_type (TREE_TYPE (reduction_op)); mode = TYPE_MODE (vectype); @@ -1557,7 +1557,7 @@ vectorizable_reduction (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) operation = GIMPLE_STMT_OPERAND (stmt, 1); code = TREE_CODE (operation); - op_type = TREE_CODE_LENGTH (code); + op_type = TREE_OPERAND_LENGTH (operation); if (op_type != binary_op && op_type != ternary_op) return false; scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0); @@ -1803,13 +1803,14 @@ vectorizable_call (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) tree vec_dest; tree scalar_dest; tree operation; - tree args, type; + tree op, type; stmt_vec_info stmt_info = vinfo_for_stmt (stmt), prev_stmt_info; tree vectype_out, vectype_in; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); tree fndecl, rhs, new_temp, def, def_stmt, rhs_type, lhs_type; enum vect_def_type dt[2]; int ncopies, j, nargs; + call_expr_arg_iterator iter; /* Is STMT a vectorizable call? */ if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT) @@ -1824,15 +1825,15 @@ vectorizable_call (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) /* Process function arguments. */ rhs_type = NULL_TREE; - for (args = TREE_OPERAND (operation, 1), nargs = 0; - args; args = TREE_CHAIN (args), ++nargs) + nargs = 0; + FOR_EACH_CALL_EXPR_ARG (op, iter, operation) { - tree op = TREE_VALUE (args); + ++nargs; /* Bail out if the function has more than two arguments, we do not have interesting builtin functions to vectorize with more than two arguments. */ - if (nargs >= 2) + if (nargs > 2) return false; /* We can only handle calls with arguments of the same type. */ @@ -1911,11 +1912,13 @@ vectorizable_call (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) int n; /* Build argument list for the vectorized call. */ + /* FIXME: Rewrite this so that it doesn't construct a temporary + list. */ vargs = NULL_TREE; - for (args = TREE_OPERAND (operation, 1), n = 0; - args; args = TREE_CHAIN (args), ++n) + n = -1; + FOR_EACH_CALL_EXPR_ARG (op, iter, operation) { - tree op = TREE_VALUE (args); + ++n; if (j == 0) vec_oprnd[n] = vect_get_vec_def_for_operand (op, stmt, NULL); @@ -1979,7 +1982,7 @@ vectorizable_conversion (tree stmt, block_stmt_iterator * bsi, int ncopies, j; tree vectype_out, vectype_in; tree rhs_type, lhs_type; - tree builtin_decl, params; + tree builtin_decl; stmt_vec_info prev_stmt_info; /* Is STMT a vectorizable conversion? */ @@ -2073,11 +2076,10 @@ vectorizable_conversion (tree stmt, block_stmt_iterator * bsi, vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL); else vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt0, vec_oprnd0); - params = build_tree_list (NULL_TREE, vec_oprnd0); builtin_decl = targetm.vectorize.builtin_conversion (code, vectype_in); - new_stmt = build_function_call_expr (builtin_decl, params); + new_stmt = build_call_expr (builtin_decl, 1, vec_oprnd0); /* Arguments are ready. create the new vector stmt. */ new_stmt = build2 (GIMPLE_MODIFY_STMT, void_type_node, vec_dest, @@ -2272,7 +2274,7 @@ vectorizable_operation (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) optab = optab_for_tree_code (code, vectype); /* Support only unary or binary operations. */ - op_type = TREE_CODE_LENGTH (code); + op_type = TREE_OPERAND_LENGTH (operation); if (op_type != unary_op && op_type != binary_op) { if (vect_print_dump_info (REPORT_DETAILS)) @@ -2642,7 +2644,6 @@ vect_gen_widened_results_half (enum tree_code code, tree vectype, tree decl, tree vec_dest, block_stmt_iterator *bsi, tree stmt) { - tree vec_params; tree expr; tree new_stmt; tree new_temp; @@ -2653,10 +2654,10 @@ vect_gen_widened_results_half (enum tree_code code, tree vectype, tree decl, if (code == CALL_EXPR) { /* Target specific support */ - vec_params = build_tree_list (NULL_TREE, vec_oprnd0); - if (op_type == binary_op) - vec_params = tree_cons (NULL_TREE, vec_oprnd1, vec_params); - expr = build_function_call_expr (decl, vec_params); + if (op_type == binary_op) + expr = build_call_expr (decl, 2, vec_oprnd0, vec_oprnd1); + else + expr = build_call_expr (decl, 1, vec_oprnd0); } else { @@ -3378,10 +3379,9 @@ vect_setup_realignment (tree stmt, block_stmt_iterator *bsi, if (targetm.vectorize.builtin_mask_for_load) { tree builtin_decl; - tree params = build_tree_list (NULL_TREE, init_addr); builtin_decl = targetm.vectorize.builtin_mask_for_load (); - new_stmt = build_function_call_expr (builtin_decl, params); + new_stmt = build_call_expr (builtin_decl, 1, init_addr); vec_dest = vect_create_destination_var (scalar_dest, TREE_TYPE (new_stmt)); new_stmt = build2 (GIMPLE_MODIFY_STMT, void_type_node, vec_dest, @@ -4011,7 +4011,6 @@ vectorizable_live_operation (tree stmt, stmt_vec_info stmt_info = vinfo_for_stmt (stmt); loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); int i; - enum tree_code code; int op_type; tree op; tree def, def_stmt; @@ -4027,9 +4026,7 @@ vectorizable_live_operation (tree stmt, return false; operation = GIMPLE_STMT_OPERAND (stmt, 1); - code = TREE_CODE (operation); - - op_type = TREE_CODE_LENGTH (code); + op_type = TREE_OPERAND_LENGTH (operation); /* FORNOW: support only if all uses are invariant. This means that the scalar operations can remain in place, unvectorized. diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 9f64f2c18b7..fab57234ed9 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -1975,7 +1975,7 @@ vect_is_simple_reduction (struct loop *loop, tree phi) return NULL_TREE; } - op_type = TREE_CODE_LENGTH (code); + op_type = TREE_OPERAND_LENGTH (operation); if (op_type != binary_op) { if (vect_print_dump_info (REPORT_DETAILS)) diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index fffeefc83bd..b3223a5e59b 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -3747,9 +3747,9 @@ stmt_interesting_for_vrp (tree stmt) && (INTEGRAL_TYPE_P (TREE_TYPE (lhs)) || POINTER_TYPE_P (TREE_TYPE (lhs))) && ((TREE_CODE (rhs) == CALL_EXPR - && TREE_CODE (TREE_OPERAND (rhs, 0)) == ADDR_EXPR - && DECL_P (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0)) - && DECL_IS_BUILTIN (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0))) + && TREE_CODE (CALL_EXPR_FN (rhs)) == ADDR_EXPR + && DECL_P (TREE_OPERAND (CALL_EXPR_FN (rhs), 0)) + && DECL_IS_BUILTIN (TREE_OPERAND (CALL_EXPR_FN (rhs), 0))) || ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))) return true; } @@ -4242,9 +4242,9 @@ vrp_visit_stmt (tree stmt, edge *taken_edge_p, tree *output_p) for deriving ranges, with the obvious exception of calls to builtin functions. */ if ((TREE_CODE (rhs) == CALL_EXPR - && TREE_CODE (TREE_OPERAND (rhs, 0)) == ADDR_EXPR - && DECL_P (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0)) - && DECL_IS_BUILTIN (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0))) + && TREE_CODE (CALL_EXPR_FN (rhs)) == ADDR_EXPR + && DECL_P (TREE_OPERAND (CALL_EXPR_FN (rhs), 0)) + && DECL_IS_BUILTIN (TREE_OPERAND (CALL_EXPR_FN (rhs), 0))) || ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)) return vrp_visit_assignment (stmt, output_p); } diff --git a/gcc/tree.c b/gcc/tree.c index ae20c2511e2..842e1d032ca 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -66,7 +66,9 @@ const char *const tree_code_class_strings[] = "unary", "binary", "statement", + "vl_exp", "expression", + "gimple_stmt" }; /* obstack.[ch] explicitly declined to prototype this. */ @@ -337,8 +339,8 @@ decl_assembler_name_equal (tree decl, tree asmname) } /* Compute the number of bytes occupied by a tree with code CODE. - This function cannot be used for TREE_VEC, PHI_NODE, or STRING_CST - codes, which are of variable length. */ + This function cannot be used for nodes that have variable sizes, + including TREE_VEC, PHI_NODE, STRING_CST, and CALL_EXPR. */ size_t tree_code_size (enum tree_code code) { @@ -386,7 +388,7 @@ tree_code_size (enum tree_code code) case tcc_unary: /* a unary arithmetic expression */ case tcc_binary: /* a binary arithmetic expression */ return (sizeof (struct tree_exp) - + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *)); + + (TREE_CODE_LENGTH (code) - 1) * sizeof (tree)); case tcc_gimple_stmt: return (sizeof (struct gimple_stmt) @@ -434,7 +436,7 @@ tree_code_size (enum tree_code code) } /* Compute the number of bytes occupied by NODE. This routine only - looks at TREE_CODE, except for PHI_NODE and TREE_VEC nodes. */ + looks at TREE_CODE, except for those nodes that have variable sizes. */ size_t tree_size (tree node) { @@ -451,7 +453,7 @@ tree_size (tree node) case TREE_VEC: return (sizeof (struct tree_vec) - + (TREE_VEC_LENGTH (node) - 1) * sizeof(char *)); + + (TREE_VEC_LENGTH (node) - 1) * sizeof (tree)); case STRING_CST: return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1; @@ -462,7 +464,11 @@ tree_size (tree node) * sizeof (tree)); default: - return tree_code_size (code); + if (TREE_CODE_CLASS (code) == tcc_vl_exp) + return (sizeof (struct tree_exp) + + (VL_EXP_OPERAND_LENGTH (node) - 1) * sizeof (tree)); + else + return tree_code_size (code); } } @@ -2166,6 +2172,7 @@ tree_node_structure (tree t) case tcc_binary: case tcc_expression: case tcc_statement: + case tcc_vl_exp: return TS_EXP; case tcc_gimple_stmt: return TS_GIMPLE_STATEMENT; @@ -2247,9 +2254,6 @@ contains_placeholder_p (tree exp) || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)) || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2))); - case CALL_EXPR: - return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)); - default: break; } @@ -2265,6 +2269,22 @@ contains_placeholder_p (tree exp) return 0; } + case tcc_vl_exp: + switch (code) + { + case CALL_EXPR: + { + tree arg; + call_expr_arg_iterator iter; + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) + if (CONTAINS_PLACEHOLDER_P (arg)) + return 1; + return 0; + } + default: + return 0; + } + default: return 0; } @@ -2472,6 +2492,27 @@ substitute_in_expr (tree exp, tree f, tree r) } break; + case tcc_vl_exp: + { + tree copy = NULL_TREE; + int i; + int n = TREE_OPERAND_LENGTH (exp); + for (i = 1; i < n; i++) + { + tree op = TREE_OPERAND (exp, i); + tree newop = SUBSTITUTE_IN_EXPR (op, f, r); + if (newop != op) + { + copy = copy_node (exp); + TREE_OPERAND (copy, i) = newop; + } + } + if (copy) + new = fold (copy); + else + return exp; + } + default: gcc_unreachable (); } @@ -2503,6 +2544,7 @@ substitute_placeholder_in_expr (tree exp, tree obj) : (REFERENCE_CLASS_P (elt) || UNARY_CLASS_P (elt) || BINARY_CLASS_P (elt) + || VL_EXP_CLASS_P (elt) || EXPRESSION_CLASS_P (elt)) ? TREE_OPERAND (elt, 0) : 0)) if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type) @@ -2515,6 +2557,7 @@ substitute_placeholder_in_expr (tree exp, tree obj) : (REFERENCE_CLASS_P (elt) || UNARY_CLASS_P (elt) || BINARY_CLASS_P (elt) + || VL_EXP_CLASS_P (elt) || EXPRESSION_CLASS_P (elt)) ? TREE_OPERAND (elt, 0) : 0)) if (POINTER_TYPE_P (TREE_TYPE (elt)) @@ -2602,6 +2645,28 @@ substitute_placeholder_in_expr (tree exp, tree obj) } break; + case tcc_vl_exp: + { + tree copy = NULL_TREE; + int i; + int n = TREE_OPERAND_LENGTH (exp); + for (i = 1; i < n; i++) + { + tree op = TREE_OPERAND (exp, i); + tree newop = SUBSTITUTE_PLACEHOLDER_IN_EXPR (op, obj); + if (newop != op) + { + if (!copy) + copy = copy_node (exp); + TREE_OPERAND (copy, i) = newop; + } + } + if (copy) + return fold (copy); + else + return exp; + } + default: gcc_unreachable (); } @@ -2727,6 +2792,7 @@ stabilize_reference_1 (tree e) case tcc_statement: case tcc_expression: case tcc_reference: + case tcc_vl_exp: /* If the expression has side-effects, then encase it in a SAVE_EXPR so that it will only be evaluated once. */ /* The reference (r) and comparison (<) classes could be handled as @@ -3074,6 +3140,7 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, tree t; gcc_assert (TREE_CODE_LENGTH (code) == 3); + gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp); t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; @@ -3084,26 +3151,6 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, PROCESS_ARG(1); PROCESS_ARG(2); - if (code == CALL_EXPR && !side_effects) - { - tree node; - int i; - - /* Calls have side-effects, except those to const or - pure functions. */ - i = call_expr_flags (t); - if (!(i & (ECF_CONST | ECF_PURE))) - side_effects = 1; - - /* And even those have side-effects if their arguments do. */ - else for (node = arg1; node; node = TREE_CHAIN (node)) - if (TREE_SIDE_EFFECTS (TREE_VALUE (node))) - { - side_effects = 1; - break; - } - } - TREE_SIDE_EFFECTS (t) = side_effects; TREE_THIS_VOLATILE (t) = (TREE_CODE_CLASS (code) == tcc_reference @@ -3209,6 +3256,8 @@ build_nt (enum tree_code code, ...) int i; va_list p; + gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp); + va_start (p, code); t = make_node (code); @@ -3220,6 +3269,23 @@ build_nt (enum tree_code code, ...) va_end (p); return t; } + +/* Similar to build_nt, but for creating a CALL_EXPR object with + ARGLIST passed as a list. */ + +tree +build_nt_call_list (tree fn, tree arglist) +{ + tree t; + int i; + + t = build_vl_exp (CALL_EXPR, list_length (arglist) + 3); + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + for (i = 0; arglist; arglist = TREE_CHAIN (arglist), i++) + CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist); + return t; +} /* Create a DECL_... node of code CODE, name NAME and data type TYPE. We do NOT enter this node in any sort of symbol table. @@ -4916,11 +4982,26 @@ simple_cst_equal (tree t1, tree t2) return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); case CALL_EXPR: - cmp = simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); + cmp = simple_cst_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)); if (cmp <= 0) return cmp; - return - simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)); + if (call_expr_nargs (t1) != call_expr_nargs (t2)) + return 0; + { + tree arg1, arg2; + call_expr_arg_iterator iter1, iter2; + for (arg1 = first_call_expr_arg (t1, &iter1), + arg2 = first_call_expr_arg (t2, &iter2); + arg1 && arg2; + arg1 = next_call_expr_arg (&iter1), + arg2 = next_call_expr_arg (&iter2)) + { + cmp = simple_cst_equal (arg1, arg2); + if (cmp <= 0) + return cmp; + } + return arg1 == arg2; + } case TARGET_EXPR: /* Special case: if either target is an unallocated VAR_DECL, @@ -5184,7 +5265,7 @@ iterative_hash_expr (tree t, hashval_t val) val = iterative_hash_hashval_t (two, val); } else - for (i = TREE_CODE_LENGTH (code) - 1; i >= 0; --i) + for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i) val = iterative_hash_expr (TREE_OPERAND (t, i), val); } return val; @@ -6246,7 +6327,7 @@ get_callee_fndecl (tree call) /* The first operand to the CALL is the address of the function called. */ - addr = TREE_OPERAND (call, 0); + addr = CALL_EXPR_FN (call); STRIP_NOPS (addr); @@ -6665,15 +6746,16 @@ phi_node_elt_check_failed (int idx, int len, const char *file, int line, } /* Similar to above, except that the check is for the bounds of the operand - vector of an expression node. */ + vector of an expression node EXP. */ void -tree_operand_check_failed (int idx, enum tree_code code, const char *file, +tree_operand_check_failed (int idx, tree exp, const char *file, int line, const char *function) { + int code = TREE_CODE (exp); internal_error ("tree check: accessed operand %d of %s with %d operands in %s, at %s:%d", - idx + 1, tree_code_name[code], TREE_CODE_LENGTH (code), + idx + 1, tree_code_name[code], TREE_OPERAND_LENGTH (exp), function, trim_filename (file), line); } @@ -7305,6 +7387,149 @@ build_omp_clause (enum omp_clause_code code) return t; } +/* Set various status flags when building a CALL_EXPR object T. */ + +static void +process_call_operands (tree t) +{ + bool side_effects; + + side_effects = TREE_SIDE_EFFECTS (t); + if (!side_effects) + { + int i, n; + n = TREE_OPERAND_LENGTH (t); + for (i = 1; i < n; i++) + { + tree op = TREE_OPERAND (t, i); + if (op && TREE_SIDE_EFFECTS (op)) + { + side_effects = 1; + break; + } + } + } + if (!side_effects) + { + int i; + + /* Calls have side-effects, except those to const or + pure functions. */ + i = call_expr_flags (t); + if (!(i & (ECF_CONST | ECF_PURE))) + side_effects = 1; + } + TREE_SIDE_EFFECTS (t) = side_effects; +} + +/* Build a tcc_vl_exp object with code CODE and room for LEN operands. LEN + includes the implicit operand count in TREE_OPERAND 0, and so must be >= 1. + Except for the CODE and operand count field, other storage for the + object is initialized to zeros. */ + +tree +build_vl_exp_stat (enum tree_code code, int len MEM_STAT_DECL) +{ + tree t; + int length = (len - 1) * sizeof (tree) + sizeof (struct tree_exp); + + gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp); + gcc_assert (len >= 1); + +#ifdef GATHER_STATISTICS + tree_node_counts[(int) e_kind]++; + tree_node_sizes[(int) e_kind] += length; +#endif + + t = ggc_alloc_zone_pass_stat (length, &tree_zone); + + memset (t, 0, length); + + TREE_SET_CODE (t, code); + + /* Can't use TREE_OPERAND to store the length because if checking is + enabled, it will try to check the length before we store it. :-P */ + t->exp.operands[0] = build_int_cst (sizetype, len); + + return t; +} + + +/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE + and FN and a null static chain slot. ARGLIST is a TREE_LIST of the + arguments. */ + +tree +build_call_list (tree return_type, tree fn, tree arglist) +{ + tree t; + int i; + + t = build_vl_exp (CALL_EXPR, list_length (arglist) + 3); + TREE_TYPE (t) = return_type; + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + for (i = 0; arglist; arglist = TREE_CHAIN (arglist), i++) + CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist); + process_call_operands (t); + return t; +} + +/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and + FN and a null static chain slot. NARGS is the number of call arguments + which are specified as "..." arguments. */ + +tree +build_call_nary (tree return_type, tree fn, int nargs, ...) +{ + tree ret; + va_list args; + va_start (args, nargs); + ret = build_call_valist (return_type, fn, nargs, args); + va_end (args); + return ret; +} + +/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and + FN and a null static chain slot. NARGS is the number of call arguments + which are specified as a va_list ARGS. */ + +tree +build_call_valist (tree return_type, tree fn, int nargs, va_list args) +{ + tree t; + int i; + + t = build_vl_exp (CALL_EXPR, nargs + 3); + TREE_TYPE (t) = return_type; + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + for (i = 0; i < nargs; i++) + CALL_EXPR_ARG (t, i) = va_arg (args, tree); + process_call_operands (t); + return t; +} + +/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and + FN and a null static chain slot. NARGS is the number of call arguments + which are specified as a tree array ARGS. */ + +tree +build_call_array (tree return_type, tree fn, int nargs, tree *args) +{ + tree t; + int i; + + t = build_vl_exp (CALL_EXPR, nargs + 3); + TREE_TYPE (t) = return_type; + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + for (i = 0; i < nargs; i++) + CALL_EXPR_ARG (t, i) = args[i]; + process_call_operands (t); + return t; +} + /* Returns true if it is possible to prove that the index of an array access REF (an ARRAY_REF expression) falls into the @@ -7988,7 +8213,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) int i, len; /* Walk over all the sub-trees of this operand. */ - len = TREE_CODE_LENGTH (code); + len = TREE_OPERAND_LENGTH (*tp); /* Go through the subtrees. We need to do this in forward order so that the scope of a FOR_EXPR is handled properly. */ @@ -8081,4 +8306,19 @@ generic_tree_type (tree node) return &TREE_TYPE (node); } +/* Build and return a TREE_LIST of arguments in the CALL_EXPR exp. + FIXME: don't use this function. It exists for compatibility with + the old representation of CALL_EXPRs where a list was used to hold the + arguments. Places that currently extract the arglist from a CALL_EXPR + ought to be rewritten to use the CALL_EXPR itself. */ +tree +call_expr_arglist (tree exp) +{ + tree arglist = NULL_TREE; + int i; + for (i = call_expr_nargs (exp) - 1; i >= 0; i--) + arglist = tree_cons (NULL_TREE, CALL_EXPR_ARG (exp, i), arglist); + return arglist; +} + #include "gt-tree.h" diff --git a/gcc/tree.def b/gcc/tree.def index a85f02d72ae..1789de839ad 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -523,11 +523,13 @@ DEFTREECODE (VEC_COND_EXPR, "vec_cond_expr", tcc_expression, 3) nodes for the function. */ DEFTREECODE (BIND_EXPR, "bind_expr", tcc_expression, 3) -/* Function call. Operand 0 is the function. - Operand 1 is the argument list, a list of expressions - made out of a chain of TREE_LIST nodes. - Operand 2 is the static chain argument, or NULL. */ -DEFTREECODE (CALL_EXPR, "call_expr", tcc_expression, 3) +/* Function call. CALL_EXPRs are represented by variably-sized expression + nodes. There are at least three fixed operands. Operand 0 is an + INTEGER_CST node containing the total operand count, the number of + arguments plus 3. Operand 1 is the function, while operand 2 is + is static chain argument, or NULL. The remaining operands are the + arguments to the call. */ +DEFTREECODE (CALL_EXPR, "call_expr", tcc_vl_exp, 3) /* Specify a value to compute along with its corresponding cleanup. Operand 0 is the cleanup expression. diff --git a/gcc/tree.h b/gcc/tree.h index ed0379c7a87..2df9aabc8f3 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -64,6 +64,8 @@ enum tree_code_class { tcc_binary, /* A binary arithmetic expression. */ tcc_statement, /* A statement expression, which have side effects but usually no interesting value. */ + tcc_vl_exp, /* A function call or other expression with a + variable-length operand vector. */ tcc_expression, /* Any other expression. */ tcc_gimple_stmt /* A GIMPLE statement. */ }; @@ -149,6 +151,12 @@ extern const enum tree_code_class tree_code_type[]; #define STATEMENT_CLASS_P(CODE)\ (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_statement) +/* Nonzero if CODE represents a function call-like expression with a + variable-length operand vector. */ + +#define VL_EXP_CLASS_P(CODE)\ + (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_vl_exp) + /* Nonzero if CODE represents any other expression. */ #define EXPRESSION_CLASS_P(CODE)\ @@ -779,8 +787,8 @@ enum tree_node_structure_enum { const int __i = (I); \ if (GIMPLE_TUPLE_P (__t)) \ gcc_unreachable (); \ - if (__i < 0 || __i >= TREE_CODE_LENGTH (TREE_CODE (__t))) \ - tree_operand_check_failed (__i, TREE_CODE (__t), \ + if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t)) \ + tree_operand_check_failed (__i, __t, \ __FILE__, __LINE__, __FUNCTION__); \ &__t->exp.operands[__i]; })) @@ -789,8 +797,8 @@ enum tree_node_structure_enum { const int __i = (I); \ if (TREE_CODE (__t) != CODE) \ tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, (CODE), 0);\ - if (__i < 0 || __i >= TREE_CODE_LENGTH (CODE)) \ - tree_operand_check_failed (__i, (CODE), \ + if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t)) \ + tree_operand_check_failed (__i, __t, \ __FILE__, __LINE__, __FUNCTION__); \ &__t->exp.operands[__i]; })) @@ -798,8 +806,8 @@ enum tree_node_structure_enum { #define GIMPLE_STMT_OPERAND_CHECK(T, I) __extension__ \ (*({const tree __t = GIMPLE_STMT_CHECK (T); \ const int __i = (I); \ - if (__i < 0 || __i >= TREE_CODE_LENGTH (TREE_CODE (__t))) \ - tree_operand_check_failed (__i, TREE_CODE (__t), \ + if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t)) \ + tree_operand_check_failed (__i, __t, \ __FILE__, __LINE__, __FUNCTION__); \ &__t->gstmt.operands[__i]; })) @@ -809,8 +817,8 @@ enum tree_node_structure_enum { const int __i = (I); \ if (TREE_CODE (__t) != (CODE)) \ tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, (CODE), 0); \ - if (__i < 0 || __i >= TREE_CODE_LENGTH ((CODE))) \ - tree_operand_check_failed (__i, (CODE), \ + if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t)) \ + tree_operand_check_failed (__i, __t, \ __FILE__, __LINE__, __FUNCTION__); \ &__t->exp.operands[__i]; })) @@ -864,7 +872,7 @@ extern void tree_vec_elt_check_failed (int, int, const char *, extern void phi_node_elt_check_failed (int, int, const char *, int, const char *) ATTRIBUTE_NORETURN; -extern void tree_operand_check_failed (int, enum tree_code, +extern void tree_operand_check_failed (int, tree, const char *, int, const char *) ATTRIBUTE_NORETURN; extern void omp_clause_check_failed (const tree, const char *, int, @@ -924,6 +932,7 @@ extern void omp_clause_range_check_failed (const tree, const char *, int, #define DECL_NON_COMMON_CHECK(T) CONTAINS_STRUCT_CHECK (T, TS_DECL_NON_COMMON) #define CST_CHECK(T) TREE_CLASS_CHECK (T, tcc_constant) #define STMT_CHECK(T) TREE_CLASS_CHECK (T, tcc_statement) +#define VL_EXP_CHECK(T) TREE_CLASS_CHECK (T, tcc_vl_exp) #define FUNC_OR_METHOD_CHECK(T) TREE_CHECK2 (T, FUNCTION_TYPE, METHOD_TYPE) #define PTR_OR_REF_CHECK(T) TREE_CHECK2 (T, POINTER_TYPE, REFERENCE_TYPE) @@ -1497,8 +1506,17 @@ struct tree_constructor GTY(()) && integer_zerop (TREE_OPERAND (NODE, 0))) /* In ordinary expression nodes. */ +#define TREE_OPERAND_LENGTH(NODE) tree_operand_length (NODE) #define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I) +/* In a tcc_vl_exp node, operand 0 is an INT_CST node holding the operand + length. Its value includes the length operand itself; that is, + the minimum valid length is 1. + Note that we have to bypass the use of TREE_OPERAND to access + that field to avoid infinite recursion in expanding the macros. */ +#define VL_EXP_OPERAND_LENGTH(NODE) \ + ((int)TREE_INT_CST_LOW (VL_EXP_CHECK (NODE)->exp.operands[0])) + /* In gimple statements. */ #define GIMPLE_STMT_OPERAND(NODE, I) GIMPLE_STMT_OPERAND_CHECK (NODE, I) #define GIMPLE_STMT_LOCUS(NODE) (GIMPLE_STMT_CHECK (NODE)->gstmt.locus) @@ -1613,6 +1631,23 @@ struct tree_constructor GTY(()) #define ASSERT_EXPR_VAR(NODE) TREE_OPERAND (ASSERT_EXPR_CHECK (NODE), 0) #define ASSERT_EXPR_COND(NODE) TREE_OPERAND (ASSERT_EXPR_CHECK (NODE), 1) +/* CALL_EXPR accessors. + */ +#define CALL_EXPR_FN(NODE) TREE_OPERAND (CALL_EXPR_CHECK (NODE), 1) +#define CALL_EXPR_STATIC_CHAIN(NODE) TREE_OPERAND (CALL_EXPR_CHECK (NODE), 2) +#define CALL_EXPR_ARGS(NODE) call_expr_arglist (NODE) +#define CALL_EXPR_ARG(NODE, I) TREE_OPERAND (CALL_EXPR_CHECK (NODE), (I) + 3) +#define call_expr_nargs(NODE) (VL_EXP_OPERAND_LENGTH(NODE) - 3) + +/* CALL_EXPR_ARGP returns a pointer to the argument vector for NODE. + We can't use &CALL_EXPR_ARG (NODE, 0) because that will complain if + the argument count is zero when checking is enabled. Instead, do + the pointer arithmetic to advance past the 3 fixed operands in a + CALL_EXPR. That produces a valid pointer to just past the end of the + operand array, even if it's not valid to dereference it. */ +#define CALL_EXPR_ARGP(NODE) \ + (&(TREE_OPERAND (CALL_EXPR_CHECK (NODE), 0)) + 3) + /* OpenMP directive and clause accessors. */ #define OMP_BODY(NODE) \ @@ -3641,6 +3676,7 @@ extern tree maybe_get_identifier (const char *); /* Construct various types of nodes. */ extern tree build_nt (enum tree_code, ...); +extern tree build_nt_call_list (tree, tree); extern tree build0_stat (enum tree_code, tree MEM_STAT_DECL); #define build0(c,t) build0_stat (c,t MEM_STAT_INFO) @@ -3691,6 +3727,14 @@ extern void annotate_with_locus (tree, location_t); extern tree build_empty_stmt (void); extern tree build_omp_clause (enum omp_clause_code); +extern tree build_vl_exp_stat (enum tree_code, int MEM_STAT_DECL); +#define build_vl_exp(c,n) build_vl_exp_stat (c,n MEM_STAT_INFO) + +extern tree build_call_list (tree, tree, tree); +extern tree build_call_nary (tree, tree, int, ...); +extern tree build_call_valist (tree, tree, int, va_list); +extern tree build_call_array (tree, tree, int, tree*); + /* Construct various nodes representing data types. */ extern tree make_signed_type (int); @@ -4288,6 +4332,9 @@ extern tree upper_bound_in_type (tree, tree); extern tree lower_bound_in_type (tree, tree); extern int operand_equal_for_phi_arg_p (tree, tree); extern bool empty_body_p (tree); +extern tree call_expr_arg (tree, int); +extern tree *call_expr_argp (tree, int); +extern tree call_expr_arglist (tree); /* In stmt.c */ @@ -4329,6 +4376,8 @@ extern tree fold_build3_stat (enum tree_code, tree, tree, tree, tree MEM_STAT_DE extern tree fold_build1_initializer (enum tree_code, tree, tree); extern tree fold_build2_initializer (enum tree_code, tree, tree, tree); extern tree fold_build3_initializer (enum tree_code, tree, tree, tree, tree); +extern tree fold_build_call_list (tree, tree, tree); +extern tree fold_build_call_list_initializer (tree, tree, tree); extern tree fold_convert (tree, tree); extern tree fold_single_bit_test (enum tree_code, tree, tree, tree); extern tree fold_ignored_result (tree); @@ -4413,26 +4462,30 @@ extern bool tree_expr_nonzero_p (tree); extern bool tree_expr_nonzero_warnv_p (tree, bool *); /* In builtins.c */ -extern tree fold_builtin (tree, tree, bool); -extern tree fold_builtin_fputs (tree, bool, bool, tree); -extern tree fold_builtin_strcpy (tree, tree, tree); -extern tree fold_builtin_strncpy (tree, tree, tree); -extern tree fold_builtin_memory_chk (tree, tree, tree, bool, +extern tree fold_call_expr (tree, bool); +extern tree fold_builtin_fputs (tree, tree, bool, bool, tree); +extern tree fold_builtin_strcpy (tree, tree, tree, tree); +extern tree fold_builtin_strncpy (tree, tree, tree, tree, tree); +extern tree fold_builtin_memory_chk (tree, tree, tree, tree, tree, tree, bool, enum built_in_function); -extern tree fold_builtin_stxcpy_chk (tree, tree, tree, bool, +extern tree fold_builtin_stxcpy_chk (tree, tree, tree, tree, tree, bool, enum built_in_function); -extern tree fold_builtin_strncpy_chk (tree, tree); +extern tree fold_builtin_strncpy_chk (tree, tree, tree, tree, tree); extern tree fold_builtin_snprintf_chk (tree, tree, enum built_in_function); -extern bool fold_builtin_next_arg (tree); +extern bool fold_builtin_next_arg (tree, bool); extern enum built_in_function builtin_mathfn_code (tree); extern tree build_function_call_expr (tree, tree); +extern tree fold_build_call_expr (tree, tree, tree, tree); +extern tree fold_builtin_call_list (tree, tree, tree); +extern tree fold_builtin_call_valist (tree, tree, int, va_list); +extern tree build_call_expr (tree, int, ...); extern tree mathfn_built_in (tree, enum built_in_function fn); extern tree strip_float_extensions (tree); extern tree c_strlen (tree, int); extern tree std_gimplify_va_arg_expr (tree, tree, tree *, tree *); extern tree build_va_arg_indirect_ref (tree); extern tree build_string_literal (int, const char *); -extern int validate_arglist (tree, ...); +extern bool validate_arglist (tree, ...); extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode); extern int get_pointer_alignment (tree, unsigned int); @@ -4786,4 +4839,77 @@ extern unsigned HOST_WIDE_INT highest_pow2_factor (tree); void init_inline_once (void); +/* Compute the number of operands in an expression node NODE. For + tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself, + otherwise it is looked up from the node's code. */ +static inline int +tree_operand_length (tree node) +{ + if (VL_EXP_CLASS_P (node)) + return VL_EXP_OPERAND_LENGTH (node); + else + return TREE_CODE_LENGTH (TREE_CODE (node)); +} + +/* Abstract iterators for CALL_EXPRs. These static inline definitions + have to go towards the end of tree.h so that union tree_node is fully + defined by this point. */ + +/* Structure containing iterator state. */ +typedef struct call_expr_arg_iterator_d GTY (()) +{ + tree t; /* the call_expr */ + int n; /* argument count */ + int i; /* next argument index */ +} call_expr_arg_iterator; + +/* Initialize the abstract argument list iterator object ITER with the + arguments from CALL_EXPR node EXP. */ +static inline void +init_call_expr_arg_iterator (tree exp, call_expr_arg_iterator *iter) +{ + iter->t = exp; + iter->n = call_expr_nargs (exp); + iter->i = 0; +} + +/* Return the next argument from abstract argument list iterator object ITER, + and advance its state. Return NULL_TREE if there are no more arguments. */ +static inline tree +next_call_expr_arg (call_expr_arg_iterator *iter) +{ + tree result; + if (iter->i >= iter->n) + return NULL_TREE; + result = CALL_EXPR_ARG (iter->t, iter->i); + iter->i++; + return result; +} + +/* Initialize the abstract argument list iterator object ITER, then advance + past and return the first argument. Useful in for expressions, e.g. + for (arg = first_call_expr_arg (exp, &iter); arg; + arg = next_call_expr_arg (&iter)) */ +static inline tree +first_call_expr_arg (tree exp, call_expr_arg_iterator *iter) +{ + init_call_expr_arg_iterator (exp, iter); + return next_call_expr_arg (iter); +} + +/* Test whether there are more arguments in abstract argument list iterator + ITER, without changing its state. */ +static inline bool +more_call_expr_args_p (const call_expr_arg_iterator *iter) +{ + return (iter->i < iter->n); +} + + +/* Iterate through each argument ARG of CALL_EXPR CALL, using variable ITER + (of type call_expr_arg_iterator) to hold the iteration state. */ +#define FOR_EACH_CALL_EXPR_ARG(arg, iter, call) \ + for ((arg) = first_call_expr_arg ((call), &(iter)); (arg); \ + (arg) = next_call_expr_arg (&(iter))) + #endif /* GCC_TREE_H */ diff --git a/gcc/value-prof.c b/gcc/value-prof.c index 2de51f63be1..908481e4a98 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -1073,7 +1073,7 @@ tree_ic (tree stmt, tree call, struct cgraph_node* direct_call, tmpv = create_tmp_var (optype, "PROF"); tmp1 = create_tmp_var (optype, "PROF"); stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, tmpv, - unshare_expr (TREE_OPERAND (call, 0))); + unshare_expr (CALL_EXPR_FN (call))); stmt2 = build2 (GIMPLE_MODIFY_STMT, optype, tmp1, fold_convert (optype, build_addr (direct_call->decl, current_function_decl))); @@ -1089,8 +1089,8 @@ tree_ic (tree stmt, tree call, struct cgraph_node* direct_call, label1 = build1 (LABEL_EXPR, void_type_node, label_decl1); stmt1 = unshare_expr (stmt); new_call = get_call_expr_in (stmt1); - TREE_OPERAND (new_call, 0) = build_addr (direct_call->decl, - current_function_decl); + CALL_EXPR_FN (new_call) = build_addr (direct_call->decl, + current_function_decl); bsi_insert_before (&bsi, label1, BSI_SAME_STMT); bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT); bb2end = stmt1; @@ -1165,7 +1165,7 @@ tree_ic_transform (tree stmt) if (!call || TREE_CODE (call) != CALL_EXPR) return false; - callee = TREE_OPERAND (call, 0); + callee = CALL_EXPR_FN (call); if (TREE_CODE (callee) == ADDR_EXPR) return false; @@ -1205,9 +1205,9 @@ tree_ic_transform (tree stmt) return true; } -/* Return true if the stringop FNDECL with ARGLIST shall be profiled. */ +/* Return true if the stringop CALL with FNDECL shall be profiled. */ static bool -interesting_stringop_to_profile_p (tree fndecl, tree arglist) +interesting_stringop_to_profile_p (tree fndecl, tree call) { enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); @@ -1219,18 +1219,18 @@ interesting_stringop_to_profile_p (tree fndecl, tree arglist) { case BUILT_IN_MEMCPY: case BUILT_IN_MEMPCPY: - return validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, - VOID_TYPE); + return validate_arglist (call, + POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, + VOID_TYPE); case BUILT_IN_MEMSET: - return validate_arglist (arglist, - POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, - VOID_TYPE); + return validate_arglist (call, + POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, + VOID_TYPE); case BUILT_IN_BZERO: - return validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, - VOID_TYPE); + return validate_arglist (call, POINTER_TYPE, INTEGER_TYPE, + VOID_TYPE); default: - gcc_unreachable (); + gcc_unreachable (); } } @@ -1256,8 +1256,7 @@ tree_stringop_fixed_value (tree stmt, tree value, int prob, gcov_type count, edge e12, e13, e23, e24, e34; block_stmt_iterator bsi; tree call = get_call_expr_in (stmt); - tree arglist = TREE_OPERAND (call, 1); - tree blck_size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + tree blck_size = CALL_EXPR_ARG (call, 2); tree optype = TREE_TYPE (blck_size); int region; @@ -1295,8 +1294,7 @@ tree_stringop_fixed_value (tree stmt, tree value, int prob, gcov_type count, label1 = build1 (LABEL_EXPR, void_type_node, label_decl1); stmt1 = unshare_expr (stmt); call = get_call_expr_in (stmt1); - arglist = TREE_OPERAND (call, 1); - TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))) = value; + CALL_EXPR_ARG (call, 2) = value; bsi_insert_before (&bsi, label1, BSI_SAME_STMT); bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT); region = lookup_stmt_eh_region (stmt); @@ -1342,7 +1340,6 @@ tree_stringops_transform (block_stmt_iterator *bsi) tree stmt = bsi_stmt (*bsi); tree call = get_call_expr_in (stmt); tree fndecl; - tree arglist; tree blck_size; enum built_in_function fcode; histogram_value histogram; @@ -1359,14 +1356,13 @@ tree_stringops_transform (block_stmt_iterator *bsi) if (!fndecl) return false; fcode = DECL_FUNCTION_CODE (fndecl); - arglist = TREE_OPERAND (call, 1); - if (!interesting_stringop_to_profile_p (fndecl, arglist)) + if (!interesting_stringop_to_profile_p (fndecl, call)) return false; if (fcode == BUILT_IN_BZERO) - blck_size = TREE_VALUE (TREE_CHAIN (arglist)); + blck_size = CALL_EXPR_ARG (call, 1); else - blck_size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + blck_size = CALL_EXPR_ARG (call, 2); if (TREE_CODE (blck_size) == INTEGER_CST) return false; @@ -1386,20 +1382,20 @@ tree_stringops_transform (block_stmt_iterator *bsi) if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count)) return false; prob = (count * REG_BR_PROB_BASE + all / 2) / all; - dest = TREE_VALUE (arglist); + dest = CALL_EXPR_ARG (call, 0); dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); switch (fcode) { case BUILT_IN_MEMCPY: case BUILT_IN_MEMPCPY: - src = TREE_VALUE (TREE_CHAIN (arglist)); + src = CALL_EXPR_ARG (call, 1); src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); if (!can_move_by_pieces (val, MIN (dest_align, src_align))) return false; break; case BUILT_IN_MEMSET: if (!can_store_by_pieces (val, builtin_memset_read_str, - TREE_VALUE (TREE_CHAIN (arglist)), + CALL_EXPR_ARG (call, 1), dest_align)) return false; break; @@ -1561,7 +1557,7 @@ tree_indirect_call_to_profile (tree stmt, histogram_values *values) if (!call || TREE_CODE (call) != CALL_EXPR) return; - callee = TREE_OPERAND (call, 0); + callee = CALL_EXPR_FN (call); if (TREE_CODE (callee) == ADDR_EXPR) return; @@ -1582,7 +1578,6 @@ tree_stringops_values_to_profile (tree stmt, histogram_values *values) { tree call = get_call_expr_in (stmt); tree fndecl; - tree arglist; tree blck_size; tree dest; enum built_in_function fcode; @@ -1593,16 +1588,15 @@ tree_stringops_values_to_profile (tree stmt, histogram_values *values) if (!fndecl) return; fcode = DECL_FUNCTION_CODE (fndecl); - arglist = TREE_OPERAND (call, 1); - if (!interesting_stringop_to_profile_p (fndecl, arglist)) + if (!interesting_stringop_to_profile_p (fndecl, call)) return; - dest = TREE_VALUE (arglist); + dest = CALL_EXPR_ARG (call, 0); if (fcode == BUILT_IN_BZERO) - blck_size = TREE_VALUE (TREE_CHAIN (arglist)); + blck_size = CALL_EXPR_ARG (call, 1); else - blck_size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + blck_size = CALL_EXPR_ARG (call, 2); if (TREE_CODE (blck_size) != INTEGER_CST) { |