From: Richard Kenner Date: Tue, 22 Jun 2004 03:07:05 +0000 (+0000) Subject: alias.c (adjust_offset_for_component_ref): Use component_ref_field_offset. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=44de5aeb00a66307236cb5b7ccfca1a21aaca080;p=gcc.git alias.c (adjust_offset_for_component_ref): Use component_ref_field_offset. * alias.c (adjust_offset_for_component_ref): Use component_ref_field_offset. * c-decl.c (build_array_declarator): Add news args for ARRAY_REF. * c-gimplify.c (gimplify_expr_stmt): Use alloc_stmt_list. (gimplify_decl_stmt): Call gimplify_type_sizes for type. For decl, call gimplify_one_sizepos and use statement list. (gimplify_compound_literal_expr): New arg PRE_P. Add statement to PRE_P list and return DECL. (c_gimplify_expr, case COMPOUND_LITERAL_EXPR): Add arg to gimplify_compound_literal_expr. * c-tree.h (getdecls): Deleted. * c-typeck.c (build_component_ref): Add operand for COMPONENT_REF. (build_array_ref): Add two operands for ARRAY_REF. (build_unary_op): Set TREE_INVARIANT and TREE_CONSTANT for COMPOUND_LITERAL_EXPR. * coverage.c (tree_coverage_counter_ref): Add new operands for ARRAY_REF. * emit-rtl.c (component_ref_for_mem_expr): Add new operand for COMPONENT_REF. (set_mem_attributes_minus_bitpos): Use array_ref_low_bound and array_ref_element_size. (widen_memory_access):Use component_ref_field_offset. * explow.c (update_nonlocal_goto_save_area): Add two operands for ARRAY_REF. * expr.c (array_ref_element_size, array_ref_low_bound): New functions. (component_ref_field_offset): Likewise. (get_inner_reference): Use them. (expand_expr_real_1, case ARRAY_REF): Use array_ref_low_bound. * fold-const.c (fold, case EQ_EXPR): Properly handle DECL_SIZE. (fold_read_from_constant_string): Use array_ref_low_bound. Verify that result is a character type. (build_fold_indirect_ref): Add two operands for ARRAY_REF. * function.c (expand_function_start): Likewise. * gimple-low.c (expand_var_p): Delete duplicated line. * gimplify.c: Add static decls for local functions. (cgraph.h): Now included. (create_tmp_var): Remove check for ARRAY_TYPE. (copy_if_shared_r): Look at bounds and sizes of types. (build_and_jump): Return alloc_stmt_list instead of build_empty_stmt. (gimplify_exit_expr, shortcut_cond_expr): Likewise. (gimplify_save_expr, gimple_push_cleanup): Likewise. (gimplify_init_constructor): Likewise. WANT_VALUE now bool. If empty list with no result wanted, return GS_UNHANDLED. Add additional operands for ARRAY_REF and COMPONENT_REF. (canonicalize_component_ref): Convert to &array[L]. (gimplify_array_ref_to_plus): Use array_ref_element_size and array_ref_lower_bound. (build_addr_expr_with_type, build_addr_expr): New functions. (gimplify_compound_lval): WANT_LVALUE now bool. Major rework to allow handle_component_p and initialize and gimplify new operands for ARRAY_REF, ARRAY_RANGE_REF, and COMPONENT_REF. (gimplify_array_ref): Deleted. (gimplify_self_mod_expr): WANT_VALUE now bool. (gimplify_modify_expr): Gimplify to_p and from_p later. Factor out code into gimplify_modify_expr_rhs and call twice. Move variable-size code earlier and handle PLACEHOLDER_EXPR. (gimplify_modify_expr_rhs, gimplify_variable_sized_compare): New fns. (gimplify_addr_expr, case VIEW_CONVERT_EXPR): New case. (gimplify_expr, case ARRAY_REF): Delete special case. Instead handle like COMPONENT_REF; also do ARRAY_RANGE_REF, IMAGPART, and REALPART the same way. (gimplify_expr, case VIEW_CONVERT_EXPR): New case. (gimplify_expr): Call gimplify_variable_sized_compare if applicable. Call alloc_stmt_list instead of build_empty_stmt. Deal with _REF that's volatile. (gimplify_type_sizes, gimplify_one_sizepos): New functions. (unshare_body, unvisit_body): New functions. (gimplify_body): Call them. * stmt.c (expand_stack_alloc): Don't expand TYPE_MAX_VALUE. * stor-layout.c (get_pending_sizes): Don't change SAVE_EXPR_CONTEXT. * tree-alias-common.c (get_alias_var): Also skip ARRAY_RANGE_REF. * tree-cfg.c (tree_node_can_be_shared): Treat ARRAY_RANGE_REF like ARRAY_REF. (verify_expr, case ADDR_EXPR): Use handled_component_p. * tree-dfa.c (get_virtual_var): Likewise. * tree-dump.c (dequeue_and_dump, case COMPONENT_REF, ARRAY_REF): New cases to dump new operands; likewise for ARRAY_RANGE_REF. * tree-eh.c (tree_could_trap, case ARRAY_RANGE_REF): Like ARRAY_REF. * tree-gimple.c (is_gimple_addr_expr_arg): Add ARRAY_RANGE_REF and INDIRECT_REF. (get_base_address): Use handled_component_p. * tree-gimple.h (gimplify_type_sizes, gimplify_one_sizepos): New. * tree-line.c (walk_tree): Walk more things for types and decls. * tree-mudflap.c (mf_build_check_statement_for): Add new operands for ARRAY_REF and COMPONENT_REF. (mx_xform_derefs_1): Clean up usage of decl sizes. * tree-nested.c (build_addr): Use handled_component_p. (walk_stmts, case CATCH_EXPR): Add missing "break". (get_static_chain, get_frame_field): Add new operand for COMPONENT_REF. (finalize_nesting_tree_1): Likewise. (convert_nonlocal_reference, case ARRAY_RANGE_REF): Like ARRAY_REF and process additional operands. (convert_local_reference): Likewise. * tree-outof-ssa.c (discover_nonconstant_array_refs_r): Treat ARRAY_RANGE_REF similarly to ARRAY_REF. * tree-pretty-print.c (dump_generic_node, case QUAL_UNION_TYPE): Handle like RECORD_TYPE. (dump_generic_node, case COMPONENT_REF): Print offset operand. (dump_generic_node, case ARRAY_RANGE_REF): Treat like ARRAY_REF and print lower bound and element size for both. (op_prio, case ARRAY_RANGE_REF): Like ARRAY_REF. * tree-sra.c (csc_build_component_ref): Add new operand. (scalarize_call_expr): Use get_base_address. * tree-ssa-ccp.c (widen_bitfield): Clean up size handling. (maybe_fold_offset_to_array_ref): Rework to handle input having an ARRAY_REF, refine handling of lower bound, and add new operands for ARRAY_REF. (maybe_fold_to_component_ref): Add new operand for COMPONENT_REF. (maybe_fold_stmt_indirect): Only fold *&B to B if types match. (maybe_fold_stmt_addition): Only handle constant lower bound. * tree-ssa-operands.c (get_expr_operands): Minor rearrangements. Treat ARRAY_REF and ARRAY_RANGE_REF the same; look at extra operands. Look at new offset operand of COMPONENT_REF. * tree-ssa.c (set_is_used): Use handled_component_p. * tree.c (substitute_in_expr, case COMPONENT_REF): Add new operand. (stabilize_reference, case COMPONENT_REF): Likewise. (stabilize_reference, case ARRAY_RANGE_REF, ARRAY_REF): Similarly. (recompute_tree_invariant_for_addr_expr): Completely rework to be more precise. Also set TREE_SIDE_EFFECTS. (build1_stat, case ARRAY_EXPR): Don't handle TREE_SIDE_EFFECTS here. (build2_stat, build3_stat, build4_stat): For references, propagate TREE_THIS_VOLATILE. (get_unwidened): Add new operand for COMPONENT_REF. (get_narrower): Likewise; use host_integerp for DECL_SIZE. * tree.def (COMPONENT_REF): Add new operand. (ARRAY_REF, ARRAY_RANGE_REF): Add two new operands. * tree.h (array_ref_element_size, array_ref_low_bound): New decls. (component_ref_field_offset): Likewise. * config/alpha/alpha.c (alpha_va_start): Add new op for COMPONENT_REF. (alpha_gimplify_va_arg): Likewise. * config/i386/i386.c (ix86_va_start, ix86_gimplify_va_arg): Likewise. * config/i860/i860.c (i860_va_start, i860_va_arg): Likewise. * config/iq2000/iq2000.c (iq2000_va_arg): Likewise. * config/mips/mips.c (mips_va_start, mips_va_arg): Likewise. * config/rs6000/rs6000.c (rs6000_va_start, rs6000_gimplify_va_arg): Likewise. * config/s390/s390.c (s390_va_start, s390_gimplify_va_arg): Likewise. * config/sh/sh.c (sh_va_start, sh_va_arg): Likewise. * config/stormy16/stormy16.c (xstormy1_expand_builin_va_start): Likewise. (xstormy16_expand_builtin_va_arg): Likewise. * config/xtensa/xtensa.c (xtensa_va_start, xtensa_va_arg): Likewise. * cp/call.c (build_vfield_ref): Add new operand for COMPONENT_REF. (build_new_method_call): Likewise. * cp/decl.c (local_variable_p_walkfn): Don't walk into types. * cp/decl2.c (grok_array_decl): Add new operands for ARRAY_REF. (build_anon_union_vars): Add new operand for COMPONENT_REF. * cp/init.c (buld_new): Add new operand for ARRAY_REF. * cp/method.c (do_build_copy_constructor): New op for COMPONENT_REF. (do_build_assign_ref): Likewise. * cp/parser.c (cp_parser_direct_new_declarator): Add new operands for ARRAY_REF. (cp_parser_direct_declarator): Likewise. * cp/pt.c (tsubst): Likewise. (tsubst_copy, tsubst_copy_and_build): Likewise; also add new operand for COMPONENT_REF. * cp/semantics.c (finish_non_static_data_member): Add new operand for COMPONENT_REF. * cp/typeck.c (build_class_member_access_expr): Likewise. (build_class_member_access_expr, finish_class_member_access_expr): Likewise. (build_ptrmemfunc_access_expr): Likewise. (build_array_ref): Add new operands for ARRAY_REF. * cp/typeck2.c (split_nonconstant_init_1): Likewise; COMPONENT_REF too. * cp/tree.c (count_trees_r, no_linkage_helper): Don't walk in types. * fortran/f95-lang.c (LANG_HOOKS_GIMPLE_BEFORE_INLINING): Deleted. * fortran/trans-array.c (gfc_conv_descriptor_data): Add operand for COMPONENT_REF. (gfc_conv_descriptor_offset, gfc_conv_descriptor_dtype): Likewise. (gfc_conv_descriptor_dimension, gfc_conv_descriptor_stride): Likewise. (gfc_conv_descriptor_lbound, gfc_conv_descriptor_ubound): Likewise. * fortran/trans-common.c (create_common): Likewise. * fortran/trans-expr.c (gfc_conv_component_ref): Likewise. * fortran/trans-io.c (set_parameter_value): Likewise. (set_parameter_ref, set_string, set_flag, io_result): Likewise. (transfer_expr): Likewise. * fortran/trans-decl.c (gfc_trans_auto_character_variable): Set up to get DECL_SIZE and DECL_SIZE_UNIT gimplified. (gfc_simplify_function): New function. (gfc_generate_function-code): Properly handle nested functions. * fortran/trans.c (gfc_build_array_ref): Add two new operands for ARRAY_REF. * java/class.c (build_class_ref): Add new operand for COMPONENT_REF. (build_static_field_ref): Likewise and add new operands for ARRAY_REF. * java/constants.c (build_ref_from_constant_pool): Likewise. * java/expr.c (build_java_array_length_access): Likewise. (build_get_class, build_field_ref, build_known_method_ref): Likewise. (invoke_build_dtable, build_invokevirtual): Likewise. (build_invokeinterface, java_expand_expr): Likewise. (emit_init_test_initialization): Likewise. * java/java-gimplify.c (java_gimplify_new_array_init): Likewise. * java/parse.y (make_qualifed_name, build_array_ref): Likewise. * objc/ojbc-act.c (generate_static_references): Add additional operands to ARRAY_REF. (generate_strings, build_method_prototype_list_template): Likewise. (generate_protocol_list): Likewise. From-SVN: r83474 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9f124c17310..8829c32b0ff 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,153 @@ +2004-06-21 Richard Kenner + + * alias.c (adjust_offset_for_component_ref): Use + component_ref_field_offset. + * c-decl.c (build_array_declarator): Add news args for ARRAY_REF. + * c-gimplify.c (gimplify_expr_stmt): Use alloc_stmt_list. + (gimplify_decl_stmt): Call gimplify_type_sizes for type. + For decl, call gimplify_one_sizepos and use statement list. + (gimplify_compound_literal_expr): New arg PRE_P. + Add statement to PRE_P list and return DECL. + (c_gimplify_expr, case COMPOUND_LITERAL_EXPR): Add arg to + gimplify_compound_literal_expr. + * c-tree.h (getdecls): Deleted. + * c-typeck.c (build_component_ref): Add operand for COMPONENT_REF. + (build_array_ref): Add two operands for ARRAY_REF. + (build_unary_op): Set TREE_INVARIANT and TREE_CONSTANT for + COMPOUND_LITERAL_EXPR. + * coverage.c (tree_coverage_counter_ref): Add new operands + for ARRAY_REF. + * emit-rtl.c (component_ref_for_mem_expr): Add new operand + for COMPONENT_REF. + (set_mem_attributes_minus_bitpos): Use array_ref_low_bound + and array_ref_element_size. + (widen_memory_access):Use component_ref_field_offset. + * explow.c (update_nonlocal_goto_save_area): Add two operands + for ARRAY_REF. + * expr.c (array_ref_element_size, array_ref_low_bound): New functions. + (component_ref_field_offset): Likewise. + (get_inner_reference): Use them. + (expand_expr_real_1, case ARRAY_REF): Use array_ref_low_bound. + * fold-const.c (fold, case EQ_EXPR): Properly handle DECL_SIZE. + (fold_read_from_constant_string): Use array_ref_low_bound. + Verify that result is a character type. + (build_fold_indirect_ref): Add two operands for ARRAY_REF. + * function.c (expand_function_start): Likewise. + * gimple-low.c (expand_var_p): Delete duplicated line. + * gimplify.c: Add static decls for local functions. + (cgraph.h): Now included. + (create_tmp_var): Remove check for ARRAY_TYPE. + (copy_if_shared_r): Look at bounds and sizes of types. + (build_and_jump): Return alloc_stmt_list instead of build_empty_stmt. + (gimplify_exit_expr, shortcut_cond_expr): Likewise. + (gimplify_save_expr, gimple_push_cleanup): Likewise. + (gimplify_init_constructor): Likewise. + WANT_VALUE now bool. + If empty list with no result wanted, return GS_UNHANDLED. + Add additional operands for ARRAY_REF and COMPONENT_REF. + (canonicalize_component_ref): Convert to &array[L]. + (gimplify_array_ref_to_plus): Use array_ref_element_size and + array_ref_lower_bound. + (build_addr_expr_with_type, build_addr_expr): New functions. + (gimplify_compound_lval): WANT_LVALUE now bool. + Major rework to allow handle_component_p and initialize and + gimplify new operands for ARRAY_REF, ARRAY_RANGE_REF, and + COMPONENT_REF. + (gimplify_array_ref): Deleted. + (gimplify_self_mod_expr): WANT_VALUE now bool. + (gimplify_modify_expr): Gimplify to_p and from_p later. + Factor out code into gimplify_modify_expr_rhs and call twice. + Move variable-size code earlier and handle PLACEHOLDER_EXPR. + (gimplify_modify_expr_rhs, gimplify_variable_sized_compare): New fns. + (gimplify_addr_expr, case VIEW_CONVERT_EXPR): New case. + (gimplify_expr, case ARRAY_REF): Delete special case. + Instead handle like COMPONENT_REF; also do ARRAY_RANGE_REF, + IMAGPART, and REALPART the same way. + (gimplify_expr, case VIEW_CONVERT_EXPR): New case. + (gimplify_expr): Call gimplify_variable_sized_compare if applicable. + Call alloc_stmt_list instead of build_empty_stmt. + Deal with _REF that's volatile. + (gimplify_type_sizes, gimplify_one_sizepos): New functions. + (unshare_body, unvisit_body): New functions. + (gimplify_body): Call them. + * stmt.c (expand_stack_alloc): Don't expand TYPE_MAX_VALUE. + * stor-layout.c (get_pending_sizes): Don't change SAVE_EXPR_CONTEXT. + * tree-alias-common.c (get_alias_var): Also skip ARRAY_RANGE_REF. + * tree-cfg.c (tree_node_can_be_shared): Treat ARRAY_RANGE_REF + like ARRAY_REF. + (verify_expr, case ADDR_EXPR): Use handled_component_p. + * tree-dfa.c (get_virtual_var): Likewise. + * tree-dump.c (dequeue_and_dump, case COMPONENT_REF, ARRAY_REF): + New cases to dump new operands; likewise for ARRAY_RANGE_REF. + * tree-eh.c (tree_could_trap, case ARRAY_RANGE_REF): Like ARRAY_REF. + * tree-gimple.c (is_gimple_addr_expr_arg): Add ARRAY_RANGE_REF + and INDIRECT_REF. + (get_base_address): Use handled_component_p. + * tree-gimple.h (gimplify_type_sizes, gimplify_one_sizepos): New. + * tree-inline.c (walk_tree): Walk more things for types and decls. + * tree-mudflap.c (mf_build_check_statement_for): Add new operands + for ARRAY_REF and COMPONENT_REF. + (mx_xform_derefs_1): Clean up usage of decl sizes. + * tree-nested.c (build_addr): Use handled_component_p. + (walk_stmts, case CATCH_EXPR): Add missing "break". + (get_static_chain, get_frame_field): Add new operand for COMPONENT_REF. + (finalize_nesting_tree_1): Likewise. + (convert_nonlocal_reference, case ARRAY_RANGE_REF): Like ARRAY_REF + and process additional operands. + (convert_local_reference): Likewise. + * tree-outof-ssa.c (discover_nonconstant_array_refs_r): Treat + ARRAY_RANGE_REF similarly to ARRAY_REF. + * tree-pretty-print.c (dump_generic_node, case QUAL_UNION_TYPE): Handle + like RECORD_TYPE. + (dump_generic_node, case COMPONENT_REF): Print offset operand. + (dump_generic_node, case ARRAY_RANGE_REF): Treat like ARRAY_REF + and print lower bound and element size for both. + (op_prio, case ARRAY_RANGE_REF): Like ARRAY_REF. + * tree-sra.c (csc_build_component_ref): Add new operand. + (scalarize_call_expr): Use get_base_address. + * tree-ssa-ccp.c (widen_bitfield): Clean up size handling. + (maybe_fold_offset_to_array_ref): Rework to handle input having an + ARRAY_REF, refine handling of lower bound, and add new operands + for ARRAY_REF. + (maybe_fold_to_component_ref): Add new operand for COMPONENT_REF. + (maybe_fold_stmt_indirect): Only fold *&B to B if types match. + (maybe_fold_stmt_addition): Only handle constant lower bound. + * tree-ssa-operands.c (get_expr_operands): Minor rearrangements. + Treat ARRAY_REF and ARRAY_RANGE_REF the same; look at extra operands. + Look at new offset operand of COMPONENT_REF. + * tree-ssa.c (set_is_used): Use handled_component_p. + * tree.c (substitute_in_expr, case COMPONENT_REF): Add new operand. + (stabilize_reference, case COMPONENT_REF): Likewise. + (stabilize_reference, case ARRAY_RANGE_REF, ARRAY_REF): Similarly. + (recompute_tree_invariant_for_addr_expr): Completely rework to + be more precise. Also set TREE_SIDE_EFFECTS. + (build1_stat, case ARRAY_EXPR): Don't handle TREE_SIDE_EFFECTS here. + (build2_stat, build3_stat, build4_stat): For references, + propagate TREE_THIS_VOLATILE. + (get_unwidened): Add new operand for COMPONENT_REF. + (get_narrower): Likewise; use host_integerp for DECL_SIZE. + * tree.def (COMPONENT_REF): Add new operand. + (ARRAY_REF, ARRAY_RANGE_REF): Add two new operands. + * tree.h (array_ref_element_size, array_ref_low_bound): New decls. + (component_ref_field_offset): Likewise. + * config/alpha/alpha.c (alpha_va_start): Add new op for COMPONENT_REF. + (alpha_gimplify_va_arg): Likewise. + * config/i386/i386.c (ix86_va_start, ix86_gimplify_va_arg): Likewise. + * config/i860/i860.c (i860_va_start, i860_va_arg): Likewise. + * config/iq2000/iq2000.c (iq2000_va_arg): Likewise. + * config/mips/mips.c (mips_va_start, mips_va_arg): Likewise. + * config/rs6000/rs6000.c (rs6000_va_start, rs6000_gimplify_va_arg): + Likewise. + * config/s390/s390.c (s390_va_start, s390_gimplify_va_arg): Likewise. + * config/sh/sh.c (sh_va_start, sh_va_arg): Likewise. + * config/stormy16/stormy16.c (xstormy1_expand_builin_va_start): + Likewise. + (xstormy16_expand_builtin_va_arg): Likewise. + * config/xtensa/xtensa.c (xtensa_va_start, xtensa_va_arg): Likewise. + * objc/objc-act.c (generate_static_references): Likewise. + (generate_strings, build_method_prototype_list_template): Likewise. + (generate_protocol_list): Likewise. + 2004-06-21 John David Anglin PR rtl-optimization/14782 diff --git a/gcc/alias.c b/gcc/alias.c index 8e168c2b477..b8661d7b6bd 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -2015,11 +2015,12 @@ adjust_offset_for_component_ref (tree x, rtx offset) ioffset = INTVAL (offset); do { + tree offset = component_ref_field_offset (x); tree field = TREE_OPERAND (x, 1); - if (! host_integerp (DECL_FIELD_OFFSET (field), 1)) + if (! host_integerp (offset, 1)) return NULL_RTX; - ioffset += (tree_low_cst (DECL_FIELD_OFFSET (field), 1) + ioffset += (tree_low_cst (offset, 1) + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) / BITS_PER_UNIT)); diff --git a/gcc/c-decl.c b/gcc/c-decl.c index ec1778bc35c..4735dabf644 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -2508,7 +2508,7 @@ tree build_array_declarator (tree expr, tree quals, int static_p, int vla_unspec_p) { tree decl; - decl = build_nt (ARRAY_REF, NULL_TREE, expr); + decl = build_nt (ARRAY_REF, NULL_TREE, expr, NULL_TREE, NULL_TREE); TREE_TYPE (decl) = quals; TREE_STATIC (decl) = (static_p ? 1 : 0); if (pedantic && !flag_isoc99) diff --git a/gcc/c-gimplify.c b/gcc/c-gimplify.c index 359733116c4..113a09d1b16 100644 --- a/gcc/c-gimplify.c +++ b/gcc/c-gimplify.c @@ -243,7 +243,7 @@ gimplify_expr_stmt (tree *stmt_p) } if (stmt == NULL_TREE) - stmt = build_empty_stmt (); + stmt = alloc_stmt_list (); *stmt_p = stmt; @@ -475,8 +475,6 @@ gimplify_decl_stmt (tree *stmt_p) { tree stmt = *stmt_p; tree decl = DECL_STMT_DECL (stmt); - tree pre = NULL_TREE; - tree post = NULL_TREE; if (TREE_TYPE (decl) == error_mark_node) { @@ -485,38 +483,34 @@ gimplify_decl_stmt (tree *stmt_p) } if (TREE_CODE (decl) == TYPE_DECL) - { - tree type = TREE_TYPE (decl); - if (TYPE_SIZE_UNIT (type) - && !TREE_CONSTANT (TYPE_SIZE_UNIT (type))) - { - /* This is a variable-sized array type. Simplify its size. */ - tree temp = TYPE_SIZE_UNIT (type); - gimplify_expr (&temp, &pre, &post, is_gimple_val, fb_rvalue); - } - } + *stmt_p = gimplify_type_sizes (TREE_TYPE (decl)); - if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)) + else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)) { tree init = DECL_INITIAL (decl); + *stmt_p = NULL_TREE; + gimplify_one_sizepos (&DECL_SIZE (decl), stmt_p); + gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p); + if (!TREE_CONSTANT (DECL_SIZE (decl))) { - tree pt_type = build_pointer_type (TREE_TYPE (decl)); - tree alloc, size; - /* 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(). */ - size = get_initialized_tmp_var (DECL_SIZE_UNIT (decl), &pre, &post); + tree pt_type = build_pointer_type (TREE_TYPE (decl)); + tree alloc_stmt + = (build_function_call_expr + (implicit_built_in_decls[BUILT_IN_STACK_ALLOC], + tree_cons (NULL_TREE, + build1 (ADDR_EXPR, pt_type, decl), + tree_cons (NULL_TREE, DECL_SIZE_UNIT (decl), + NULL_TREE)))); + + gimplify_stmt (&alloc_stmt); + append_to_statement_list(alloc_stmt, stmt_p); DECL_DEFER_OUTPUT (decl) = 1; - alloc = build_function_call_expr - (implicit_built_in_decls[BUILT_IN_STACK_ALLOC], - tree_cons (NULL_TREE, - build1 (ADDR_EXPR, pt_type, decl), - tree_cons (NULL_TREE, size, NULL_TREE))); - append_to_compound_expr (alloc, &pre); } if (init && init != error_mark_node) @@ -531,14 +525,13 @@ gimplify_decl_stmt (tree *stmt_p) DECL_INITIAL (decl) = NULL_TREE; init = build (MODIFY_EXPR, void_type_node, decl, init); - append_to_compound_expr (init, &pre); + gimplify_stmt (&init); + append_to_statement_list (init, stmt_p); } else - { - /* We must still examine initializers for static variables - as they may contain a label address. */ - walk_tree (&init, force_labels_r, NULL, NULL); - } + /* We must still examine initializers for static variables + as they may contain a label address. */ + walk_tree (&init, force_labels_r, NULL, NULL); } /* This decl isn't mentioned in the enclosing block, so add it to the @@ -547,10 +540,10 @@ gimplify_decl_stmt (tree *stmt_p) if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE) gimple_add_tmp_var (decl); } + else + *stmt_p = alloc_stmt_list (); - append_to_compound_expr (post, &pre); - *stmt_p = pre; - return GS_OK; + return GS_ALL_DONE; } /* Gimplification of expression trees. */ @@ -560,7 +553,7 @@ gimplify_decl_stmt (tree *stmt_p) instead. */ static enum gimplify_status -gimplify_compound_literal_expr (tree *expr_p) +gimplify_compound_literal_expr (tree *expr_p, tree *pre_p) { tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p); tree decl = DECL_STMT_DECL (decl_s); @@ -572,7 +565,8 @@ gimplify_compound_literal_expr (tree *expr_p) gimple_add_tmp_var (decl); gimplify_decl_stmt (&decl_s); - *expr_p = decl_s ? decl_s : decl; + append_to_statement_list (decl_s, pre_p); + *expr_p = decl; return GS_OK; } @@ -586,7 +580,7 @@ c_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED) switch (code) { case COMPOUND_LITERAL_EXPR: - return gimplify_compound_literal_expr (expr_p); + return gimplify_compound_literal_expr (expr_p, pre_p); case FOR_STMT: return gimplify_for_stmt (expr_p, pre_p); diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 052275ab96f..66691eba299 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -147,7 +147,6 @@ extern int c_in_iteration_stmt; extern int c_in_case_stmt; extern int global_bindings_p (void); -extern tree getdecls (void); extern void push_scope (void); extern tree pop_scope (void); extern void insert_block (tree); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index e619fa13ea5..63c91210015 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1222,10 +1222,10 @@ default_function_array_conversion (tree exp) if (TREE_CODE (exp) == VAR_DECL) { - /* ??? This is not really quite correct - in that the type of the operand of ADDR_EXPR - is not the target type of the type of the ADDR_EXPR itself. - Question is, can this lossage be avoided? */ + /* We are making an ADDR_EXPR of ptrtype. This is a valid + ADDR_EXPR because it's the best way of representing what + happens in C when we take the address of an array and place + it in a pointer to the element type. */ adr = build1 (ADDR_EXPR, ptrtype, exp); if (!c_mark_addressable (exp)) return error_mark_node; @@ -1483,7 +1483,8 @@ build_component_ref (tree datum, tree component) if (TREE_TYPE (subdatum) == error_mark_node) return error_mark_node; - ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum); + ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum, + NULL_TREE); if (TREE_READONLY (datum) || TREE_READONLY (subdatum)) TREE_READONLY (ref) = 1; if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum)) @@ -1636,7 +1637,7 @@ build_array_ref (tree array, tree index) } type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array))); - rval = build (ARRAY_REF, type, array, index); + rval = build (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE); /* Array ref is const/volatile if the array elements are or if the array is. */ TREE_READONLY (rval) @@ -2562,6 +2563,9 @@ build_unary_op (enum tree_code code, tree xarg, int flag) else addr = build1 (code, argtype, arg); + if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR) + TREE_INVARIANT (addr) = TREE_CONSTANT (addr) = 1; + return addr; } diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 36b765ea69b..dd4409a2176 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -6274,9 +6274,9 @@ alpha_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) offset_field = TREE_CHAIN (base_field); base_field = build (COMPONENT_REF, TREE_TYPE (base_field), - valist, base_field); + valist, base_field, NULL_TREE); offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field), - valist, offset_field); + valist, offset_field, NULL_TREE); t = make_tree (ptr_type_node, virtual_incoming_args_rtx); t = build (PLUS_EXPR, ptr_type_node, t, build_int_2 (offset, 0)); @@ -6383,9 +6383,9 @@ alpha_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) base_field = TYPE_FIELDS (va_list_type_node); offset_field = TREE_CHAIN (base_field); base_field = build (COMPONENT_REF, TREE_TYPE (base_field), - valist, base_field); + valist, base_field, NULL_TREE); offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field), - valist, offset_field); + valist, offset_field, NULL_TREE); /* Pull the fields of the structure out into temporaries. Since we never modify the base field, we can use a formal temporary. Sign-extend the diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 8313e0a5f39..30d031507e2 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -3136,10 +3136,10 @@ ix86_va_start (tree valist, rtx nextarg) f_sav = TREE_CHAIN (f_ovf); valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist); - gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr); - fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr); - ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf); - sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav); + gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); + fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE); + ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE); + sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE); /* Count number of gp and fp argument registers used. */ words = current_function_args_info.words; @@ -3202,10 +3202,10 @@ ix86_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) f_sav = TREE_CHAIN (f_ovf); valist = build_fold_indirect_ref (valist); - gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr); - fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr); - ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf); - sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav); + gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); + fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE); + ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE); + sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE); size = int_size_in_bytes (type); if (size == -1) diff --git a/gcc/config/i860/i860.c b/gcc/config/i860/i860.c index 7c455eb3d61..d23277d1dbe 100644 --- a/gcc/config/i860/i860.c +++ b/gcc/config/i860/i860.c @@ -1877,10 +1877,10 @@ i860_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) f_fpr = TREE_CHAIN (f_gpr); #endif - gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr); - fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr); - sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav); - mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem); + gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); + fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE); + sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE); + mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem, NULL_TREE); /* Initialize the `mem_ptr' field to the address of the first anonymous stack argument. */ @@ -1943,10 +1943,10 @@ i860_va_arg (tree valist, tree type) f_fpr = TREE_CHAIN (f_gpr); #endif - gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr); - fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr); - mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem); - sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav); + gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); + fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE); + mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem, NULL_TREE); + sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE); size = int_size_in_bytes (type); diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c index 41d4a0e1797..786a7b6c91e 100644 --- a/gcc/config/iq2000/iq2000.c +++ b/gcc/config/iq2000/iq2000.c @@ -1656,11 +1656,11 @@ iq2000_va_arg (tree valist, tree type) f_goff = TREE_CHAIN (f_ftop); f_foff = TREE_CHAIN (f_goff); - ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl); - gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop); - ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop); - goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff); - foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff); + ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, NULL_TREE); + gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop, NULL_TREE); + ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop, NULL_TREE); + goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff, NULL_TREE); + foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff, NULL_TREE); lab_false = gen_label_rtx (); lab_over = gen_label_rtx (); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 9abd0b3c7ee..15489b19d76 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -4045,11 +4045,16 @@ mips_va_start (tree valist, rtx nextarg) f_goff = TREE_CHAIN (f_ftop); f_foff = TREE_CHAIN (f_goff); - ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl); - gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop); - ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop); - goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff); - foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff); + ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, + NULL_TREE); + gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop, + NULL_TREE); + ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop, + NULL_TREE); + goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff, + NULL_TREE); + foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff, + NULL_TREE); /* Emit code to initialize OVFL, which points to the next varargs stack argument. CUM->STACK_WORDS gives the number of stack @@ -4212,12 +4217,15 @@ mips_va_arg (tree valist, tree type) lab_false = gen_label_rtx (); lab_over = gen_label_rtx (); - ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl); + ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, + NULL_TREE); if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE) { - top = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop); - off = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff); + top = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop, + NULL_TREE); + off = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff, + NULL_TREE); /* When floating-point registers are saved to the stack, each one will take up UNITS_PER_HWFPVALUE bytes, regardless @@ -4245,8 +4253,10 @@ mips_va_arg (tree valist, tree type) } else { - top = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop); - off = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff); + top = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop, + NULL_TREE); + off = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff, + NULL_TREE); if (rsize > UNITS_PER_WORD) { /* [1] Emit code for: off &= -rsize. */ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 2376fc44498..861b00ad514 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -5026,10 +5026,10 @@ rs6000_va_start (tree valist, rtx nextarg) f_sav = TREE_CHAIN (f_ovf); valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist); - gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr); - fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr); - ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf); - sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav); + gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); + fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE); + ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE); + sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE); /* Count number of gp and fp argument registers used. */ words = current_function_args_info.words; @@ -5131,10 +5131,10 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) f_sav = TREE_CHAIN (f_ovf); valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist); - gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr); - fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr); - ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf); - sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav); + gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); + fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE); + ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE); + sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE); size = int_size_in_bytes (type); rsize = (size + 3) / 4; diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 3e2ad5a43a6..cc48d015629 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -6381,10 +6381,10 @@ s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) f_sav = TREE_CHAIN (f_ovf); valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist); - gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr); - fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr); - ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf); - sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav); + gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); + fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE); + ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE); + sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE); /* Count number of gp and fp argument registers used. */ @@ -6462,10 +6462,10 @@ s390_gimplify_va_arg (tree valist, tree type, tree *pre_p, f_sav = TREE_CHAIN (f_ovf); valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist); - gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr); - fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr); - ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf); - sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav); + gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); + fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE); + ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE); + sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE); size = int_size_in_bytes (type); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index d70178bf495..2308f1b42d7 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -6237,14 +6237,16 @@ sh_va_start (tree valist, rtx nextarg) f_next_fp_limit = TREE_CHAIN (f_next_fp); f_next_stack = TREE_CHAIN (f_next_fp_limit); - next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o); + next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o, + NULL_TREE); next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit), - valist, f_next_o_limit); - next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp), valist, f_next_fp); + valist, f_next_o_limit, NULL_TREE); + next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp), valist, f_next_fp, + NULL_TREE); next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit), - valist, f_next_fp_limit); + valist, f_next_fp_limit, NULL_TREE); next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack), - valist, f_next_stack); + valist, f_next_stack, NULL_TREE); /* Call __builtin_saveregs. */ u = make_tree (ptr_type_node, expand_builtin_saveregs ()); @@ -6317,15 +6319,16 @@ sh_va_arg (tree valist, tree type) f_next_fp_limit = TREE_CHAIN (f_next_fp); f_next_stack = TREE_CHAIN (f_next_fp_limit); - next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o); + next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o, + NULL_TREE); next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit), - valist, f_next_o_limit); + valist, f_next_o_limit, NULL_TREE); next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp), - valist, f_next_fp); + valist, f_next_fp, NULL_TREE); next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit), - valist, f_next_fp_limit); + valist, f_next_fp_limit, NULL_TREE); next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack), - valist, f_next_stack); + valist, f_next_stack, NULL_TREE); /* Structures with a single member with a distinct mode are passed like their member. This is relevant if the latter has a REAL_TYPE diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c index 9ba54c19953..821279450fa 100644 --- a/gcc/config/stormy16/stormy16.c +++ b/gcc/config/stormy16/stormy16.c @@ -1285,8 +1285,9 @@ xstormy16_expand_builtin_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) f_base = TYPE_FIELDS (va_list_type_node); f_count = TREE_CHAIN (f_base); - base = build (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base); - count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count); + base = build (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base, NULL_TREE); + count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count, + NULL_TREE); t = make_tree (TREE_TYPE (base), virtual_incoming_args_rtx); t = build (PLUS_EXPR, TREE_TYPE (base), t, @@ -1320,8 +1321,9 @@ xstormy16_expand_builtin_va_arg (tree valist, tree type) f_base = TYPE_FIELDS (va_list_type_node); f_count = TREE_CHAIN (f_base); - base = build (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base); - count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count); + base = build (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base, NULL_TREE); + count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count, + NULL_TREE); must_stack = MUST_PASS_IN_STACK (TYPE_MODE (type), type); size_tree = round_up (size_in_bytes (type), UNITS_PER_WORD); diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index e062fd9c222..2d9ea5235b9 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -2430,9 +2430,9 @@ xtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) f_reg = TREE_CHAIN (f_stk); f_ndx = TREE_CHAIN (f_reg); - stk = build (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk); - reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg); - ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx); + stk = build (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE); + reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE); + ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE); /* Call __builtin_saveregs; save the result in __va_reg */ u = make_tree (ptr_type_node, expand_builtin_saveregs ()); @@ -2494,9 +2494,9 @@ xtensa_va_arg (tree valist, tree type) f_reg = TREE_CHAIN (f_stk); f_ndx = TREE_CHAIN (f_reg); - stk = build (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk); - reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg); - ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx); + stk = build (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE); + reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE); + ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE); type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type)); diff --git a/gcc/coverage.c b/gcc/coverage.c index 3eab7a5dd46..e39f0a66cc7 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -428,16 +428,18 @@ rtl_coverage_counter_ref (unsigned counter, unsigned no) tree tree_coverage_counter_ref (unsigned counter, unsigned no) { - tree t; + tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter])); if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter]) abort (); no += prg_n_ctrs[counter] + fn_b_ctrs[counter]; /* "no" here is an array index, scaled to bytes later. */ - t = build (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter], - build_int_2 (no, 0)); - return t; + return build (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter], + fold_convert (domain_type, build_int_2 (no, 0)), + TYPE_MIN_VALUE (domain_type), + size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (GCOV_TYPE_NODE), + size_int (TYPE_ALIGN (GCOV_TYPE_NODE)))); } /* Generate a checksum for a string. CHKSUM is the current diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 029105711b4..d8b494bdff6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,29 @@ +2004-06-21 Richard Kenner + + * call.c (build_vfield_ref): Add new operand for COMPONENT_REF. + (build_new_method_call): Likewise. + * decl.c (local_variable_p_walkfn): Don't walk into types. + * decl2.c (grok_array_decl): Add new operands for ARRAY_REF. + (build_anon_union_vars): Add new operand for COMPONENT_REF. + * init.c (buld_new): Add new operand for ARRAY_REF. + * method.c (do_build_copy_constructor): New op for COMPONENT_REF. + (do_build_assign_ref): Likewise. + * parser.c (cp_parser_direct_new_declarator): Add new operands + for ARRAY_REF. + (cp_parser_direct_declarator): Likewise. + * pt.c (tsubst): Likewise. + (tsubst_copy, tsubst_copy_and_build): Likewise; also add new operand + for COMPONENT_REF. + * semantics.c (finish_non_static_data_member): Add new operand + for COMPONENT_REF. + * typeck.c (build_class_member_access_expr): Likewise. + (build_class_member_access_expr, finish_class_member_access_expr): + Likewise. + (build_ptrmemfunc_access_expr): Likewise. + (build_array_ref): Add new operands for ARRAY_REF. + * typeck2.c (split_nonconstant_init_1): Likewise; COMPONENT_REF too. + * tree.c (count_trees_r, no_linkage_helper): Don't walk in types. + 2004-06-21 Richard Henderson * dump.c (cp_dump_tree): Don't use dump_next_stmt. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 616cf812f92..0c247b8127a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -203,7 +203,7 @@ build_vfield_ref (tree datum, tree type) datum = convert_to_base (datum, type, /*check_access=*/false); return build (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)), - datum, TYPE_VFIELD (type)); + datum, TYPE_VFIELD (type), NULL_TREE); } /* Returns nonzero iff the destructor name specified in NAME @@ -3868,8 +3868,7 @@ builtin: return build_conditional_expr (arg1, arg2, arg3); case MEMBER_REF: - return build_m_component_ref - (build_indirect_ref (arg1, NULL), arg2); + return build_m_component_ref (build_indirect_ref (arg1, NULL), arg2); /* The caller will deal with these. */ case ADDR_EXPR: @@ -5360,7 +5359,7 @@ 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, - build_min_nt (COMPONENT_REF, orig_instance, orig_fns), + build_min_nt (COMPONENT_REF, orig_instance, orig_fns, NULL_TREE), orig_args, NULL_TREE)); /* Free all the conversions we allocated. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 84f3b8459af..55ce6841723 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8508,14 +8508,18 @@ nonstatic_local_decl_p (tree t) function. */ static tree -local_variable_p_walkfn (tree* tp, - int* walk_subtrees ATTRIBUTE_UNUSED , - void* data ATTRIBUTE_UNUSED ) +local_variable_p_walkfn (tree *tp, int *walk_subtrees, + void *data ATTRIBUTE_UNUSED) { - return ((local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp)) - ? *tp : NULL_TREE); + if (local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp)) + return *tp; + else if (TYPE_P (*tp)) + *walk_subtrees = 0; + + return NULL_TREE; } + /* Check that ARG, which is a default-argument expression for a parameter DECL, is valid. Returns ARG, or ERROR_MARK_NODE, if something goes wrong. DECL may also be a _TYPE node, rather than a diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index eacab5f283b..00105a6d2a6 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -369,7 +369,8 @@ grok_array_decl (tree array_expr, tree index_exp) { if (type_dependent_expression_p (array_expr) || type_dependent_expression_p (index_exp)) - return build_min_nt (ARRAY_REF, array_expr, index_exp); + return build_min_nt (ARRAY_REF, array_expr, index_exp, + NULL_TREE, NULL_TREE); array_expr = build_non_dependent_expr (array_expr); index_exp = build_non_dependent_expr (index_exp); } @@ -426,8 +427,8 @@ grok_array_decl (tree array_expr, tree index_exp) expr = build_array_ref (array_expr, index_exp); } if (processing_template_decl && expr != error_mark_node) - return build_min_non_dep (ARRAY_REF, expr, - orig_array_expr, orig_index_exp); + return build_min_non_dep (ARRAY_REF, expr, orig_array_expr, orig_index_exp, + NULL_TREE, NULL_TREE); return expr; } @@ -1175,7 +1176,8 @@ build_anon_union_vars (tree object) cp_pedwarn_at ("protected member `%#D' in anonymous union", field); if (processing_template_decl) - ref = build_min_nt (COMPONENT_REF, object, DECL_NAME (field)); + ref = build_min_nt (COMPONENT_REF, object, + DECL_NAME (field), NULL_TREE); else ref = build_class_member_access_expr (object, field, NULL_TREE, false); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 6c886238ea5..2af51185e7b 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1777,7 +1777,8 @@ build_new (tree placement, tree decl, tree init, int use_global_new) { if (has_array) t = tree_cons (tree_cons (NULL_TREE, type, NULL_TREE), - build_min_nt (ARRAY_REF, NULL_TREE, nelts), + build_min_nt (ARRAY_REF, NULL_TREE, nelts, + NULL_TREE, NULL_TREE), NULL_TREE); else t = type; @@ -1815,7 +1816,7 @@ build_new (tree placement, tree decl, tree init, int use_global_new) } if (has_array) - t = build_nt (ARRAY_REF, type, nelts); + t = build_nt (ARRAY_REF, type, nelts, NULL_TREE, NULL_TREE); else t = type; diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 357ea868ed3..495244fa748 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -591,7 +591,7 @@ do_build_copy_constructor (tree fndecl) expr_type = TREE_TYPE (field); if (TREE_CODE (expr_type) != REFERENCE_TYPE) expr_type = cp_build_qualified_type (expr_type, cvquals); - init = build (COMPONENT_REF, expr_type, init, field); + init = build (COMPONENT_REF, expr_type, init, field, NULL_TREE); init = build_tree_list (NULL_TREE, init); member_init_list @@ -687,10 +687,11 @@ do_build_assign_ref (tree fndecl) else continue; - comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field); + comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field, + NULL_TREE); init = build (COMPONENT_REF, cp_build_qualified_type (TREE_TYPE (field), cvquals), - init, field); + init, field, NULL_TREE); if (DECL_NAME (field)) finish_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bd6abe8393d..5ad4250ee0a 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -4767,7 +4767,8 @@ cp_parser_direct_new_declarator (cp_parser* parser) cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); /* Add this bound to the declarator. */ - declarator = build_nt (ARRAY_REF, declarator, expression); + declarator = build_nt (ARRAY_REF, declarator, expression, + NULL_TREE, NULL_TREE); /* If the next token is not a `[', then there are no more bounds. */ @@ -10714,7 +10715,8 @@ cp_parser_direct_declarator (cp_parser* parser, break; } - declarator = build_nt (ARRAY_REF, declarator, bounds); + declarator = build_nt (ARRAY_REF, declarator, bounds, + NULL_TREE, NULL_TREE); } else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT) { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f8e259c6fbc..1e23acbcf07 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7201,7 +7201,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (e1 == error_mark_node || e2 == error_mark_node) return error_mark_node; - return build_nt (ARRAY_REF, e1, e2); + return build_nt (ARRAY_REF, e1, e2, NULL_TREE, NULL_TREE); } case CALL_EXPR: @@ -7563,7 +7563,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) in_decl); else name = tsubst_copy (name, args, complain, in_decl); - return build_nt (COMPONENT_REF, object, name); + return build_nt (COMPONENT_REF, object, name, NULL_TREE); } case PLUS_EXPR: @@ -8143,7 +8143,7 @@ tsubst_copy_and_build (tree t, if (object) return build (COMPONENT_REF, TREE_TYPE (template), - object, template); + object, template, NULL_TREE); else return template; } @@ -8255,7 +8255,8 @@ tsubst_copy_and_build (tree t, if (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl) == NULL_TREE) /* new-type-id */ - return build_nt (ARRAY_REF, NULL_TREE, RECUR (TREE_OPERAND (t, 1))); + return build_nt (ARRAY_REF, NULL_TREE, RECUR (TREE_OPERAND (t, 1)), + NULL_TREE, NULL_TREE); op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0), args, complain, in_decl); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 0da94942c2e..9e4b884c3b3 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1233,7 +1233,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) type = cp_build_qualified_type (type, quals); } - return build_min (COMPONENT_REF, type, object, decl); + return build_min (COMPONENT_REF, type, object, decl, NULL_TREE); } else { diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 6b558800e68..527e9c27d50 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1026,11 +1026,13 @@ bind_template_template_parm (tree t, tree newargs) /* Called from count_trees via walk_tree. */ static tree -count_trees_r (tree* tp ATTRIBUTE_UNUSED , - int* walk_subtrees ATTRIBUTE_UNUSED , - void* data) +count_trees_r (tree *tp, int *walk_subtrees, void *data) { - ++ *((int*) data); + ++*((int *) data); + + if (TYPE_P (*tp)) + *walk_subtrees = 0; + return NULL_TREE; } @@ -1107,9 +1109,8 @@ find_tree (tree t, tree x) /* Passed to walk_tree. Checks for the use of types with no linkage. */ static tree -no_linkage_helper (tree* tp, - int* walk_subtrees ATTRIBUTE_UNUSED , - void* data ATTRIBUTE_UNUSED ) +no_linkage_helper (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, + void *data ATTRIBUTE_UNUSED) { tree t = *tp; @@ -1118,6 +1119,7 @@ no_linkage_helper (tree* tp, && (decl_function_context (TYPE_MAIN_DECL (t)) || TYPE_ANONYMOUS_P (t))) return t; + return NULL_TREE; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index bdf7377d0e0..880000783cf 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1752,7 +1752,8 @@ build_class_member_access_expr (tree object, tree member, member_type = cp_build_qualified_type (member_type, type_quals); } - result = fold (build (COMPONENT_REF, member_type, object, member)); + result = fold (build (COMPONENT_REF, member_type, object, member, + NULL_TREE)); /* Mark the expression const or volatile, as appropriate. Even though we've dealt with the type above, we still have to mark the @@ -1779,7 +1780,7 @@ build_class_member_access_expr (tree object, tree member, type = unknown_type_node; /* Note that we do not convert OBJECT to the BASELINK_BINFO base. That will happen when the function is called. */ - result = build (COMPONENT_REF, type, object, member); + result = build (COMPONENT_REF, type, object, member, NULL_TREE); } else if (TREE_CODE (member) == CONST_DECL) { @@ -1878,7 +1879,7 @@ finish_class_member_access_expr (tree object, tree name) || (TREE_CODE (name) == SCOPE_REF && TYPE_P (TREE_OPERAND (name, 0)) && dependent_type_p (TREE_OPERAND (name, 0)))) - return build_min_nt (COMPONENT_REF, object, name); + return build_min_nt (COMPONENT_REF, object, name, NULL_TREE); object = build_non_dependent_expr (object); } @@ -2005,7 +2006,7 @@ finish_class_member_access_expr (tree object, tree name) /*preserve_reference=*/false); if (processing_template_decl && expr != error_mark_node) return build_min_non_dep (COMPONENT_REF, expr, - orig_object, orig_name); + orig_object, orig_name, NULL_TREE); return expr; } @@ -2033,7 +2034,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name) /*want_type=*/false); member_type = cp_build_qualified_type (TREE_TYPE (member), cp_type_quals (ptrmem_type)); - return fold (build (COMPONENT_REF, member_type, ptrmem, member)); + return fold (build (COMPONENT_REF, member_type, ptrmem, member, NULL_TREE)); } /* Given an expression PTR for a pointer, return an expression @@ -2249,7 +2250,7 @@ build_array_ref (tree array, tree idx) } type = TREE_TYPE (TREE_TYPE (array)); - rval = build (ARRAY_REF, type, array, idx); + rval = build (ARRAY_REF, type, array, idx, NULL_TREE, NULL_TREE); /* Array ref is const/volatile if the array elements are or if the array is.. */ TREE_READONLY (rval) diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 9ea4f55d5fb..2e08d563079 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -320,9 +320,11 @@ split_nonconstant_init_1 (tree dest, tree init) if (TREE_CODE (value) == CONSTRUCTOR) { if (array_type_p) - sub = build (ARRAY_REF, inner_type, dest, field_index); + sub = build (ARRAY_REF, inner_type, dest, field_index, + NULL_TREE, NULL_TREE); else - sub = build (COMPONENT_REF, inner_type, dest, field_index); + sub = build (COMPONENT_REF, inner_type, dest, field_index, + NULL_TREE); split_nonconstant_init_1 (sub, value); } @@ -331,9 +333,11 @@ split_nonconstant_init_1 (tree dest, tree init) *pelt = TREE_CHAIN (elt); if (array_type_p) - sub = build (ARRAY_REF, inner_type, dest, field_index); + sub = build (ARRAY_REF, inner_type, dest, field_index, + NULL_TREE, NULL_TREE); else - sub = build (COMPONENT_REF, inner_type, dest, field_index); + sub = build (COMPONENT_REF, inner_type, dest, field_index, + NULL_TREE); code = build (MODIFY_EXPR, inner_type, sub, value); code = build_stmt (EXPR_STMT, code); diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 41679151c64..984f81ffd6a 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -1460,8 +1460,8 @@ component_ref_for_mem_expr (tree ref) if (inner == TREE_OPERAND (ref, 0)) return ref; else - return build (COMPONENT_REF, TREE_TYPE (ref), inner, - TREE_OPERAND (ref, 1)); + return build (COMPONENT_REF, TREE_TYPE (ref), inner, TREE_OPERAND (ref, 1), + NULL_TREE); } /* Returns 1 if both MEM_EXPR can be considered equal @@ -1625,28 +1625,22 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, do { tree index = TREE_OPERAND (t2, 1); - tree array = TREE_OPERAND (t2, 0); - tree domain = TYPE_DOMAIN (TREE_TYPE (array)); - tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0); - tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array))); + tree low_bound = array_ref_low_bound (t2); + tree unit_size = array_ref_element_size (t2); /* We assume all arrays have sizes that are a multiple of a byte. First subtract the lower bound, if any, in the type of the - index, then convert to sizetype and multiply by the size of the - array element. */ - if (low_bound != 0 && ! integer_zerop (low_bound)) + index, then convert to sizetype and multiply by the size of + the array element. */ + if (! integer_zerop (low_bound)) index = fold (build (MINUS_EXPR, TREE_TYPE (index), index, low_bound)); - /* If the index has a self-referential type, instantiate it; - likewise for the component size. */ - index = SUBSTITUTE_PLACEHOLDER_IN_EXPR (index, t2); - unit_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (unit_size, array); - off_tree - = fold (build (PLUS_EXPR, sizetype, - fold (build (MULT_EXPR, sizetype, - index, unit_size)), - off_tree)); + off_tree = size_binop (PLUS_EXPR, + size_binop (MULT_EXPR, convert (sizetype, + index), + unit_size), + off_tree); t2 = TREE_OPERAND (t2, 0); } while (TREE_CODE (t2) == ARRAY_REF); @@ -2042,6 +2036,7 @@ widen_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset) if (TREE_CODE (expr) == COMPONENT_REF) { tree field = TREE_OPERAND (expr, 1); + tree offset = component_ref_field_offset (expr); if (! DECL_SIZE_UNIT (field)) { @@ -2056,17 +2051,18 @@ widen_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset) && INTVAL (memoffset) >= 0) break; - if (! host_integerp (DECL_FIELD_OFFSET (field), 1)) + if (! host_integerp (offset, 1)) { expr = NULL_TREE; break; } expr = TREE_OPERAND (expr, 0); - memoffset = (GEN_INT (INTVAL (memoffset) - + tree_low_cst (DECL_FIELD_OFFSET (field), 1) - + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) - / BITS_PER_UNIT))); + memoffset + = (GEN_INT (INTVAL (memoffset) + + tree_low_cst (offset, 1) + + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) + / BITS_PER_UNIT))); } /* Similarly for the decl. */ else if (DECL_P (expr) diff --git a/gcc/explow.c b/gcc/explow.c index af67003eacf..672d3f6525a 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -1100,7 +1100,7 @@ update_nonlocal_goto_save_area (void) STACK_SAVEAREA_MODE. Create a reference to array index 1, the first of the stack save area slots. */ t_save = build (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area, - integer_one_node); + integer_one_node, NULL_TREE, NULL_TREE); r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE); emit_stack_save (SAVE_NONLOCAL, &r_save, NULL_RTX); diff --git a/gcc/expr.c b/gcc/expr.c index aad7b1cb5ae..989a5fa6dca 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -5591,15 +5591,13 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, else if (TREE_CODE (exp) == COMPONENT_REF) { tree field = TREE_OPERAND (exp, 1); - tree this_offset = DECL_FIELD_OFFSET (field); + tree this_offset = component_ref_field_offset (exp); /* If this field hasn't been filled in yet, don't go past it. This should only happen when folding expressions made during type construction. */ if (this_offset == 0) break; - else - this_offset = SUBSTITUTE_PLACEHOLDER_IN_EXPR (this_offset, exp); offset = size_binop (PLUS_EXPR, offset, this_offset); bit_offset = size_binop (PLUS_EXPR, bit_offset, @@ -5612,23 +5610,17 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, || TREE_CODE (exp) == ARRAY_RANGE_REF) { tree index = TREE_OPERAND (exp, 1); - tree array = TREE_OPERAND (exp, 0); - tree domain = TYPE_DOMAIN (TREE_TYPE (array)); - tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0); - tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array))); + tree low_bound = array_ref_low_bound (exp); + tree unit_size = array_ref_element_size (exp); /* We assume all arrays have sizes that are a multiple of a byte. First subtract the lower bound, if any, in the type of the index, then convert to sizetype and multiply by the size of the array element. */ - if (low_bound != 0 && ! integer_zerop (low_bound)) + if (! integer_zerop (low_bound)) index = fold (build (MINUS_EXPR, TREE_TYPE (index), index, low_bound)); - /* If the index has a self-referential type, instantiate it with - the object; likewise for the component size. */ - index = SUBSTITUTE_PLACEHOLDER_IN_EXPR (index, exp); - unit_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (unit_size, array); offset = size_binop (PLUS_EXPR, offset, size_binop (MULT_EXPR, convert (sizetype, index), @@ -5676,6 +5668,70 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, return exp; } +/* Return a tree of sizetype representing the size, in bytes, of the element + of EXP, an ARRAY_REF. */ + +tree +array_ref_element_size (tree exp) +{ + tree aligned_size = TREE_OPERAND (exp, 3); + tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))); + + /* If a size was specified in the ARRAY_REF, it's the size measured + in alignment units of the element type. So multiply by that value. */ + if (aligned_size) + return size_binop (MULT_EXPR, aligned_size, + size_int (TYPE_ALIGN (elmt_type) / BITS_PER_UNIT)); + + /* Otherwise, take the size from that of the element type. Substitute + any PLACEHOLDER_EXPR that we have. */ + else + return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp); +} + +/* Return a tree representing the lower bound of the array mentioned in + EXP, an ARRAY_REF. */ + +tree +array_ref_low_bound (tree exp) +{ + tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0))); + + /* If a lower bound is specified in EXP, use it. */ + if (TREE_OPERAND (exp, 2)) + return TREE_OPERAND (exp, 2); + + /* Otherwise, if there is a domain type and it has a lower bound, use it, + substituting for a PLACEHOLDER_EXPR as needed. */ + if (domain_type && TYPE_MIN_VALUE (domain_type)) + return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), exp); + + /* Otherwise, return a zero of the appropriate type. */ + return fold_convert (TREE_TYPE (TREE_OPERAND (exp, 1)), integer_zero_node); +} + +/* Return a tree representing the offset, in bytes, of the field referenced + by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */ + +tree +component_ref_field_offset (tree exp) +{ + tree aligned_offset = TREE_OPERAND (exp, 2); + tree field = TREE_OPERAND (exp, 1); + + /* If an offset was specified in the COMPONENT_REF, it's the offset measured + in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT. So multiply by that + value. */ + if (aligned_offset) + return size_binop (MULT_EXPR, aligned_offset, + size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT)); + + /* Otherwise, take the offset from that of the field. Substitute + any PLACEHOLDER_EXPR that we have. */ + else + return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp); +} + /* Return 1 if T is an expression that get_inner_reference handles. */ int @@ -7001,8 +7057,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, { tree array = TREE_OPERAND (exp, 0); - tree domain = TYPE_DOMAIN (TREE_TYPE (array)); - tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node; + tree low_bound = array_ref_low_bound (exp); tree index = convert (sizetype, TREE_OPERAND (exp, 1)); HOST_WIDE_INT i; diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 68c9722ea18..3d4cccaaa6b 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -2019,9 +2019,9 @@ non_lvalue (tree x) case COMPONENT_REF: case INDIRECT_REF: case ARRAY_REF: + case ARRAY_RANGE_REF: case BIT_FIELD_REF: case BUFFER_REF: - case ARRAY_RANGE_REF: case VTABLE_REF: case REALPART_EXPR: @@ -7901,24 +7901,26 @@ fold (tree expr) /* If VAROP is a reference to a bitfield, we must mask the constant by the width of the field. */ if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF - && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (varop, 0), 1))) + && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (varop, 0), 1)) + && host_integerp (DECL_SIZE (TREE_OPERAND + (TREE_OPERAND (varop, 0), 1)), 1)) { tree fielddecl = TREE_OPERAND (TREE_OPERAND (varop, 0), 1); - int size = TREE_INT_CST_LOW (DECL_SIZE (fielddecl)); + HOST_WIDE_INT size = tree_low_cst (DECL_SIZE (fielddecl), 1); tree folded_compare, shift; /* First check whether the comparison would come out always the same. If we don't do that we would change the meaning with the masking. */ folded_compare = fold (build2 (code, type, - TREE_OPERAND (varop, 0), - arg1)); + TREE_OPERAND (varop, 0), arg1)); if (integer_zerop (folded_compare) || integer_onep (folded_compare)) return omit_one_operand (type, folded_compare, varop); shift = build_int_2 (TYPE_PRECISION (TREE_TYPE (varop)) - size, 0); + shift = fold_convert (TREE_TYPE (varop), shift); newconst = fold (build2 (LSHIFT_EXPR, TREE_TYPE (varop), newconst, shift)); newconst = fold (build2 (RSHIFT_EXPR, TREE_TYPE (varop), @@ -10106,13 +10108,10 @@ fold_read_from_constant_string (tree exp) tree string; if (TREE_CODE (exp) == INDIRECT_REF) - { - string = string_constant (exp1, &index); - } + string = string_constant (exp1, &index); else { - tree domain = TYPE_DOMAIN (TREE_TYPE (exp1)); - tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node; + tree low_bound = array_ref_low_bound (exp); index = fold_convert (sizetype, TREE_OPERAND (exp, 1)); /* Optimize the special-case of a zero lower bound. @@ -10129,6 +10128,7 @@ fold_read_from_constant_string (tree exp) } if (string + && TREE_TYPE (exp) == TREE_TYPE (TREE_TYPE (string)) && TREE_CODE (string) == STRING_CST && TREE_CODE (index) == INTEGER_CST && compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0 @@ -10456,7 +10456,7 @@ build_fold_indirect_ref (tree t) /* *(foo *)&fooarray => fooarray[0] */ else if (TREE_CODE (optype) == ARRAY_TYPE && lang_hooks.types_compatible_p (type, TREE_TYPE (optype))) - return build2 (ARRAY_REF, type, op, size_zero_node); + return build4 (ARRAY_REF, type, op, size_zero_node, NULL_TREE, NULL_TREE); } /* *(foo *)fooarrptr => (*fooarrptr)[0] */ @@ -10465,7 +10465,7 @@ build_fold_indirect_ref (tree t) && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype)))) { sub = build_fold_indirect_ref (sub); - return build2 (ARRAY_REF, type, sub, size_zero_node); + return build4 (ARRAY_REF, type, sub, size_zero_node, NULL_TREE, NULL_TREE); } return build1 (INDIRECT_REF, type, t); diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 01147289fb4..a2bb02c019c 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,22 @@ +2004-06-21 Richard Kenner + + * f95-lang.c (LANG_HOOKS_GIMPLE_BEFORE_INLINING): Deleted. + * trans-array.c (gfc_conv_descriptor_data): Add operand + for COMPONENT_REF. + (gfc_conv_descriptor_offset, gfc_conv_descriptor_dtype): Likewise. + (gfc_conv_descriptor_dimension, gfc_conv_descriptor_stride): Likewise. + (gfc_conv_descriptor_lbound, gfc_conv_descriptor_ubound): Likewise. + * trans-common.c (create_common): Likewise. + * trans-expr.c (gfc_conv_component_ref): Likewise. + * trans-io.c (set_parameter_value): Likewise. + (set_parameter_ref, set_string, set_flag, io_result): Likewise. + (transfer_expr): Likewise. + * trans-decl.c (gfc_trans_auto_character_variable): + Set up to get DECL_SIZE and DECL_SIZE_UNIT gimplified. + (gfc_simplify_function): New function. + (gfc_generate_function-code): Properly handle nested functions. + * trans.c (gfc_build_array_ref): Add two new operands for ARRAY_REF. + 2004-06-22 Janne Blomqvist PR fortran/15750 diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index ab151fcd737..fd4fe5c2616 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -122,7 +122,6 @@ static void gfc_expand_function (tree); #undef LANG_HOOKS_UNSIGNED_TYPE #undef LANG_HOOKS_SIGNED_TYPE #undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE -#undef LANG_HOOKS_GIMPLE_BEFORE_INLINING #undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION /* Define lang hooks. */ @@ -141,7 +140,6 @@ static void gfc_expand_function (tree); #define LANG_HOOKS_UNSIGNED_TYPE gfc_unsigned_type #define LANG_HOOKS_SIGNED_TYPE gfc_signed_type #define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE gfc_signed_or_unsigned_type -#define LANG_HOOKS_GIMPLE_BEFORE_INLINING false #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION gfc_expand_function const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index e83a45d030f..bccaf414895 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -189,7 +189,7 @@ gfc_conv_descriptor_data (tree desc) && TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == ARRAY_TYPE); - return build (COMPONENT_REF, TREE_TYPE (field), desc, field); + return build (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE); } tree @@ -204,7 +204,7 @@ gfc_conv_descriptor_offset (tree desc) field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD); assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type); - return build (COMPONENT_REF, TREE_TYPE (field), desc, field); + return build (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE); } tree @@ -219,7 +219,7 @@ gfc_conv_descriptor_dtype (tree desc) field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD); assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type); - return build (COMPONENT_REF, TREE_TYPE (field), desc, field); + return build (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE); } static tree @@ -237,7 +237,7 @@ gfc_conv_descriptor_dimension (tree desc, tree dim) && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE); - tmp = build (COMPONENT_REF, TREE_TYPE (field), desc, field); + tmp = build (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE); tmp = gfc_build_array_ref (tmp, dim); return tmp; } @@ -253,7 +253,7 @@ gfc_conv_descriptor_stride (tree desc, tree dim) field = gfc_advance_chain (field, STRIDE_SUBFIELD); assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type); - tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field); + tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE); return tmp; } @@ -268,7 +268,7 @@ gfc_conv_descriptor_lbound (tree desc, tree dim) field = gfc_advance_chain (field, LBOUND_SUBFIELD); assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type); - tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field); + tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE); return tmp; } @@ -283,7 +283,7 @@ gfc_conv_descriptor_ubound (tree desc, tree dim) field = gfc_advance_chain (field, UBOUND_SUBFIELD); assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type); - tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field); + tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE); return tmp; } diff --git a/gcc/fortran/trans-common.c b/gcc/fortran/trans-common.c index 667038d5cc4..f0c385adfbb 100644 --- a/gcc/fortran/trans-common.c +++ b/gcc/fortran/trans-common.c @@ -425,7 +425,7 @@ create_common (gfc_symbol *sym) for (h = current_common; h; h = next_s) { h->sym->backend_decl = build (COMPONENT_REF, TREE_TYPE (h->field), - decl, h->field); + decl, h->field, NULL_TREE); next_s = h->next; gfc_free (h); diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index ecabfc4d550..8cf6cbb185d 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -1645,6 +1645,14 @@ gfc_trans_auto_character_variable (gfc_symbol * sym, tree fnbody) DECL_DEFER_OUTPUT (decl) = 1; + /* Since we don't use a DECL_STMT or equivalent, we have to deal + with getting these gimplified. But we can't gimplify it yet since + we're still generating statements. + + ??? This should be cleaned up and handled like other front ends. */ + gfc_add_expr_to_block (&body, save_expr (DECL_SIZE (decl))); + gfc_add_expr_to_block (&body, save_expr (DECL_SIZE_UNIT (decl))); + /* Generate code to allocate the automatic variable. It will be freed automatically. */ tmp = gfc_build_addr_expr (NULL, decl); @@ -1949,6 +1957,24 @@ gfc_finalize (tree decl) cgraph_finalize_function (decl, false); } +/* Convert FNDECL's code to GIMPLE and handle any nested functions. */ + +static void +gfc_gimplify_function (tree fndecl) +{ + struct cgraph_node *cgn; + + gimplify_function_tree (fndecl); + dump_function (TDI_generic, fndecl); + + /* Convert all nested functions to GIMPLE now. We do things in this order + so that items like VLA sizes are expanded properly in the context of the + correct function. */ + cgn = cgraph_node (fndecl); + for (cgn = cgn->nested; cgn; cgn = cgn->next_nested) + gfc_gimplify_function (cgn->decl); +} + /* Generate code for a function. */ void @@ -2120,26 +2146,17 @@ gfc_generate_function_code (gfc_namespace * ns) current_function_decl = old_context; if (decl_function_context (fndecl)) - { - /* Register this function with cgraph just far enough to get it - added to our parent's nested function list. */ - (void) cgraph_node (fndecl); - - /* Lowering nested functions requires gimple input. */ - gimplify_function_tree (fndecl); - } + /* Register this function with cgraph just far enough to get it + added to our parent's nested function list. */ + (void) cgraph_node (fndecl); else { - if (cgraph_node (fndecl)->nested) - { - gimplify_function_tree (fndecl); - lower_nested_functions (fndecl); - } + gfc_gimplify_function (fndecl); + lower_nested_functions (fndecl); gfc_finalize (fndecl); } } - void gfc_generate_constructors (void) { diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index e4953f6f080..717a5d83bb3 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -221,7 +221,7 @@ gfc_conv_component_ref (gfc_se * se, gfc_ref * ref) field = c->backend_decl; assert (TREE_CODE (field) == FIELD_DECL); decl = se->expr; - tmp = build (COMPONENT_REF, TREE_TYPE (field), decl, field); + tmp = build (COMPONENT_REF, TREE_TYPE (field), decl, field, NULL_TREE); se->expr = tmp; diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c index 3f4076fc557..f3aa37d28d8 100644 --- a/gcc/fortran/trans-io.c +++ b/gcc/fortran/trans-io.c @@ -359,7 +359,7 @@ set_parameter_value (stmtblock_t * block, tree var, gfc_expr * e) gfc_conv_expr_type (&se, e, TREE_TYPE (var)); gfc_add_block_to_block (block, &se.pre); - tmp = build (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var); + tmp = build (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var, NULL_TREE); gfc_add_modify_expr (block, tmp, se.expr); } @@ -379,7 +379,7 @@ set_parameter_ref (stmtblock_t * block, tree var, gfc_expr * e) gfc_conv_expr_type (&se, e, TREE_TYPE (var)); gfc_add_block_to_block (block, &se.pre); - tmp = build (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var); + tmp = build (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var, NULL_TREE); gfc_add_modify_expr (block, tmp, se.expr); } @@ -400,8 +400,9 @@ set_string (stmtblock_t * block, stmtblock_t * postblock, tree var, gfc_init_se (&se, NULL); gfc_conv_expr (&se, e); - io = build (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var); - len = build (COMPONENT_REF, TREE_TYPE (var_len), ioparm_var, var_len); + io = build (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var, NULL_TREE); + len = build (COMPONENT_REF, TREE_TYPE (var_len), ioparm_var, var_len, + NULL_TREE); /* Integer variable assigned a format label. */ if (e->ts.type == BT_INTEGER && e->symtree->n.sym->attr.assign == 1) @@ -433,7 +434,7 @@ set_flag (stmtblock_t *block, tree var) { tree tmp; - tmp = build (COMPONENT_REF, TREE_TYPE(var), ioparm_var, var); + tmp = build (COMPONENT_REF, TREE_TYPE(var), ioparm_var, var, NULL_TREE); gfc_add_modify_expr (block, tmp, integer_one_node); } @@ -496,7 +497,7 @@ io_result (stmtblock_t * block, gfc_st_label * err_label, tmp = gfc_finish_block (&body); rc = build (COMPONENT_REF, TREE_TYPE (ioparm_library_return), ioparm_var, - ioparm_library_return); + ioparm_library_return, NULL_TREE); tmp = build_v (SWITCH_EXPR, rc, tmp, NULL_TREE); @@ -1127,7 +1128,8 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr) field = c->backend_decl; assert (field && TREE_CODE (field) == FIELD_DECL); - tmp = build (COMPONENT_REF, TREE_TYPE (field), expr, field); + tmp = build (COMPONENT_REF, TREE_TYPE (field), expr, field, + NULL_TREE); if (c->ts.type == BT_CHARACTER) { diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index bb994a7f6da..29277282b5e 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -306,7 +306,7 @@ gfc_build_array_ref (tree base, tree offset) if (DECL_P (base)) TREE_ADDRESSABLE (base) = 1; - return build (ARRAY_REF, type, base, offset); + return build (ARRAY_REF, type, base, offset, NULL_TREE, NULL_TREE); } diff --git a/gcc/function.c b/gcc/function.c index 3f1f45bbcaa..8fd0a6f35ab 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -6544,7 +6544,7 @@ expand_function_start (tree subr, int parms_have_cleanups) expand_var (TREE_OPERAND (cfun->nonlocal_goto_save_area, 0)); t_save = build (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area, - integer_zero_node); + integer_zero_node, NULL_TREE, NULL_TREE); r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE); emit_move_insn (r_save, virtual_stack_vars_rtx); diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index 98346cc2bf2..32e5ceec5f4 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -476,8 +476,6 @@ expand_var_p (tree var) if (TREE_CODE (var) != VAR_DECL) return true; - ann = var_ann (var); - /* Remove all unused, unaliased temporaries. Also remove unused, unaliased local variables during highly optimizing compilations. */ ann = var_ann (var); diff --git a/gcc/gimplify.c b/gcc/gimplify.c index f6e4a04bf9b..36492720ff9 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1,6 +1,5 @@ /* Tree lowering pass. This pass converts the GENERIC functions-as-trees tree representation into the GIMPLE form. - Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. Major work done by Sebastian Pop , Diego Novillo and Jason Merrill . @@ -36,6 +35,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "langhooks.h" #include "langhooks-def.h" #include "tree-flow.h" +#include "cgraph.h" #include "timevar.h" #include "except.h" #include "hashtab.h" @@ -71,6 +71,73 @@ typedef struct gimple_temp_hash_elt tree temp; /* Value */ } elt_t; +/* Forward declarations. */ +static hashval_t gimple_tree_hash (const void *); +static int gimple_tree_eq (const void *, const void *); +static bool gimple_conditional_context (void); +static void gimple_push_condition (void); +static void gimple_pop_condition (tree *); +static void append_to_statement_list_1 (tree, tree *, bool); +static inline void remove_suffix (char *, int); +static inline tree create_tmp_from_val (tree); +static tree lookup_tmp_var (tree, bool); +static tree internal_get_tmp_var (tree, tree *, tree *, bool); +static bool should_carry_locus_p (tree); +static tree mostly_copy_tree_r (tree *, int *, void *); +static tree mark_decls_volatile_r (tree *, int *, void *); +static tree copy_if_shared_r (tree *, int *, void *); +static tree unmark_visited_r (tree *, int *, void *); +static void unshare_body (tree *, tree); +static void unvisit_body (tree *, tree); +static void build_stack_save_restore (tree *, tree *); +static enum gimplify_status gimplify_bind_expr (tree *, tree, tree *); +static enum gimplify_status gimplify_return_expr (tree, tree *); +static enum gimplify_status gimplify_loop_expr (tree *, tree *); +static int compare_case_labels (const void *, const void *); +static enum gimplify_status gimplify_switch_expr (tree *, tree *); +static enum gimplify_status gimplify_case_label_expr (tree *); +static enum gimplify_status gimplify_labeled_block_expr (tree *); +static enum gimplify_status gimplify_exit_block_expr (tree *); +static enum gimplify_status gimplify_exit_expr (tree *); +static enum gimplify_status gimplify_init_constructor (tree *, tree *, tree *, + bool); +static void canonicalize_component_ref (tree *); +static void canonicalize_addr_expr (tree *); +static enum gimplify_status gimplify_conversion (tree *); +static enum gimplify_status gimplify_minimax_expr (tree *, tree *, tree *); +static enum gimplify_status gimplify_array_ref_to_plus (tree *, tree *, + tree *); +static tree build_addr_expr_with_type (tree, tree); +static tree build_addr_expr (tree); +static enum gimplify_status gimplify_compound_lval (tree *, tree *, tree *, + bool); +static enum gimplify_status gimplify_self_mod_expr (tree *, tree *, tree *, + bool); +static enum gimplify_status gimplify_call_expr (tree *, tree *, + bool (*) (tree)); +static tree shortcut_cond_r (tree, tree *, tree *); +static tree shortcut_cond_expr (tree); +static tree gimple_boolify (tree); +static enum gimplify_status gimplify_cond_expr (tree *, tree *, tree); +static enum gimplify_status gimplify_modify_expr (tree *, tree *, tree *, + bool); +static enum gimplify_status gimplify_modify_expr_rhs (tree *, tree *, tree *, + tree *, tree *, bool); +static enum gimplify_status gimplify_variable_sized_compare (tree *); +static enum gimplify_status gimplify_boolean_expr (tree *); +static enum gimplify_status gimplify_compound_expr (tree *, tree *, bool); +static enum gimplify_status gimplify_statement_list (tree *); +static enum gimplify_status gimplify_save_expr (tree *, tree *, tree *); +static enum gimplify_status gimplify_addr_expr (tree *, tree *, tree *); +static enum gimplify_status gimplify_asm_expr (tree *, tree *, tree *); +static enum gimplify_status gimplify_cleanup_point_expr (tree *, tree *); +static void gimple_push_cleanup (tree, tree, tree *); +static enum gimplify_status gimplify_target_expr (tree *, tree *, tree *); +#ifdef ENABLE_CHECKING +static bool cpt_same_type (tree, tree); +static tree check_pointer_types_r (tree *, int *, void *); +#endif + /* Return a hash value for a formal temporary table entry. */ static hashval_t @@ -355,15 +422,11 @@ create_tmp_var (tree type, const char *prefix) tree tmp_var; #if defined ENABLE_CHECKING - /* If the type is an array or a type which must be created by the - frontend, something is wrong. */ - if (TREE_CODE (type) == ARRAY_TYPE || TREE_ADDRESSABLE (type)) - abort (); - if (!COMPLETE_TYPE_P (type)) - abort (); - /* Variable sized types require lots of machinery to create; the - optimizers shouldn't be doing anything of the sort. */ - if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST) + /* We don't allow types that are addressable (meaning we can't make copies), + incomplete, or of variable size. */ + if (TREE_ADDRESSABLE (type) + || !COMPLETE_TYPE_P (type) + || TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST) abort (); #endif @@ -653,11 +716,19 @@ copy_if_shared_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, tree t = *tp; enum tree_code code = TREE_CODE (t); - /* Skip types, decls, and constants. */ + /* Skip types, decls, and constants. But we do want to look at their + types and the bounds of types. Mark them as visited so we properly + unmark their subtrees on the unmark pass. If we've already seen them, + don't look down further. */ if (TREE_CODE_CLASS (code) == 't' || TREE_CODE_CLASS (code) == 'd' || TREE_CODE_CLASS (code) == 'c') - *walk_subtrees = 0; + { + if (TREE_VISITED (t)) + *walk_subtrees = 0; + else + TREE_VISITED (t) = 1; + } /* Special-case BIND_EXPR. We should never be copying these, therefore we can omit examining BIND_EXPR_VARS. Which also avoids problems with @@ -715,6 +786,31 @@ unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, return NULL_TREE; } +/* Unshare all the trees in BODY_P, a pointer to the body of FNDECL, and the + bodies of any nested functions. */ + +static void +unshare_body (tree *body_p, tree fndecl) +{ + struct cgraph_node *cgn = cgraph_node (fndecl); + + walk_tree (body_p, copy_if_shared_r, NULL, NULL); + for (cgn = cgn->nested; cgn; cgn = cgn->next_nested) + unshare_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl); +} + +/* Likewise, but mark all trees as not visited. */ + +static void +unvisit_body (tree *body_p, tree fndecl) +{ + struct cgraph_node *cgn = cgraph_node (fndecl); + + walk_tree (body_p, unmark_visited_r, NULL, NULL); + for (cgn = cgn->nested; cgn; cgn = cgn->next_nested) + unvisit_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl); +} + /* Unshare T and all the trees reached from T via TREE_CHAIN. */ void @@ -1192,7 +1288,7 @@ build_and_jump (tree *label_p) { if (label_p == NULL) /* If there's nowhere to jump, just fall through. */ - return build_empty_stmt (); + return alloc_stmt_list (); if (*label_p == NULL_TREE) { @@ -1214,7 +1310,7 @@ gimplify_exit_expr (tree *expr_p) tree expr; expr = build_and_jump (&gimplify_ctxp->exit_label); - expr = build (COND_EXPR, void_type_node, cond, expr, build_empty_stmt ()); + expr = build (COND_EXPR, void_type_node, cond, expr, alloc_stmt_list ()); *expr_p = expr; return GS_OK; @@ -1243,7 +1339,7 @@ force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) static enum gimplify_status gimplify_init_constructor (tree *expr_p, tree *pre_p, - tree *post_p, int want_value) + tree *post_p, bool want_value) { tree object = TREE_OPERAND (*expr_p, 0); tree ctor = TREE_OPERAND (*expr_p, 1); @@ -1279,7 +1375,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, return GS_OK; } else - return GS_ALL_DONE; + return GS_UNHANDLED; } categorize_ctor_elements (ctor, &num_nonzero_elements, @@ -1307,7 +1403,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, TU-local symbol, we must invoke the lhd version now. */ lhd_set_decl_assembler_name (object); - *expr_p = build_empty_stmt (); + *expr_p = alloc_stmt_list (); break; } @@ -1416,13 +1512,11 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, if (TREE_CODE (purpose) == RANGE_EXPR) abort (); - cref = build (ARRAY_REF, t, object, purpose); + cref = build (ARRAY_REF, t, object, purpose, NULL_TREE, NULL_TREE); } else - { - cref = build (COMPONENT_REF, TREE_TYPE (purpose), - object, purpose); - } + cref = build (COMPONENT_REF, TREE_TYPE (purpose), object, + purpose, NULL_TREE); init = build (MODIFY_EXPR, TREE_TYPE (purpose), cref, value); /* Each member initialization is a full-expression. */ @@ -1430,7 +1524,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, append_to_statement_list (init, pre_p); } - *expr_p = build_empty_stmt (); + *expr_p = alloc_stmt_list (); } break; @@ -1552,18 +1646,17 @@ canonicalize_component_ref (tree *expr_p) } /* If a NOP conversion is changing a pointer to array of foo to a pointer - to foo, embed that change in the ADDR_EXPR. Lest we perturb the type - system too badly, we must take extra steps to ensure that the ADDR_EXPR - and the addressed object continue to agree on types. */ -/* ??? We might could do better if we recognize - T array[N][M]; - (T *)&array + to foo, embed that change in the ADDR_EXPR by converting + T array[U]; + (T *)&array ==> - &array[0][0]; -*/ + &array[L] + where L is the lower bound. Only do this for constant lower bound since + we have no place to put any statements made during gimplification of + the lower bound. */ static void -canonicalize_addr_expr (tree* expr_p) +canonicalize_addr_expr (tree *expr_p) { tree expr = *expr_p; tree ctype = TREE_TYPE (expr); @@ -1592,8 +1685,20 @@ canonicalize_addr_expr (tree* expr_p) if (!lang_hooks.types_compatible_p (otype, datype)) return; + /* The lower bound and element sizes must be constant. */ + if (TREE_CODE (TYPE_SIZE_UNIT (dctype)) != INTEGER_CST + || !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype)) + || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST) + return; + /* All checks succeeded. Build a new node to merge the cast. */ - *expr_p = build1 (ADDR_EXPR, ctype, obj_expr); + *expr_p = build4 (ARRAY_REF, dctype, obj_expr, + TYPE_MIN_VALUE (TYPE_DOMAIN (datype)), + TYPE_MIN_VALUE (TYPE_DOMAIN (datype)), + size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (dctype), + size_int (TYPE_ALIGN (dctype) + / BITS_PER_UNIT))); + *expr_p = build1 (ADDR_EXPR, ctype, *expr_p); } /* *EXPR_P is a NOP_EXPR or CONVERT_EXPR. Remove it and/or other conversions @@ -1666,7 +1771,7 @@ gimplify_minimax_expr (tree *expr_p, tree *pre_p, tree *post_p) return GS_OK; } -/* Subroutine of gimplify_compound_lval and gimplify_array_ref. +/* Subroutine of gimplify_compound_lval. Converts an ARRAY_REF to the equivalent *(&array + offset) form. */ static enum gimplify_status @@ -1675,25 +1780,21 @@ gimplify_array_ref_to_plus (tree *expr_p, tree *pre_p, tree *post_p) tree array = TREE_OPERAND (*expr_p, 0); tree arrtype = TREE_TYPE (array); tree elttype = TREE_TYPE (arrtype); - tree size = size_in_bytes (elttype); + tree size = array_ref_element_size (*expr_p); tree ptrtype = build_pointer_type (elttype); enum tree_code add_code = PLUS_EXPR; tree idx = TREE_OPERAND (*expr_p, 1); - tree minidx, offset, addr, result; + tree minidx = unshare_expr (array_ref_low_bound (*expr_p)); + tree offset, addr, result; enum gimplify_status ret; /* If the array domain does not start at zero, apply the offset. */ - minidx = TYPE_DOMAIN (arrtype); - if (minidx) + if (!integer_zerop (minidx)) { - minidx = TYPE_MIN_VALUE (minidx); - if (minidx && !integer_zerop (minidx)) - { - idx = convert (TREE_TYPE (minidx), idx); - idx = fold (build (MINUS_EXPR, TREE_TYPE (minidx), idx, minidx)); - } + idx = convert (TREE_TYPE (minidx), idx); + idx = fold (build (MINUS_EXPR, TREE_TYPE (minidx), idx, minidx)); } - + /* If the index is negative -- a technically invalid situation now that we've biased the index back to zero -- then casting it to unsigned has ill effects. In particular, -1*4U/4U != -1. @@ -1707,7 +1808,7 @@ gimplify_array_ref_to_plus (tree *expr_p, tree *pre_p, tree *post_p) } /* Pointer arithmetic must be done in sizetype. */ - idx = convert (sizetype, idx); + idx = fold_convert (sizetype, idx); /* Convert the index to a byte offset. */ offset = size_binop (MULT_EXPR, size, idx); @@ -1723,6 +1824,44 @@ gimplify_array_ref_to_plus (tree *expr_p, tree *pre_p, tree *post_p) return GS_OK; } +/* Build an expression for the address of T. Folds away INDIRECT_REF to + avoid confusing the gimplify process. */ + +static tree +build_addr_expr_with_type (tree t, tree ptrtype) +{ + if (TREE_CODE (t) == INDIRECT_REF) + { + t = TREE_OPERAND (t, 0); + if (TREE_TYPE (t) != ptrtype) + t = build1 (NOP_EXPR, ptrtype, t); + } + else + { + tree base = t; + + if (TREE_CODE (base) == REALPART_EXPR + || TREE_CODE (base) == IMAGPART_EXPR) + base = TREE_OPERAND (base, 0); + else + while (handled_component_p (base)) + base = TREE_OPERAND (base, 0); + + if (DECL_P (base)) + TREE_ADDRESSABLE (base) = 1; + + t = build1 (ADDR_EXPR, ptrtype, t); + } + + return t; +} + +static tree +build_addr_expr (tree t) +{ + return build_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t))); +} + /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR node pointed by EXPR_P. @@ -1747,63 +1886,49 @@ gimplify_array_ref_to_plus (tree *expr_p, tree *pre_p, tree *post_p) static enum gimplify_status gimplify_compound_lval (tree *expr_p, tree *pre_p, - tree *post_p, int want_lvalue) + tree *post_p, bool want_lvalue) { tree *p; - enum tree_code code; varray_type stack; - enum gimplify_status ret; + enum gimplify_status ret = GS_OK, tret; #if defined ENABLE_CHECKING if (TREE_CODE (*expr_p) != ARRAY_REF + && TREE_CODE (*expr_p) != ARRAY_RANGE_REF && TREE_CODE (*expr_p) != COMPONENT_REF + && TREE_CODE (*expr_p) != BIT_FIELD_REF && TREE_CODE (*expr_p) != REALPART_EXPR && TREE_CODE (*expr_p) != IMAGPART_EXPR) abort (); #endif - code = ERROR_MARK; /* [GIMPLE] Avoid uninitialized use warning. */ - /* Create a stack of the subexpressions so later we can walk them in order from inner to outer. */ VARRAY_TREE_INIT (stack, 10, "stack"); - for (p = expr_p; - TREE_CODE (*p) == ARRAY_REF - || TREE_CODE (*p) == COMPONENT_REF - || TREE_CODE (*p) == REALPART_EXPR - || TREE_CODE (*p) == IMAGPART_EXPR; - p = &TREE_OPERAND (*p, 0)) - { - code = TREE_CODE (*p); - if (code == ARRAY_REF) - { - tree elttype = TREE_TYPE (TREE_TYPE (TREE_OPERAND (*p, 0))); - if (!TREE_CONSTANT (TYPE_SIZE_UNIT (elttype))) - /* If the size of the array elements is not constant, - computing the offset is non-trivial, so expose it. */ - break; - } + /* We can either handle one REALPART_EXPR or IMAGEPART_EXPR or + nest of handled components. */ + if (TREE_CODE (*expr_p) == REALPART_EXPR + || TREE_CODE (*expr_p) == IMAGPART_EXPR) + p = &TREE_OPERAND (*expr_p, 0); + else + for (p = expr_p; handled_component_p (*p); p = &TREE_OPERAND (*p, 0)) VARRAY_PUSH_TREE (stack, *p); - } - - /* Now 'p' points to the first bit that isn't a ref, 'code' is the - TREE_CODE of the last bit that was, and 'stack' is a stack of pointers - to all the refs we've walked through. - Gimplify the base, and then process each of the outer nodes from left - to right. */ - ret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval, - code != ARRAY_REF ? fb_either : fb_lvalue); + /* Now STACK is a stack of pointers to all the refs we've walked through + and P points to the innermost expression. + Process each of the outer nodes from left to right, then gimplify the + base. We need to do it in this order so that PLACEHOLDER_EXPRs + can be resolved. */ for (; VARRAY_ACTIVE_SIZE (stack) > 0; ) { tree t = VARRAY_TOP_TREE (stack); - if (TREE_CODE (t) == ARRAY_REF) + + if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF) { - /* Gimplify the dimension. */ - enum gimplify_status tret; - /* Temporary fix for gcc.c-torture/execute/20040313-1.c. + /* Gimplify the dimension. + Temporary fix for gcc.c-torture/execute/20040313-1.c. Gimplify non-constant array indices into a temporary variable. FIXME - The real fix is to gimplify post-modify @@ -1815,14 +1940,82 @@ gimplify_compound_lval (tree *expr_p, tree *pre_p, { tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p, is_gimple_tmp_var, fb_rvalue); - if (tret == GS_ERROR) - ret = GS_ERROR; + ret = MIN (ret, tret); + } + + /* Gimplify the low bound and element type size and put them into + the ARRAY_REF. If these values are set, they have already been + gimplified. */ + if (!TREE_OPERAND (t, 2)) + { + TREE_OPERAND (t, 2) = unshare_expr (array_ref_low_bound (t)); + if (!is_gimple_min_invariant (TREE_OPERAND (t, 2))) + { + tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, + is_gimple_tmp_var, fb_rvalue); + ret = MIN (ret, tret); + } + } + + if (!TREE_OPERAND (t, 3)) + { + tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0))); + tree elmt_size = unshare_expr (array_ref_element_size (t)); + tree factor = size_int (TYPE_ALIGN (elmt_type) / BITS_PER_UNIT); + + /* Divide the element size by the alignment of the element + type (above). */ + elmt_size = size_binop (EXACT_DIV_EXPR, elmt_size, factor); + + TREE_OPERAND (t, 3) = elmt_size; + if (!is_gimple_min_invariant (TREE_OPERAND (t, 3))) + { + tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p, + is_gimple_tmp_var, fb_rvalue); + ret = MIN (ret, tret); + } } } + else if (TREE_CODE (t) == COMPONENT_REF) + { + /* Set the field offset into T and gimplify it. */ + if (!TREE_OPERAND (t, 2)) + { + tree offset = unshare_expr (component_ref_field_offset (t)); + tree field = TREE_OPERAND (t, 1); + tree factor + = size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT); + + /* Divide the offset by its alignment. */ + offset = size_binop (EXACT_DIV_EXPR, offset, factor); + + TREE_OPERAND (t, 2) = offset; + if (!is_gimple_min_invariant (TREE_OPERAND (t, 2))) + { + tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, + is_gimple_tmp_var, fb_rvalue); + ret = MIN (ret, tret); + } + } + } + else if (TREE_CODE (t) == BIT_FIELD_REF) + { + tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p, + is_gimple_val, fb_rvalue); + ret = MIN (ret, tret); + tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, + is_gimple_val, fb_rvalue); + ret = MIN (ret, tret); + } + recalculate_side_effects (t); VARRAY_POP (stack); } + tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval, + want_lvalue ? fb_lvalue : fb_rvalue); + ret = MIN (ret, tret); + /* If the outermost expression is a COMPONENT_REF, canonicalize its type. */ if (!want_lvalue && TREE_CODE (*expr_p) == COMPONENT_REF) { @@ -1833,33 +2026,6 @@ gimplify_compound_lval (tree *expr_p, tree *pre_p, return ret; } -/* Re-write the ARRAY_REF node pointed by EXPR_P. - - PRE_P points to the list where side effects that must happen before - *EXPR_P should be stored. - - POST_P points to the list where side effects that must happen after - *EXPR_P should be stored. - - FIXME: ARRAY_REF currently doesn't accept a pointer as the array - argument, so this gimplification uses an INDIRECT_REF of ARRAY_TYPE. - ARRAY_REF should be extended. */ - -static enum gimplify_status -gimplify_array_ref (tree *expr_p, tree *pre_p, - tree *post_p, int want_lvalue) -{ - tree elttype = TREE_TYPE (TREE_TYPE (TREE_OPERAND (*expr_p, 0))); - if (!TREE_CONSTANT (TYPE_SIZE_UNIT (elttype))) - /* If the size of the array elements is not constant, - computing the offset is non-trivial, so expose it. */ - return gimplify_array_ref_to_plus (expr_p, pre_p, post_p); - else - /* Handle array and member refs together for now. When alias analysis - improves, we may want to go back to handling them separately. */ - return gimplify_compound_lval (expr_p, pre_p, post_p, want_lvalue); -} - /* Gimplify the self modifying expression pointed by EXPR_P (++, --, +=, -=). PRE_P points to the list where side effects that must happen before @@ -1873,7 +2039,7 @@ gimplify_array_ref (tree *expr_p, tree *pre_p, static enum gimplify_status gimplify_self_mod_expr (tree *expr_p, tree *pre_p, tree *post_p, - int want_value) + bool want_value) { enum tree_code code; tree lhs, lvalue, rhs, t1; @@ -2166,7 +2332,7 @@ shortcut_cond_expr (tree expr) then_ = shortcut_cond_expr (expr); pred = TREE_OPERAND (pred, 0); expr = build (COND_EXPR, void_type_node, pred, then_, - build_empty_stmt ()); + alloc_stmt_list ()); } } if (!TREE_SIDE_EFFECTS (then_)) @@ -2181,7 +2347,7 @@ shortcut_cond_expr (tree expr) else_ = shortcut_cond_expr (expr); pred = TREE_OPERAND (pred, 0); expr = build (COND_EXPR, void_type_node, pred, - build_empty_stmt (), else_); + alloc_stmt_list (), else_); } } @@ -2207,14 +2373,14 @@ shortcut_cond_expr (tree expr) && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL) { true_label = GOTO_DESTINATION (then_); - then_ = build_empty_stmt (); + then_ = alloc_stmt_list (); } if (TREE_CODE (else_) == GOTO_EXPR && TREE_CODE (GOTO_DESTINATION (else_)) == LABEL_DECL) { false_label = GOTO_DESTINATION (else_); - else_ = build_empty_stmt (); + else_ = alloc_stmt_list (); } /* If we aren't hijacking a label for the 'then' branch, it falls through. */ @@ -2329,6 +2495,8 @@ gimple_boolify (tree expr) The second form is used when *EXPR_P is of type void. + TARGET is the tree for T1 above. + PRE_P points to the list where side effects that must happen before *EXPR_P should be stored. */ @@ -2456,7 +2624,7 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value) { tree *from_p = &TREE_OPERAND (*expr_p, 1); tree *to_p = &TREE_OPERAND (*expr_p, 0); - enum gimplify_status ret; + enum gimplify_status ret = GS_UNHANDLED; #if defined ENABLE_CHECKING if (TREE_CODE (*expr_p) != MODIFY_EXPR && TREE_CODE (*expr_p) != INIT_EXPR) @@ -2467,40 +2635,51 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value) if (TREE_CODE (*expr_p) == INIT_EXPR) TREE_SET_CODE (*expr_p, MODIFY_EXPR); - ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue); - if (ret == GS_ERROR) + /* See if any simplifications can be done based on what the RHS is. */ + ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p, + want_value); + if (ret != GS_UNHANDLED) return ret; - /* If we are initializing something from a TARGET_EXPR, strip the - TARGET_EXPR and initialize it directly, if possible. This can't - be done if the initializer is void, since that implies that the - temporary is set in some non-trivial way. */ - /* What about code that pulls out the temp and uses it elsewhere? I - think that such code never uses the TARGET_EXPR as an initializer. If - I'm wrong, we'll abort because the temp won't have any RTL. In that - case, I guess we'll need to replace references somehow. */ - if (TREE_CODE (*from_p) == TARGET_EXPR) + /* If the value being copied is of variable width, expose the length + if the copy by converting the whole thing to a memcpy. Note that + we need to do this before gimplifying any of the operands + so that we can resolve any PLACEHOLDER_EXPRs in the size. */ + if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p))) != INTEGER_CST) { - tree init = TARGET_EXPR_INITIAL (*from_p); - if (!VOID_TYPE_P (TREE_TYPE (init))) - *from_p = init; + tree args, t, dest; + + t = TYPE_SIZE_UNIT (TREE_TYPE (*to_p)); + t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, *to_p); + t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, *from_p); + t = unshare_expr (t); + args = tree_cons (NULL, t, NULL); + t = build_fold_addr_expr (*from_p); + args = tree_cons (NULL, t, args); + dest = build_fold_addr_expr (*to_p); + args = tree_cons (NULL, dest, args); + t = implicit_built_in_decls[BUILT_IN_MEMCPY]; + t = build_function_call_expr (t, args); + if (want_value) + { + t = build1 (NOP_EXPR, TREE_TYPE (dest), t); + t = build1 (INDIRECT_REF, TREE_TYPE (*to_p), t); + } + *expr_p = t; + return GS_OK; } - /* If we're assigning from a ?: expression with ADDRESSABLE type, push - the assignment down into the branches, since we can't generate a - temporary of such a type. */ - if (TREE_CODE (*from_p) == COND_EXPR - && TREE_ADDRESSABLE (TREE_TYPE (*from_p))) - { - *expr_p = *from_p; - return gimplify_cond_expr (expr_p, pre_p, *to_p); - } + ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue); + if (ret == GS_ERROR) + return ret; ret = gimplify_expr (from_p, pre_p, post_p, is_gimple_rhs, fb_rvalue); if (ret == GS_ERROR) return ret; - ret = gimplify_init_constructor (expr_p, pre_p, post_p, want_value); + /* Now see if the above changed *from_p to something we handle specially. */ + ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p, + want_value); if (ret != GS_UNHANDLED) return ret; @@ -2530,35 +2709,6 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value) && !is_gimple_reg (*to_p))) gimplify_expr (from_p, pre_p, post_p, is_gimple_val, fb_rvalue); - /* If the value being copied is of variable width, expose the length - if the copy by converting the whole thing to a memcpy. */ - /* ??? Except that we can't manage this with VA_ARG_EXPR. Yes, this - does leave us with an edge condition that doesn't work. The only - way out is to rearrange how VA_ARG_EXPR works. */ - if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p))) != INTEGER_CST - && TREE_CODE (*from_p) != VA_ARG_EXPR) - { - tree args, t, dest; - - t = TYPE_SIZE_UNIT (TREE_TYPE (*to_p)); - t = unshare_expr (t); - args = tree_cons (NULL, t, NULL); - t = build_fold_addr_expr (*from_p); - args = tree_cons (NULL, t, args); - dest = build_fold_addr_expr (*to_p); - args = tree_cons (NULL, dest, args); - t = implicit_built_in_decls[BUILT_IN_MEMCPY]; - t = build_function_call_expr (t, args); - if (want_value) - { - t = build1 (NOP_EXPR, TREE_TYPE (dest), t); - t = build1 (INDIRECT_REF, TREE_TYPE (*to_p), t); - } - *expr_p = t; - - return GS_OK; - } - ret = want_value ? GS_OK : GS_ALL_DONE; } @@ -2571,6 +2721,101 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value) return ret; } +/* Subroutine of above to do simplications of MODIFY_EXPRs based on + the code of the RHS. We loop for as long as we can do something. */ + +static enum gimplify_status +gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, + tree *post_p, bool want_value) +{ + enum gimplify_status ret = GS_OK; + + while (ret != GS_UNHANDLED) + switch (TREE_CODE (*from_p)) + { + case TARGET_EXPR: + { + /* If we are initializing something from a TARGET_EXPR, strip the + TARGET_EXPR and initialize it directly, if possible. This can't + be done if the initializer is void, since that implies that the + temporary is set in some non-trivial way. + + ??? What about code that pulls out the temp and uses it + elsewhere? I think that such code never uses the TARGET_EXPR as + an initializer. If I'm wrong, we'll abort because the temp won't + have any RTL. In that case, I guess we'll need to replace + references somehow. */ + tree init = TARGET_EXPR_INITIAL (*from_p); + + if (!VOID_TYPE_P (TREE_TYPE (init))) + { + *from_p = init; + ret = GS_OK; + } + else + ret = GS_UNHANDLED; + } + break; + + case COMPOUND_EXPR: + /* Remove any COMPOUND_EXPR in the RHS so the following cases will be + caught. */ + gimplify_compound_expr (from_p, pre_p, true); + ret = GS_OK; + break; + + case CONSTRUCTOR: + /* If we're initializing from a CONSTRUCTOR, break this into + individual MODIFY_EXPRs. */ + return gimplify_init_constructor (expr_p, pre_p, post_p, want_value); + + case COND_EXPR: + /* If we're assigning from a ?: expression with ADDRESSABLE type, push + the assignment down into the branches, since we can't generate a + temporary of such a type. */ + if (TREE_ADDRESSABLE (TREE_TYPE (*from_p))) + { + *expr_p = *from_p; + return gimplify_cond_expr (expr_p, pre_p, *to_p); + } + else + ret = GS_UNHANDLED; + break; + + default: + ret = GS_UNHANDLED; + break; + } + + return ret; +} + +/* Gimplify a comparison between two variable-sized objects. Do this + with a call to BUILT_IN_MEMCMP. */ + +static enum gimplify_status +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 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, op0); + t = unshare_expr (t); + args = tree_cons (NULL, t, NULL); + t = build_addr_expr (op1); + args = tree_cons (NULL, t, args); + dest = build_addr_expr (op0); + args = tree_cons (NULL, dest, args); + t = implicit_built_in_decls[BUILT_IN_MEMCMP]; + t = build_function_call_expr (t, args); + *expr_p + = build (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node); + + return GS_OK; +} + /* Gimplify TRUTH_ANDIF_EXPR and TRUTH_ORIF_EXPR expressions. EXPR_P points to the expression to gimplify. @@ -2696,7 +2941,7 @@ gimplify_save_expr (tree *expr_p, tree *pre_p, tree *post_p) tree body = TREE_OPERAND (*expr_p, 0); ret = gimplify_expr (& body, pre_p, post_p, is_gimple_stmt, fb_none); append_to_statement_list (body, pre_p); - *expr_p = build_empty_stmt (); + *expr_p = alloc_stmt_list (); } else *expr_p = TREE_OPERAND (*expr_p, 0) @@ -2742,9 +2987,15 @@ gimplify_addr_expr (tree *expr_p, tree *pre_p, tree *post_p) pre_p, post_p); /* This added an INDIRECT_REF. Fold it away. */ - op0 = TREE_OPERAND (TREE_OPERAND (expr, 0), 0); + *expr_p = TREE_OPERAND (TREE_OPERAND (expr, 0), 0); + break; - *expr_p = op0; + case VIEW_CONVERT_EXPR: + /* Take the address of our operand and then convert it to the type of + this ADDR_EXPR. */ + *expr_p = fold_convert (TREE_TYPE (expr), + build_addr_expr (TREE_OPERAND (op0, 0))); + ret = GS_OK; break; default: @@ -2993,7 +3244,7 @@ gimple_push_cleanup (tree var, tree cleanup, tree *pre_p) tree ftrue = build (MODIFY_EXPR, void_type_node, flag, boolean_true_node); cleanup = build (COND_EXPR, void_type_node, flag, cleanup, - build_empty_stmt ()); + alloc_stmt_list ()); wce = build (WITH_CLEANUP_EXPR, void_type_node, NULL_TREE, cleanup, NULL_TREE); append_to_statement_list (ffalse, &gimplify_ctxp->conditional_cleanups); @@ -3208,10 +3459,9 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, break; case ARRAY_REF: - ret = gimplify_array_ref (expr_p, pre_p, post_p, - fallback & fb_lvalue); - break; - + case ARRAY_RANGE_REF: + case REALPART_EXPR: + case IMAGPART_EXPR: case COMPONENT_REF: ret = gimplify_compound_lval (expr_p, pre_p, post_p, fallback & fb_lvalue); @@ -3232,12 +3482,6 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none); break; - case REALPART_EXPR: - case IMAGPART_EXPR: - ret = gimplify_compound_lval (expr_p, pre_p, post_p, - fallback & fb_lvalue); - break; - case MODIFY_EXPR: case INIT_EXPR: ret = gimplify_modify_expr (expr_p, pre_p, post_p, @@ -3265,6 +3509,34 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, ret = gimplify_va_arg_expr (expr_p, pre_p, post_p); break; + case VIEW_CONVERT_EXPR: + if (VOID_TYPE_P (TREE_TYPE (*expr_p)) + || fallback == fb_none) + { + /* Just strip a conversion to void (or in void context) and + try again. */ + *expr_p = TREE_OPERAND (*expr_p, 0); + break; + } + + /* If both types are BLKmode or if one type is of variable size, + convert this into a pointer punning operation. This avoids + copies of large data or making a variable-size temporary. */ + if ((TYPE_MODE (TREE_TYPE (*expr_p)) == BLKmode + && TYPE_MODE (TREE_TYPE (TREE_OPERAND (*expr_p, 0))) == BLKmode) + || !TREE_CONSTANT (TYPE_SIZE (TREE_TYPE (*expr_p))) + || !TREE_CONSTANT (TYPE_SIZE (TREE_TYPE + (TREE_OPERAND (*expr_p,0))))) + { + tree restype = TREE_TYPE (*expr_p); + *expr_p = build1 (INDIRECT_REF, TREE_TYPE (*expr_p), + fold_convert (build_pointer_type (restype), + build_addr_expr + (TREE_OPERAND (*expr_p, 0)))); + break; + } + goto unary; + case CONVERT_EXPR: case NOP_EXPR: if (IS_EMPTY_STMT (*expr_p)) @@ -3293,6 +3565,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, case FIX_CEIL_EXPR: case FIX_FLOOR_EXPR: case FIX_ROUND_EXPR: + unary: /* unary_expr: ... | '(' cast ')' val | ... */ ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_gimple_val, fb_rvalue); @@ -3484,9 +3757,18 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, break; default: + /* If this is a comparison of objects of aggregate type, handle + it specially (by converting to a call to memcmp). It would be + nice to only have to do this for variable-sized objects, but + then we'd have to allow the same nest of reference nodes we + allow for MODIFY_EXPR and that's too complex. */ + if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '<' + && (AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 1))))) + ret = gimplify_variable_sized_compare (expr_p); + /* If *EXPR_P does not need to be special-cased, handle it according to its class. */ - if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '1') + else if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '1') ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_gimple_val, fb_rvalue); else if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '2' @@ -3529,7 +3811,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, if (ret == GS_ERROR) { if (is_statement) - *expr_p = build_empty_stmt (); + *expr_p = alloc_stmt_list (); goto out; } @@ -3541,17 +3823,37 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, #endif if (!*expr_p) - *expr_p = build_empty_stmt (); + *expr_p = alloc_stmt_list (); if (fallback == fb_none && !is_gimple_stmt (*expr_p)) { /* We aren't looking for a value, and we don't have a valid statement. If it doesn't have side-effects, throw it away. */ if (!TREE_SIDE_EFFECTS (*expr_p)) - *expr_p = build_empty_stmt (); + *expr_p = alloc_stmt_list (); else if (!TREE_THIS_VOLATILE (*expr_p)) - /* We only handle volatiles here; anything else with side-effects - must be converted to a valid statement before we get here. */ - abort (); + { + /* This is probably a _REF that contains something nested that + has side effects. Recurse through the operands to find it. */ + enum tree_code code = TREE_CODE (*expr_p); + + if (code == COMPONENT_REF + || code == REALPART_EXPR || code == IMAGPART_EXPR) + gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, + gimple_test_f, fallback); + else if (code == ARRAY_REF || code == ARRAY_RANGE_REF) + { + gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, + gimple_test_f, fallback); + gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, + gimple_test_f, fallback); + } + else + /* Anything else with side-effects + must be converted to a valid statement before we get here. */ + abort (); + + *expr_p = alloc_stmt_list (); + } else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p))) { /* Historically, the compiler has treated a bare @@ -3562,7 +3864,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, else /* We can't do anything useful with a volatile reference to incomplete type, so just throw it away. */ - *expr_p = build_empty_stmt (); + *expr_p = alloc_stmt_list (); } /* If we are gimplifying at the statement level, we're done. Tack @@ -3660,6 +3962,78 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, return ret; } +/* Look through TYPE for variable-sized objects and gimplify each such + size that we find. Return a STATEMENT_LIST containing the result. */ + +tree +gimplify_type_sizes (tree type) +{ + tree stmts = NULL_TREE; + tree field; + + switch (TREE_CODE (type)) + { + case ERROR_MARK: + return alloc_stmt_list (); + + case INTEGER_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + case CHAR_TYPE: + case REAL_TYPE: + gimplify_one_sizepos (&TYPE_MIN_VALUE (type), &stmts); + gimplify_one_sizepos (&TYPE_MAX_VALUE (type), &stmts); + break; + + case ARRAY_TYPE: + /* These anonymous types don't have declarations, so handle them here. */ + append_to_statement_list (gimplify_type_sizes (TYPE_DOMAIN (type)), + &stmts); + break; + + case RECORD_TYPE: + case UNION_TYPE: + case QUAL_UNION_TYPE: + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL) + gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), &stmts); + break; + + default: + break; + } + + gimplify_one_sizepos (&TYPE_SIZE (type), &stmts); + gimplify_one_sizepos (&TYPE_SIZE_UNIT (type), &stmts); + + if (!stmts) + stmts = alloc_stmt_list (); + + return stmts; +} + +/* Subroutine of the above to gimplify one size or position, *EXPR_P. + We add any required statements to STMT_P. */ + +void +gimplify_one_sizepos (tree *expr_p, tree *stmt_p) +{ + tree pre = NULL_TREE, post = NULL_TREE; + + /* We don't do anything if the value isn't there, is constant, or contains + A PLACEHOLDER_EXPR. */ + if (*expr_p == NULL_TREE || TREE_CONSTANT (*expr_p) + || CONTAINS_PLACEHOLDER_P (*expr_p)) + return; + + gimplify_expr (expr_p, &pre, &post, is_gimple_val, fb_rvalue); + + if (pre) + append_to_statement_list (pre, stmt_p); + if (post) + append_to_statement_list (post, stmt_p); +} + #ifdef ENABLE_CHECKING /* Compare types A and B for a "close enough" match. */ @@ -3720,8 +4094,10 @@ check_pointer_types_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, dtype = TREE_TYPE (ptype); if (!cpt_same_type (otype, dtype)) { - /* &array is allowed to produce a pointer to the element, - rather than a pointer to the array type. */ + /* &array is allowed to produce a pointer to the element, rather than + a pointer to the array type. We must allow this in order to + properly represent assigning the address of an array in C into + pointer to the element type. */ if (TREE_CODE (otype) == ARRAY_TYPE && POINTER_TYPE_P (ptype) && cpt_same_type (TREE_TYPE (otype), dtype)) @@ -3751,8 +4127,12 @@ gimplify_body (tree *body_p, tree fndecl) timevar_push (TV_TREE_GIMPLIFY); push_gimplify_context (); - /* Unshare most shared trees in the body. */ - unshare_all_trees (*body_p); + /* Unshare most shared trees in the body and in that of any nested functions. + It would seem we don't have to do this for nested functions because + they are supposed to be output and then the outer function gimplified + first, but the g++ front end doesn't always do it that way. */ + unshare_body (body_p, fndecl); + unvisit_body (body_p, fndecl); /* Make sure input_location isn't set to something wierd. */ input_location = DECL_SOURCE_LOCATION (fndecl); @@ -3764,13 +4144,14 @@ gimplify_body (tree *body_p, tree fndecl) /* Unshare again, in case gimplification was sloppy. */ unshare_all_trees (body); - /* If there isn't an outer BIND_EXPR, add one. */ if (TREE_CODE (body) == STATEMENT_LIST) { tree t = expr_only (*body_p); if (t) body = t; } + + /* If there isn't an outer BIND_EXPR, add one. */ if (TREE_CODE (body) != BIND_EXPR) { tree b = build (BIND_EXPR, void_type_node, NULL_TREE, diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index cd9cffb67d2..fd899174028 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,16 @@ +2004-06-21 Richard Kenner + + * class.c (build_class_ref): Add new operand for COMPONENT_REF. + (build_static_field_ref): Likewise and add new operands for ARRAY_REF. + * constants.c (build_ref_from_constant_pool): Likewise. + * expr.c (build_java_array_length_access): Likewise. + (build_get_class, build_field_ref, build_known_method_ref): Likewise. + (invoke_build_dtable, build_invokevirtual): Likewise. + (build_invokeinterface, java_expand_expr): Likewise. + (emit_init_test_initialization): Likewise. + * java-gimplify.c (java_gimplify_new_array_init): Likewise. + * parse.y (make_qualifed_name, build_array_ref): Likewise. + 2004-06-21 Andrew Haley * java-gimplify.c (java_gimplify_block): set TREE_USED on the new diff --git a/gcc/java/class.c b/gcc/java/class.c index cfb3366eece..ca9d62721c7 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -1023,7 +1023,7 @@ build_class_ref (tree type) prim_class = lookup_class (get_identifier (prim_class_name)); return build (COMPONENT_REF, NULL_TREE, - prim_class, TYPE_identifier_node); + prim_class, TYPE_identifier_node, NULL_TREE); } decl_name = TYPE_NAME (type); if (TREE_CODE (decl_name) == TYPE_DECL) @@ -1088,7 +1088,8 @@ build_static_field_ref (tree fdecl) (fdecl, &TYPE_ATABLE_METHODS (output_class)), 0); tree field_address = build (ARRAY_REF, build_pointer_type (TREE_TYPE (fdecl)), - TYPE_ATABLE_DECL (output_class), table_index); + TYPE_ATABLE_DECL (output_class), table_index, + NULL_TREE, NULL_TREE); return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl), field_address)); } @@ -1101,7 +1102,8 @@ build_static_field_ref (tree fdecl) int field_index = 0; ref = build1 (INDIRECT_REF, class_type_node, ref); ref = build (COMPONENT_REF, field_ptr_type_node, ref, - lookup_field (&class_type_node, fields_ident)); + lookup_field (&class_type_node, fields_ident), + NULL_TREE); for (fld = TYPE_FIELDS (fclass); ; fld = TREE_CHAIN (fld)) { @@ -1118,9 +1120,11 @@ build_static_field_ref (tree fdecl) ref, build_int_2 (field_index, 0))); ref = build1 (INDIRECT_REF, field_type_node, ref); ref = build (COMPONENT_REF, field_info_union_node, - ref, lookup_field (&field_type_node, info_ident)); + ref, lookup_field (&field_type_node, info_ident), + NULL_TREE); ref = build (COMPONENT_REF, ptr_type_node, - ref, TREE_CHAIN (TYPE_FIELDS (field_info_union_node))); + ref, TREE_CHAIN (TYPE_FIELDS (field_info_union_node)), + NULL_TREE); return fold (build1 (INDIRECT_REF, TREE_TYPE(fdecl), ref)); } } diff --git a/gcc/java/constants.c b/gcc/java/constants.c index 32fc854c9db..98127f590db 100644 --- a/gcc/java/constants.c +++ b/gcc/java/constants.c @@ -424,7 +424,8 @@ build_ref_from_constant_pool (int index) { tree d = build_constant_data_ref (); tree i = build_int_2 (index, 0); - return build (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i); + return build (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i, + NULL_TREE, NULL_TREE); } /* Build an initializer for the constants field of the current constant pool. diff --git a/gcc/java/expr.c b/gcc/java/expr.c index 86a7899c9a8..446f8afe2db 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -698,7 +698,8 @@ build_java_array_length_access (tree node) node = build (COMPONENT_REF, int_type_node, build_java_indirect_ref (array_type, node, flag_check_references), - lookup_field (&array_type, get_identifier ("length"))); + lookup_field (&array_type, get_identifier ("length")), + NULL_TREE); IS_ARRAY_LENGTH_ACCESS (node) = 1; return node; } @@ -780,9 +781,9 @@ build_java_arrayaccess (tree array, tree type, tree index) ref = build (COMPONENT_REF, TREE_TYPE (data_field), build_java_indirect_ref (array_type, array, flag_check_references), - data_field); + data_field, NULL_TREE); - node = build (ARRAY_REF, type, ref, index); + node = build (ARRAY_REF, type, ref, index, NULL_TREE, NULL_TREE); return node; } @@ -1181,8 +1182,8 @@ build_get_class (tree value) build (COMPONENT_REF, dtable_ptr_type, build_java_indirect_ref (object_type_node, value, flag_check_references), - vtable_field)), - class_field); + vtable_field, NULL_TREE)), + class_field, NULL_TREE); } /* This builds the tree representation of the `instanceof' operator. @@ -1531,13 +1532,16 @@ build_field_ref (tree self_value, tree self_class, tree name) in the same translation unit as output_class. If it is, we can make a direct reference. */ { - tree otable_index = - build_int_2 (get_symbol_table_index - (field_decl, &TYPE_OTABLE_METHODS (output_class)), 0); - tree field_offset = - build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class), - otable_index); + tree otable_index + = build_int_2 (get_symbol_table_index + (field_decl, &TYPE_OTABLE_METHODS (output_class)), + 0); + tree field_offset + = build (ARRAY_REF, integer_type_node, + TYPE_OTABLE_DECL (output_class), otable_index, + NULL_TREE, NULL_TREE); tree address; + field_offset = fold (convert (sizetype, field_offset)); address = fold (build (PLUS_EXPR, @@ -1549,7 +1553,7 @@ build_field_ref (tree self_value, tree self_class, tree name) self_value = build_java_indirect_ref (TREE_TYPE (TREE_TYPE (self_value)), self_value, check); return fold (build (COMPONENT_REF, TREE_TYPE (field_decl), - self_value, field_decl)); + self_value, field_decl, NULL_TREE)); } } @@ -1826,12 +1830,12 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED, } else { - tree table_index = - build_int_2 (get_symbol_table_index - (method, &TYPE_ATABLE_METHODS (output_class)), 0); - func = - build (ARRAY_REF, method_ptr_type_node, - TYPE_ATABLE_DECL (output_class), table_index); + tree table_index + = build_int_2 (get_symbol_table_index + (method, &TYPE_ATABLE_METHODS (output_class)), 0); + func = build (ARRAY_REF, method_ptr_type_node, + TYPE_ATABLE_DECL (output_class), table_index, + NULL_TREE, NULL_TREE); } func = convert (method_ptr_type_node, func); } @@ -1858,7 +1862,7 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED, if (methods_ident == NULL_TREE) methods_ident = get_identifier ("methods"); ref = build (COMPONENT_REF, method_ptr_type_node, ref, - lookup_field (&class_type_node, methods_ident)); + lookup_field (&class_type_node, methods_ident), NULL_TREE); for (meth = TYPE_METHODS (self_type); ; meth = TREE_CHAIN (meth)) { @@ -1874,8 +1878,8 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED, ref, build_int_2 (method_index, 0))); ref = build1 (INDIRECT_REF, method_type_node, ref); func = build (COMPONENT_REF, nativecode_ptr_type_node, - ref, - lookup_field (&method_type_node, ncode_ident)); + ref, lookup_field (&method_type_node, ncode_ident), + NULL_TREE); } return func; } @@ -1899,7 +1903,7 @@ invoke_build_dtable (int is_invoke_interface, tree arg_list) dtable = build_java_indirect_ref (object_type_node, objectref, flag_check_references); dtable = build (COMPONENT_REF, dtable_ptr_type, dtable, - lookup_field (&object_type_node, dtable_ident)); + lookup_field (&object_type_node, dtable_ident), NULL_TREE); return dtable; } @@ -1955,7 +1959,7 @@ build_invokevirtual (tree dtable, tree method) (method, &TYPE_OTABLE_METHODS (output_class)), 0); method_index = build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class), - otable_index); + otable_index, NULL_TREE, NULL_TREE); } else { @@ -2001,7 +2005,7 @@ build_invokeinterface (tree dtable, tree method) dtable = build_java_indirect_ref (dtable_type, dtable, flag_check_references); dtable = build (COMPONENT_REF, class_ptr_type, dtable, - lookup_field (&dtable_type, class_ident)); + lookup_field (&dtable_type, class_ident), NULL_TREE); interface = DECL_CONTEXT (method); if (! CLASS_INTERFACE (TYPE_NAME (interface))) @@ -2010,17 +2014,15 @@ build_invokeinterface (tree dtable, tree method) if (flag_indirect_dispatch) { - otable_index = - build_int_2 (get_symbol_table_index - (method, &TYPE_OTABLE_METHODS (output_class)), 0); - idx = - build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class), - otable_index); + otable_index + = build_int_2 (get_symbol_table_index + (method, &TYPE_OTABLE_METHODS (output_class)), 0); + idx = build (ARRAY_REF, integer_type_node, + TYPE_OTABLE_DECL (output_class), otable_index, + NULL_TREE, NULL_TREE); } else - { - idx = build_int_2 (get_interface_method_index (method, interface), 0); - } + idx = build_int_2 (get_interface_method_index (method, interface), 0); lookup_arg = tree_cons (NULL_TREE, dtable, tree_cons (NULL_TREE, build_class_ref (interface), @@ -2577,7 +2579,8 @@ java_expand_expr (tree exp, rtx target, enum machine_mode tmode, expand_assignment (build (COMPONENT_REF, TREE_TYPE (data_fld), build_java_indirect_ref (array_type, array_decl, flag_check_references), - data_fld), init, 0); + data_fld, NULL_TREE), + init, 0); return tmp; } case BLOCK: @@ -3460,7 +3463,8 @@ emit_init_test_initialization (void **entry, void *x ATTRIBUTE_UNUSED) build (COMPONENT_REF, byte_type_node, build1 (INDIRECT_REF, class_type_node, klass), lookup_field (&class_type_node, - get_identifier ("state"))), + get_identifier ("state")), + NULL_TREE), build_int_2 (JV_STATE_DONE, 0)); expand_expr_stmt (build (MODIFY_EXPR, boolean_type_node, diff --git a/gcc/java/java-gimplify.c b/gcc/java/java-gimplify.c index 3c446672255..766995e8254 100644 --- a/gcc/java/java-gimplify.c +++ b/gcc/java/java-gimplify.c @@ -1,5 +1,4 @@ /* Java(TM) language-specific gimplification routines. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -223,10 +222,11 @@ java_gimplify_new_array_init (tree exp) bounds checking. */ tree lhs = build (COMPONENT_REF, TREE_TYPE (data_field), build_java_indirect_ref (array_type, tmp, 0), - data_field); + data_field, NULL_TREE); tree assignment = build (MODIFY_EXPR, element_type, build (ARRAY_REF, element_type, lhs, - build_int_2 (index++, 0)), + build_int_2 (index++, 0), + NULL_TREE, NULL_TREE), TREE_VALUE (values)); body = build (COMPOUND_EXPR, element_type, body, assignment); values = TREE_CHAIN (values); diff --git a/gcc/java/parse.y b/gcc/java/parse.y index dd52a39359d..ed1f05040ec 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -9254,7 +9254,7 @@ static tree make_qualified_name (tree left, tree right, int location) { #ifdef USE_COMPONENT_REF - tree node = build (COMPONENT_REF, NULL_TREE, left, right); + tree node = build (COMPONENT_REF, NULL_TREE, left, right, NULL_TREE); EXPR_WFL_LINECOL (node) = location; return node; #else @@ -14353,7 +14353,7 @@ build_null_of_type (tree type) static tree build_array_ref (int location, tree array, tree index) { - tree node = build (ARRAY_REF, NULL_TREE, array, index); + tree node = build (ARRAY_REF, NULL_TREE, array, index, NULL_TREE, NULL_TREE); EXPR_WFL_LINECOL (node) = location; return node; } diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 4414309ca7d..bf739565cad 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -1975,7 +1975,7 @@ generate_static_references (void) sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class); ident = get_identifier (buf); - expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE); + expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE, NULL_TREE, NULL_TREE); decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node), build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC])); @@ -2014,7 +2014,7 @@ generate_static_references (void) decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls); ident = get_identifier ("_OBJC_STATIC_INSTANCES"); - expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE); + expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE, NULL_TREE, NULL_TREE); decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node), build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC])); @@ -2044,7 +2044,8 @@ generate_strings (void) sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); - expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE); + expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE, + NULL_TREE, NULL_TREE); decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE); DECL_CONTEXT (decl) = NULL_TREE; string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, @@ -2059,7 +2060,8 @@ generate_strings (void) sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); - expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE); + expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE, + NULL_TREE, NULL_TREE); decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE); DECL_CONTEXT (decl) = NULL_TREE; string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, @@ -2074,7 +2076,8 @@ generate_strings (void) sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); - expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE); + expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE, + NULL_TREE, NULL_TREE); decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE); DECL_CONTEXT (decl) = NULL_TREE; string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, @@ -3521,7 +3524,7 @@ build_method_prototype_list_template (tree list_type, int size) decl_specs = build_tree_list (NULL_TREE, list_type); field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"), - build_int_2 (size, 0)); + build_int_2 (size, 0), NULL_TREE, NULL_TREE); field_decl = grokfield (field_decl, decl_specs, NULL_TREE); chainon (field_decl_chain, field_decl); @@ -4405,7 +4408,7 @@ build_ivar_list_template (tree list_type, int size) decl_specs = build_tree_list (NULL_TREE, list_type); field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"), - build_int_2 (size, 0)); + build_int_2 (size, 0), NULL_TREE, NULL_TREE); field_decl = grokfield (field_decl, decl_specs, NULL_TREE); chainon (field_decl_chain, field_decl); @@ -4453,7 +4456,7 @@ build_method_list_template (tree list_type, int size) decl_specs = build_tree_list (NULL_TREE, list_type); field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"), - build_int_2 (size, 0)); + build_int_2 (size, 0), NULL_TREE, NULL_TREE); field_decl = grokfield (field_decl, decl_specs, NULL_TREE); chainon (field_decl_chain, field_decl); @@ -4860,18 +4863,18 @@ generate_protocol_list (tree i_or_p) expr_decl = build_nt (ARRAY_REF, synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS", i_or_p), - build_int_2 (size + 2, 0)); + build_int_2 (size + 2, 0), NULL_TREE, NULL_TREE); else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE) expr_decl = build_nt (ARRAY_REF, synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS", i_or_p), - build_int_2 (size + 2, 0)); + build_int_2 (size + 2, 0), NULL_TREE, NULL_TREE); else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE) expr_decl = build_nt (ARRAY_REF, synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS", i_or_p), - build_int_2 (size + 2, 0)); + build_int_2 (size + 2, 0), NULL_TREE, NULL_TREE); else abort (); diff --git a/gcc/stmt.c b/gcc/stmt.c index 4d878e3b081..5ee55b9e699 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -3391,12 +3391,6 @@ expand_stack_alloc (tree alloc, tree t_size) type = TREE_TYPE (var); - /* In function-at-a-time mode, variable_size doesn't expand this, - so do it now. */ - if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type)) - expand_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), - const0_rtx, VOIDmode, 0); - /* Compute the variable's size, in bytes. */ size = expand_expr (t_size, NULL_RTX, VOIDmode, 0); free_temp_slots (); diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index aa452b495fc..b2ef41dbda2 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -93,11 +93,6 @@ tree get_pending_sizes (void) { tree chain = pending_sizes; - tree t; - - /* Put each SAVE_EXPR into the current function. */ - for (t = chain; t; t = TREE_CHAIN (t)) - SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = current_function_decl; pending_sizes = 0; return chain; diff --git a/gcc/tree-alias-common.c b/gcc/tree-alias-common.c index 33ef6d34db3..561feb5210a 100644 --- a/gcc/tree-alias-common.c +++ b/gcc/tree-alias-common.c @@ -207,12 +207,15 @@ get_alias_var (tree expr) switch (TREE_CODE (expr)) { case ARRAY_REF: + case ARRAY_RANGE_REF: { - /* Find the first non-array ref, and return it's alias - variable */ + /* Find the first non-array ref, and return its alias variable. */ tree p; - for (p = expr; TREE_CODE (p) == ARRAY_REF; - p = TREE_OPERAND (p, 0)); + + for (p = expr; + TREE_CODE (p) == ARRAY_REF || TREE_CODE (p) == ARRAY_RANGE_REF; + p = TREE_OPERAND (p, 0)) + ; return get_alias_var (p); } break; diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 8babdc293c5..9b420733766 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -3156,12 +3156,10 @@ verify_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, break; case ADDR_EXPR: - x = TREE_OPERAND (t, 0); - while (TREE_CODE (x) == ARRAY_REF - || TREE_CODE (x) == COMPONENT_REF - || TREE_CODE (x) == REALPART_EXPR - || TREE_CODE (x) == IMAGPART_EXPR) - x = TREE_OPERAND (x, 0); + for (x = TREE_OPERAND (t, 0); handled_component_p (x); + x = TREE_OPERAND (x, 0)) + ; + if (TREE_CODE (x) != VAR_DECL && TREE_CODE (x) != PARM_DECL) return NULL; if (!TREE_ADDRESSABLE (x)) @@ -3309,7 +3307,7 @@ tree_node_can_be_shared (tree t) || TREE_CODE (t) == SSA_NAME) return true; - while ((TREE_CODE (t) == ARRAY_REF + while (((TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF) /* We check for constants explicitly since they are not considered gimple invariants if they overflowed. */ && (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 1))) == 'c' diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index e1445be4874..307086bedb7 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -926,24 +926,17 @@ add_referenced_var (tree var, struct walk_state *walk_state) tree get_virtual_var (tree var) { - enum tree_code code; - STRIP_NOPS (var); if (TREE_CODE (var) == SSA_NAME) var = SSA_NAME_VAR (var); - code = TREE_CODE (var); - - while (code == ARRAY_REF - || code == COMPONENT_REF - || code == REALPART_EXPR - || code == IMAGPART_EXPR) - { + if (TREE_CODE (var) == REALPART_EXPR || TREE_CODE (var) == IMAGPART_EXPR) + var = TREE_OPERAND (var, 0); + else + while (handled_component_p (var)) var = TREE_OPERAND (var, 0); - code = TREE_CODE (var); - } - + #ifdef ENABLE_CHECKING /* Treating GIMPLE registers as virtual variables makes no sense. Also complain if we couldn't extract a _DECL out of the original diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c index 45accaee0ed..39aeeaddf41 100644 --- a/gcc/tree-dump.c +++ b/gcc/tree-dump.c @@ -536,9 +536,7 @@ dequeue_and_dump (dump_info_p di) case TRUTH_ORIF_EXPR: case INIT_EXPR: case MODIFY_EXPR: - case COMPONENT_REF: case COMPOUND_EXPR: - case ARRAY_REF: case PREDECREMENT_EXPR: case PREINCREMENT_EXPR: case POSTDECREMENT_EXPR: @@ -548,6 +546,20 @@ dequeue_and_dump (dump_info_p di) dump_child ("op 1", TREE_OPERAND (t, 1)); break; + case COMPONENT_REF: + dump_child ("op 0", TREE_OPERAND (t, 0)); + dump_child ("op 1", TREE_OPERAND (t, 1)); + dump_child ("op 2", TREE_OPERAND (t, 2)); + break; + + case ARRAY_REF: + case ARRAY_RANGE_REF: + dump_child ("op 0", TREE_OPERAND (t, 0)); + dump_child ("op 1", TREE_OPERAND (t, 1)); + dump_child ("op 2", TREE_OPERAND (t, 2)); + dump_child ("op 3", TREE_OPERAND (t, 3)); + break; + case COND_EXPR: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 27f33c9141f..21c3a1c3815 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -1682,6 +1682,7 @@ tree_could_trap_p (tree expr) switch (code) { case ARRAY_REF: + case ARRAY_RANGE_REF: case COMPONENT_REF: case REALPART_EXPR: case IMAGPART_EXPR: diff --git a/gcc/tree-gimple.c b/gcc/tree-gimple.c index d3231c01fb6..7c992b36adc 100644 --- a/gcc/tree-gimple.c +++ b/gcc/tree-gimple.c @@ -119,17 +119,34 @@ Boston, MA 02111-1307, USA. */ min-lval: ID | '*' ID bitfieldref : BIT_FIELD_REF - op0 -> compref | min-lval + op0 -> inner_compref op1 -> CONST - op2 -> CONST + op2 -> var compref : COMPONENT_REF - op0 -> compref | min-lval + op0 -> inner_compref | ARRAY_REF - op0 -> compref | min-lval + op0 -> inner_compref op1 -> val + op2 -> val + op3 -> val + | ARRAY_RANGE_REF + op0 -> inner_compref + op1 -> val + op2 -> val + op3 -> val | REALPART_EXPR + op0 -> inner_compref | IMAGPART_EXPR + op0 -> inner_compref + + inner_compref : compref | min_lval + | VIEW_CONVERT_EXPR + op0 -> inner_compref + | NOP_EXPR + op0 -> inner_compref + | CONVERT_EXPR + op0 -> inner_compref condition : val | val relop val val : ID | CONST @@ -284,9 +301,11 @@ is_gimple_addr_expr_arg (tree t) { return (is_gimple_id (t) || TREE_CODE (t) == ARRAY_REF + || TREE_CODE (t) == ARRAY_RANGE_REF || TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == REALPART_EXPR - || TREE_CODE (t) == IMAGPART_EXPR); + || TREE_CODE (t) == IMAGPART_EXPR + || TREE_CODE (t) == INDIRECT_REF); } /* Return nonzero if T is function invariant. Or rather a restricted @@ -581,19 +600,12 @@ get_base_address (tree t) || TREE_CODE (t) == INDIRECT_REF) return t; - switch (TREE_CODE (t)) - { - case ARRAY_REF: - case COMPONENT_REF: - case REALPART_EXPR: - case IMAGPART_EXPR: - case BIT_FIELD_REF: - t = TREE_OPERAND (t, 0); - break; - - default: - return NULL_TREE; - } + if (TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR) + t = TREE_OPERAND (t, 0); + else if (handled_component_p (t)) + t = get_base_address (TREE_OPERAND (t, 0)); + else + return NULL_TREE; } while (t); diff --git a/gcc/tree-gimple.h b/gcc/tree-gimple.h index 29352a54b81..98f46951af4 100644 --- a/gcc/tree-gimple.h +++ b/gcc/tree-gimple.h @@ -42,45 +42,45 @@ extern void annotate_all_with_locus (tree *, location_t); underlying nodes are also of the right form. */ /* Returns true iff T is a valid GIMPLE statement. */ -bool is_gimple_stmt (tree); +extern bool is_gimple_stmt (tree); /* Returns true iff TYPE is a valid type for a scalar register variable. */ -bool is_gimple_reg_type (tree); +extern bool is_gimple_reg_type (tree); /* Returns true iff T is a scalar register variable. */ -bool is_gimple_reg (tree); +extern bool is_gimple_reg (tree); /* Returns true iff T is any sort of variable. */ -bool is_gimple_variable (tree); +extern bool is_gimple_variable (tree); /* Returns true iff T is a variable or an INDIRECT_REF (of a variable). */ -bool is_gimple_min_lval (tree); +extern bool is_gimple_min_lval (tree); /* Returns true iff T is an lvalue other than an INDIRECT_REF. */ -bool is_gimple_addr_expr_arg (tree); +extern bool is_gimple_addr_expr_arg (tree); /* Returns true iff T is any valid GIMPLE lvalue. */ -bool is_gimple_lvalue (tree); +extern bool is_gimple_lvalue (tree); /* Returns true iff T is a GIMPLE restricted function invariant. */ -bool is_gimple_min_invariant (tree); +extern bool is_gimple_min_invariant (tree); /* Returns true iff T is a GIMPLE rvalue. */ -bool is_gimple_val (tree); +extern bool is_gimple_val (tree); /* Returns true iff T is a valid rhs for a MODIFY_EXPR. */ -bool is_gimple_rhs (tree); +extern bool is_gimple_rhs (tree); /* Returns true iff T is a valid if-statement condition. */ -bool is_gimple_condexpr (tree); +extern bool is_gimple_condexpr (tree); /* Returns true iff T is a type conversion. */ -bool is_gimple_cast (tree); +extern bool is_gimple_cast (tree); /* Returns true iff T is a valid CONSTRUCTOR element (either an rvalue or another CONSTRUCTOR). */ -bool is_gimple_constructor_elt (tree); +extern bool is_gimple_constructor_elt (tree); /* Returns true iff T is a variable that does not need to live in memory. */ -bool is_gimple_non_addressable (tree t); +extern bool is_gimple_non_addressable (tree t); /* If T makes a function call, returns the CALL_EXPR operand. */ -tree get_call_expr_in (tree t); +extern tree get_call_expr_in (tree t); -void recalculate_side_effects (tree); +extern void recalculate_side_effects (tree); -void append_to_compound_expr (tree, tree *); +extern void append_to_compound_expr (tree, tree *); /* FIXME we should deduce this from the predicate. */ typedef enum fallback_t { @@ -98,29 +98,31 @@ enum gimplify_status { GS_ALL_DONE = 1 /* The expression is fully gimplified. */ }; -enum gimplify_status gimplify_expr (tree *, tree *, tree *, - bool (*) (tree), fallback_t); -void gimplify_stmt (tree *); -void gimplify_to_stmt_list (tree *); -void gimplify_body (tree *, tree); -void push_gimplify_context (void); -void pop_gimplify_context (tree); -void gimplify_and_add (tree, tree *); +extern enum gimplify_status gimplify_expr (tree *, tree *, tree *, + bool (*) (tree), fallback_t); +extern tree gimplify_type_sizes (tree); +extern void gimplify_one_sizepos (tree *, tree *); +extern void gimplify_stmt (tree *); +extern void gimplify_to_stmt_list (tree *); +extern void gimplify_body (tree *, tree); +extern void push_gimplify_context (void); +extern void pop_gimplify_context (tree); +extern void gimplify_and_add (tree, tree *); /* Miscellaneous helpers. */ -tree get_base_address (tree t); -void gimple_add_tmp_var (tree); -tree gimple_current_bind_expr (void); -void gimple_push_bind_expr (tree); -void gimple_pop_bind_expr (void); -void unshare_all_trees (tree); -tree voidify_wrapper_expr (tree, tree); -tree gimple_build_eh_filter (tree, tree, tree); -tree build_and_jump (tree *); -tree alloc_stmt_list (void); -void free_stmt_list (tree); -tree force_labels_r (tree *, int *, void *); -enum gimplify_status gimplify_va_arg_expr (tree *, tree *, tree *); +extern tree get_base_address (tree t); +extern void gimple_add_tmp_var (tree); +extern tree gimple_current_bind_expr (void); +extern void gimple_push_bind_expr (tree); +extern void gimple_pop_bind_expr (void); +extern void unshare_all_trees (tree); +extern tree voidify_wrapper_expr (tree, tree); +extern tree gimple_build_eh_filter (tree, tree, tree); +extern tree build_and_jump (tree *); +extern tree alloc_stmt_list (void); +extern void free_stmt_list (tree); +extern tree force_labels_r (tree *, int *, void *); +extern enum gimplify_status gimplify_va_arg_expr (tree *, tree *, tree *); /* In tree-nested.c. */ extern void lower_nested_functions (tree); diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 24bf3d1b2ff..deb73605ca2 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -2054,8 +2054,14 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_) } #endif } - else if (TREE_CODE_CLASS (code) == 'd') + + /* Look inside the sizes of decls, but we don't ever use the values for + FIELD_DECL and RESULT_DECL, so ignore them. */ + else if (TREE_CODE_CLASS (code) == 'd' + && code != FIELD_DECL && code != RESULT_DECL) { + WALK_SUBTREE (DECL_SIZE (*tp)); + WALK_SUBTREE (DECL_SIZE_UNIT (*tp)); WALK_SUBTREE_TAIL (TREE_TYPE (*tp)); } else @@ -2077,23 +2083,20 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_) case REAL_CST: case VECTOR_CST: case STRING_CST: - case REAL_TYPE: - case COMPLEX_TYPE: case VECTOR_TYPE: case VOID_TYPE: - case BOOLEAN_TYPE: - case UNION_TYPE: - case ENUMERAL_TYPE: case BLOCK: - case RECORD_TYPE: case PLACEHOLDER_EXPR: case SSA_NAME: + case FIELD_DECL: + case RESULT_DECL: /* None of thse have subtrees other than those already walked above. */ break; case POINTER_TYPE: case REFERENCE_TYPE: + case COMPLEX_TYPE: WALK_SUBTREE_TAIL (TREE_TYPE (*tp)); break; @@ -2126,6 +2129,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_) case METHOD_TYPE: WALK_SUBTREE (TYPE_METHOD_BASETYPE (*tp)); + /* Fall through. */ case FUNCTION_TYPE: @@ -2139,12 +2143,43 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_) } break; + case RECORD_TYPE: + case UNION_TYPE: + case QUAL_UNION_TYPE: + { + tree field; + + for (field = TYPE_FIELDS (*tp); field; field = TREE_CHAIN (field)) + { + /* We would like to look at the type of the field, but we + can easily get infinite recursion. So assume it's + pointed to elsewhere in the tree. Also, ignore things that + aren't fields. */ + if (TREE_CODE (field) != FIELD_DECL) + continue; + + WALK_SUBTREE (DECL_FIELD_OFFSET (field)); + WALK_SUBTREE (DECL_SIZE (field)); + WALK_SUBTREE (DECL_SIZE_UNIT (field)); + if (code == QUAL_UNION_TYPE) + WALK_SUBTREE (DECL_QUALIFIER (field)); + } + } + break; + case ARRAY_TYPE: - WALK_SUBTREE (TREE_TYPE (*tp)); + /* Don't follow this nodes's type if a pointer for fear that we'll + have infinite recursion. Those types are uninteresting anyway. */ + if (!POINTER_TYPE_P (TREE_TYPE (*tp)) + && TREE_CODE (TREE_TYPE (*tp)) != OFFSET_TYPE) + WALK_SUBTREE (TREE_TYPE (*tp)); WALK_SUBTREE_TAIL (TYPE_DOMAIN (*tp)); + case BOOLEAN_TYPE: + case ENUMERAL_TYPE: case INTEGER_TYPE: case CHAR_TYPE: + case REAL_TYPE: WALK_SUBTREE (TYPE_MIN_VALUE (*tp)); WALK_SUBTREE_TAIL (TYPE_MAX_VALUE (*tp)); @@ -2166,8 +2201,8 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_) /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk into declarations that are just mentioned, rather than declared; they don't really belong to this part of the tree. - And, we can see cycles: the initializer for a declaration can - refer to the declaration itself. */ + And, we can see cycles: the initializer for a declaration + can refer to the declaration itself. */ WALK_SUBTREE (DECL_INITIAL (decl)); WALK_SUBTREE (DECL_SIZE (decl)); WALK_SUBTREE (DECL_SIZE_UNIT (decl)); @@ -2185,7 +2220,9 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_) break; default: - abort (); + /* ??? This could be a language-defined node. We really should make + a hook for it, but right now just ignore it. */ + break; } } diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c index 732ef5e4106..6181bb6ab13 100644 --- a/gcc/tree-mudflap.c +++ b/gcc/tree-mudflap.c @@ -463,7 +463,7 @@ mf_build_check_statement_for (tree addr, tree size, (flag_mudflap_threads ? mf_cache_mask_decl : mf_cache_mask_decl_l)); t = build (ARRAY_REF, TREE_TYPE (TREE_TYPE (mf_cache_array_decl)), - mf_cache_array_decl, t); + mf_cache_array_decl, t, NULL_TREE, NULL_TREE); t = build1 (ADDR_EXPR, mf_cache_structptr_type, t); t = build (MODIFY_EXPR, void_type_node, mf_elem, t); SET_EXPR_LOCUS (t, locus); @@ -487,7 +487,7 @@ mf_build_check_statement_for (tree addr, tree size, /* Construct t <-- '__mf_elem->low > __mf_base'. */ t = build (COMPONENT_REF, mf_uintptr_type, build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem), - TYPE_FIELDS (mf_cache_struct_type)); + TYPE_FIELDS (mf_cache_struct_type), NULL_TREE); t = build (GT_EXPR, boolean_type_node, t, mf_base); /* Construct '__mf_elem->high < __mf_base + sizeof(T) - 1'. @@ -501,7 +501,7 @@ mf_build_check_statement_for (tree addr, tree size, u = build (COMPONENT_REF, mf_uintptr_type, build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem), - TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type))); + TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE); v = convert (mf_uintptr_type, size_binop (MINUS_EXPR, size, size_one_node)); @@ -660,14 +660,14 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp, things the hard way with PLUS. */ if (DECL_BIT_FIELD_TYPE (field)) { - size = bitsize_int (BITS_PER_UNIT); - size = size_binop (CEIL_DIV_EXPR, DECL_SIZE (field), size); - size = convert (sizetype, size); + if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST) + size = DECL_SIZE_UNIT (field); addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0); - addr = convert (ptr_type_node, addr); + addr = fold_convert (ptr_type_node, addr); addr = fold (build (PLUS_EXPR, ptr_type_node, - addr, byte_position (field))); + addr, fold_convert (ptr_type_node, + byte_position (field)))); } else { diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index 24d3e74b746..1f32e1f60f9 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -157,8 +157,13 @@ static tree build_addr (tree exp) { tree base = exp; - while (TREE_CODE (base) == COMPONENT_REF || TREE_CODE (base) == ARRAY_REF) + + if (TREE_CODE (base) == REALPART_EXPR || TREE_CODE (base) == IMAGPART_EXPR) base = TREE_OPERAND (base, 0); + else + while (handled_component_p (base)) + base = TREE_OPERAND (base, 0); + if (DECL_P (base)) TREE_ADDRESSABLE (base) = 1; @@ -550,6 +555,7 @@ walk_stmts (struct walk_stmt_info *wi, tree *tp) break; case CATCH_EXPR: walk_stmts (wi, &CATCH_BODY (t)); + break; case EH_FILTER_EXPR: walk_stmts (wi, &EH_FILTER_FAILURE (t)); break; @@ -657,7 +663,7 @@ get_static_chain (struct nesting_info *info, tree target_context, tree field = get_chain_field (i); x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x); - x = build (COMPONENT_REF, TREE_TYPE (field), x, field); + x = build (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); x = init_tmp_var (info, x, tsi); } } @@ -691,14 +697,14 @@ get_frame_field (struct nesting_info *info, tree target_context, tree field = get_chain_field (i); x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x); - x = build (COMPONENT_REF, TREE_TYPE (field), x, field); + x = build (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); x = init_tmp_var (info, x, tsi); } x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x); } - x = build (COMPONENT_REF, TREE_TYPE (field), x, field); + x = build (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE); return x; } @@ -800,10 +806,13 @@ convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data) break; case ARRAY_REF: + case ARRAY_RANGE_REF: wi->val_only = false; walk_tree (&TREE_OPERAND (t, 0), convert_nonlocal_reference, wi, NULL); wi->val_only = true; walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference, wi, NULL); + walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi, NULL); + walk_tree (&TREE_OPERAND (t, 3), convert_nonlocal_reference, wi, NULL); break; case BIT_FIELD_REF: @@ -932,10 +941,13 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data) break; case ARRAY_REF: + case ARRAY_RANGE_REF: wi->val_only = false; walk_tree (&TREE_OPERAND (t, 0), convert_local_reference, wi, NULL); wi->val_only = true; walk_tree (&TREE_OPERAND (t, 1), convert_local_reference, wi, NULL); + walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi, NULL); + walk_tree (&TREE_OPERAND (t, 3), convert_local_reference, wi, NULL); break; case BIT_FIELD_REF: @@ -1242,7 +1254,7 @@ finalize_nesting_tree_1 (struct nesting_info *root) x = p; y = build (COMPONENT_REF, TREE_TYPE (field), - root->frame_decl, field); + root->frame_decl, field, NULL_TREE); x = build (MODIFY_EXPR, TREE_TYPE (field), y, x); append_to_statement_list (x, &stmt_list); } @@ -1252,9 +1264,8 @@ finalize_nesting_tree_1 (struct nesting_info *root) from chain_decl. */ if (root->chain_field) { - tree x; - x = build (COMPONENT_REF, TREE_TYPE (root->chain_field), - root->frame_decl, root->chain_field); + tree x = build (COMPONENT_REF, TREE_TYPE (root->chain_field), + root->frame_decl, root->chain_field, NULL_TREE); x = build (MODIFY_EXPR, TREE_TYPE (x), x, get_chain_decl (root)); append_to_statement_list (x, &stmt_list); } @@ -1281,7 +1292,7 @@ finalize_nesting_tree_1 (struct nesting_info *root) arg = tree_cons (NULL, x, arg); x = build (COMPONENT_REF, TREE_TYPE (field), - root->frame_decl, field); + root->frame_decl, field, NULL_TREE); x = build_addr (x); arg = tree_cons (NULL, x, arg); diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c index 28c802381d0..f19afdde6a1 100644 --- a/gcc/tree-outof-ssa.c +++ b/gcc/tree-outof-ssa.c @@ -1763,17 +1763,20 @@ discover_nonconstant_array_refs_r (tree * tp, int *walk_subtrees, if (TYPE_P (t) || DECL_P (t)) *walk_subtrees = 0; - else if (TREE_CODE (t) == ARRAY_REF) + else if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF) { - while ((TREE_CODE (t) == ARRAY_REF + while (((TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF) && is_gimple_min_invariant (TREE_OPERAND (t, 1))) || (TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == BIT_FIELD_REF || TREE_CODE (t) == REALPART_EXPR - || TREE_CODE (t) == IMAGPART_EXPR)) + || TREE_CODE (t) == IMAGPART_EXPR + || TREE_CODE (t) == VIEW_CONVERT_EXPR + || TREE_CODE (t) == NOP_EXPR + || TREE_CODE (t) == CONVERT_EXPR)) t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == ARRAY_REF) + if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF) { t = get_base_address (t); if (t && DECL_P (t)) diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 4b8d2d40080..52aa1819417 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -392,6 +392,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, case RECORD_TYPE: case UNION_TYPE: + case QUAL_UNION_TYPE: /* Print the name of the structure. */ if (TREE_CODE (node) == RECORD_TYPE) pp_string (buffer, "struct "); @@ -404,11 +405,6 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, print_struct_decl (buffer, node, spc, flags); break; - case QUAL_UNION_TYPE: - NIY; - break; - - case LANG_TYPE: NIY; break; @@ -598,6 +594,14 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, pp_character (buffer, ')'); pp_string (buffer, str); dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false); + if (TREE_OPERAND (node, 2) + && TREE_CODE (TREE_OPERAND (node, 2)) != INTEGER_CST) + { + pp_string (buffer, "{off: "); + dump_generic_node (buffer, TREE_OPERAND (node, 2), + spc, flags, false); + pp_character (buffer, '}'); + } break; case BIT_FIELD_REF: @@ -615,6 +619,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, break; case ARRAY_REF: + case ARRAY_RANGE_REF: op0 = TREE_OPERAND (node, 0); if (op_prio (op0) < op_prio (node)) pp_character (buffer, '('); @@ -623,11 +628,23 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, pp_character (buffer, ')'); pp_character (buffer, '['); dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false); + if (TREE_CODE (node) == ARRAY_RANGE_REF) + pp_string (buffer, " ..."); pp_character (buffer, ']'); - break; - case ARRAY_RANGE_REF: - NIY; + if ((TREE_OPERAND (node, 2) + && TREE_CODE (TREE_OPERAND (node, 2)) != INTEGER_CST) + || (TREE_OPERAND (node, 3) + && TREE_CODE (TREE_OPERAND (node, 3)) != INTEGER_CST)) + { + pp_string (buffer, "{lb: "); + dump_generic_node (buffer, TREE_OPERAND (node, 2), + spc, flags, false); + pp_string (buffer, " sz: "); + dump_generic_node (buffer, TREE_OPERAND (node, 3), + spc, flags, false); + pp_character (buffer, '}'); + } break; case CONSTRUCTOR: @@ -1490,10 +1507,10 @@ print_struct_decl (pretty_printer *buffer, tree node, int spc, int flags) INDENT (spc); if (TREE_CODE (node) == RECORD_TYPE) pp_string (buffer, "struct "); - else if (TREE_CODE (node) == UNION_TYPE) + else if ((TREE_CODE (node) == UNION_TYPE + || TREE_CODE (node) == QUAL_UNION_TYPE)) pp_string (buffer, "union "); - else - NIY; + dump_generic_node (buffer, TYPE_NAME (node), spc, 0, false); } @@ -1515,8 +1532,8 @@ print_struct_decl (pretty_printer *buffer, tree node, int spc, int flags) Maybe this could be solved by looking at the scope in which the structure was declared. */ if (TREE_TYPE (tmp) != node - || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE && - TREE_TYPE (TREE_TYPE (tmp)) != node)) + || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE + && TREE_TYPE (TREE_TYPE (tmp)) != node)) { print_declaration (buffer, tmp, spc+2, flags); pp_newline (buffer); @@ -1656,6 +1673,7 @@ op_prio (tree op) case CALL_EXPR: case ARRAY_REF: + case ARRAY_RANGE_REF: case COMPONENT_REF: return 15; diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index b5e4735e29d..bbb5942db24 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -621,7 +621,7 @@ csc_build_component_ref (tree base, tree field) break; } - return build (COMPONENT_REF, TREE_TYPE (field), base, field); + return build (COMPONENT_REF, TREE_TYPE (field), base, field, NULL_TREE); } /* Similarly for REALPART_EXPR and IMAGPART_EXPR for complex types. */ @@ -1011,7 +1011,7 @@ scalarize_call_expr (block_stmt_iterator *si_p) /* Scalarize the return value, if any. */ if (TREE_CODE (stmt) == MODIFY_EXPR) { - tree var = TREE_OPERAND (stmt, 0); + tree var = get_base_address (TREE_OPERAND (stmt, 0)); /* If the LHS of the assignment is a scalarizable structure, insert copies into the scalar replacements after the call. */ diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index fb7a8258f69..658a2cb9061 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -1041,40 +1041,43 @@ dump_lattice_value (FILE *outf, const char *prefix, value val) tree widen_bitfield (tree val, tree field, tree var) { - unsigned var_size, field_size; + unsigned HOST_WIDE_INT var_size, field_size; tree wide_val; unsigned HOST_WIDE_INT mask; - unsigned i; + unsigned int i; - var_size = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE ((var)))); - field_size = TREE_INT_CST_LOW (DECL_SIZE (field)); + /* We can only do this if the size of the type and field and VAL are + all constants representable in HOST_WIDE_INT. */ + if (!host_integerp (TYPE_SIZE (TREE_TYPE (var)), 1) + || !host_integerp (DECL_SIZE (field), 1) + || !host_integerp (val, 0)) + return NULL_TREE; + + var_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (var)), 1); + field_size = tree_low_cst (DECL_SIZE (field), 1); /* Give up if either the bitfield or the variable are too wide. */ if (field_size > HOST_BITS_PER_WIDE_INT || var_size > HOST_BITS_PER_WIDE_INT) - return NULL; + return NULL_TREE; #if defined ENABLE_CHECKING if (var_size < field_size) abort (); #endif - /* If VAL is not an integer constant, then give up. */ - if (TREE_CODE (val) != INTEGER_CST) - return NULL; - - /* If the sign bit of the value is not set, or the field's type is - unsigned, then just mask off the high order bits of the value. */ - if ((TREE_INT_CST_LOW (val) & (1 << (field_size - 1))) == 0 - || DECL_UNSIGNED (field)) + /* If the sign bit of the value is not set or the field's type is unsigned, + just mask off the high order bits of the value. */ + if (DECL_UNSIGNED (field) + || !(tree_low_cst (val, 0) & (((HOST_WIDE_INT)1) << (field_size - 1)))) { /* Zero extension. Build a mask with the lower 'field_size' bits set and a BIT_AND_EXPR node to clear the high order bits of the value. */ for (i = 0, mask = 0; i < field_size; i++) - mask |= 1 << i; + mask |= ((HOST_WIDE_INT) 1) << i; wide_val = build (BIT_AND_EXPR, TREE_TYPE (var), val, - build_int_2 (mask, 0)); + fold_convert (TREE_TYPE (var), build_int_2 (mask, 0))); } else { @@ -1082,10 +1085,10 @@ widen_bitfield (tree val, tree field, tree var) bits set and a BIT_IOR_EXPR to set the high order bits of the value. */ for (i = 0, mask = 0; i < (var_size - field_size); i++) - mask |= 1 << (var_size - i - 1); + mask |= ((HOST_WIDE_INT) 1) << (var_size - i - 1); wide_val = build (BIT_IOR_EXPR, TREE_TYPE (var), val, - build_int_2 (mask, 0)); + fold_convert (TREE_TYPE (var), build_int_2 (mask, 0))); } return fold (wide_val); @@ -1493,10 +1496,26 @@ likely_value (tree stmt) static tree maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type) { - unsigned HOST_WIDE_INT lquo, lrem; - HOST_WIDE_INT hquo, hrem; - tree elt_size, min_idx, idx; - tree array_type, elt_type; + tree min_idx, idx, elt_offset = integer_zero_node; + tree array_type, elt_type, elt_size; + + /* If BASE is an ARRAY_REF, we can pick up another offset (this time + measured in units of the size of elements type) from that ARRAY_REF). + We can't do anything if either is variable. + + The case we handle here is *(&A[N]+O). */ + if (TREE_CODE (base) == ARRAY_REF) + { + tree low_bound = array_ref_low_bound (base); + + elt_offset = TREE_OPERAND (base, 1); + if (TREE_CODE (low_bound) != INTEGER_CST + || TREE_CODE (elt_offset) != INTEGER_CST) + return NULL_TREE; + + elt_offset = int_const_binop (MINUS_EXPR, elt_offset, low_bound, 0); + base = TREE_OPERAND (base, 0); + } /* Ignore stupid user tricks of indexing non-array variables. */ array_type = TREE_TYPE (base); @@ -1506,37 +1525,62 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type) if (!lang_hooks.types_compatible_p (orig_type, elt_type)) return NULL_TREE; - /* Whee. Ignore indexing of variable sized types. */ + /* If OFFSET and ELT_OFFSET are zero, we don't care about the size of the + element type (so we can use the alignment if it's not constant). + Otherwise, compute the offset as an index by using a division. If the + division isn't exact, then don't do anything. */ elt_size = TYPE_SIZE_UNIT (elt_type); - if (TREE_CODE (elt_size) != INTEGER_CST) - return NULL_TREE; + if (integer_zerop (offset)) + { + if (TREE_CODE (elt_size) != INTEGER_CST) + elt_size = size_int (TYPE_ALIGN (elt_type)); - /* If the division isn't exact, then don't do anything. Equally - invalid as the above indexing of non-array variables. */ - if (div_and_round_double (TRUNC_DIV_EXPR, 1, - TREE_INT_CST_LOW (offset), - TREE_INT_CST_HIGH (offset), - TREE_INT_CST_LOW (elt_size), - TREE_INT_CST_HIGH (elt_size), - &lquo, &hquo, &lrem, &hrem) - || lrem || hrem) - return NULL_TREE; - idx = build_int_2_wide (lquo, hquo); + idx = integer_zero_node; + } + else + { + unsigned HOST_WIDE_INT lquo, lrem; + HOST_WIDE_INT hquo, hrem; + + if (TREE_CODE (elt_size) != INTEGER_CST + || div_and_round_double (TRUNC_DIV_EXPR, 1, + TREE_INT_CST_LOW (offset), + TREE_INT_CST_HIGH (offset), + TREE_INT_CST_LOW (elt_size), + TREE_INT_CST_HIGH (elt_size), + &lquo, &hquo, &lrem, &hrem) + || lrem || hrem) + return NULL_TREE; - /* Re-bias the index by the min index of the array type. */ - min_idx = TYPE_DOMAIN (TREE_TYPE (base)); - if (min_idx) + idx = build_int_2_wide (lquo, hquo); + } + + /* Assume the low bound is zero. If there is a domain type, get the + low bound, if any, convert the index into that type, and add the + low bound. */ + min_idx = integer_zero_node; + if (TYPE_DOMAIN (array_type)) { - min_idx = TYPE_MIN_VALUE (min_idx); - if (min_idx) - { - idx = convert (TREE_TYPE (min_idx), idx); - if (!integer_zerop (min_idx)) - idx = int_const_binop (PLUS_EXPR, idx, min_idx, 1); - } + if (TYPE_MIN_VALUE (TYPE_DOMAIN (array_type))) + min_idx = TYPE_MIN_VALUE (TYPE_DOMAIN (array_type)); + else + min_idx = fold_convert (TYPE_DOMAIN (array_type), min_idx); + + if (TREE_CODE (min_idx) != INTEGER_CST) + return NULL_TREE; + + idx = fold_convert (TYPE_DOMAIN (array_type), idx); + elt_offset = fold_convert (TYPE_DOMAIN (array_type), elt_offset); } - return build (ARRAY_REF, orig_type, base, idx); + if (!integer_zerop (min_idx)) + idx = int_const_binop (PLUS_EXPR, idx, min_idx, 0); + if (!integer_zerop (elt_offset)) + idx = int_const_binop (PLUS_EXPR, idx, elt_offset, 0); + + return build (ARRAY_REF, orig_type, base, idx, min_idx, + size_int (tree_low_cst (elt_size, 1) + / (TYPE_ALIGN (elt_type) / BITS_PER_UNIT))); } /* A subroutine of fold_stmt_r. Attempts to fold *(S+O) to S.X. @@ -1617,7 +1661,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset, { if (base_is_ptr) base = build1 (INDIRECT_REF, record_type, base); - t = build (COMPONENT_REF, field_type, base, f); + t = build (COMPONENT_REF, field_type, base, f, NULL_TREE); return t; } @@ -1639,7 +1683,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset, nonzero offset into them. Recurse and hope for a valid match. */ if (base_is_ptr) base = build1 (INDIRECT_REF, record_type, base); - base = build (COMPONENT_REF, field_type, base, f); + base = build (COMPONENT_REF, field_type, base, f, NULL_TREE); t = maybe_fold_offset_to_array_ref (base, offset, orig_type); if (t) @@ -1697,8 +1741,12 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset) if (t) return t; - /* Fold *&B to B. */ - if (integer_zerop (offset)) + /* Fold *&B to B. We can only do this if EXPR is the same type + as BASE. We can't do this if EXPR is the element type of an array + and BASE is the array. */ + if (integer_zerop (offset) + && lang_hooks.types_compatible_p (TREE_TYPE (base), + TREE_TYPE (expr))) return base; } else @@ -1803,6 +1851,9 @@ maybe_fold_stmt_addition (tree expr) min_idx = TYPE_MIN_VALUE (min_idx); if (min_idx) { + if (TREE_CODE (min_idx) != INTEGER_CST) + break; + array_idx = convert (TREE_TYPE (min_idx), array_idx); if (!integer_zerop (min_idx)) array_idx = int_const_binop (MINUS_EXPR, array_idx, diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 9eb0bd12e11..08330abd51f 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -897,30 +897,18 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops) code = TREE_CODE (expr); class = TREE_CODE_CLASS (code); - /* Expressions that make no memory references. */ - if (class == 'c' - || class == 't' - || code == BLOCK - || code == FUNCTION_DECL - || code == EXC_PTR_EXPR - || code == FILTER_EXPR - || code == LABEL_DECL) - return; - /* We could have the address of a component, array member, etc which has interesting variable references. */ if (code == ADDR_EXPR) { - enum tree_code subcode = TREE_CODE (TREE_OPERAND (expr, 0)); - /* Taking the address of a variable does not represent a reference to it, but the fact that STMT takes its address will be of interest to some passes (e.g. alias resolution). */ add_stmt_operand (expr_p, stmt, 0, NULL); - /* If the address is invariant, there may be no interesting variable - references inside. */ - if (is_gimple_min_invariant (expr)) + /* If the address is constant (invariant is not sufficient), there will + be no interesting variable references inside. */ + if (TREE_CONSTANT (expr)) return; /* There should be no VUSEs created, since the referenced objects are @@ -930,12 +918,22 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops) flags |= opf_no_vops; /* Avoid recursion. */ - code = subcode; - class = TREE_CODE_CLASS (code); expr_p = &TREE_OPERAND (expr, 0); expr = *expr_p; + code = TREE_CODE (expr); + class = TREE_CODE_CLASS (code); } + /* Expressions that make no memory references. */ + if (class == 'c' + || class == 't' + || code == BLOCK + || code == FUNCTION_DECL + || code == EXC_PTR_EXPR + || code == FILTER_EXPR + || code == LABEL_DECL) + return; + /* If we found a variable, add it to DEFS or USES depending on the operand flags. */ if (SSA_VAR_P (expr)) @@ -1043,7 +1041,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops) /* Treat array references as references to the virtual variable representing the array. The virtual variable for an ARRAY_REF is the VAR_DECL for the array. */ - if (code == ARRAY_REF) + if (code == ARRAY_REF || code == ARRAY_RANGE_REF) { /* Add the virtual variable for the ARRAY_REF to VDEFS or VUSES according to the value of IS_DEF. Recurse if the LHS of the @@ -1054,6 +1052,8 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops) get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, prev_vops); get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops); + get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, prev_vops); + get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_none, prev_vops); return; } @@ -1078,6 +1078,8 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops) else get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, prev_vops); + if (code == COMPONENT_REF) + get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, prev_vops); return; } diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 5ba8f65b510..89d40a1b918 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -473,20 +473,11 @@ set_is_used (tree t) if (SSA_VAR_P (t)) break; - switch (TREE_CODE (t)) - { - case ARRAY_REF: - case COMPONENT_REF: - case REALPART_EXPR: - case IMAGPART_EXPR: - case BIT_FIELD_REF: - case INDIRECT_REF: + if (TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR) + t = TREE_OPERAND (t, 0); + else + while (handled_component_p (t)) t = TREE_OPERAND (t, 0); - break; - - default: - return; - } } if (TREE_CODE (t) == SSA_NAME) diff --git a/gcc/tree.c b/gcc/tree.c index fb1f4d77b69..716bc35fa70 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1927,7 +1927,8 @@ substitute_in_expr (tree exp, tree f, tree r) if (op0 == TREE_OPERAND (exp, 0)) return exp; - new = fold (build2 (code, TREE_TYPE (exp), op0, TREE_OPERAND (exp, 1))); + new = fold (build (code, TREE_TYPE (exp), op0, TREE_OPERAND (exp, 1), + NULL_TREE)); } else switch (TREE_CODE_CLASS (code)) @@ -2157,7 +2158,7 @@ stabilize_reference (tree ref) case COMPONENT_REF: result = build_nt (COMPONENT_REF, stabilize_reference (TREE_OPERAND (ref, 0)), - TREE_OPERAND (ref, 1)); + TREE_OPERAND (ref, 1), NULL_TREE); break; case BIT_FIELD_REF: @@ -2170,13 +2171,15 @@ stabilize_reference (tree ref) case ARRAY_REF: result = build_nt (ARRAY_REF, stabilize_reference (TREE_OPERAND (ref, 0)), - stabilize_reference_1 (TREE_OPERAND (ref, 1))); + stabilize_reference_1 (TREE_OPERAND (ref, 1)), + TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3)); break; case ARRAY_RANGE_REF: result = build_nt (ARRAY_RANGE_REF, stabilize_reference (TREE_OPERAND (ref, 0)), - stabilize_reference_1 (TREE_OPERAND (ref, 1))); + stabilize_reference_1 (TREE_OPERAND (ref, 1)), + TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3)); break; case COMPOUND_EXPR: @@ -2292,41 +2295,77 @@ stabilize_reference_1 (tree e) /* Low-level constructors for expressions. */ -/* A helper function for build1 and constant folders. - Set TREE_CONSTANT and TREE_INVARIANT for an ADDR_EXPR. */ +/* A helper function for build1 and constant folders. Set TREE_CONSTANT, + TREE_INVARIANT, and TREE_SIDE_EFFECTS for an ADDR_EXPR. */ void recompute_tree_invarant_for_addr_expr (tree t) { - tree node = TREE_OPERAND (t, 0); - bool tc = false, ti = false; + tree node; + bool tc = true, ti = true, se = false; - /* Addresses of constants and static variables are constant; - all other decl addresses are invariant. */ - if (staticp (node)) - tc = ti = true; - else + /* We started out assuming this address is both invariant and constant, but + does not have side effects. Now go down any handled components and see if + any of them involve offsets that are either non-constant or non-invariant. + Also check for side-effects. + + ??? Note that this code makes no attempt to deal with the case where + taking the address of something causes a copy due to misalignment. */ + +#define UPDATE_TITCSE(NODE) \ +do { tree _node = (NODE); \ + if (_node && !TREE_INVARIANT (_node)) ti = false; \ + if (_node && !TREE_CONSTANT (_node)) tc = false; \ + if (_node && TREE_SIDE_EFFECTS (_node)) se = true; } while (0) + + for (node = TREE_OPERAND (t, 0); handled_component_p (node); + node = TREE_OPERAND (node, 0)) { - /* Step past constant offsets. */ - while (1) + /* If the first operand doesn't have an ARRAY_TYPE, this is a bogus + array reference (probably made temporarily by the G++ front end), + so ignore all the operands. */ + if ((TREE_CODE (node) == ARRAY_REF + || TREE_CODE (node) == ARRAY_RANGE_REF) + && TREE_CODE (TREE_TYPE (TREE_OPERAND (node, 0))) == ARRAY_TYPE) { - if (TREE_CODE (node) == COMPONENT_REF - && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL - && ! DECL_BIT_FIELD (TREE_OPERAND (node, 1))) - ; - else if (TREE_CODE (node) == ARRAY_REF - && TREE_CONSTANT (TREE_OPERAND (node, 1))) - ; - else - break; - node = TREE_OPERAND (node, 0); + UPDATE_TITCSE (TREE_OPERAND (node, 1)); + UPDATE_TITCSE (array_ref_low_bound (node)); + UPDATE_TITCSE (array_ref_element_size (node)); } - if (DECL_P (node)) - ti = true; + /* Likewise, just because this is a COMPONENT_REF doesn't mean we have a + FIELD_DECL, apparently. The G++ front end can put something else + there, at least temporarily. */ + else if (TREE_CODE (node) == COMPONENT_REF + && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL) + UPDATE_TITCSE (component_ref_field_offset (node)); + else if (TREE_CODE (node) == BIT_FIELD_REF) + UPDATE_TITCSE (TREE_OPERAND (node, 2)); + } + + /* Now see what's inside. If it's an INDIRECT_REF, copy our properties from + it. If it's a decl, it's definitely invariant and it's constant if the + decl is static. (Taking the address of a volatile variable is not + volatile.) If it's a constant, the address is both invariant and + constant. Otherwise it's neither. */ + if (TREE_CODE (node) == INDIRECT_REF) + UPDATE_TITCSE (node); + else if (DECL_P (node)) + { + if (!staticp (node)) + tc = false; + } + else if (TREE_CODE_CLASS (TREE_CODE (node)) == 'c') + ; + else + { + ti = tc = false; + se |= TREE_SIDE_EFFECTS (node); } TREE_CONSTANT (t) = tc; TREE_INVARIANT (t) = ti; + TREE_SIDE_EFFECTS (t) = se; +#undef UPDATE_TITCSE } /* Build an expression of code CODE, data type TYPE, and operands as @@ -2429,27 +2468,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) case ADDR_EXPR: if (node) - { - recompute_tree_invarant_for_addr_expr (t); - - /* The address of a volatile decl or reference does not have - side-effects. But be careful not to ignore side-effects from - other sources deeper in the expression--if node is a _REF and - one of its operands has side-effects, so do we. */ - if (TREE_THIS_VOLATILE (node)) - { - TREE_SIDE_EFFECTS (t) = 0; - if (!DECL_P (node)) - { - int i = first_rtl_op (TREE_CODE (node)) - 1; - for (; i >= 0; --i) - { - if (TREE_SIDE_EFFECTS (TREE_OPERAND (node, i))) - TREE_SIDE_EFFECTS (t) = 1; - } - } - } - } + recompute_tree_invarant_for_addr_expr (t); break; default: @@ -2516,6 +2535,8 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) TREE_CONSTANT (t) = constant; TREE_INVARIANT (t) = invariant; TREE_SIDE_EFFECTS (t) = side_effects; + TREE_THIS_VOLATILE (t) + = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0); return t; } @@ -2565,6 +2586,8 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, } TREE_SIDE_EFFECTS (t) = side_effects; + TREE_THIS_VOLATILE (t) + = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0); return t; } @@ -2595,6 +2618,8 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1, PROCESS_ARG(3); TREE_SIDE_EFFECTS (t) = side_effects; + TREE_THIS_VOLATILE (t) + = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0); return t; } @@ -4457,8 +4482,8 @@ get_unwidened (tree op, tree for_type) && (for_type || ! DECL_BIT_FIELD (TREE_OPERAND (op, 1))) && (! uns || final_prec <= innerprec || unsignedp)) { - win = build2 (COMPONENT_REF, type, TREE_OPERAND (op, 0), - TREE_OPERAND (op, 1)); + win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0), + TREE_OPERAND (op, 1), NULL_TREE); TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op); TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op); } @@ -4523,7 +4548,8 @@ get_narrower (tree op, int *unsignedp_ptr) /* Since type_for_size always gives an integer type. */ && TREE_CODE (TREE_TYPE (op)) != REAL_TYPE /* Ensure field is laid out already. */ - && DECL_SIZE (TREE_OPERAND (op, 1)) != 0) + && DECL_SIZE (TREE_OPERAND (op, 1)) != 0 + && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1)) { unsigned HOST_WIDE_INT innerprec = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1); @@ -4546,8 +4572,8 @@ get_narrower (tree op, int *unsignedp_ptr) { if (first) uns = DECL_UNSIGNED (TREE_OPERAND (op, 1)); - win = build2 (COMPONENT_REF, type, TREE_OPERAND (op, 0), - TREE_OPERAND (op, 1)); + win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0), + TREE_OPERAND (op, 1), NULL_TREE); TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op); TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op); } diff --git a/gcc/tree.def b/gcc/tree.def index 5afe7658a5e..12a6394c5b1 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -354,9 +354,11 @@ DEFTREECODE (TRANSLATION_UNIT_DECL, "translation_unit_decl", 'd', 0) /* References to storage. */ /* Value is structure or union component. - Operand 0 is the structure or union (an expression); - operand 1 is the field (a node of type FIELD_DECL). */ -DEFTREECODE (COMPONENT_REF, "component_ref", 'r', 2) + Operand 0 is the structure or union (an expression). + Operand 1 is the field (a node of type FIELD_DECL). + Operand 2, if present, is the value of DECL_FIELD_OFFSET, measured + in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT. */ +DEFTREECODE (COMPONENT_REF, "component_ref", 'r', 3) /* Reference to a group of bits within an object. Similar to COMPONENT_REF except the position is given explicitly rather than via a FIELD_DECL. @@ -374,13 +376,16 @@ DEFTREECODE (INDIRECT_REF, "indirect_ref", 'r', 1) DEFTREECODE (BUFFER_REF, "buffer_ref", 'r', 1) /* Array indexing. - Operand 0 is the array; operand 1 is a (single) array index. */ -DEFTREECODE (ARRAY_REF, "array_ref", 'r', 2) + Operand 0 is the array; operand 1 is a (single) array index. + Operand 2, if present, is a copy of TYPE_MIN_VALUE of the index. + Operand 3, if present, is the element size, measured in units of + the alignment of the element type. */ +DEFTREECODE (ARRAY_REF, "array_ref", 'r', 4) /* Likewise, except that the result is a range ("slice") of the array. The starting index of the resulting array is taken from operand 1 and the size of the range is taken from the type of the expression. */ -DEFTREECODE (ARRAY_RANGE_REF, "array_range_ref", 'r', 2) +DEFTREECODE (ARRAY_RANGE_REF, "array_range_ref", 'r', 4) /* Vtable indexing. Carries data useful for emitting information for vtable garbage collection. diff --git a/gcc/tree.h b/gcc/tree.h index d5d87b69d65..9b753a341f6 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3166,6 +3166,21 @@ extern tree get_inner_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, extern int handled_component_p (tree); +/* Return a tree of sizetype representing the size, in bytes, of the element + of EXP, an ARRAY_REF. */ + +extern tree array_ref_element_size (tree); + +/* Return a tree representing the lower bound of the array mentioned in + EXP, an ARRAY_REF. */ + +extern tree array_ref_low_bound (tree); + +/* Return a tree representing the offset, in bytes, of the field referenced + by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */ + +extern tree component_ref_field_offset (tree); + /* Given a DECL or TYPE, return the scope in which it was declared, or NUL_TREE if there is no containing scope. */