diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-10-08 05:57:48 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-10-08 05:57:48 +0000 |
commit | c95b9ae3504a8da1a31c1ed2224f97b3d4b829a2 (patch) | |
tree | 775928cf6a1e9f1553ce9d66715128ff7443febe | |
parent | 6b478e0035aa8103bd1985b85280892386cd32ef (diff) | |
download | gcc-c95b9ae3504a8da1a31c1ed2224f97b3d4b829a2.tar.gz |
2008-10-08 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk r140962
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@140963 138bc75d-0d04-0410-961f-82ee72b054a4
122 files changed, 3654 insertions, 962 deletions
diff --git a/ChangeLog.melt b/ChangeLog.melt index a0df0bf9333..be537e1ac1e 100644 --- a/ChangeLog.melt +++ b/ChangeLog.melt @@ -1,3 +1,6 @@ +2008-10-08 Basile Starynkevitch <basile@starynkevitch.net> + MELT branch merged with trunk r140962 + 2008-10-05 Basile Starynkevitch <basile@starynkevitch.net> MELT branch merged with trunk r140892 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 71eaead3463..abe7fdc4959 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,277 @@ +2008-10-07 H.J. Lu <hongjiu.lu@intel.com> + + * config/i386/i386.md: Remove trailing white spaces. + +2008-10-07 Kenneth Zadeck <zadeck@naturalbridge.com> + + PR rtl-optimization/37448 + alloc_pool_desc (elt_size): New field. + alloc_pool_desc (created, allocated, current, peak): Make unsigned + long. + output_info (count): Renamed total_created and made unsigned long. + output_info (size): Renamed total_allocated and made unsigned long. + alloc-pool.c (create_alloc_pool, empty_alloc_pool, pool_alloc, + pool_free): Properly keep track of desc->size. + (print_statistics, dump_alloc_pool_statistics): Enhance the + printing of statistics to print the number of elements and to use + unsigned longs. + +2008-10-07 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/37576 + * opts.h (CL_SAVE): Move up to flags range. + (CL_PARAMS, CL_WARNING, CL_OPTIMIZATION, CL_TARGET, + CL_COMMON): Renumber. + (CL_MIN_OPTION_CLASS): Set to CL_PARAMS. + * opts.c (common_handle_option): Revert last change. + +2008-10-07 H.J. Lu <hongjiu.lu@intel.com> + + * config/i386/i386-protos.h (ix86_schedule): New. + + * config/i386/i386.c (ix86_schedule): New. + (override_options): Add schedule to processor_alias_table. Set + ix86_schedule from the schedule field in processor_alias_table. + (ix86_function_specific_save): Save ix86_schedule. + (ix86_function_specific_restore): Restore ix86_schedule. + + * config/i386/i386.md (cpu): Map to ix86_schedule instead of + ix86_tune. Add none and remove i386, i486, pentium4, nocona + and generic32. + + * config/i386/i386.opt: Add schedule. + + * config/i386/ppro.md: Remove generic32. + +2008-10-07 Simon Martin <simartin@users.sourceforge.net> + + PR c/35437 + * expr.c (count_type_elements): Handle ERROR_MARK. + +2008-10-07 Jakub Jelinek <jakub@redhat.com> + + PR debug/29609 + PR debug/36690 + PR debug/37616 + * basic-block.h (struct edge_def): Add goto_block field. + * cfglayout.c (fixup_reorder_chain): Ensure that there is at least + one insn with locus corresponding to edge's goto_locus if !optimize. + * profile.c (branch_prob): Copy edge's goto_block. + * cfgrtl.c (force_nonfallthru_and_redirect): Use goto_locus for + emitted jumps. + (cfg_layout_merge_blocks): Emit a nop with edge's goto_locus + locator in between the merged basic blocks if !optimize and needed. + * cfgexpand.c (expand_gimple_cond): Convert goto_block and + goto_locus into RTL locator. For unconditional jump use that + locator for the jump insn. + (expand_gimple_cond): Convert goto_block and goto_locus into + RTL locator for all remaining edges. For unconditional jump + use that locator for the jump insn. + * cfgcleanup.c (try_forward_edges): Avoid the optimization if + there is more than one edge or insn locator along the forwarding + edges and !optimize. If there is just one, set e->goto_locus. + * tree-cfg.c (make_cond_expr_edges, make_goto_expr_edges): Set also + edge's goto_block. + (move_block_to_fn): Adjust edge's goto_block. + +2008-10-07 H.J. Lu <hongjiu.lu@intel.com> + + PR middle-end/37731 + * expmed.c (expand_mult): Properly check DImode constant in + CONST_DOUBLE. + +2008-10-07 Jakub Jelinek <jakub@redhat.com> + + PR debug/37738 + * dwarf2out.c (common_block_die_table): New variable. + (common_block_die_table_hash, common_block_die_table_eq): New + functions. + (gen_variable_die): Look up a DW_TAG_common_block die for a particular + COMMON block in the current scope rather than globally. Optimize + DW_OP_addr SYMBOL_REF DW_OP_plus_uconst off into + DW_OP_addr SYMBOL_REF+off. + +2008-10-07 Eric Botcazou <ebotcazou@adacore.com> + + * tree-ssa-loop-ivopts.c (may_be_nonaddressable_p) <VIEW_CONVERT_EXPR>: + Return true for non-addressable GIMPLE operands. + +2008-10-07 H.J. Lu <hongjiu.lu@intel.com> + + PR target/24765 + * config/i386/i386.c (initial_ix86_tune_features): Remove + X86_TUNE_USE_BIT_TEST. + * config/i386/i386.h (ix86_tune_indices): Likewise. + (TARGET_USE_BIT_TEST): Removed. + +2008-10-07 Bernhard Reutner-Fischer <aldot@gcc.gnu.org> + + * config.gcc (arm*-*-*): Add aapcs-linux to supported ABIs. + +2008-10-06 Adam Nemet <anemet@caviumnetworks.com> + + * config/mips/mips.md (mulsi3_mul3, muldi3_mul3): Merge these ... + (mul<mode>3_mul3): ... into this new template. + +2008-10-06 Aldy Hernandez <aldyh@redhat.com> + + * gimplify.c (gimplify_arg): Add location argument. Use it. + (gimplify_call_expr): Pass location to gimplify_arg. + (gimplify_modify_expr_to_memcpy): Same. + (gimplify_modify_expr_to_memset): Same. + +2008-10-06 Andrew Pinski <andrew_pinski@playstation.sony.com> + + * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin): + Update calls to build_unary_op and build_indirect_ref for location + changes. + +2008-10-06 Aldy Hernandez <aldyh@redhat.com> + + build_modify_expr. + * c-decl.c (finish_decl): Pass input_location to build_unary_op. + * c-typeck.c (array_to_pointer_conversion): Pass location to + build_unary_op. + (function_to_pointer_conversion): Use error_at and warning_at. + (build_indirect_ref): Same. + (build_array_ref): Pass location to build_binary_op. + (parser_build_unary_op): Do not set location after calling + build_unary_op. + (build_unary_op): Add location argument. Use it throughout. Set + EXPR_LOCATION before returning new tree. + (build_modify_expr): Same. + (build_binary_op): Use location throughout. Set EXPR_LOCATION before + returning node. + * c-omp.c (c_finish_omp_atomic): Pass location to build_unary_op, + build_indirect_ref, build_modify_expr. + (c_finish_omp_for): Same. Use error_at instead of error. + * c-common.c (c_common_truthvalue_conversion): Pass location to + build_unary_op. + (warn_for_div_by_zero): Add location argument. + * c-common.h: Add argument to build_modify_expr, build_indirect_ref, + build_unary_op, warn_for_div_by_zero. + * c-parser.c (c_parser_typeof_specifier): Use + protected_set_expr_location. + (c_parser_statement_after_labels): Same. + (c_parser_condition): Same. + (c_parser_expr_no_commas): Pass correct location to build_modify_expr. + (c_parser_conditional_expression): Use protected_set_expr_location. + (c_parser_unary_expression): Pass location to build_indirect_ref. + (c_parser_postfix_expression_after_primary): Pass location to + build_indirect_ref, build_unary_op. + (c_parser_omp_for_loop): Set the increment expression's EXPR_LOCATION. + +2008-10-06 Joshua Kinard <kumba@gentoo.org> + + * doc/invoke.texi: List r1x000 family under the -march MIPS option. + * config/mips/mips.h (PROCESSOR_R10000): New processor_type. + * config/mips/mips.c (mips_cpu_info_table): Add r10000, r12000, + r14000 and r16000. + (mips_rtx_cost_data): Add a PROCESSOR_R10000 entry. + (mips_issue_rate): Handle PROCESSOR_R10000. + * config/mips/mips.md (cpu): Add r10000. + Include r10000.md. + * config/mips/10000.md: New file. + +2008-10-06 Richard Sandiford <rdsandiford@googlemail.com> + + * config/rs6000/rs6000-protos.h (rs6000_find_base_term): Declare. + * config/rs6000/rs6000.h (FIND_BASE_TERM): New macro. + * config/rs6000/rs6000.c (rs6000_find_base_term): New function. + +2008-10-06 Richard Sandiford <rdsandiford@googlemail.com> + + * config/darwin-protos.h (machopic_function_base_name): Delete. + (machopic_function_base_sym): Likewise. + (machopic_gen_offset): Declare. + * config/darwin.h (MACHOPIC_FUNCTION_BASE_NAME): New macro. + (ASM_OUTPUT_LABELREF): Use it instead of a hard-coded string constant. + * config/darwin.c (machopic_function_base_name): Delete. + (machopic_function_base_sym): Likewise. + (gen_pic_offset): Rename to... + (machopic_gen_offset): ...this and remove the pic_base argument. + Instead use MACHO_DYNAMIC_NO_PIC_P to decide whether a PIC offset + is needed. Create an UNSPEC_MACHOPIC_OFFSET if so, and set + crtl->uses_pic_offset_table. + (machopic_indirect_data_reference): Use new machopic_gen_offset + interface. + (machopic_legitimize_pic_address): Likewise. + (machopic_operand_p): Check for UNSPEC_MACHOPIC_OFFSET. + + * config/i386/darwin.h (GOT_SYMBOL_NAME): Use + MACHOPIC_FUNCTION_BASE_NAME instead of machopic_function_base_name. + * config/i386/i386.c (output_set_got): Likewise. + (darwin_local_data_pic): Check for an UNSPEC_MACHOPIC_OFFSET + instead of a MINUS. + (legitimate_pic_operand_p): Handle UNSPEC_MACHOPIC_OFFSET. + (legitimate_address_p): Likewise. + (output_pic_addr_const): Likewise. + (output_addr_const_extra): Likewise. + (ix86_delegitimize_address): Expect darwin_local_data_pic to + match an UNSPEC rather than a MINUS. + * config/i386/i386.md (UNSPEC_MACHOPIC_OFFSET): Define. + (builtin_setjmp_receiver): Use machopic_gen_offset. + * config/i386/predicates.md (pic_symbolic_operand): Handle + UNSPEC_MACHOPIC_OFFSET. + + * config/rs6000/rs6000.c (rs6000_legitimize_reload_address): + Use machopic_gen_offset and machopic_operand_p. + (rs6000_output_addr_const_extra): Handle UNSPEC_MACHOPIC_OFFSET. + (rs6000_emit_prologue): Use MACHOPIC_FUNCTION_BASE_NAME. + * config/rs6000/rs6000.md (UNSPEC_MACHOPIC_OFFSET): Define. + (builtin_setjmp_receiver): Use MACHOPIC_FUNCTION_BASE_NAME. + Set crtl->uses_pic_offset_table. + +2008-10-06 Richard Sandiford <rdsandiford@googlemail.com> + + * config/rs6000/rs6000-protos.h (rs6000_output_addr_const_extra): + Declare. + * config/rs6000/rs6000.h (OUTPUT_ADDR_CONST_EXTRA): New macro. + * config/rs6000/rs6000.md (UNSPEC_TOCREL): New constant. + * config/rs6000/rs6000.c (constant_pool_expr_1): Delete. + (constant_pool_expr_p): Use split_const and check the base. + (toc_relative_expr_p): Likewise, checking for an UNSPEC_TOCREL + instead of a MINUS. + (legitimate_constant_pool_address_p): Check toc_relative_p + instead of constant_pool_expr_p. + (print_operand_address): Always use output_addr_const for + constant pool addresses. + (rs6000_output_addr_const_extra): New function. + (create_TOC_reference): Create an UNSPEC_TOCREL instead of + a MINUS. + +2008-10-06 Vladimir Makarov <vmakarov@redhat.com> + + PR middle-end/37535 + + * ira-lives.c (mark_reg_live, mark_reg_dead): New functions. + (mark_ref_live, mark_ref_dead): Use them. + (def_conflicts_with_inputs_p): Remove. + (mark_early_clobbers): New function. + (process_bb_node_lives): Call preprocess_constraints and + mark_early_clobbers. + + * doc/rtx.texi (clobber): Change how RA deals with clobbers. + +2008-10-06 Danny Smith <dannysmith@users.sourceforge.net> + + * config/i386/mingw32.h (REAL_LIBGCC_SPEC): Add thread cleanup + lib with -mthread switch. + +2008-10-05 Dodji Seketeli <dodji@redhat.com> + + PR c++/37410 + * dwarf2out.c (dwarf2out_imported_module_or_decl): Split this + function in two, making it call a new and reusable + dwarf2out_imported_module_or_decl() that takes the containing + BLOCK of the declaration in argument. + (dwarf2out_imported_module_or_decl_real): New function. + (decls_for_scope, gen_decl_die, dwarf2out_decl): Take + IMPORTED_DECL in account. + * tree.def: Added IMPORTED_DECL node type. + * tree.h: Added accessors for IMPORTED_DECL nodes. + * tree.c (init_ttree): Initialise IMPORTED_DECL node type. + 2008-10-05 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> * doc/gimple.texi: Fix some typos, wrap some long lines, diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index ff0adc38af2..12db959fdbc 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20081005 +20081008 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7d06122ccaa..d384ff538b2 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,21 @@ +2008-10-07 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/decl.c (gnat_to_gnu_entity) <object>: Move code + dealing with volatileness to after code dealing with renaming. + +2008-10-06 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/decl.c (gnat_to_gnu_entity) <object>: Minor tweaks. + * gcc-interface/trans.c (Pragma_to_gnu): Likewise. + +2008-10-06 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/utils.c (can_fold_for_view_convert_p): New predicate. + (unchecked_convert): Use it to disable problematic folding with + VIEW_CONVERT_EXPR in the general case. Always disable it for the + special VIEW_CONVERT_EXPR built for integral types and cope with + its addressability issues by preserving the first conversion. + 2008-10-01 Andreas Schwab <schwab@suse.de> * system-linux-ppc64.ads: New file. diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index b0dfc7d33e4..cdee2277608 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -828,22 +828,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) "PAD", false, definition, gnu_size ? true : false); - /* Make a volatile version of this object's type if we are to make - the object volatile. We also interpret 13.3(19) conservatively - and disallow any optimizations for an object covered by it. */ - if ((Treat_As_Volatile (gnat_entity) - || (Is_Exported (gnat_entity) - /* Exclude exported constants created by the compiler, - which should boil down to static dispatch tables and - make it possible to put them in read-only memory. */ - && (Comes_From_Source (gnat_entity) || !const_flag)) - || Is_Imported (gnat_entity) - || Present (Address_Clause (gnat_entity))) - && !TYPE_VOLATILE (gnu_type)) - gnu_type = build_qualified_type (gnu_type, - (TYPE_QUALS (gnu_type) - | TYPE_QUAL_VOLATILE)); - /* If this is a renaming, avoid as much as possible to create a new object. However, in several cases, creating it is required. This processing needs to be applied to the raw expression so @@ -991,22 +975,38 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) } } - /* If this is an aliased object whose nominal subtype is unconstrained, - the object is a record that contains both the template and - the object. If there is an initializer, it will have already - been converted to the right type, but we need to create the - template if there is no initializer. */ - else if (definition - && TREE_CODE (gnu_type) == RECORD_TYPE - && (TYPE_CONTAINS_TEMPLATE_P (gnu_type) - /* Beware that padding might have been introduced - via maybe_pad_type above. */ - || (TYPE_IS_PADDING_P (gnu_type) - && TREE_CODE (TREE_TYPE (TYPE_FIELDS (gnu_type))) - == RECORD_TYPE - && TYPE_CONTAINS_TEMPLATE_P - (TREE_TYPE (TYPE_FIELDS (gnu_type))))) - && !gnu_expr) + /* Make a volatile version of this object's type if we are to make + the object volatile. We also interpret 13.3(19) conservatively + and disallow any optimizations for an object covered by it. */ + if ((Treat_As_Volatile (gnat_entity) + || (Is_Exported (gnat_entity) + /* Exclude exported constants created by the compiler, + which should boil down to static dispatch tables and + make it possible to put them in read-only memory. */ + && (Comes_From_Source (gnat_entity) || !const_flag)) + || Is_Imported (gnat_entity) + || Present (Address_Clause (gnat_entity))) + && !TYPE_VOLATILE (gnu_type)) + gnu_type = build_qualified_type (gnu_type, + (TYPE_QUALS (gnu_type) + | TYPE_QUAL_VOLATILE)); + + /* If we are defining an aliased object whose nominal subtype is + unconstrained, the object is a record that contains both the + template and the object. If there is an initializer, it will + have already been converted to the right type, but we need to + create the template if there is no initializer. */ + if (definition + && !gnu_expr + && TREE_CODE (gnu_type) == RECORD_TYPE + && (TYPE_CONTAINS_TEMPLATE_P (gnu_type) + /* Beware that padding might have been introduced + via maybe_pad_type above. */ + || (TYPE_IS_PADDING_P (gnu_type) + && TREE_CODE (TREE_TYPE (TYPE_FIELDS (gnu_type))) + == RECORD_TYPE + && TYPE_CONTAINS_TEMPLATE_P + (TREE_TYPE (TYPE_FIELDS (gnu_type)))))) { tree template_field = TYPE_IS_PADDING_P (gnu_type) @@ -1328,7 +1328,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) && (definition || Sloc (gnat_entity) > Standard_Location) && ((Is_Public (gnat_entity) && !Present (Address_Clause (gnat_entity))) - || optimize == 0 + || !optimize || Address_Taken (gnat_entity) || Is_Aliased (gnat_entity) || Is_Aliased (Etype (gnat_entity)))) @@ -1343,7 +1343,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* As debugging information will be generated for the variable, do not generate information for the constant. */ - DECL_IGNORED_P (gnu_decl) = true; + DECL_IGNORED_P (gnu_decl) = 1; } /* If this is declared in a block that contains a block with an diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 9a6f4cf36ef..e4c86225fac 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -801,12 +801,12 @@ Pragma_to_gnu (Node_Id gnat_node) (First (Pragma_Argument_Associations (gnat_node))))) { case Name_Time: case Name_Space: - if (optimize == 0) + if (!optimize) post_error ("insufficient -O value?", gnat_node); break; case Name_Off: - if (optimize != 0) + if (optimize) post_error ("must specify -O0?", gnat_node); break; diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 7f1bc7bebbb..d883d533e46 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -4489,8 +4489,72 @@ maybe_unconstrained_array (tree exp) return exp; } +/* Return true if EXPR is an expression that can be folded as an operand + of a VIEW_CONVERT_EXPR. See the head comment of unchecked_convert for + the rationale. */ + +static bool +can_fold_for_view_convert_p (tree expr) +{ + tree t1, t2; + + /* The folder will fold NOP_EXPRs between integral types with the same + precision (in the middle-end's sense). We cannot allow it if the + types don't have the same precision in the Ada sense as well. */ + if (TREE_CODE (expr) != NOP_EXPR) + return true; + + t1 = TREE_TYPE (expr); + t2 = TREE_TYPE (TREE_OPERAND (expr, 0)); + + /* Defer to the folder for non-integral conversions. */ + if (!(INTEGRAL_TYPE_P (t1) && INTEGRAL_TYPE_P (t2))) + return true; + + /* Only fold conversions that preserve both precisions. */ + if (TYPE_PRECISION (t1) == TYPE_PRECISION (t2) + && operand_equal_p (rm_size (t1), rm_size (t2), 0)) + return true; + + return false; +} + /* Return an expression that does an unchecked conversion of EXPR to TYPE. - If NOTRUNC_P is true, truncation operations should be suppressed. */ + If NOTRUNC_P is true, truncation operations should be suppressed. + + Special care is required with (source or target) integral types whose + precision is not equal to their size, to make sure we fetch or assign + the value bits whose location might depend on the endianness, e.g. + + Rmsize : constant := 8; + subtype Int is Integer range 0 .. 2 ** Rmsize - 1; + + type Bit_Array is array (1 .. Rmsize) of Boolean; + pragma Pack (Bit_Array); + + function To_Bit_Array is new Unchecked_Conversion (Int, Bit_Array); + + Value : Int := 2#1000_0001#; + Vbits : Bit_Array := To_Bit_Array (Value); + + we expect the 8 bits at Vbits'Address to always contain Value, while + their original location depends on the endianness, at Value'Address + on a little-endian architecture but not on a big-endian one. + + ??? There is a problematic discrepancy between what is called precision + here (and more generally throughout gigi) for integral types and what is + called precision in the middle-end. In the former case it's the RM size + as given by TYPE_RM_SIZE (or rm_size) whereas it's TYPE_PRECISION in the + latter case, the hitch being that they are not equal when they matter, + that is when the number of value bits is not equal to the type's size: + TYPE_RM_SIZE does give the number of value bits but TYPE_PRECISION is set + to the size. The sole exception are BOOLEAN_TYPEs for which both are 1. + + The consequence is that gigi must duplicate code bridging the gap between + the type's size and its precision that exists for TYPE_PRECISION in the + middle-end, because the latter knows nothing about TYPE_RM_SIZE, and be + wary of transformations applied in the middle-end based on TYPE_PRECISION + because this value doesn't reflect the actual precision for Ada. */ tree unchecked_convert (tree type, tree expr, bool notrunc_p) @@ -4517,14 +4581,10 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) && TYPE_JUSTIFIED_MODULAR_P (etype)))) || TREE_CODE (type) == UNCONSTRAINED_ARRAY_TYPE) { - tree rtype = type; - bool final_unchecked = false; - if (TREE_CODE (etype) == INTEGER_TYPE && TYPE_BIASED_REPRESENTATION_P (etype)) { tree ntype = copy_type (etype); - TYPE_BIASED_REPRESENTATION_P (ntype) = 0; TYPE_MAIN_VARIANT (ntype) = ntype; expr = build1 (NOP_EXPR, ntype, expr); @@ -4533,15 +4593,18 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) if (TREE_CODE (type) == INTEGER_TYPE && TYPE_BIASED_REPRESENTATION_P (type)) { - rtype = copy_type (type); + tree rtype = copy_type (type); TYPE_BIASED_REPRESENTATION_P (rtype) = 0; TYPE_MAIN_VARIANT (rtype) = rtype; + expr = convert (rtype, expr); + expr = build1 (NOP_EXPR, type, expr); } - /* We have another special case: if we are unchecked converting subtype - into a base type, we need to ensure that VRP doesn't propagate range - information since this conversion may be done precisely to validate - that the object is within the range it is supposed to have. */ + /* We have another special case: if we are unchecked converting either + a subtype or a type with limited range into a base type, we need to + ensure that VRP doesn't propagate range information because this + conversion may be done precisely to validate that the object is + within the range it is supposed to have. */ else if (TREE_CODE (expr) != INTEGER_CST && TREE_CODE (type) == INTEGER_TYPE && !TREE_TYPE (type) && ((TREE_CODE (etype) == INTEGER_TYPE && TREE_TYPE (etype)) @@ -4552,26 +4615,34 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) in order not to be deemed an useless type conversion, it must be from subtype to base type. + Therefore we first do the bulk of the conversion to a subtype of + the final type. And this conversion must itself not be deemed + useless if the source type is not a subtype because, otherwise, + the final VIEW_CONVERT_EXPR will be deemed so as well. That's + why we toggle the unsigned flag in this conversion, which is + harmless since the final conversion is only a reinterpretation + of the bit pattern. + ??? This may raise addressability and/or aliasing issues because VIEW_CONVERT_EXPR gets gimplified as an lvalue, thus causing the address of its operand to be taken if it is deemed addressable and not already in GIMPLE form. */ - rtype = gnat_type_for_mode (TYPE_MODE (type), TYPE_UNSIGNED (type)); + tree rtype + = gnat_type_for_mode (TYPE_MODE (type), !TYPE_UNSIGNED (etype)); rtype = copy_type (rtype); TYPE_MAIN_VARIANT (rtype) = rtype; TREE_TYPE (rtype) = type; - final_unchecked = true; + expr = convert (rtype, expr); + expr = build1 (VIEW_CONVERT_EXPR, type, expr); } - expr = convert (rtype, expr); - if (type != rtype) - expr = fold_build1 (final_unchecked ? VIEW_CONVERT_EXPR : NOP_EXPR, - type, expr); + else + expr = convert (type, expr); } - /* If we are converting TO an integral type whose precision is not the - same as its size, first unchecked convert to a record that contains - an object of the output type. Then extract the field. */ + /* If we are converting to an integral type whose precision is not equal + to its size, first unchecked convert to a record that contains an + object of the output type. Then extract the field. */ else if (INTEGRAL_TYPE_P (type) && TYPE_RM_SIZE (type) && 0 != compare_tree_int (TYPE_RM_SIZE (type), GET_MODE_BITSIZE (TYPE_MODE (type)))) @@ -4587,8 +4658,8 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) expr = build_component_ref (expr, NULL_TREE, field, 0); } - /* Similarly for integral input type whose precision is not equal to its - size. */ + /* Similarly if we are converting from an integral type whose precision + is not equal to its size. */ else if (INTEGRAL_TYPE_P (etype) && TYPE_RM_SIZE (etype) && 0 != compare_tree_int (TYPE_RM_SIZE (etype), GET_MODE_BITSIZE (TYPE_MODE (etype)))) @@ -4618,13 +4689,15 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) { expr = maybe_unconstrained_array (expr); etype = TREE_TYPE (expr); - expr = fold_build1 (VIEW_CONVERT_EXPR, type, expr); + if (can_fold_for_view_convert_p (expr)) + expr = fold_build1 (VIEW_CONVERT_EXPR, type, expr); + else + expr = build1 (VIEW_CONVERT_EXPR, type, expr); } - /* If the result is an integral type whose size is not equal to - the size of the underlying machine type, sign- or zero-extend - the result. We need not do this in the case where the input is - an integral type of the same precision and signedness or if the output + /* If the result is an integral type whose precision is not equal to its + size, sign- or zero-extend the result. We need not do this if the input + is an integral type of the same precision and signedness or if the output is a biased type or if both the input and output are unsigned. */ if (!notrunc_p && INTEGRAL_TYPE_P (type) && TYPE_RM_SIZE (type) diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c index 7f0dc8ce7d2..f098a84b19c 100644 --- a/gcc/alloc-pool.c +++ b/gcc/alloc-pool.c @@ -64,14 +64,25 @@ static ALLOC_POOL_ID_TYPE last_id; #ifdef GATHER_STATISTICS -/* Store information about each particular alloc_pool. */ +/* Store information about each particular alloc_pool. Note that this + will underestimate the amount the amount of storage used by a small amount: + 1) The overhead in a pool is not accounted for. + 2) The unallocated elements in a block are not accounted for. Note + that this can at worst case be one element smaller that the block + size for that pool. */ struct alloc_pool_descriptor { const char *name; - int allocated; - int created; - int peak; - int current; + /* Number of pools allocated. */ + unsigned long created; + /* Gross allocated storage. */ + unsigned long allocated; + /* Amount of currently active storage. */ + unsigned long current; + /* Peak amount of storage used. */ + unsigned long peak; + /* Size of element in the pool. */ + int elt_size; }; /* Hashtable mapping alloc_pool names to descriptors. */ @@ -150,6 +161,7 @@ create_alloc_pool (const char *name, size_t size, size_t num) pool->name = /*xstrdup (name)*/name; #ifdef GATHER_STATISTICS desc = alloc_pool_descriptor (name); + desc->elt_size = size; desc->created++; #endif pool->elt_size = size; @@ -196,11 +208,11 @@ empty_alloc_pool (alloc_pool pool) { next_block = block->next; free (block); -#ifdef GATHER_STATISTICS - desc->current -= pool->block_size; -#endif } +#ifdef GATHER_STATISTICS + desc->current -= (pool->elts_allocated - pool->elts_free) * pool->elt_size; +#endif pool->returned_free_list = NULL; pool->virgin_free_list = NULL; pool->virgin_elts_remaining = 0; @@ -242,7 +254,10 @@ pool_alloc (alloc_pool pool) #ifdef GATHER_STATISTICS struct alloc_pool_descriptor *desc = alloc_pool_descriptor (pool->name); - desc->allocated+=pool->elt_size; + desc->allocated += pool->elt_size; + desc->current += pool->elt_size; + if (desc->peak < desc->current) + desc->peak = desc->current; #endif gcc_assert (pool); @@ -259,11 +274,6 @@ pool_alloc (alloc_pool pool) block = XNEWVEC (char, pool->block_size); block_header = (alloc_pool_list) block; block += align_eight (sizeof (struct alloc_pool_list_def)); -#ifdef GATHER_STATISTICS - desc->current += pool->block_size; - if (desc->peak < desc->current) - desc->peak = desc->current; -#endif /* Throw it on the block list. */ block_header->next = pool->block_list; @@ -314,6 +324,9 @@ void pool_free (alloc_pool pool, void *ptr) { alloc_pool_list header; +#ifdef GATHER_STATISTICS + struct alloc_pool_descriptor *desc = alloc_pool_descriptor (pool->name); +#endif gcc_assert (ptr); @@ -334,6 +347,11 @@ pool_free (alloc_pool pool, void *ptr) header->next = pool->returned_free_list; pool->returned_free_list = header; pool->elts_free++; + +#ifdef GATHER_STATISTICS + desc->current -= pool->elt_size; +#endif + } /* Output per-alloc_pool statistics. */ #ifdef GATHER_STATISTICS @@ -341,8 +359,8 @@ pool_free (alloc_pool pool, void *ptr) /* Used to accumulate statistics about alloc_pool sizes. */ struct output_info { - int count; - int size; + unsigned long total_created; + unsigned long total_allocated; }; /* Called via htab_traverse. Output alloc_pool descriptor pointed out by SLOT @@ -355,10 +373,12 @@ print_statistics (void **slot, void *b) if (d->allocated) { - fprintf (stderr, "%-21s %6d %10d %10d %10d\n", d->name, - d->created, d->allocated, d->peak, d->current); - i->size += d->allocated; - i->count += d->created; + fprintf (stderr, "%-22s %6d %10lu %10lu(%10lu) %10lu(%10lu) %10lu(%10lu)\n", d->name, + d->elt_size, d->created, d->allocated, d->allocated / d->elt_size, + d->peak, d->peak / d->elt_size, + d->current, d->current / d->elt_size); + i->total_allocated += d->allocated; + i->total_created += d->created; } return 1; } @@ -374,14 +394,14 @@ dump_alloc_pool_statistics (void) if (!alloc_pool_hash) return; - fprintf (stderr, "\nAlloc-pool Kind Pools Allocated Peak Leak\n"); - fprintf (stderr, "-------------------------------------------------------------\n"); - info.count = 0; - info.size = 0; + fprintf (stderr, "\nAlloc-pool Kind Elt size Pools Allocated (elts) Peak (elts) Leak (elts)\n"); + fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n"); + info.total_created = 0; + info.total_allocated = 0; htab_traverse (alloc_pool_hash, print_statistics, &info); - fprintf (stderr, "-------------------------------------------------------------\n"); - fprintf (stderr, "%-20s %7d %10d\n", - "Total", info.count, info.size); - fprintf (stderr, "-------------------------------------------------------------\n"); + fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n"); + fprintf (stderr, "%-22s %7lu %10lu\n", + "Total", info.total_created, info.total_allocated); + fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n"); #endif } diff --git a/gcc/basic-block.h b/gcc/basic-block.h index d848357b1d1..e84ed88a8e1 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -129,7 +129,8 @@ struct edge_def GTY(()) /* Auxiliary info specific to a pass. */ PTR GTY ((skip (""))) aux; - /* Location of any goto implicit in the edge, during tree-ssa. */ + /* Location of any goto implicit in the edge and associated BLOCK. */ + tree goto_block; location_t goto_locus; /* The index number corresponding to this edge in the edge vector diff --git a/gcc/c-common.c b/gcc/c-common.c index 57bd0bb5ca9..61d80fd82bc 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -3423,7 +3423,7 @@ c_common_truthvalue_conversion (location_t location, tree expr) : truthvalue_false_node; case FUNCTION_DECL: - expr = build_unary_op (ADDR_EXPR, expr, 0); + expr = build_unary_op (location, ADDR_EXPR, expr, 0); /* Fall through. */ case ADDR_EXPR: @@ -3526,10 +3526,12 @@ c_common_truthvalue_conversion (location_t location, tree expr) (EXPR_LOCATION (expr), (TREE_SIDE_EFFECTS (expr) ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), - c_common_truthvalue_conversion (location, - build_unary_op (REALPART_EXPR, t, 0)), - c_common_truthvalue_conversion (location, - build_unary_op (IMAGPART_EXPR, t, 0)), + c_common_truthvalue_conversion + (location, + build_unary_op (location, REALPART_EXPR, t, 0)), + c_common_truthvalue_conversion + (location, + build_unary_op (location, IMAGPART_EXPR, t, 0)), 0)); } @@ -8219,10 +8221,11 @@ warn_for_unused_label (tree label) struct gcc_targetcm targetcm = TARGETCM_INITIALIZER; #endif -/* Warn for division by zero according to the value of DIVISOR. */ +/* Warn for division by zero according to the value of DIVISOR. LOC + is the location of the division operator. */ void -warn_for_div_by_zero (tree divisor) +warn_for_div_by_zero (location_t loc, tree divisor) { /* If DIVISOR is zero, and has integral or fixed-point type, issue a warning about division by zero. Do not issue a warning if DIVISOR has a @@ -8230,7 +8233,7 @@ warn_for_div_by_zero (tree divisor) generating a NaN. */ if (skip_evaluation == 0 && (integer_zerop (divisor) || fixed_zerop (divisor))) - warning (OPT_Wdiv_by_zero, "division by zero"); + warning_at (loc, OPT_Wdiv_by_zero, "division by zero"); } /* Subroutine of build_binary_op. Give warnings for comparisons diff --git a/gcc/c-common.h b/gcc/c-common.h index 622100a40cf..cd4eb3138b7 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -356,8 +356,8 @@ extern tree add_stmt (tree); extern void push_cleanup (tree, tree, bool); extern tree pushdecl_top_level (tree); extern tree pushdecl (tree); -extern tree build_modify_expr (tree, enum tree_code, tree); -extern tree build_indirect_ref (tree, const char *, location_t); +extern tree build_modify_expr (location_t, tree, enum tree_code, tree); +extern tree build_indirect_ref (location_t, tree, const char *); extern int c_expand_decl (tree); @@ -815,7 +815,7 @@ extern tree build_case_label (tree, tree, tree); /* These functions must be defined by each front-end which implements a variant of the C language. They are used in c-common.c. */ -extern tree build_unary_op (enum tree_code, tree, int); +extern tree build_unary_op (location_t, enum tree_code, tree, int); extern tree build_binary_op (location_t, enum tree_code, tree, tree, int); extern tree perform_integral_promotions (tree); @@ -915,7 +915,7 @@ extern void warn_array_subscript_with_type_char (tree); extern void warn_about_parentheses (enum tree_code, enum tree_code, enum tree_code); extern void warn_for_unused_label (tree label); -extern void warn_for_div_by_zero (tree divisor); +extern void warn_for_div_by_zero (location_t, tree divisor); extern void warn_for_sign_compare (location_t, tree orig_op0, tree orig_op1, tree op0, tree op1, diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 70265557269..2a6dcf2361c 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -3650,7 +3650,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree) tree cleanup; /* Build "cleanup(&decl)" for the destructor. */ - cleanup = build_unary_op (ADDR_EXPR, decl, 0); + cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0); cleanup = build_tree_list (NULL_TREE, cleanup); cleanup = build_function_call (cleanup_decl, cleanup); diff --git a/gcc/c-omp.c b/gcc/c-omp.c index 6d9d5fa3810..b06c83039b9 100644 --- a/gcc/c-omp.c +++ b/gcc/c-omp.c @@ -124,7 +124,7 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs) /* Take and save the address of the lhs. From then on we'll reference it via indirection. */ - addr = build_unary_op (ADDR_EXPR, lhs, 0); + addr = build_unary_op (input_location, ADDR_EXPR, lhs, 0); if (addr == error_mark_node) return error_mark_node; addr = save_expr (addr); @@ -137,12 +137,12 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs) tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL); addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL); } - lhs = build_indirect_ref (addr, NULL, EXPR_LOCATION (addr)); + lhs = build_indirect_ref (input_location, addr, NULL); /* There are lots of warnings, errors, and conversions that need to happen in the course of interpreting a statement. Use the normal mechanisms to do this, and then take it apart again. */ - x = build_modify_expr (lhs, code, rhs); + x = build_modify_expr (input_location, lhs, code, rhs); if (x == error_mark_node) return error_mark_node; gcc_assert (TREE_CODE (x) == MODIFY_EXPR); @@ -242,7 +242,7 @@ c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv, if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)) && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE) { - error ("%Hinvalid type for iteration variable %qE", &elocus, decl); + error_at (elocus, "invalid type for iteration variable %qE", decl); fail = true; } @@ -255,20 +255,19 @@ c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv, init = DECL_INITIAL (decl); if (init == NULL) { - error ("%H%qE is not initialized", &elocus, decl); + error_at (elocus, "%qE is not initialized", decl); init = integer_zero_node; fail = true; } - init = build_modify_expr (decl, NOP_EXPR, init); - SET_EXPR_LOCATION (init, elocus); + init = build_modify_expr (elocus, decl, NOP_EXPR, init); } gcc_assert (TREE_CODE (init) == MODIFY_EXPR); gcc_assert (TREE_OPERAND (init, 0) == decl); if (cond == NULL_TREE) { - error ("%Hmissing controlling predicate", &elocus); + error_at (elocus, "missing controlling predicate"); fail = true; } else @@ -329,14 +328,14 @@ c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv, if (!cond_ok) { - error ("%Hinvalid controlling predicate", &elocus); + error_at (elocus, "invalid controlling predicate"); fail = true; } } if (incr == NULL_TREE) { - error ("%Hmissing increment expression", &elocus); + error_at (elocus, "missing increment expression"); fail = true; } else @@ -402,7 +401,7 @@ c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv, } if (!incr_ok) { - error ("%Hinvalid increment expression", &elocus); + error_at (elocus, "invalid increment expression"); fail = true; } } diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 9597660915d..f08b2813010 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -2098,8 +2098,7 @@ c_parser_typeof_specifier (c_parser *parser) if (DECL_P (e) || CONSTANT_CLASS_P (e)) e = build1 (NOP_EXPR, void_type_node, e); - if (CAN_HAVE_LOCATION_P (e)) - SET_EXPR_LOCATION (e, here); + protected_set_expr_location (e, here); add_stmt (e); } @@ -3789,8 +3788,7 @@ c_parser_statement_after_labels (c_parser *parser) (recursively) all of the component statements should already have line numbers assigned. ??? Can we discard no-op statements earlier? */ - if (stmt && CAN_HAVE_LOCATION_P (stmt)) - SET_EXPR_LOCATION (stmt, loc); + protected_set_expr_location (stmt, loc); parser->in_if_block = in_if_block; } @@ -3805,8 +3803,7 @@ c_parser_condition (c_parser *parser) loc = c_parser_peek_token (parser)->location; cond = c_objc_common_truthvalue_conversion (loc, c_parser_expression_conv (parser).value); - if (CAN_HAVE_LOCATION_P (cond)) - SET_EXPR_LOCATION (cond, loc); + protected_set_expr_location (cond, loc); if (warn_sequence_point) verify_sequence_points (cond); return cond; @@ -4361,8 +4358,10 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after) { struct c_expr lhs, rhs, ret; enum tree_code code; + location_t op_location; gcc_assert (!after || c_dialect_objc ()); lhs = c_parser_conditional_expression (parser, after); + op_location = c_parser_peek_token (parser)->location; switch (c_parser_peek_token (parser)->type) { case CPP_EQ: @@ -4404,7 +4403,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after) c_parser_consume_token (parser); rhs = c_parser_expr_no_commas (parser, NULL); rhs = default_function_array_conversion (rhs); - ret.value = build_modify_expr (lhs.value, code, rhs.value); + ret.value = build_modify_expr (op_location, lhs.value, code, rhs.value); if (code == NOP_EXPR) ret.original_code = MODIFY_EXPR; else @@ -4439,6 +4438,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after) cond_loc = c_parser_peek_token (parser)->location; cond = c_parser_binary_expression (parser, after); + protected_set_expr_location (cond.value, cond_loc); if (c_parser_next_token_is_not (parser, CPP_QUERY)) return cond; @@ -4836,7 +4836,7 @@ c_parser_unary_expression (c_parser *parser) c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); op = default_function_array_conversion (op); - ret.value = build_indirect_ref (op.value, "unary *", loc); + ret.value = build_indirect_ref (loc, op.value, "unary *"); ret.original_code = ERROR_MARK; return ret; case CPP_PLUS: @@ -5594,8 +5594,9 @@ c_parser_postfix_expression_after_primary (c_parser *parser, return expr; } c_parser_consume_token (parser); - expr.value = build_component_ref (build_indirect_ref (expr.value, - "->", loc), + expr.value = build_component_ref (build_indirect_ref (loc, + expr.value, + "->"), ident); expr.original_code = ERROR_MARK; break; @@ -5603,14 +5604,16 @@ c_parser_postfix_expression_after_primary (c_parser *parser, /* Postincrement. */ c_parser_consume_token (parser); expr = default_function_array_conversion (expr); - expr.value = build_unary_op (POSTINCREMENT_EXPR, expr.value, 0); + expr.value = build_unary_op (loc, + POSTINCREMENT_EXPR, expr.value, 0); expr.original_code = ERROR_MARK; break; case CPP_MINUS_MINUS: /* Postdecrement. */ c_parser_consume_token (parser); expr = default_function_array_conversion (expr); - expr.value = build_unary_op (POSTDECREMENT_EXPR, expr.value, 0); + expr.value = build_unary_op (loc, + POSTDECREMENT_EXPR, expr.value, 0); expr.original_code = ERROR_MARK; break; default: @@ -7594,14 +7597,17 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) && c_parser_peek_2nd_token (parser)->type == CPP_EQ) { struct c_expr init_exp; + location_t init_loc; decl = c_parser_postfix_expression (parser).value; c_parser_require (parser, CPP_EQ, "expected %<=%>"); + init_loc = c_parser_peek_token (parser)->location; init_exp = c_parser_expr_no_commas (parser, NULL); init_exp = default_function_array_conversion (init_exp); - init = build_modify_expr (decl, NOP_EXPR, init_exp.value); + init = build_modify_expr (init_loc, + decl, NOP_EXPR, init_exp.value); init = c_process_expr_stmt (init); c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); @@ -7625,15 +7631,19 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) cond = c_parser_expression_conv (parser).value; cond = c_objc_common_truthvalue_conversion (cond_loc, cond); - if (CAN_HAVE_LOCATION_P (cond)) - SET_EXPR_LOCATION (cond, cond_loc); + protected_set_expr_location (cond, cond_loc); } c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); /* Parse the increment expression. */ incr = NULL_TREE; if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) - incr = c_process_expr_stmt (c_parser_expression (parser).value); + { + location_t incr_loc = c_parser_peek_token (parser)->location; + + incr = c_process_expr_stmt (c_parser_expression (parser).value); + protected_set_expr_location (incr, incr_loc); + } c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); if (decl == NULL || decl == error_mark_node || init == error_mark_node) diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index c6474ed5da1..ab8df375448 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1618,7 +1618,7 @@ array_to_pointer_conversion (tree exp) /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ - adr = build_unary_op (ADDR_EXPR, exp, 1); + adr = build_unary_op (EXPR_LOCATION (exp), ADDR_EXPR, exp, 1); return convert (ptrtype, adr); } @@ -1635,7 +1635,7 @@ function_to_pointer_conversion (tree exp) if (TREE_NO_WARNING (orig_exp)) TREE_NO_WARNING (exp) = 1; - return build_unary_op (ADDR_EXPR, exp, 0); + return build_unary_op (EXPR_LOCATION (exp), ADDR_EXPR, exp, 0); } /* Perform the default conversion of arrays and functions to pointers. @@ -1972,7 +1972,7 @@ build_component_ref (tree datum, tree component) LOC is the location to use for the generated tree. */ tree -build_indirect_ref (tree ptr, const char *errorstring, location_t loc) +build_indirect_ref (location_t loc, tree ptr, const char *errorstring) { tree pointer = default_conversion (ptr); tree type = TREE_TYPE (pointer); @@ -2008,11 +2008,11 @@ build_indirect_ref (tree ptr, const char *errorstring, location_t loc) if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE) { - error ("dereferencing pointer to incomplete type"); + error_at (loc, "dereferencing pointer to incomplete type"); return error_mark_node; } if (VOID_TYPE_P (t) && skip_evaluation == 0) - warning (0, "dereferencing %<void *%> pointer"); + warning_at (loc, 0, "dereferencing %<void *%> pointer"); /* We *must* set TREE_READONLY when dereferencing a pointer to const, so that we get the proper error message if the result is used @@ -2030,7 +2030,8 @@ build_indirect_ref (tree ptr, const char *errorstring, location_t loc) } } else if (TREE_CODE (pointer) != ERROR_MARK) - error ("invalid type argument of %qs (have %qT)", errorstring, type); + error_at (loc, + "invalid type argument of %qs (have %qT)", errorstring, type); return error_mark_node; } @@ -2164,8 +2165,8 @@ build_array_ref (tree array, tree index, location_t loc) gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE); return build_indirect_ref - (build_binary_op (loc, PLUS_EXPR, ar, index, 0), - "array indexing", loc); + (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0), + "array indexing"); } } @@ -2748,8 +2749,7 @@ parser_build_unary_op (enum tree_code code, struct c_expr arg, location_t loc) struct c_expr result; result.original_code = ERROR_MARK; - result.value = build_unary_op (code, arg.value, 0); - protected_set_expr_location (result.value, loc); + result.value = build_unary_op (loc, code, arg.value, 0); if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value)) overflow_warning (result.value); @@ -2901,16 +2901,20 @@ pointer_diff (tree op0, tree op1) the default promotions (such as from short to int). For ADDR_EXPR, the default promotions are not applied; FLAG nonzero allows non-lvalues; this is only used to handle conversion of non-lvalue - arrays to pointers in C99. */ + arrays to pointers in C99. + + LOCATION is the location of the operator. */ tree -build_unary_op (enum tree_code code, tree xarg, int flag) +build_unary_op (location_t location, + enum tree_code code, tree xarg, int flag) { /* No default_conversion here. It causes trouble for ADDR_EXPR. */ tree arg = xarg; tree argtype = 0; enum tree_code typecode; tree val; + tree ret = error_mark_node; int noconvert = flag; const char *invalid_op_diag; @@ -2926,7 +2930,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if ((invalid_op_diag = targetm.invalid_unary_op (code, TREE_TYPE (xarg)))) { - error (invalid_op_diag); + error_at (location, invalid_op_diag); return error_mark_node; } @@ -2940,7 +2944,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE || typecode == VECTOR_TYPE)) { - error ("wrong type argument to unary plus"); + error_at (location, "wrong type argument to unary plus"); return error_mark_node; } else if (!noconvert) @@ -2953,7 +2957,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE || typecode == VECTOR_TYPE)) { - error ("wrong type argument to unary minus"); + error_at (location, "wrong type argument to unary minus"); return error_mark_node; } else if (!noconvert) @@ -2972,14 +2976,14 @@ build_unary_op (enum tree_code code, tree xarg, int flag) else if (typecode == COMPLEX_TYPE) { code = CONJ_EXPR; - pedwarn (input_location, OPT_pedantic, + pedwarn (location, OPT_pedantic, "ISO C does not support %<~%> for complex conjugation"); if (!noconvert) arg = default_conversion (arg); } else { - error ("wrong type argument to bit-complement"); + error_at (location, "wrong type argument to bit-complement"); return error_mark_node; } break; @@ -2987,7 +2991,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) case ABS_EXPR: if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE)) { - error ("wrong type argument to abs"); + error_at (location, "wrong type argument to abs"); return error_mark_node; } else if (!noconvert) @@ -2999,7 +3003,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE || typecode == COMPLEX_TYPE)) { - error ("wrong type argument to conjugation"); + error_at (location, "wrong type argument to conjugation"); return error_mark_node; } else if (!noconvert) @@ -3011,27 +3015,31 @@ build_unary_op (enum tree_code code, tree xarg, int flag) && typecode != REAL_TYPE && typecode != POINTER_TYPE && typecode != COMPLEX_TYPE) { - error ("wrong type argument to unary exclamation mark"); + error_at (location, + "wrong type argument to unary exclamation mark"); return error_mark_node; } - arg = c_objc_common_truthvalue_conversion (input_location, arg); - return invert_truthvalue (arg); + arg = c_objc_common_truthvalue_conversion (location, arg); + ret = invert_truthvalue (arg); + goto return_build_unary_op; case REALPART_EXPR: if (TREE_CODE (arg) == COMPLEX_CST) - return TREE_REALPART (arg); + ret = TREE_REALPART (arg); else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - return fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); + ret = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); else - return arg; + ret = arg; + goto return_build_unary_op; case IMAGPART_EXPR: if (TREE_CODE (arg) == COMPLEX_CST) - return TREE_IMAGPART (arg); + ret = TREE_IMAGPART (arg); else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - return fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); + ret = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); else - return convert (TREE_TYPE (arg), integer_zero_node); + ret = convert (TREE_TYPE (arg), integer_zero_node); + goto return_build_unary_op; case PREINCREMENT_EXPR: case POSTINCREMENT_EXPR: @@ -3044,17 +3052,18 @@ build_unary_op (enum tree_code code, tree xarg, int flag) { tree real, imag; - pedwarn (input_location, OPT_pedantic, + pedwarn (location, OPT_pedantic, "ISO C does not support %<++%> and %<--%> on complex types"); arg = stabilize_reference (arg); - real = build_unary_op (REALPART_EXPR, arg, 1); - imag = build_unary_op (IMAGPART_EXPR, arg, 1); - real = build_unary_op (code, real, 1); + real = build_unary_op (EXPR_LOCATION (arg), REALPART_EXPR, arg, 1); + imag = build_unary_op (EXPR_LOCATION (arg), IMAGPART_EXPR, arg, 1); + real = build_unary_op (EXPR_LOCATION (arg), code, real, 1); if (real == error_mark_node || imag == error_mark_node) return error_mark_node; - return build2 (COMPLEX_EXPR, TREE_TYPE (arg), - real, imag); + ret = build2 (COMPLEX_EXPR, TREE_TYPE (arg), + real, imag); + goto return_build_unary_op; } /* Report invalid types. */ @@ -3063,9 +3072,9 @@ build_unary_op (enum tree_code code, tree xarg, int flag) && typecode != INTEGER_TYPE && typecode != REAL_TYPE) { if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - error ("wrong type argument to increment"); + error_at (location, "wrong type argument to increment"); else - error ("wrong type argument to decrement"); + error_at (location, "wrong type argument to decrement"); return error_mark_node; } @@ -3086,18 +3095,20 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type))) { if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - error ("increment of pointer to unknown structure"); + error_at (location, + "increment of pointer to unknown structure"); else - error ("decrement of pointer to unknown structure"); + error_at (location, + "decrement of pointer to unknown structure"); } else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE) { if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, "wrong type argument to increment"); else - pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, "wrong type argument to decrement"); } @@ -3154,7 +3165,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag) val = convert (result_type, val); if (TREE_CODE (val) != code) TREE_NO_WARNING (val) = 1; - return val; + ret = val; + goto return_build_unary_op; } case ADDR_EXPR: @@ -3166,7 +3178,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag) /* Don't let this be an lvalue. */ if (lvalue_p (TREE_OPERAND (arg, 0))) return non_lvalue (TREE_OPERAND (arg, 0)); - return TREE_OPERAND (arg, 0); + ret = TREE_OPERAND (arg, 0); + goto return_build_unary_op; } /* For &x[y], return x+y */ @@ -3175,7 +3188,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) tree op0 = TREE_OPERAND (arg, 0); if (!c_mark_addressable (op0)) return error_mark_node; - return build_binary_op (EXPR_LOCATION (xarg), PLUS_EXPR, + return build_binary_op (location, PLUS_EXPR, (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE ? array_to_pointer_conversion (op0) : op0), @@ -3218,12 +3231,14 @@ build_unary_op (enum tree_code code, tree xarg, int flag) tree op0 = fold_convert (sizetype, fold_offsetof (arg, val)), op1; op1 = fold_convert (argtype, TREE_OPERAND (val, 0)); - return fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0); + ret = fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0); + goto return_build_unary_op; } val = build1 (ADDR_EXPR, argtype, arg); - return val; + ret = val; + goto return_build_unary_op; default: gcc_unreachable (); @@ -3231,8 +3246,12 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if (argtype == 0) argtype = TREE_TYPE (arg); - return require_constant_value ? fold_build1_initializer (code, argtype, arg) - : fold_build1 (code, argtype, arg); + ret = require_constant_value ? fold_build1_initializer (code, argtype, arg) + : fold_build1 (code, argtype, arg); + return_build_unary_op: + gcc_assert (ret != error_mark_node); + protected_set_expr_location (ret, location); + return ret; } /* Return nonzero if REF is an lvalue valid for this language. @@ -3837,10 +3856,13 @@ c_cast_expr (struct c_type_name *type_name, tree expr) /* Build an assignment expression of lvalue LHS from value RHS. MODIFYCODE is the code for a binary operator that we use to combine the old value of LHS with RHS to get the new value. - Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment. */ + Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment. + + LOCATION is the location of the MODIFYCODE operator. */ tree -build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) +build_modify_expr (location_t location, + tree lhs, enum tree_code modifycode, tree rhs) { tree result; tree newrhs; @@ -3867,7 +3889,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (modifycode != NOP_EXPR) { lhs = stabilize_reference (lhs); - newrhs = build_binary_op (EXPR_LOCATION (lhs), + newrhs = build_binary_op (location, modifycode, lhs, rhs, 1); } @@ -3915,13 +3937,17 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) { result = objc_generate_write_barrier (lhs, modifycode, newrhs); if (result) - return result; + { + protected_set_expr_location (result, location); + return result; + } } /* Scan operands. */ result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs); TREE_SIDE_EFFECTS (result) = 1; + protected_set_expr_location (result, location); /* If we got the LHS in a different type for storing in, convert the result back to the nominal type of LHS @@ -3930,8 +3956,11 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (olhstype == TREE_TYPE (result)) return result; - return convert_for_assignment (olhstype, result, ic_assign, - NULL_TREE, NULL_TREE, 0); + + result = convert_for_assignment (olhstype, result, ic_assign, + NULL_TREE, NULL_TREE, 0); + protected_set_expr_location (result, location); + return result; } /* Convert value RHS to type TYPE as preparation for an assignment @@ -7942,6 +7971,7 @@ build_binary_op (location_t location, enum tree_code code, tree type0, type1; enum tree_code code0, code1; tree op0, op1; + tree ret = error_mark_node; const char *invalid_op_diag; /* Expression code to give to the expression when it is built. @@ -8035,9 +8065,15 @@ build_binary_op (location_t location, enum tree_code code, case PLUS_EXPR: /* Handle the pointer + int case. */ if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) - return pointer_int_sum (PLUS_EXPR, op0, op1); + { + ret = pointer_int_sum (PLUS_EXPR, op0, op1); + goto return_build_binary_op; + } else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE) - return pointer_int_sum (PLUS_EXPR, op1, op0); + { + ret = pointer_int_sum (PLUS_EXPR, op1, op0); + goto return_build_binary_op; + } else common = 1; break; @@ -8047,10 +8083,16 @@ build_binary_op (location_t location, enum tree_code code, We must subtract them as integers, then divide by object size. */ if (code0 == POINTER_TYPE && code1 == POINTER_TYPE && comp_target_types (type0, type1)) - return pointer_diff (op0, op1); + { + ret = pointer_diff (op0, op1); + goto return_build_binary_op; + } /* Handle pointer minus int. Just like pointer plus int. */ else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) - return pointer_int_sum (MINUS_EXPR, op0, op1); + { + ret = pointer_int_sum (MINUS_EXPR, op0, op1); + goto return_build_binary_op; + } else common = 1; break; @@ -8064,7 +8106,7 @@ build_binary_op (location_t location, enum tree_code code, case FLOOR_DIV_EXPR: case ROUND_DIV_EXPR: case EXACT_DIV_EXPR: - warn_for_div_by_zero (op1); + warn_for_div_by_zero (location, op1); if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == FIXED_POINT_TYPE @@ -8111,7 +8153,7 @@ build_binary_op (location_t location, enum tree_code code, case TRUNC_MOD_EXPR: case FLOOR_MOD_EXPR: - warn_for_div_by_zero (op1); + warn_for_div_by_zero (location, op1); if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { @@ -8435,7 +8477,10 @@ build_binary_op (location_t location, enum tree_code code, = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode); if (val != 0) - return val; + { + ret = val; + goto return_build_binary_op; + } op0 = xop0, op1 = xop1; converted = 1; @@ -8477,18 +8522,19 @@ build_binary_op (location_t location, enum tree_code code, if (build_type == NULL_TREE) build_type = result_type; - { - /* Treat expressions in initializers specially as they can't trap. */ - tree result = require_constant_value ? fold_build2_initializer (resultcode, - build_type, - op0, op1) - : fold_build2 (resultcode, build_type, - op0, op1); - - if (final_type != 0) - result = convert (final_type, result); - return result; - } + /* Treat expressions in initializers specially as they can't trap. */ + ret = require_constant_value ? fold_build2_initializer (resultcode, + build_type, + op0, op1) + : fold_build2 (resultcode, build_type, + op0, op1); + if (final_type != 0) + ret = convert (final_type, ret); + + return_build_binary_op: + gcc_assert (ret != error_mark_node); + protected_set_expr_location (ret, location); + return ret; } diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index a778e28e386..8b9756def21 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -429,7 +429,7 @@ try_forward_edges (int mode, basic_block b) for (ei = ei_start (b->succs); (e = ei_safe_edge (ei)); ) { basic_block target, first; - int counter; + int counter, goto_locus; bool threaded = false; int nthreaded_edges = 0; bool may_thread = first_pass | df_get_bb_dirty (b); @@ -447,6 +447,7 @@ try_forward_edges (int mode, basic_block b) target = first = e->dest; counter = NUM_FIXED_BLOCKS; + goto_locus = e->goto_locus; /* If we are partitioning hot/cold basic_blocks, we don't want to mess up jumps that cross between hot/cold sections. @@ -476,6 +477,27 @@ try_forward_edges (int mode, basic_block b) new_target = single_succ (target); if (target == new_target) counter = n_basic_blocks; + else if (!optimize) + { + /* When not optimizing, ensure that edges or forwarder + blocks with different locus are not optimized out. */ + int locus = single_succ_edge (target)->goto_locus; + + if (locus && goto_locus && locus != goto_locus) + counter = n_basic_blocks; + else if (locus) + goto_locus = locus; + + if (INSN_P (BB_END (target))) + { + locus = INSN_LOCATOR (BB_END (target)); + + if (locus && goto_locus && locus != goto_locus) + counter = n_basic_blocks; + else if (locus) + goto_locus = locus; + } + } } /* Allow to thread only over one edge at time to simplify updating @@ -539,6 +561,8 @@ try_forward_edges (int mode, basic_block b) int edge_frequency; int n = 0; + e->goto_locus = goto_locus; + /* Don't force if target is exit block. */ if (threaded && target != EXIT_BLOCK_PTR) { diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 06111cc85df..e94fe356e1c 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1666,7 +1666,12 @@ expand_gimple_cond (basic_block bb, gimple stmt) add_reg_br_prob_note (last, true_edge->probability); maybe_dump_rtl_for_gimple_stmt (stmt, last); if (true_edge->goto_locus) - set_curr_insn_source_location (true_edge->goto_locus); + { + set_curr_insn_source_location (true_edge->goto_locus); + set_curr_insn_block (true_edge->goto_block); + true_edge->goto_locus = curr_insn_locator (); + } + true_edge->goto_block = NULL; false_edge->flags |= EDGE_FALLTHRU; ggc_free (pred); return NULL; @@ -1677,7 +1682,12 @@ expand_gimple_cond (basic_block bb, gimple stmt) add_reg_br_prob_note (last, false_edge->probability); maybe_dump_rtl_for_gimple_stmt (stmt, last); if (false_edge->goto_locus) - set_curr_insn_source_location (false_edge->goto_locus); + { + set_curr_insn_source_location (false_edge->goto_locus); + set_curr_insn_block (false_edge->goto_block); + false_edge->goto_locus = curr_insn_locator (); + } + false_edge->goto_block = NULL; true_edge->flags |= EDGE_FALLTHRU; ggc_free (pred); return NULL; @@ -1686,6 +1696,13 @@ expand_gimple_cond (basic_block bb, gimple stmt) jumpif (pred, label_rtx_for_bb (true_edge->dest)); add_reg_br_prob_note (last, true_edge->probability); last = get_last_insn (); + if (false_edge->goto_locus) + { + set_curr_insn_source_location (false_edge->goto_locus); + set_curr_insn_block (false_edge->goto_block); + false_edge->goto_locus = curr_insn_locator (); + } + false_edge->goto_block = NULL; emit_jump (label_rtx_for_bb (false_edge->dest)); BB_END (bb) = last; @@ -1708,9 +1725,6 @@ expand_gimple_cond (basic_block bb, gimple stmt) maybe_dump_rtl_for_gimple_stmt (stmt, last2); - if (false_edge->goto_locus) - set_curr_insn_source_location (false_edge->goto_locus); - ggc_free (pred); return new_bb; } @@ -1962,19 +1976,21 @@ expand_gimple_basic_block (basic_block bb) } } - /* Expand implicit goto. */ + /* Expand implicit goto and convert goto_locus. */ FOR_EACH_EDGE (e, ei, bb->succs) { - if (e->flags & EDGE_FALLTHRU) - break; - } - - if (e && e->dest != bb->next_bb) - { - emit_jump (label_rtx_for_bb (e->dest)); - if (e->goto_locus) - set_curr_insn_source_location (e->goto_locus); - e->flags &= ~EDGE_FALLTHRU; + if (e->goto_locus && e->goto_block) + { + set_curr_insn_source_location (e->goto_locus); + set_curr_insn_block (e->goto_block); + e->goto_locus = curr_insn_locator (); + } + e->goto_block = NULL; + if ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb) + { + emit_jump (label_rtx_for_bb (e->dest)); + e->flags &= ~EDGE_FALLTHRU; + } } do_pending_stack_adjust (); diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c index b4ca49f4324..be1188d0b61 100644 --- a/gcc/cfglayout.c +++ b/gcc/cfglayout.c @@ -887,6 +887,46 @@ fixup_reorder_chain (void) if (e && !can_fallthru (e->src, e->dest)) force_nonfallthru (e); } + + /* Ensure goto_locus from edges has some instructions with that locus + in RTL. */ + if (!optimize) + FOR_EACH_BB (bb) + { + edge e; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, bb->succs) + if (e->goto_locus && !(e->flags & EDGE_ABNORMAL)) + { + basic_block nb; + + if (simplejump_p (BB_END (e->src))) + { + if (INSN_LOCATOR (BB_END (e->src)) == (int) e->goto_locus) + continue; + if (INSN_LOCATOR (BB_END (e->src)) == 0) + { + INSN_LOCATOR (BB_END (e->src)) = e->goto_locus; + continue; + } + } + if (e->dest != EXIT_BLOCK_PTR) + { + insn = BB_HEAD (e->dest); + if (!INSN_P (insn)) + insn = next_insn (insn); + if (insn && INSN_P (insn) + && INSN_LOCATOR (insn) == (int) e->goto_locus) + continue; + } + nb = split_edge (e); + if (!INSN_P (BB_END (nb))) + BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb), + nb); + INSN_LOCATOR (BB_END (nb)) = e->goto_locus; + } + } } /* Perform sanity checks on the insn chain. diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index f9e3e17e1a7..24469ebf30d 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -1009,6 +1009,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target) rtx note; edge new_edge; int abnormal_edge_flags = 0; + int loc; /* In the case the last instruction is conditional jump to the next instruction, first redirect the jump itself and then continue @@ -1127,11 +1128,15 @@ force_nonfallthru_and_redirect (edge e, basic_block target) else jump_block = e->src; + if (e->goto_locus && e->goto_block == NULL) + loc = e->goto_locus; + else + loc = 0; e->flags &= ~EDGE_FALLTHRU; if (target == EXIT_BLOCK_PTR) { #ifdef HAVE_return - emit_jump_insn_after_noloc (gen_return (), BB_END (jump_block)); + emit_jump_insn_after_setloc (gen_return (), BB_END (jump_block), loc); #else gcc_unreachable (); #endif @@ -1139,7 +1144,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target) else { rtx label = block_label (target); - emit_jump_insn_after_noloc (gen_jump (label), BB_END (jump_block)); + emit_jump_insn_after_setloc (gen_jump (label), BB_END (jump_block), loc); JUMP_LABEL (BB_END (jump_block)) = label; LABEL_NUSES (label)++; } @@ -2606,6 +2611,32 @@ cfg_layout_merge_blocks (basic_block a, basic_block b) try_redirect_by_replacing_jump (EDGE_SUCC (a, 0), b, true); gcc_assert (!JUMP_P (BB_END (a))); + /* When not optimizing and the edge is the only place in RTL which holds + some unique locus, emit a nop with that locus in between. */ + if (!optimize && EDGE_SUCC (a, 0)->goto_locus) + { + rtx insn = BB_END (a); + int goto_locus = EDGE_SUCC (a, 0)->goto_locus; + + if (NOTE_P (insn)) + insn = prev_nonnote_insn (insn); + if (insn && INSN_P (insn) && INSN_LOCATOR (insn) == goto_locus) + goto_locus = 0; + else + { + insn = BB_HEAD (b); + if (!INSN_P (insn)) + insn = next_insn (insn); + if (insn && INSN_P (insn) && INSN_LOCATOR (insn) == goto_locus) + goto_locus = 0; + } + if (goto_locus) + { + BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a); + INSN_LOCATOR (BB_END (a)) = goto_locus; + } + } + /* Possible line number notes should appear in between. */ if (b->il.rtl->header) { diff --git a/gcc/config.gcc b/gcc/config.gcc index e3d170aad95..37afa852abb 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2656,7 +2656,7 @@ case "${target}" in case "$with_abi" in "" \ - | apcs-gnu | atpcs | aapcs | iwmmxt ) + | apcs-gnu | atpcs | aapcs | iwmmxt | aapcs-linux ) #OK ;; *) diff --git a/gcc/config/darwin-protos.h b/gcc/config/darwin-protos.h index c894bf05104..5fe55965fd1 100644 --- a/gcc/config/darwin-protos.h +++ b/gcc/config/darwin-protos.h @@ -22,14 +22,13 @@ extern int name_needs_quotes (const char *); extern void machopic_validate_stub_or_non_lazy_ptr (const char *); -extern const char *machopic_function_base_name (void); extern void machopic_output_function_base_name (FILE *); extern const char *machopic_indirection_name (rtx, bool); extern const char *machopic_mcount_stub_name (void); #ifdef RTX_CODE -extern rtx machopic_function_base_sym (void); +extern rtx machopic_gen_offset (rtx); extern int machopic_operand_p (rtx); extern enum machopic_addr_class machopic_classify_symbol (rtx); diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index fe332738c54..3a4fc99c5b3 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -267,44 +267,26 @@ machopic_define_symbol (rtx mem) SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED; } -static GTY(()) const char * function_base; +/* Return either ORIG or: -const char * -machopic_function_base_name (void) -{ - /* if dynamic-no-pic is on, we should not get here */ - gcc_assert (!MACHO_DYNAMIC_NO_PIC_P); - - if (function_base == NULL) - function_base = ggc_alloc_string ("<pic base>", sizeof ("<pic base>")); - - crtl->uses_pic_offset_table = 1; - - return function_base; -} - -/* Return a SYMBOL_REF for the PIC function base. */ + (const:P (unspec:P [ORIG] UNSPEC_MACHOPIC_OFFSET)) + depending on MACHO_DYNAMIC_NO_PIC_P. */ rtx -machopic_function_base_sym (void) +machopic_gen_offset (rtx orig) { - rtx sym_ref; - - sym_ref = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ()); - SYMBOL_REF_FLAGS (sym_ref) - |= (MACHO_SYMBOL_FLAG_VARIABLE | MACHO_SYMBOL_FLAG_DEFINED); - return sym_ref; -} - -/* Return either ORIG or (const:P (minus:P ORIG PIC_BASE)), depending - on whether pic_base is NULL or not. */ -static inline rtx -gen_pic_offset (rtx orig, rtx pic_base) -{ - if (!pic_base) + if (MACHO_DYNAMIC_NO_PIC_P) return orig; else - return gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, orig, pic_base)); + { + /* Play games to avoid marking the function as needing pic if we + are being called as part of the cost-estimation process. */ + if (current_ir_type () != IR_GIMPLE) + crtl->uses_pic_offset_table = 1; + orig = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), + UNSPEC_MACHOPIC_OFFSET); + return gen_rtx_CONST (Pmode, orig); + } } static GTY(()) const char * function_base_func_name; @@ -528,8 +510,7 @@ machopic_indirect_data_reference (rtx orig, rtx reg) else if (defined) { #if defined (TARGET_TOC) || defined (HAVE_lo_sum) - rtx pic_base = machopic_function_base_sym (); - rtx offset = gen_pic_offset (orig, pic_base); + rtx offset = machopic_gen_offset (orig); #endif #if defined (TARGET_TOC) /* i.e., PowerPC */ @@ -675,8 +656,6 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) )) { /* addr(foo) = &func+(foo-func) */ - rtx pic_base; - orig = machopic_indirect_data_reference (orig, reg); if (GET_CODE (orig) == PLUS @@ -689,12 +668,6 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) return reg; } - /* if dynamic-no-pic we don't have a pic base */ - if (MACHO_DYNAMIC_NO_PIC_P) - pic_base = NULL; - else - pic_base = machopic_function_base_sym (); - if (GET_CODE (orig) == MEM) { if (reg == 0) @@ -731,7 +704,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF || GET_CODE (XEXP (orig, 0)) == LABEL_REF) { - rtx offset = gen_pic_offset (XEXP (orig, 0), pic_base); + rtx offset = machopic_gen_offset (XEXP (orig, 0)); #if defined (TARGET_TOC) /* i.e., PowerPC */ /* Generating a new reg may expose opportunities for common subexpression elimination. */ @@ -787,8 +760,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) if (reload_in_progress) df_set_regs_ever_live (REGNO (pic), true); pic_ref = gen_rtx_PLUS (Pmode, pic, - gen_pic_offset (XEXP (orig, 0), - pic_base)); + machopic_gen_offset (XEXP (orig, 0))); } #if !defined (TARGET_TOC) @@ -803,7 +775,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF) { - rtx offset = gen_pic_offset (orig, pic_base); + rtx offset = machopic_gen_offset (orig); #if defined (TARGET_TOC) /* i.e., PowerPC */ rtx hi_sum_reg; @@ -860,7 +832,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) df_set_regs_ever_live (REGNO (pic), true); pic_ref = gen_rtx_PLUS (Pmode, pic, - gen_pic_offset (orig, pic_base)); + machopic_gen_offset (orig)); } } } @@ -1064,27 +1036,12 @@ int machopic_operand_p (rtx op) { if (MACHOPIC_JUST_INDIRECT) - { - while (GET_CODE (op) == CONST) - op = XEXP (op, 0); - - if (GET_CODE (op) == SYMBOL_REF) - return machopic_symbol_defined_p (op); - else - return 0; - } - - while (GET_CODE (op) == CONST) - op = XEXP (op, 0); - - if (GET_CODE (op) == MINUS - && GET_CODE (XEXP (op, 0)) == SYMBOL_REF - && GET_CODE (XEXP (op, 1)) == SYMBOL_REF - && machopic_symbol_defined_p (XEXP (op, 0)) - && machopic_symbol_defined_p (XEXP (op, 1))) - return 1; - - return 0; + return (GET_CODE (op) == SYMBOL_REF + && machopic_symbol_defined_p (op)); + else + return (GET_CODE (op) == CONST + && GET_CODE (XEXP (op, 0)) == UNSPEC + && XINT (XEXP (op, 0), 1) == UNSPEC_MACHOPIC_OFFSET); } /* This function records whether a given name corresponds to a defined diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index c2685a893f6..03955c64d0a 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -525,6 +525,9 @@ extern GTY(()) int darwin_ms_struct; #define USER_LABEL_PREFIX "_" +/* A dummy symbol that will be replaced with the function base name. */ +#define MACHOPIC_FUNCTION_BASE_NAME "<pic base>" + /* Don't output a .file directive. That is only used by the assembler for error reporting. */ #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE @@ -609,7 +612,7 @@ extern GTY(()) int darwin_ms_struct; #define ASM_OUTPUT_LABELREF(FILE,NAME) \ do { \ const char *xname = (NAME); \ - if (! strcmp (xname, "<pic base>")) \ + if (! strcmp (xname, MACHOPIC_FUNCTION_BASE_NAME)) \ machopic_output_function_base_name(FILE); \ else if (xname[0] == '&' || xname[0] == '*') \ { \ diff --git a/gcc/config/i386/darwin.h b/gcc/config/i386/darwin.h index a1defcf9bc6..e2b6025b2c0 100644 --- a/gcc/config/i386/darwin.h +++ b/gcc/config/i386/darwin.h @@ -176,7 +176,7 @@ extern void darwin_x86_file_end (void); #define TARGET_DYNAMIC_NO_PIC (target_flags & MASK_MACHO_DYNAMIC_NO_PIC) #undef GOT_SYMBOL_NAME -#define GOT_SYMBOL_NAME (machopic_function_base_name ()) +#define GOT_SYMBOL_NAME MACHOPIC_FUNCTION_BASE_NAME /* Define the syntax of pseudo-ops, labels and comments. */ diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index de024581e80..1abd11dead7 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -272,3 +272,7 @@ extern enum rtx_code ix86_fp_compare_code_to_integer (enum rtx_code); extern rtx construct_plt_address (rtx); #endif extern int asm_preferred_eh_data_format (int, int); + +#ifdef HAVE_ATTR_cpu +extern enum attr_cpu ix86_schedule; +#endif diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 86be390a139..be371173fa2 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1229,9 +1229,6 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = { /* X86_TUNE_ZERO_EXTEND_WITH_AND */ m_486 | m_PENT, - /* X86_TUNE_USE_BIT_TEST */ - m_386, - /* X86_TUNE_UNROLL_STRLEN */ m_486 | m_PENT | m_PPRO | m_AMD_MULTIPLE | m_K6 | m_CORE2 | m_GENERIC, @@ -1693,6 +1690,9 @@ enum tls_dialect ix86_tls_dialect = TLS_DIALECT_GNU; enum fpmath_unit ix86_fpmath; /* Which cpu are we scheduling for. */ +enum attr_cpu ix86_schedule; + +/* Which cpu are we optimizing for. */ enum processor_type ix86_tune; /* Which instruction set architecture to use. */ @@ -2490,93 +2490,89 @@ override_options (bool main_args_p) { const char *const name; /* processor name or nickname. */ const enum processor_type processor; + const enum attr_cpu schedule; const unsigned /*enum pta_flags*/ flags; } const processor_alias_table[] = { - {"i386", PROCESSOR_I386, 0}, - {"i486", PROCESSOR_I486, 0}, - {"i586", PROCESSOR_PENTIUM, 0}, - {"pentium", PROCESSOR_PENTIUM, 0}, - {"pentium-mmx", PROCESSOR_PENTIUM, PTA_MMX}, - {"winchip-c6", PROCESSOR_I486, PTA_MMX}, - {"winchip2", PROCESSOR_I486, PTA_MMX | PTA_3DNOW}, - {"c3", PROCESSOR_I486, PTA_MMX | PTA_3DNOW}, - {"c3-2", PROCESSOR_PENTIUMPRO, PTA_MMX | PTA_SSE}, - {"i686", PROCESSOR_PENTIUMPRO, 0}, - {"pentiumpro", PROCESSOR_PENTIUMPRO, 0}, - {"pentium2", PROCESSOR_PENTIUMPRO, PTA_MMX}, - {"pentium3", PROCESSOR_PENTIUMPRO, PTA_MMX | PTA_SSE}, - {"pentium3m", PROCESSOR_PENTIUMPRO, PTA_MMX | PTA_SSE}, - {"pentium-m", PROCESSOR_PENTIUMPRO, PTA_MMX | PTA_SSE | PTA_SSE2}, - {"pentium4", PROCESSOR_PENTIUM4, PTA_MMX |PTA_SSE | PTA_SSE2}, - {"pentium4m", PROCESSOR_PENTIUM4, PTA_MMX | PTA_SSE | PTA_SSE2}, - {"prescott", PROCESSOR_NOCONA, PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3}, - {"nocona", PROCESSOR_NOCONA, (PTA_64BIT - | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_CX16 | PTA_NO_SAHF)}, - {"core2", PROCESSOR_CORE2, (PTA_64BIT - | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_SSSE3 - | PTA_CX16)}, - {"geode", PROCESSOR_GEODE, (PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - |PTA_PREFETCH_SSE)}, - {"k6", PROCESSOR_K6, PTA_MMX}, - {"k6-2", PROCESSOR_K6, PTA_MMX | PTA_3DNOW}, - {"k6-3", PROCESSOR_K6, PTA_MMX | PTA_3DNOW}, - {"athlon", PROCESSOR_ATHLON, (PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_PREFETCH_SSE)}, - {"athlon-tbird", PROCESSOR_ATHLON, (PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_PREFETCH_SSE)}, - {"athlon-4", PROCESSOR_ATHLON, (PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_SSE)}, - {"athlon-xp", PROCESSOR_ATHLON, (PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_SSE)}, - {"athlon-mp", PROCESSOR_ATHLON, (PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_SSE)}, - {"x86-64", PROCESSOR_K8, (PTA_64BIT - | PTA_MMX | PTA_SSE | PTA_SSE2 - | PTA_NO_SAHF)}, - {"k8", PROCESSOR_K8, (PTA_64BIT - | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_SSE | PTA_SSE2 - | PTA_NO_SAHF)}, - {"k8-sse3", PROCESSOR_K8, (PTA_64BIT - | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_NO_SAHF)}, - {"opteron", PROCESSOR_K8, (PTA_64BIT - | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_SSE | PTA_SSE2 - | PTA_NO_SAHF)}, - {"opteron-sse3", PROCESSOR_K8, (PTA_64BIT - | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_NO_SAHF)}, - {"athlon64", PROCESSOR_K8, (PTA_64BIT - | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_SSE | PTA_SSE2 - | PTA_NO_SAHF)}, - {"athlon64-sse3", PROCESSOR_K8, (PTA_64BIT - | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_NO_SAHF)}, - {"athlon-fx", PROCESSOR_K8, (PTA_64BIT - | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_SSE | PTA_SSE2 - | PTA_NO_SAHF)}, - {"amdfam10", PROCESSOR_AMDFAM10, (PTA_64BIT - | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_SSE4A - | PTA_CX16 | PTA_ABM)}, - {"barcelona", PROCESSOR_AMDFAM10, (PTA_64BIT - | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A - | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_SSE4A - | PTA_CX16 | PTA_ABM)}, - {"generic32", PROCESSOR_GENERIC32, 0 /* flags are only used for -march switch. */ }, - {"generic64", PROCESSOR_GENERIC64, PTA_64BIT /* flags are only used for -march switch. */ }, + {"i386", PROCESSOR_I386, CPU_NONE, 0}, + {"i486", PROCESSOR_I486, CPU_NONE, 0}, + {"i586", PROCESSOR_PENTIUM, CPU_PENTIUM, 0}, + {"pentium", PROCESSOR_PENTIUM, CPU_PENTIUM, 0}, + {"pentium-mmx", PROCESSOR_PENTIUM, CPU_PENTIUM, PTA_MMX}, + {"winchip-c6", PROCESSOR_I486, CPU_NONE, PTA_MMX}, + {"winchip2", PROCESSOR_I486, CPU_NONE, PTA_MMX | PTA_3DNOW}, + {"c3", PROCESSOR_I486, CPU_NONE, PTA_MMX | PTA_3DNOW}, + {"c3-2", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, PTA_MMX | PTA_SSE}, + {"i686", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, 0}, + {"pentiumpro", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, 0}, + {"pentium2", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, PTA_MMX}, + {"pentium3", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, + PTA_MMX | PTA_SSE}, + {"pentium3m", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, + PTA_MMX | PTA_SSE}, + {"pentium-m", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, + PTA_MMX | PTA_SSE | PTA_SSE2}, + {"pentium4", PROCESSOR_PENTIUM4, CPU_NONE, + PTA_MMX |PTA_SSE | PTA_SSE2}, + {"pentium4m", PROCESSOR_PENTIUM4, CPU_NONE, + PTA_MMX | PTA_SSE | PTA_SSE2}, + {"prescott", PROCESSOR_NOCONA, CPU_NONE, + PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3}, + {"nocona", PROCESSOR_NOCONA, CPU_NONE, + PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 + | PTA_CX16 | PTA_NO_SAHF}, + {"core2", PROCESSOR_CORE2, CPU_CORE2, + PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 + | PTA_SSSE3 | PTA_CX16}, + {"geode", PROCESSOR_GEODE, CPU_GEODE, + PTA_MMX | PTA_3DNOW | PTA_3DNOW_A |PTA_PREFETCH_SSE}, + {"k6", PROCESSOR_K6, CPU_K6, PTA_MMX}, + {"k6-2", PROCESSOR_K6, CPU_K6, PTA_MMX | PTA_3DNOW}, + {"k6-3", PROCESSOR_K6, CPU_K6, PTA_MMX | PTA_3DNOW}, + {"athlon", PROCESSOR_ATHLON, CPU_ATHLON, + PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_PREFETCH_SSE}, + {"athlon-tbird", PROCESSOR_ATHLON, CPU_ATHLON, + PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_PREFETCH_SSE}, + {"athlon-4", PROCESSOR_ATHLON, CPU_ATHLON, + PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE}, + {"athlon-xp", PROCESSOR_ATHLON, CPU_ATHLON, + PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE}, + {"athlon-mp", PROCESSOR_ATHLON, CPU_ATHLON, + PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE}, + {"x86-64", PROCESSOR_K8, CPU_K8, + PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_NO_SAHF}, + {"k8", PROCESSOR_K8, CPU_K8, + PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE + | PTA_SSE2 | PTA_NO_SAHF}, + {"k8-sse3", PROCESSOR_K8, CPU_K8, + PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE + | PTA_SSE2 | PTA_SSE3 | PTA_NO_SAHF}, + {"opteron", PROCESSOR_K8, CPU_K8, + PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE + | PTA_SSE2 | PTA_NO_SAHF}, + {"opteron-sse3", PROCESSOR_K8, CPU_K8, + PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE + | PTA_SSE2 | PTA_SSE3 | PTA_NO_SAHF}, + {"athlon64", PROCESSOR_K8, CPU_K8, + PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE + | PTA_SSE2 | PTA_NO_SAHF}, + {"athlon64-sse3", PROCESSOR_K8, CPU_K8, + PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE + | PTA_SSE2 | PTA_SSE3 | PTA_NO_SAHF}, + {"athlon-fx", PROCESSOR_K8, CPU_K8, + PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE + | PTA_SSE2 | PTA_NO_SAHF}, + {"amdfam10", PROCESSOR_AMDFAM10, CPU_AMDFAM10, + PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE + | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM}, + {"barcelona", PROCESSOR_AMDFAM10, PROCESSOR_AMDFAM10, + PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE + | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM}, + {"generic32", PROCESSOR_GENERIC32, CPU_PENTIUMPRO, + 0 /* flags are only used for -march switch. */ }, + {"generic64", PROCESSOR_GENERIC64, CPU_GENERIC64, + PTA_64BIT /* flags are only used for -march switch. */ }, }; int const pta_size = ARRAY_SIZE (processor_alias_table); @@ -2766,6 +2762,7 @@ override_options (bool main_args_p) for (i = 0; i < pta_size; i++) if (! strcmp (ix86_arch_string, processor_alias_table[i].name)) { + ix86_schedule = processor_alias_table[i].schedule; ix86_arch = processor_alias_table[i].processor; /* Default cpu tuning to the architecture. */ ix86_tune = ix86_arch; @@ -2848,6 +2845,7 @@ override_options (bool main_args_p) for (i = 0; i < pta_size; i++) if (! strcmp (ix86_tune_string, processor_alias_table[i].name)) { + ix86_schedule = processor_alias_table[i].schedule; ix86_tune = processor_alias_table[i].processor; if (TARGET_64BIT && !(processor_alias_table[i].flags & PTA_64BIT)) { @@ -2858,6 +2856,7 @@ override_options (bool main_args_p) if (! strcmp (ix86_tune_string, processor_alias_table[i].name)) break; + ix86_schedule = processor_alias_table[i].schedule; ix86_tune = processor_alias_table[i].processor; } else @@ -3276,11 +3275,13 @@ static void ix86_function_specific_save (struct cl_target_option *ptr) { gcc_assert (IN_RANGE (ix86_arch, 0, 255)); + gcc_assert (IN_RANGE (ix86_schedule, 0, 255)); gcc_assert (IN_RANGE (ix86_tune, 0, 255)); gcc_assert (IN_RANGE (ix86_fpmath, 0, 255)); gcc_assert (IN_RANGE (ix86_branch_cost, 0, 255)); ptr->arch = ix86_arch; + ptr->schedule = ix86_schedule; ptr->tune = ix86_tune; ptr->fpmath = ix86_fpmath; ptr->branch_cost = ix86_branch_cost; @@ -3301,6 +3302,7 @@ ix86_function_specific_restore (struct cl_target_option *ptr) int i; ix86_arch = ptr->arch; + ix86_schedule = ptr->schedule; ix86_tune = ptr->tune; ix86_fpmath = ptr->fpmath; ix86_branch_cost = ptr->branch_cost; @@ -7268,7 +7270,7 @@ output_set_got (rtx dest, rtx label ATTRIBUTE_UNUSED) /* Output the Mach-O "canonical" label name ("Lxx$pb") here too. This is what will be referenced by the Mach-O PIC subsystem. */ if (!label) - ASM_OUTPUT_LABEL (asm_out_file, machopic_function_base_name ()); + ASM_OUTPUT_LABEL (asm_out_file, MACHOPIC_FUNCTION_BASE_NAME); #endif (*targetm.asm_out.internal_label) (asm_out_file, "L", @@ -7290,7 +7292,7 @@ output_set_got (rtx dest, rtx label ATTRIBUTE_UNUSED) is what will be referenced by the Mach-O PIC subsystem. */ #if TARGET_MACHO if (!label) - ASM_OUTPUT_LABEL (asm_out_file, machopic_function_base_name ()); + ASM_OUTPUT_LABEL (asm_out_file, MACHOPIC_FUNCTION_BASE_NAME); else targetm.asm_out.internal_label (asm_out_file, "L", CODE_LABEL_NUMBER (label)); @@ -8557,19 +8559,8 @@ ix86_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED) static bool darwin_local_data_pic (rtx disp) { - if (GET_CODE (disp) == MINUS) - { - if (GET_CODE (XEXP (disp, 0)) == LABEL_REF - || GET_CODE (XEXP (disp, 0)) == SYMBOL_REF) - if (GET_CODE (XEXP (disp, 1)) == SYMBOL_REF) - { - const char *sym_name = XSTR (XEXP (disp, 1), 0); - if (! strcmp (sym_name, "<pic base>")) - return true; - } - } - - return false; + return (GET_CODE (disp) == UNSPEC + && XINT (disp, 1) == UNSPEC_MACHOPIC_OFFSET); } /* Determine if a given RTX is a valid constant. We already know this @@ -8710,6 +8701,8 @@ legitimate_pic_operand_p (rtx x) x = XVECEXP (inner, 0, 0); return (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_EXEC); + case UNSPEC_MACHOPIC_OFFSET: + return legitimate_pic_address_disp_p (x); default: return false; } @@ -8972,7 +8965,8 @@ legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, reason_rtx = disp; if (GET_CODE (disp) == CONST - && GET_CODE (XEXP (disp, 0)) == UNSPEC) + && GET_CODE (XEXP (disp, 0)) == UNSPEC + && XINT (XEXP (disp, 0), 1) != UNSPEC_MACHOPIC_OFFSET) switch (XINT (XEXP (disp, 0), 1)) { /* Refuse GOTOFF and GOT in 64bit mode since it is always 64bit when @@ -9935,6 +9929,12 @@ output_pic_addr_const (FILE *file, rtx x, int code) case UNSPEC_INDNTPOFF: fputs ("@INDNTPOFF", file); break; +#if TARGET_MACHO + case UNSPEC_MACHOPIC_OFFSET: + putc ('-', file); + machopic_output_function_base_name (file); + break; +#endif default: output_operand_lossage ("invalid UNSPEC as operand"); break; @@ -10055,7 +10055,7 @@ ix86_delegitimize_address (rtx orig_x) if (TARGET_MACHO && darwin_local_data_pic (x) && !MEM_P (orig_x)) - result = XEXP (x, 0); + result = XVECEXP (x, 0, 0); if (! result) return orig_x; @@ -11167,6 +11167,13 @@ output_addr_const_extra (FILE *file, rtx x) output_addr_const (file, op); fputs ("@INDNTPOFF", file); break; +#if TARGET_MACHO + case UNSPEC_MACHOPIC_OFFSET: + output_addr_const (file, op); + putc ('-', file); + machopic_output_function_base_name (file); + break; +#endif default: return false; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 3af68e9a8a6..81a282e0553 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -237,7 +237,6 @@ enum ix86_tune_indices { X86_TUNE_USE_LEAVE, X86_TUNE_PUSH_MEMORY, X86_TUNE_ZERO_EXTEND_WITH_AND, - X86_TUNE_USE_BIT_TEST, X86_TUNE_UNROLL_STRLEN, X86_TUNE_DEEP_BRANCH_PREDICTION, X86_TUNE_BRANCH_PREDICTION_HINTS, @@ -305,7 +304,6 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST]; #define TARGET_PUSH_MEMORY ix86_tune_features[X86_TUNE_PUSH_MEMORY] #define TARGET_ZERO_EXTEND_WITH_AND \ ix86_tune_features[X86_TUNE_ZERO_EXTEND_WITH_AND] -#define TARGET_USE_BIT_TEST ix86_tune_features[X86_TUNE_USE_BIT_TEST] #define TARGET_UNROLL_STRLEN ix86_tune_features[X86_TUNE_UNROLL_STRLEN] #define TARGET_DEEP_BRANCH_PREDICTION \ ix86_tune_features[X86_TUNE_DEEP_BRANCH_PREDICTION] diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index c6fba67ffbe..88040fc2201 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -58,6 +58,7 @@ (UNSPEC_GOTNTPOFF 7) (UNSPEC_INDNTPOFF 8) (UNSPEC_PLTOFF 9) + (UNSPEC_MACHOPIC_OFFSET 10) ; Prologue support (UNSPEC_STACK_ALLOC 11) @@ -295,11 +296,10 @@ ;; "reload_completed && TARGET_64BIT". -;; Processor type. This attribute must exactly match the processor_type -;; enumeration in i386.h. -(define_attr "cpu" "i386,i486,pentium,pentiumpro,geode,k6,athlon,pentium4,k8, - nocona,core2,generic32,generic64,amdfam10" - (const (symbol_ref "ix86_tune"))) +;; Processor type. +(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2, + generic64,amdfam10" + (const (symbol_ref "ix86_schedule"))) ;; A basic instruction type. Refinements due to arguments to be ;; provided in other attributes. @@ -2559,14 +2559,14 @@ to stack may result in unaligned memory access. */ if (misaligned_operand (operands[0], TImode) || misaligned_operand (operands[1], TImode)) - { + { if (get_attr_mode (insn) == MODE_V4SF) return "%vmovups\t{%1, %0|%0, %1}"; else return "%vmovdqu\t{%1, %0|%0, %1}"; } else - { + { if (get_attr_mode (insn) == MODE_V4SF) return "%vmovaps\t{%1, %0|%0, %1}"; else @@ -2610,14 +2610,14 @@ to stack may result in unaligned memory access. */ if (misaligned_operand (operands[0], TImode) || misaligned_operand (operands[1], TImode)) - { + { if (get_attr_mode (insn) == MODE_V4SF) return "%vmovups\t{%1, %0|%0, %1}"; else return "%vmovdqu\t{%1, %0|%0, %1}"; } else - { + { if (get_attr_mode (insn) == MODE_V4SF) return "%vmovaps\t{%1, %0|%0, %1}"; else @@ -5150,8 +5150,8 @@ /* Avoid store forwarding (partial memory) stall penalty by passing DImode value through XMM registers. */ - if (<SSEMODEI24:MODE>mode == DImode && !TARGET_64BIT - && TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES + if (<SSEMODEI24:MODE>mode == DImode && !TARGET_64BIT + && TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES && optimize_function_for_speed_p (cfun)) { emit_insn (gen_floatdi<X87MODEF:mode>2_i387_with_xmm (operands[0], @@ -20245,6 +20245,7 @@ [(label_ref (match_operand 0 "" ""))] "!TARGET_64BIT && flag_pic" { +#if TARGET_MACHO if (TARGET_MACHO) { rtx xops[3]; @@ -20252,13 +20253,11 @@ rtx label_rtx = gen_label_rtx (); emit_insn (gen_set_got_labelled (pic_offset_table_rtx, label_rtx)); xops[0] = xops[1] = picreg; - xops[2] = gen_rtx_CONST (SImode, - gen_rtx_MINUS (SImode, - gen_rtx_LABEL_REF (SImode, label_rtx), - gen_rtx_SYMBOL_REF (SImode, GOT_SYMBOL_NAME))); + xops[2] = machopic_gen_offset (gen_rtx_LABEL_REF (SImode, label_rtx)); ix86_expand_binary_operator (MINUS, SImode, xops); } else +#endif emit_insn (gen_set_got (pic_offset_table_rtx)); DONE; }) diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 406727139c8..2881ea255ad 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -31,6 +31,10 @@ unsigned char tune TargetSave unsigned char fpmath +;; CPU schedule model +TargetSave +unsigned char schedule + ;; branch cost TargetSave unsigned char branch_cost diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h index 7a1ae9ebc6b..b4137ea1394 100644 --- a/gcc/config/i386/mingw32.h +++ b/gcc/config/i386/mingw32.h @@ -91,7 +91,7 @@ along with GCC; see the file COPYING3. If not see /* Include in the mingw32 libraries with libgcc */ #undef REAL_LIBGCC_SPEC #define REAL_LIBGCC_SPEC \ - "-lmingw32 \ + "%{mthreads:-lmingwthrd} -lmingw32 \ %{shared-libgcc:-lgcc_s} \ %{!shared-libgcc:-lgcc_eh} \ -lgcc \ diff --git a/gcc/config/i386/ppro.md b/gcc/config/i386/ppro.md index b971e51089e..81c0746ea1e 100644 --- a/gcc/config/i386/ppro.md +++ b/gcc/config/i386/ppro.md @@ -135,25 +135,25 @@ ;; on decoder 0, and say that it takes a little while before the result ;; is available. (define_insn_reservation "ppro_complex_insn" 6 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (eq_attr "type" "other,multi,call,callv,str")) "decoder0") ;; imov with memory operands does not use the integer units. (define_insn_reservation "ppro_imov" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "imov"))) "decodern,(p0|p1)") (define_insn_reservation "ppro_imov_load" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (eq_attr "type" "imov"))) "decodern,p2") (define_insn_reservation "ppro_imov_store" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "store") (eq_attr "type" "imov"))) "decoder0,p4+p3") @@ -161,20 +161,20 @@ ;; imovx always decodes to one uop, and also doesn't use the integer ;; units if it has memory operands. (define_insn_reservation "ppro_imovx" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "imovx"))) "decodern,(p0|p1)") (define_insn_reservation "ppro_imovx_load" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (eq_attr "type" "imovx"))) "decodern,p2") ;; lea executes on port 0 with latency one and throughput 1. (define_insn_reservation "ppro_lea" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "lea"))) "decodern,p0") @@ -183,13 +183,13 @@ ;; The load and store units need to be reserved when memory operands ;; are involved. (define_insn_reservation "ppro_shift_rotate" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "ishift,ishift1,rotate,rotate1"))) "decodern,p0") (define_insn_reservation "ppro_shift_rotate_mem" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "!none") (eq_attr "type" "ishift,ishift1,rotate,rotate1"))) "decoder0,p2+p0,p4+p3") @@ -213,32 +213,32 @@ ;; results because we can assume these instructions can decode on all ;; decoders. (define_insn_reservation "ppro_branch" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "ibr"))) "decodern,p1") ;; ??? Indirect branches probably have worse latency than this. (define_insn_reservation "ppro_indirect_branch" 6 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "!none") (eq_attr "type" "ibr"))) "decoder0,p2+p1") (define_insn_reservation "ppro_leave" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (eq_attr "type" "leave")) "decoder0,p2+(p0|p1),(p0|p1)") ;; imul has throughput one, but latency 4, and can only execute on port 0. (define_insn_reservation "ppro_imul" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "imul"))) "decodern,p0") (define_insn_reservation "ppro_imul_mem" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "!none") (eq_attr "type" "imul"))) "decoder0,p2+p0") @@ -247,42 +247,42 @@ ;; QI, HI, and SI have issue latency 12, 21, and 37, respectively. ;; These issue latencies are modelled via the ppro_div automaton. (define_insn_reservation "ppro_idiv_QI" 19 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "QI") (eq_attr "type" "idiv")))) "decoder0,(p0+idiv)*2,(p0|p1)+idiv,idiv*9") (define_insn_reservation "ppro_idiv_QI_load" 19 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "QI") (eq_attr "type" "idiv")))) "decoder0,p2+p0+idiv,p0+idiv,(p0|p1)+idiv,idiv*9") (define_insn_reservation "ppro_idiv_HI" 23 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "HI") (eq_attr "type" "idiv")))) "decoder0,(p0+idiv)*3,(p0|p1)+idiv,idiv*17") (define_insn_reservation "ppro_idiv_HI_load" 23 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "HI") (eq_attr "type" "idiv")))) "decoder0,p2+p0+idiv,p0+idiv,(p0|p1)+idiv,idiv*18") (define_insn_reservation "ppro_idiv_SI" 39 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "SI") (eq_attr "type" "idiv")))) "decoder0,(p0+idiv)*3,(p0|p1)+idiv,idiv*33") (define_insn_reservation "ppro_idiv_SI_load" 39 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "SI") (eq_attr "type" "idiv")))) @@ -293,85 +293,85 @@ ;; has throughput "1/cycle (align with FADD)". What do they ;; mean and how can we model that? (define_insn_reservation "ppro_fop" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none,unknown") (eq_attr "type" "fop"))) "decodern,p0") (define_insn_reservation "ppro_fop_load" 5 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (eq_attr "type" "fop"))) "decoder0,p2+p0,p0") (define_insn_reservation "ppro_fop_store" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "store") (eq_attr "type" "fop"))) "decoder0,p0,p0,p0+p4+p3") (define_insn_reservation "ppro_fop_both" 5 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "both") (eq_attr "type" "fop"))) "decoder0,p2+p0,p0+p4+p3") (define_insn_reservation "ppro_fsgn" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (eq_attr "type" "fsgn")) "decodern,p0") (define_insn_reservation "ppro_fistp" 5 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (eq_attr "type" "fistp")) "decoder0,p0*2,p4+p3") (define_insn_reservation "ppro_fcmov" 2 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (eq_attr "type" "fcmov")) "decoder0,p0*2") (define_insn_reservation "ppro_fcmp" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "fcmp"))) "decodern,p0") (define_insn_reservation "ppro_fcmp_load" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (eq_attr "type" "fcmp"))) "decoder0,p2+p0") (define_insn_reservation "ppro_fmov" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "fmov"))) "decodern,p0") (define_insn_reservation "ppro_fmov_load" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "!XF") (eq_attr "type" "fmov")))) "decodern,p2") (define_insn_reservation "ppro_fmov_XF_load" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "XF") (eq_attr "type" "fmov")))) "decoder0,(p2+p0)*2") (define_insn_reservation "ppro_fmov_store" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "store") (and (eq_attr "mode" "!XF") (eq_attr "type" "fmov")))) "decodern,p0") (define_insn_reservation "ppro_fmov_XF_store" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "store") (and (eq_attr "mode" "XF") (eq_attr "type" "fmov")))) @@ -380,13 +380,13 @@ ;; fmul executes on port 0 with latency 5. It has issue latency 2, ;; but we don't model this. (define_insn_reservation "ppro_fmul" 5 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "fmul"))) "decoder0,p0*2") (define_insn_reservation "ppro_fmul_load" 6 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (eq_attr "type" "fmul"))) "decoder0,p2+p0,p0") @@ -397,42 +397,42 @@ ;; that. Throughput is equal to latency - 1, which we model using the ;; ppro_div automaton. (define_insn_reservation "ppro_fdiv_SF" 18 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "SF") (eq_attr "type" "fdiv,fpspc")))) "decodern,p0+fdiv,fdiv*16") (define_insn_reservation "ppro_fdiv_SF_load" 19 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "SF") (eq_attr "type" "fdiv,fpspc")))) "decoder0,p2+p0+fdiv,fdiv*16") (define_insn_reservation "ppro_fdiv_DF" 32 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "DF") (eq_attr "type" "fdiv,fpspc")))) "decodern,p0+fdiv,fdiv*30") (define_insn_reservation "ppro_fdiv_DF_load" 33 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "DF") (eq_attr "type" "fdiv,fpspc")))) "decoder0,p2+p0+fdiv,fdiv*30") (define_insn_reservation "ppro_fdiv_XF" 38 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "XF") (eq_attr "type" "fdiv,fpspc")))) "decodern,p0+fdiv,fdiv*36") (define_insn_reservation "ppro_fdiv_XF_load" 39 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "XF") (eq_attr "type" "fdiv,fpspc")))) @@ -450,31 +450,31 @@ ;; so they behave as "simple" instructions that need no special modelling. ;; We only have to model mmxshft and mmxmul. (define_insn_reservation "ppro_mmx_shft" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "mmxshft"))) "decodern,p1") (define_insn_reservation "ppro_mmx_shft_load" 2 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "mmxshft"))) "decoder0,p2+p1") (define_insn_reservation "ppro_mmx_mul" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "mmxmul"))) "decodern,p0") (define_insn_reservation "ppro_mmx_mul_load" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (eq_attr "type" "mmxmul"))) "decoder0,p2+p0") (define_insn_reservation "ppro_sse_mmxcvt" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "mode" "DI") (eq_attr "type" "mmxcvt"))) "decodern,p1") @@ -482,7 +482,7 @@ ;; FIXME: These are Pentium III only, but we cannot tell here if ;; we're generating code for PentiumPro/Pentium II or Pentium III ;; (define_insn_reservation "ppro_sse_mmxshft" 2 -;; (and (eq_attr "cpu" "pentiumpro,generic32") +;; (and (eq_attr "cpu" "pentiumpro") ;; (and (eq_attr "mode" "DI") ;; (eq_attr "type" "mmxshft"))) ;; "decodern,p0") @@ -493,69 +493,69 @@ ;; The sfence instruction. (define_insn_reservation "ppro_sse_sfence" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "unknown") (eq_attr "type" "sse"))) "decoder0,p4+p3") ;; FIXME: This reservation is all wrong when we're scheduling sqrtss. (define_insn_reservation "ppro_sse_SF" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "mode" "SF") (eq_attr "type" "sse"))) "decodern,p0") (define_insn_reservation "ppro_sse_add_SF" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "SF") (eq_attr "type" "sseadd")))) "decodern,p1") (define_insn_reservation "ppro_sse_add_SF_load" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "SF") (eq_attr "type" "sseadd")))) "decoder0,p2+p1") (define_insn_reservation "ppro_sse_cmp_SF" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "SF") (eq_attr "type" "ssecmp")))) "decoder0,p1") (define_insn_reservation "ppro_sse_cmp_SF_load" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "SF") (eq_attr "type" "ssecmp")))) "decoder0,p2+p1") (define_insn_reservation "ppro_sse_comi_SF" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "SF") (eq_attr "type" "ssecomi")))) "decodern,p0") (define_insn_reservation "ppro_sse_comi_SF_load" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "SF") (eq_attr "type" "ssecomi")))) "decoder0,p2+p0") (define_insn_reservation "ppro_sse_mul_SF" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "SF") (eq_attr "type" "ssemul")))) "decodern,p0") (define_insn_reservation "ppro_sse_mul_SF_load" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "SF") (eq_attr "type" "ssemul")))) @@ -563,109 +563,109 @@ ;; FIXME: ssediv doesn't close p0 for 17 cycles, surely??? (define_insn_reservation "ppro_sse_div_SF" 18 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "SF") (eq_attr "type" "ssediv")))) "decoder0,p0*17") (define_insn_reservation "ppro_sse_div_SF_load" 18 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "SF") (eq_attr "type" "ssediv")))) "decoder0,(p2+p0),p0*16") (define_insn_reservation "ppro_sse_icvt_SF" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "mode" "SF") (eq_attr "type" "sseicvt"))) "decoder0,(p2+p1)*2") (define_insn_reservation "ppro_sse_icvt_SI" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "mode" "SI") (eq_attr "type" "sseicvt"))) "decoder0,(p2+p1)") (define_insn_reservation "ppro_sse_mov_SF" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "SF") (eq_attr "type" "ssemov")))) "decoder0,(p0|p1)") (define_insn_reservation "ppro_sse_mov_SF_load" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "SF") (eq_attr "type" "ssemov")))) "decoder0,p2+(p0|p1)") (define_insn_reservation "ppro_sse_mov_SF_store" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "store") (and (eq_attr "mode" "SF") (eq_attr "type" "ssemov")))) "decoder0,p4+p3") (define_insn_reservation "ppro_sse_V4SF" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "mode" "V4SF") (eq_attr "type" "sse"))) "decoder0,p1*2") (define_insn_reservation "ppro_sse_add_V4SF" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "V4SF") (eq_attr "type" "sseadd")))) "decoder0,p1*2") (define_insn_reservation "ppro_sse_add_V4SF_load" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "V4SF") (eq_attr "type" "sseadd")))) "decoder0,(p2+p1)*2") (define_insn_reservation "ppro_sse_cmp_V4SF" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "V4SF") (eq_attr "type" "ssecmp")))) "decoder0,p1*2") (define_insn_reservation "ppro_sse_cmp_V4SF_load" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "V4SF") (eq_attr "type" "ssecmp")))) "decoder0,(p2+p1)*2") (define_insn_reservation "ppro_sse_cvt_V4SF" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none,unknown") (and (eq_attr "mode" "V4SF") (eq_attr "type" "ssecvt")))) "decoder0,p1*2") (define_insn_reservation "ppro_sse_cvt_V4SF_other" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "!none,unknown") (and (eq_attr "mode" "V4SF") (eq_attr "type" "ssecmp")))) "decoder0,p1,p4+p3") (define_insn_reservation "ppro_sse_mul_V4SF" 5 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "V4SF") (eq_attr "type" "ssemul")))) "decoder0,p0*2") (define_insn_reservation "ppro_sse_mul_V4SF_load" 5 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "V4SF") (eq_attr "type" "ssemul")))) @@ -673,49 +673,49 @@ ;; FIXME: p0 really closed this long??? (define_insn_reservation "ppro_sse_div_V4SF" 48 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "V4SF") (eq_attr "type" "ssediv")))) "decoder0,p0*34") (define_insn_reservation "ppro_sse_div_V4SF_load" 48 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "V4SF") (eq_attr "type" "ssediv")))) "decoder0,(p2+p0)*2,p0*32") (define_insn_reservation "ppro_sse_log_V4SF" 2 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "V4SF") (eq_attr "type" "sselog,sselog1")))) "decodern,p1") (define_insn_reservation "ppro_sse_log_V4SF_load" 2 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "V4SF") (eq_attr "type" "sselog,sselog1")))) "decoder0,(p2+p1)") (define_insn_reservation "ppro_sse_mov_V4SF" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none") (and (eq_attr "mode" "V4SF") (eq_attr "type" "ssemov")))) "decoder0,(p0|p1)*2") (define_insn_reservation "ppro_sse_mov_V4SF_load" 2 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (and (eq_attr "mode" "V4SF") (eq_attr "type" "ssemov")))) "decoder0,p2*2") (define_insn_reservation "ppro_sse_mov_V4SF_store" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "store") (and (eq_attr "mode" "V4SF") (eq_attr "type" "ssemov")))) @@ -729,7 +729,7 @@ ;; reg-reg instructions produce 1 uop so they can be decoded on any of ;; the three decoders. (define_insn_reservation "ppro_insn" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "none,unknown") (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseimul,mmx,mmxadd,mmxcmp"))) "decodern,(p0|p1)") @@ -737,13 +737,13 @@ ;; read-modify and register-memory instructions have 2 or three uops, ;; so they have to be decoded on decoder0. (define_insn_reservation "ppro_insn_load" 3 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "load") (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseimul,mmx,mmxadd,mmxcmp"))) "decoder0,p2+(p0|p1)") (define_insn_reservation "ppro_insn_store" 1 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "store") (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseimul,mmx,mmxadd,mmxcmp"))) "decoder0,(p0|p1),p4+p3") @@ -751,7 +751,7 @@ ;; read-modify-store instructions produce 4 uops so they have to be ;; decoded on decoder0 as well. (define_insn_reservation "ppro_insn_both" 4 - (and (eq_attr "cpu" "pentiumpro,generic32") + (and (eq_attr "cpu" "pentiumpro") (and (eq_attr "memory" "both") (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseimul,mmx,mmxadd,mmxcmp"))) "decoder0,p2+(p0|p1),p4+p3") diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 36a1b3a7397..bdac2102617 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -428,7 +428,8 @@ || !CONST_INT_P (XEXP (op, 1))) return 0; op = XEXP (op, 0); - if (GET_CODE (op) == UNSPEC) + if (GET_CODE (op) == UNSPEC + && XINT (op, 1) != UNSPEC_MACHOPIC_OFFSET) return 1; } return 0; diff --git a/gcc/config/mips/10000.md b/gcc/config/mips/10000.md new file mode 100644 index 00000000000..ad21e9e936e --- /dev/null +++ b/gcc/config/mips/10000.md @@ -0,0 +1,253 @@ +;; DFA-based pipeline description for the VR1x000. +;; Copyright (C) 2005, 2006, 2008 Free Software Foundation, Inc. +;; +;; This file is part of GCC. + +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published +;; by the Free Software Foundation; either version 3, or (at your +;; option) any later version. + +;; GCC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + + +;; R12K/R14K/R16K are derivatives of R10K, thus copy its description +;; until specific tuning for each is added. + +;; R10000 has an int queue, fp queue, address queue. +;; The int queue feeds ALU1 and ALU2. +;; The fp queue feeds the fp-adder and fp-multiplier. +;; The addr queue feeds the Load/Store unit. +;; +;; However, we define the fp-adder and fp-multiplier as +;; separate automatons, because the fp-multiplier is +;; divided into fp-multiplier, fp-division, and +;; fp-squareroot units, all of which share the same +;; issue and completion logic, yet can operate in +;; parallel. +;; +;; This is based on the model described in the R10K Manual +;; and it helps to reduce the size of the automata. +(define_automaton "r10k_a_int, r10k_a_fpadder, r10k_a_addr, + r10k_a_fpmpy, r10k_a_fpdiv, r10k_a_fpsqrt") + +(define_cpu_unit "r10k_alu1" "r10k_a_int") +(define_cpu_unit "r10k_alu2" "r10k_a_int") +(define_cpu_unit "r10k_fpadd" "r10k_a_fpadder") +(define_cpu_unit "r10k_fpmpy" "r10k_a_fpmpy") +(define_cpu_unit "r10k_fpdiv" "r10k_a_fpdiv") +(define_cpu_unit "r10k_fpsqrt" "r10k_a_fpsqrt") +(define_cpu_unit "r10k_loadstore" "r10k_a_addr") + + +;; R10k Loads and Stores. +(define_insn_reservation "r10k_load" 2 + (and (eq_attr "cpu" "r10000") + (eq_attr "type" "load,prefetch,prefetchx")) + "r10k_loadstore") + +(define_insn_reservation "r10k_store" 0 + (and (eq_attr "cpu" "r10000") + (eq_attr "type" "store,fpstore,fpidxstore")) + "r10k_loadstore") + +(define_insn_reservation "r10k_fpload" 3 + (and (eq_attr "cpu" "r10000") + (eq_attr "type" "fpload,fpidxload")) + "r10k_loadstore") + + +;; Integer add/sub + logic ops, and mt hi/lo can be done by alu1 or alu2. +;; Miscellaneous arith goes here too (this is a guess). +(define_insn_reservation "r10k_arith" 1 + (and (eq_attr "cpu" "r10000") + (eq_attr "type" "arith,mthilo,slt,clz,const,nop,trap,logical")) + "r10k_alu1 | r10k_alu2") + +;; We treat mfhilo differently, because we need to know when +;; it's HI and when it's LO. +(define_insn_reservation "r10k_mfhi" 1 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "mfhilo") + (not (match_operand 1 "lo_operand")))) + "r10k_alu1 | r10k_alu2") + +(define_insn_reservation "r10k_mflo" 1 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "mfhilo") + (match_operand 1 "lo_operand"))) + "r10k_alu1 | r10k_alu2") + + +;; ALU1 handles shifts, branch eval, and condmove. +;; +;; Brancher is separate, but part of ALU1, but can only +;; do one branch per cycle (is this even implementable?). +;; +;; Unsure if the brancher handles jumps and calls as well, but since +;; they're related, we'll add them here for now. +(define_insn_reservation "r10k_brancher" 1 + (and (eq_attr "cpu" "r10000") + (eq_attr "type" "shift,branch,jump,call")) + "r10k_alu1") + +(define_insn_reservation "r10k_int_cmove" 1 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "condmove") + (eq_attr "mode" "SI,DI"))) + "r10k_alu1") + + +;; Coprocessor Moves. +;; mtc1/dmtc1 are handled by ALU1. +;; mfc1/dmfc1 are handled by the fp-multiplier. +(define_insn_reservation "r10k_mt_xfer" 3 + (and (eq_attr "cpu" "r10000") + (eq_attr "type" "mtc")) + "r10k_alu1") + +(define_insn_reservation "r10k_mf_xfer" 2 + (and (eq_attr "cpu" "r10000") + (eq_attr "type" "mfc")) + "r10k_fpmpy") + + +;; Only ALU2 does int multiplications and divisions. +;; +;; According to the Vr10000 series user manual, +;; integer mult and div insns can be issued one +;; cycle earlier if using register Lo. We model +;; this by using the Lo value by default, as it +;; is the more common value, and use a bypass +;; for the Hi value when needed. +;; +;; Also of note, There are different latencies +;; for MULT/DMULT (Lo 5/Hi 6) and MULTU/DMULTU (Lo 6/Hi 7). +;; However, gcc does not have separate types +;; for these insns. Thus to strike a balance, +;; we use the Hi latency value for imul +;; operations until the imul type can be split. +(define_insn_reservation "r10k_imul_single" 6 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "imul,imul3") + (eq_attr "mode" "SI"))) + "r10k_alu2 * 6") + +(define_insn_reservation "r10k_imul_double" 10 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "imul,imul3") + (eq_attr "mode" "DI"))) + "r10k_alu2 * 10") + +;; Divides keep ALU2 busy. +(define_insn_reservation "r10k_idiv_single" 34 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "idiv") + (eq_attr "mode" "SI"))) + "r10k_alu2 * 35") + +(define_insn_reservation "r10k_idiv_double" 66 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "idiv") + (eq_attr "mode" "DI"))) + "r10k_alu2 * 67") + +(define_bypass 35 "r10k_idiv_single" "r10k_mfhi") +(define_bypass 67 "r10k_idiv_double" "r10k_mfhi") + + +;; Floating point add/sub, mul, abs value, neg, comp, & moves. +(define_insn_reservation "r10k_fp_miscadd" 2 + (and (eq_attr "cpu" "r10000") + (eq_attr "type" "fadd,fabs,fneg,fcmp")) + "r10k_fpadd") + +(define_insn_reservation "r10k_fp_miscmul" 2 + (and (eq_attr "cpu" "r10000") + (eq_attr "type" "fmul,fmove")) + "r10k_fpmpy") + +(define_insn_reservation "r10k_fp_cmove" 2 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "condmove") + (eq_attr "mode" "SF,DF"))) + "r10k_fpmpy") + + +;; The fcvt.s.[wl] insn has latency 4, repeat 2. +;; All other fcvt insns have latency 2, repeat 1. +(define_insn_reservation "r10k_fcvt_single" 4 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "fcvt") + (eq_attr "cnv_mode" "I2S"))) + "r10k_fpadd * 2") + +(define_insn_reservation "r10k_fcvt_other" 2 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "fcvt") + (eq_attr "cnv_mode" "!I2S"))) + "r10k_fpadd") + + +;; Run the fmadd insn through fp-adder first, then fp-multiplier. +;; +;; The latency for fmadd is 2 cycles if the result is used +;; by another fmadd instruction. +(define_insn_reservation "r10k_fmadd" 4 + (and (eq_attr "cpu" "r10000") + (eq_attr "type" "fmadd")) + "r10k_fpadd, r10k_fpmpy") + +(define_bypass 2 "r10k_fmadd" "r10k_fmadd") + + +;; Floating point Divisions & square roots. +(define_insn_reservation "r10k_fdiv_single" 12 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "fdiv,frdiv") + (eq_attr "mode" "SF"))) + "r10k_fpdiv * 14") + +(define_insn_reservation "r10k_fdiv_double" 19 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "fdiv,frdiv") + (eq_attr "mode" "DF"))) + "r10k_fpdiv * 21") + +(define_insn_reservation "r10k_fsqrt_single" 18 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "fsqrt") + (eq_attr "mode" "SF"))) + "r10k_fpsqrt * 20") + +(define_insn_reservation "r10k_fsqrt_double" 33 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "fsqrt") + (eq_attr "mode" "DF"))) + "r10k_fpsqrt * 35") + +(define_insn_reservation "r10k_frsqrt_single" 30 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "frsqrt") + (eq_attr "mode" "SF"))) + "r10k_fpsqrt * 20") + +(define_insn_reservation "r10k_frsqrt_double" 52 + (and (eq_attr "cpu" "r10000") + (and (eq_attr "type" "frsqrt") + (eq_attr "mode" "DF"))) + "r10k_fpsqrt * 35") + + +;; Handle unknown/multi insns here (this is a guess). +(define_insn_reservation "r10k_unknown" 1 + (and (eq_attr "cpu" "r10000") + (eq_attr "type" "unknown,multi")) + "r10k_alu1 + r10k_alu2") diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 20532ba3de2..597f1edd567 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -607,6 +607,10 @@ static const struct mips_cpu_info mips_cpu_info_table[] = { /* MIPS IV processors. */ { "r8000", PROCESSOR_R8000, 4, 0 }, + { "r10000", PROCESSOR_R10000, 4, 0 }, + { "r12000", PROCESSOR_R10000, 4, 0 }, + { "r14000", PROCESSOR_R10000, 4, 0 }, + { "r16000", PROCESSOR_R10000, 4, 0 }, { "vr5000", PROCESSOR_R5000, 4, 0 }, { "vr5400", PROCESSOR_R5400, 4, 0 }, { "vr5500", PROCESSOR_R5500, 4, PTF_AVOID_BRANCHLIKELY }, @@ -1015,6 +1019,19 @@ static const struct mips_rtx_cost_data mips_rtx_cost_data[PROCESSOR_MAX] = { 1, /* branch_cost */ 4 /* memory_latency */ }, + { /* R1x000 */ + COSTS_N_INSNS (2), /* fp_add */ + COSTS_N_INSNS (2), /* fp_mult_sf */ + COSTS_N_INSNS (2), /* fp_mult_df */ + COSTS_N_INSNS (12), /* fp_div_sf */ + COSTS_N_INSNS (19), /* fp_div_df */ + COSTS_N_INSNS (5), /* int_mult_si */ + COSTS_N_INSNS (9), /* int_mult_di */ + COSTS_N_INSNS (34), /* int_div_si */ + COSTS_N_INSNS (66), /* int_div_di */ + 1, /* branch_cost */ + 4 /* memory_latency */ + }, { /* SB1 */ /* These costs are the same as the SB-1A below. */ COSTS_N_INSNS (4), /* fp_add */ @@ -10369,7 +10386,10 @@ mips_issue_rate (void) but in reality only a maximum of 3 insns can be issued as floating-point loads and stores also require a slot in the AGEN pipe. */ - return 4; + case PROCESSOR_R10000: + /* All R10K Processors are quad-issue (being the first MIPS + processors to support this feature). */ + return 4; case PROCESSOR_20KC: case PROCESSOR_R4130: diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index dc390dfe745..b0f39dc9a57 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -67,6 +67,7 @@ enum processor_type { PROCESSOR_R7000, PROCESSOR_R8000, PROCESSOR_R9000, + PROCESSOR_R10000, PROCESSOR_SB1, PROCESSOR_SB1A, PROCESSOR_SR71000, diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index f3fdaeaf45b..3f56feb2ee9 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -560,7 +560,7 @@ ;; Attribute describing the processor. This attribute must match exactly ;; with the processor_type enumeration in mips.h. (define_attr "cpu" - "r3000,4kc,4kp,5kc,5kf,20kc,24kc,24kf2_1,24kf1_1,74kc,74kf2_1,74kf1_1,74kf3_2,loongson_2e,loongson_2f,m4k,octeon,r3900,r6000,r4000,r4100,r4111,r4120,r4130,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,sb1,sb1a,sr71000,xlr" + "r3000,4kc,4kp,5kc,5kf,20kc,24kc,24kf2_1,24kf1_1,74kc,74kf2_1,74kf1_1,74kf3_2,loongson_2e,loongson_2f,m4k,octeon,r3900,r6000,r4000,r4100,r4111,r4120,r4130,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,r10000,sb1,sb1a,sr71000,xlr" (const (symbol_ref "mips_tune"))) ;; The type of hardware hazard associated with this instruction. @@ -935,6 +935,7 @@ (include "6000.md") (include "7000.md") (include "9000.md") +(include "10000.md") (include "loongson2ef.md") (include "octeon.md") (include "sb1.md") @@ -1366,35 +1367,21 @@ DONE; }) -(define_insn "mulsi3_mul3" - [(set (match_operand:SI 0 "register_operand" "=d,l") - (mult:SI (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "register_operand" "d,d"))) - (clobber (match_scratch:SI 3 "=l,X"))] - "ISA_HAS_MUL3" +(define_insn "mul<mode>3_mul3" + [(set (match_operand:GPR 0 "register_operand" "=d,l") + (mult:GPR (match_operand:GPR 1 "register_operand" "d,d") + (match_operand:GPR 2 "register_operand" "d,d"))) + (clobber (match_scratch:GPR 3 "=l,X"))] + "ISA_HAS_<D>MUL3" { if (which_alternative == 1) - return "mult\t%1,%2"; - if (TARGET_MIPS3900) + return "<d>mult\t%1,%2"; + if (<MODE>mode == SImode && TARGET_MIPS3900) return "mult\t%0,%1,%2"; - return "mul\t%0,%1,%2"; + return "<d>mul\t%0,%1,%2"; } [(set_attr "type" "imul3,imul") - (set_attr "mode" "SI")]) - -(define_insn "muldi3_mul3" - [(set (match_operand:DI 0 "register_operand" "=d,l") - (mult:DI (match_operand:DI 1 "register_operand" "d,d") - (match_operand:DI 2 "register_operand" "d,d"))) - (clobber (match_scratch:DI 3 "=l,X"))] - "ISA_HAS_DMUL3" -{ - if (which_alternative == 1) - return "dmult\t%1,%2"; - return "dmul\t%0,%1,%2"; -} - [(set_attr "type" "imul3,imul") - (set_attr "mode" "DI")]) + (set_attr "mode" "<MODE>")]) ;; If a register gets allocated to LO, and we spill to memory, the reload ;; will include a move from LO to a GPR. Merge it into the multiplication diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index ed9b6c03683..f968b2f1467 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -3097,10 +3097,10 @@ altivec_resolve_overloaded_builtin (tree fndecl, tree arglist) innerptrtype = build_pointer_type (arg1_inner_type); - stmt = build_unary_op (ADDR_EXPR, stmt, 0); + stmt = build_unary_op (input_location, ADDR_EXPR, stmt, 0); stmt = convert (innerptrtype, stmt); stmt = build_binary_op (input_location, PLUS_EXPR, stmt, arg2, 1); - stmt = build_indirect_ref (stmt, NULL, input_location); + stmt = build_indirect_ref (input_location, stmt, NULL); return stmt; } @@ -3155,10 +3155,10 @@ altivec_resolve_overloaded_builtin (tree fndecl, tree arglist) innerptrtype = build_pointer_type (arg1_inner_type); - stmt = build_unary_op (ADDR_EXPR, stmt, 0); + stmt = build_unary_op (input_location, ADDR_EXPR, stmt, 0); stmt = convert (innerptrtype, stmt); stmt = build_binary_op (input_location, PLUS_EXPR, stmt, arg2, 1); - stmt = build_indirect_ref (stmt, NULL, input_location); + stmt = build_indirect_ref (input_location, stmt, NULL); stmt = build2 (MODIFY_EXPR, TREE_TYPE (stmt), stmt, convert (TREE_TYPE (stmt), arg0)); stmt = build2 (COMPOUND_EXPR, arg1_type, stmt, decl); diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index a9fb2ab237f..13e7becc526 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -77,6 +77,7 @@ extern int extract_ME (rtx); extern void rs6000_output_function_entry (FILE *, const char *); extern void print_operand (FILE *, rtx, int); extern void print_operand_address (FILE *, rtx); +extern bool rs6000_output_addr_const_extra (FILE *, rtx); extern enum rtx_code rs6000_reverse_condition (enum machine_mode, enum rtx_code); extern void rs6000_emit_sCOND (enum rtx_code, rtx); @@ -111,6 +112,7 @@ extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode, extern int rs6000_legitimate_address (enum machine_mode, rtx, int); extern bool rs6000_legitimate_offset_address_p (enum machine_mode, rtx, int); extern bool rs6000_mode_dependent_address (rtx); +extern rtx rs6000_find_base_term (rtx); extern bool rs6000_offsettable_memref_p (rtx); extern rtx rs6000_return_addr (int, rtx); extern void rs6000_output_symbol_ref (FILE*, rtx); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index d230dfd336b..9f48b611e6f 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -765,7 +765,6 @@ static void rs6000_emit_allocate_stack (HOST_WIDE_INT, int, int); static unsigned rs6000_hash_constant (rtx); static unsigned toc_hash_function (const void *); static int toc_hash_eq (const void *, const void *); -static int constant_pool_expr_1 (rtx, int *, int *); static bool constant_pool_expr_p (rtx); static bool legitimate_small_data_p (enum machine_mode, rtx); static bool legitimate_lo_sum_address_p (enum machine_mode, rtx, int); @@ -3505,58 +3504,28 @@ gpr_or_gpr_p (rtx op0, rtx op1) /* Subroutines of rs6000_legitimize_address and rs6000_legitimate_address. */ -static int -constant_pool_expr_1 (rtx op, int *have_sym, int *have_toc) -{ - switch (GET_CODE (op)) - { - case SYMBOL_REF: - if (RS6000_SYMBOL_REF_TLS_P (op)) - return 0; - else if (CONSTANT_POOL_ADDRESS_P (op)) - { - if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (op), Pmode)) - { - *have_sym = 1; - return 1; - } - else - return 0; - } - else if (! strcmp (XSTR (op, 0), toc_label_name)) - { - *have_toc = 1; - return 1; - } - else - return 0; - case PLUS: - case MINUS: - return (constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc) - && constant_pool_expr_1 (XEXP (op, 1), have_sym, have_toc)); - case CONST: - return constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc); - case CONST_INT: - return 1; - default: - return 0; - } -} - static bool constant_pool_expr_p (rtx op) { - int have_sym = 0; - int have_toc = 0; - return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_sym; + rtx base, offset; + + split_const (op, &base, &offset); + return (GET_CODE (base) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (base) + && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (base), Pmode)); } bool toc_relative_expr_p (rtx op) { - int have_sym = 0; - int have_toc = 0; - return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_toc; + rtx base, offset; + + if (GET_CODE (op) != CONST) + return false; + + split_const (op, &base, &offset); + return (GET_CODE (base) == UNSPEC + && XINT (base, 1) == UNSPEC_TOCREL); } bool @@ -3566,7 +3535,7 @@ legitimate_constant_pool_address_p (rtx x) && GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == REG && (TARGET_MINIMAL_TOC || REGNO (XEXP (x, 0)) == TOC_REGISTER) - && constant_pool_expr_p (XEXP (x, 1))); + && toc_relative_expr_p (XEXP (x, 1))); } static bool @@ -4190,8 +4159,8 @@ rs6000_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED) On Darwin, we use this to generate code for floating point constants. A movsf_low is generated so we wind up with 2 instructions rather than 3. - The Darwin code is inside #if TARGET_MACHO because only then is - machopic_function_base_name() defined. */ + The Darwin code is inside #if TARGET_MACHO because only then are the + machopic_* functions defined. */ rtx rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, int opnum, int type, @@ -4217,11 +4186,8 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, && GET_CODE (XEXP (x, 0)) == PLUS && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH - && GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == CONST && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1) - && GET_CODE (XEXP (XEXP (x, 1), 0)) == MINUS - && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == SYMBOL_REF - && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == SYMBOL_REF) + && machopic_operand_p (XEXP (x, 1))) { /* Result of previous invocation of this function on Darwin floating point constant. */ @@ -4313,9 +4279,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, #if TARGET_MACHO if (flag_pic) { - rtx offset = gen_rtx_CONST (Pmode, - gen_rtx_MINUS (Pmode, x, - machopic_function_base_sym ())); + rtx offset = machopic_gen_offset (x); x = gen_rtx_LO_SUM (GET_MODE (x), gen_rtx_PLUS (Pmode, pic_offset_table_rtx, gen_rtx_HIGH (Pmode, offset)), offset); @@ -4491,6 +4455,27 @@ rs6000_mode_dependent_address (rtx addr) return false; } +/* Implement FIND_BASE_TERM. */ + +rtx +rs6000_find_base_term (rtx op) +{ + rtx base, offset; + + split_const (op, &base, &offset); + if (GET_CODE (base) == UNSPEC) + switch (XINT (base, 1)) + { + case UNSPEC_TOCREL: + case UNSPEC_MACHOPIC_OFFSET: + /* OP represents SYM [+ OFFSET] - ANCHOR. SYM is the base term + for aliasing purposes. */ + return XVECEXP (base, 0, 0); + } + + return op; +} + /* More elaborate version of recog's offsettable_memref_p predicate that works around the ??? note of rs6000_mode_dependent_address. In particular it accepts @@ -12572,45 +12557,45 @@ print_operand_address (FILE *file, rtx x) #endif else if (legitimate_constant_pool_address_p (x)) { - if (TARGET_AIX && (!TARGET_ELF || !TARGET_MINIMAL_TOC)) - { - rtx contains_minus = XEXP (x, 1); - rtx minus, symref; - const char *name; - - /* Find the (minus (sym) (toc)) buried in X, and temporarily - turn it into (sym) for output_addr_const. */ - while (GET_CODE (XEXP (contains_minus, 0)) != MINUS) - contains_minus = XEXP (contains_minus, 0); - - minus = XEXP (contains_minus, 0); - symref = XEXP (minus, 0); - gcc_assert (GET_CODE (XEXP (minus, 1)) == SYMBOL_REF); - XEXP (contains_minus, 0) = symref; - if (TARGET_ELF) - { - char *newname; - - name = XSTR (symref, 0); - newname = XALLOCAVEC (char, strlen (name) + sizeof ("@toc")); - strcpy (newname, name); - strcat (newname, "@toc"); - XSTR (symref, 0) = newname; - } - output_addr_const (file, XEXP (x, 1)); - if (TARGET_ELF) - XSTR (symref, 0) = name; - XEXP (contains_minus, 0) = minus; - } - else - output_addr_const (file, XEXP (x, 1)); - + output_addr_const (file, XEXP (x, 1)); fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]); } else gcc_unreachable (); } +/* Implement OUTPUT_ADDR_CONST_EXTRA for address X. */ + +bool +rs6000_output_addr_const_extra (FILE *file, rtx x) +{ + if (GET_CODE (x) == UNSPEC) + switch (XINT (x, 1)) + { + case UNSPEC_TOCREL: + x = XVECEXP (x, 0, 0); + gcc_assert (GET_CODE (x) == SYMBOL_REF); + output_addr_const (file, x); + if (!TARGET_AIX || (TARGET_ELF && TARGET_MINIMAL_TOC)) + { + putc ('-', file); + assemble_name (file, toc_label_name); + } + else if (TARGET_ELF) + fputs ("@toc", file); + return true; + +#if TARGET_MACHO + case UNSPEC_MACHOPIC_OFFSET: + output_addr_const (file, XVECEXP (x, 0, 0)); + putc ('-', file); + machopic_output_function_base_name (file); + return true; +#endif + } + return false; +} + /* Target hook for assembling integer objects. The PowerPC version has to handle fixup entries for relocatable code if RELOCATABLE_NEEDS_FIXUP is defined. It also needs to handle DI-mode objects on 64-bit @@ -15431,8 +15416,7 @@ create_TOC_reference (rtx symbol) return gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, TOC_REGISTER), gen_rtx_CONST (Pmode, - gen_rtx_MINUS (Pmode, symbol, - gen_rtx_SYMBOL_REF (Pmode, toc_label_name)))); + gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), UNSPEC_TOCREL))); } /* If _Unwind_* has been called from within the same module, @@ -16707,7 +16691,7 @@ rs6000_emit_prologue (void) && flag_pic && crtl->uses_pic_offset_table) { rtx lr = gen_rtx_REG (Pmode, LR_REGNO); - rtx src = machopic_function_base_sym (); + rtx src = gen_rtx_SYMBOL_REF (Pmode, MACHOPIC_FUNCTION_BASE_NAME); /* Save and restore LR locally around this call (in R0). */ if (!info->lr_save_p) diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index e1023daa022..39fc0f6c9b6 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1856,6 +1856,8 @@ do { \ if (rs6000_mode_dependent_address (ADDR)) \ goto LABEL; \ } while (0) + +#define FIND_BASE_TERM rs6000_find_base_term /* The register number of the register used to address a table of static data addresses in memory. In some cases this register is @@ -2352,6 +2354,12 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */ #define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) +#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \ + do \ + if (!rs6000_output_addr_const_extra (STREAM, X)) \ + goto FAIL; \ + while (0) + /* uncomment for disabling the corresponding default options */ /* #define MACHINE_no_sched_interblock */ /* #define MACHINE_no_sched_speculative */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 71a73ad4eb5..044b11765e9 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -99,6 +99,8 @@ (UNSPEC_DLMZB_CR 46) (UNSPEC_DLMZB_STRLEN 47) (UNSPEC_RSQRT 48) + (UNSPEC_TOCREL 49) + (UNSPEC_MACHOPIC_OFFSET 50) ]) ;; @@ -10593,12 +10595,12 @@ #if TARGET_MACHO if (DEFAULT_ABI == ABI_DARWIN) { - const char *picbase = machopic_function_base_name (); - rtx picrtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (picbase)); + rtx picrtx = gen_rtx_SYMBOL_REF (Pmode, MACHOPIC_FUNCTION_BASE_NAME); rtx picreg = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM); rtx tmplabrtx; char tmplab[20]; + crtl->uses_pic_offset_table = 1; ASM_GENERATE_INTERNAL_LABEL(tmplab, \"LSJR\", CODE_LABEL_NUMBER (operands[0])); tmplabrtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (tmplab)); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index acb766f7124..bb4b6b21bed 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,37 @@ +2008-10-07 Steve Ellcey <sje@cup.hp.com> + + * decl.c (start_cleanup_fn): Declare as inline. + +2008-10-06 Jason Merrill <jason@redhat.com> + + PR c++/37376, other mangling issues + * mangle.c (write_type): Update TYPE_PACK_EXPANSION mangling. + (write_member_name): Break out from... + (write_expression): ...here. Handle dependent COMPONENT_REF. + (write_template_arg): Wrap an argument pack in 'I'/'E'. + (write_builtin_type): Update char16/32_t mangling. + (write_nested_name, write_prefix): Don't forget template args + for typename types. + * operators.def: Add ARROW_EXPR, update COMPONENT_REF and + EXPR_PACK_EXPANSION. + +2008-10-06 Aldy Hernandez <aldyh@redhat.com> + + * typeck.c (build_x_indirect_ref): Add location argument. + (cp_build_binary_op): Pass location to warn_for_div_by_zero. + (cp_build_unary_op): Add location argument. + (cp_build_modify_expr): Same. + * class.c (build_base_path): Pass location to build_indirect_ref. + * semantics.c (handle_omp_for_class_iterator): Pass elocus to + build_modify_expr. + +2008-10-05 Dodji Seketeli <dodji@redhat.com> + + PR c++/37410 + * cp-gimplify.c (cp_gimplify_expr): For each USING_STMT + make sure an IMPORTED_DECL node is added to the BLOCK_VARS list + of the innermost containing BLOCK. + 2008-10-03 Paolo Carlini <paolo.carlini@oracle.com> PR c++/37719 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index ab8391b4a72..910dc291f8e 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -299,7 +299,7 @@ build_base_path (enum tree_code code, { expr = build_nop (build_pointer_type (target_type), expr); if (!want_pointer) - expr = build_indirect_ref (expr, NULL, EXPR_LOCATION (expr)); + expr = build_indirect_ref (EXPR_LOCATION (expr), expr, NULL); return expr; } diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 243b1c61bfb..a1542b9f804 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -508,6 +508,8 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) int saved_stmts_are_full_exprs_p = 0; enum tree_code code = TREE_CODE (*expr_p); enum gimplify_status ret; + tree block = NULL; + VEC(gimple, heap) *bind_expr_stack = NULL; if (STATEMENT_CODE_P (code)) { @@ -574,8 +576,37 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) break; case USING_STMT: - /* Just ignore for now. Eventually we will want to pass this on to - the debugger. */ + /* Get the innermost inclosing GIMPLE_BIND that has a non NULL + BLOCK, and append an IMPORTED_DECL to its + BLOCK_VARS chained list. */ + + bind_expr_stack = gimple_bind_expr_stack (); + if (bind_expr_stack) + { + int i; + for (i = VEC_length (gimple, bind_expr_stack) - 1; i >= 0; i--) + if ((block = gimple_bind_block (VEC_index (gimple, + bind_expr_stack, + i)))) + break; + } + if (block) + { + tree using_directive; + gcc_assert (TREE_OPERAND (*expr_p,0) + && NAMESPACE_DECL_CHECK (TREE_OPERAND (*expr_p, 0))); + + using_directive = make_node (IMPORTED_DECL); + TREE_TYPE (using_directive) = void_type_node; + + IMPORTED_DECL_ASSOCIATED_DECL (using_directive) + = TREE_OPERAND (*expr_p, 0); + DECL_NAME (using_directive) + = DECL_NAME (TREE_OPERAND (*expr_p, 0)); + TREE_CHAIN (using_directive) = BLOCK_VARS (block); + BLOCK_VARS (block) = using_directive; + } + /* The USING_STMT won't appear in GIMPLE. */ *expr_p = NULL; ret = GS_ALL_DONE; break; diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index be28e788600..b0b03a549e6 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6006,6 +6006,7 @@ start_cleanup_fn (void) actually needed. It is unlikely that it will be inlined, since it is only called via a function pointer, but we avoid unnecessary emissions this way. */ + DECL_DECLARED_INLINE_P (fndecl) = 1; DECL_INTERFACE_KNOWN (fndecl) = 1; /* Build the parameter. */ if (use_cxa_atexit) diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 7b4c30344cc..c0282d8ade5 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -887,6 +887,20 @@ write_nested_name (const tree decl) write_template_prefix (decl); write_template_args (TI_ARGS (template_info)); } + else if (TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE) + { + tree name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (decl)); + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + { + write_template_prefix (decl); + write_template_args (TREE_OPERAND (name, 1)); + } + else + { + write_prefix (CP_DECL_CONTEXT (decl)); + write_unqualified_name (decl); + } + } else { /* No, just use <prefix> */ @@ -953,6 +967,20 @@ write_prefix (const tree node) write_template_prefix (decl); write_template_args (TI_ARGS (template_info)); } + else if (TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE) + { + tree name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (decl)); + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + { + write_template_prefix (decl); + write_template_args (TREE_OPERAND (name, 1)); + } + else + { + write_prefix (CP_DECL_CONTEXT (decl)); + write_unqualified_name (decl); + } + } else /* Not templated. */ { @@ -982,6 +1010,9 @@ write_template_prefix (const tree node) /* Find the template decl. */ if (decl_is_template_id (decl, &template_info)) templ = TI_TEMPLATE (template_info); + else if (TREE_CODE (type) == TYPENAME_TYPE) + /* For a typename type, all we have is the name. */ + templ = DECL_NAME (decl); else { gcc_assert (CLASSTYPE_TEMPLATE_ID_P (type)); @@ -1020,11 +1051,13 @@ write_template_prefix (const tree node) return; /* In G++ 3.2, the name of the template template parameter was used. */ - if (TREE_CODE (TREE_TYPE (templ)) == TEMPLATE_TEMPLATE_PARM + if (TREE_TYPE (templ) + && TREE_CODE (TREE_TYPE (templ)) == TEMPLATE_TEMPLATE_PARM && !abi_version_at_least (2)) G.need_abi_warning = true; - if (TREE_CODE (TREE_TYPE (templ)) == TEMPLATE_TEMPLATE_PARM + if (TREE_TYPE (templ) + && TREE_CODE (TREE_TYPE (templ)) == TEMPLATE_TEMPLATE_PARM && abi_version_at_least (2)) write_template_param (TREE_TYPE (templ)); else @@ -1636,7 +1669,7 @@ write_type (tree type) break; case TYPE_PACK_EXPANSION: - write_string ("U10__variadic"); + write_string ("Dp"); write_type (PACK_EXPANSION_PATTERN (type)); break; @@ -1750,9 +1783,9 @@ write_builtin_type (tree type) if (type == wchar_type_node) write_char ('w'); else if (type == char16_type_node) - write_string ("u8char16_t"); + write_string ("Ds"); else if (type == char32_type_node) - write_string ("u8char32_t"); + write_string ("Di"); else if (TYPE_FOR_JAVA (type)) write_java_integer_type_codes (type); else @@ -2009,6 +2042,35 @@ write_template_args (tree args) write_char ('E'); } +/* Write out the + <unqualified-name> + <unqualified-name> <template-args> + part of SCOPE_REF or COMPONENT_REF mangling. */ + +static void +write_member_name (tree member) +{ + if (TREE_CODE (member) == IDENTIFIER_NODE) + write_source_name (member); + else if (DECL_P (member)) + { + /* G++ 3.2 incorrectly put out both the "sr" code and + the nested name of the qualified name. */ + G.need_abi_warning = 1; + write_unqualified_name (member); + } + else if (TREE_CODE (member) == TEMPLATE_ID_EXPR) + { + tree name = TREE_OPERAND (member, 0); + if (TREE_CODE (name) == OVERLOAD) + name = OVL_FUNCTION (name); + write_member_name (name); + write_template_args (TREE_OPERAND (member, 1)); + } + else + write_expression (member); +} + /* <expression> ::= <unary operator-name> <expression> ::= <binary operator-name> <expression> <expression> ::= <expr-primary> @@ -2161,6 +2223,20 @@ write_expression (tree expr) write_template_args (template_args); } } + else if (code == COMPONENT_REF) + { + tree ob = TREE_OPERAND (expr, 0); + + if (TREE_CODE (ob) == ARROW_EXPR) + { + code = ARROW_EXPR; + ob = TREE_OPERAND (ob, 0); + } + + write_string (operator_name_info[(int)code].mangled_name); + write_expression (ob); + write_member_name (TREE_OPERAND (expr, 1)); + } else { int i; @@ -2198,8 +2274,12 @@ write_expression (tree expr) case CAST_EXPR: write_type (TREE_TYPE (expr)); if (!TREE_OPERAND (expr, 0)) - /* "T()" is mangled as "T(void)". */ + /* "T()" is mangled as "T(void)". */ write_char ('v'); + else if (list_length (TREE_OPERAND (expr, 0)) > 1) + /* FIXME the above hack for T() needs to be replaced with + something more general. */ + sorry ("mangling function-style cast with more than one argument"); else write_expression (TREE_VALUE (TREE_OPERAND (expr, 0))); break; @@ -2213,27 +2293,7 @@ write_expression (tree expr) /* Handle pointers-to-members specially. */ case SCOPE_REF: write_type (TREE_OPERAND (expr, 0)); - if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE) - write_source_name (TREE_OPERAND (expr, 1)); - else if (TREE_CODE (TREE_OPERAND (expr, 1)) == TEMPLATE_ID_EXPR) - { - tree template_id; - tree name; - - template_id = TREE_OPERAND (expr, 1); - name = TREE_OPERAND (template_id, 0); - /* FIXME: What about operators? */ - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); - write_source_name (TREE_OPERAND (template_id, 0)); - write_template_args (TREE_OPERAND (template_id, 1)); - } - else - { - /* G++ 3.2 incorrectly put out both the "sr" code and - the nested name of the qualified name. */ - G.need_abi_warning = 1; - write_encoding (TREE_OPERAND (expr, 1)); - } + write_member_name (TREE_OPERAND (expr, 1)); break; default: @@ -2338,8 +2398,10 @@ write_template_arg (tree node) /* Expand the template argument pack. */ tree args = ARGUMENT_PACK_ARGS (node); int i, length = TREE_VEC_LENGTH (args); + write_char ('I'); for (i = 0; i < length; ++i) write_template_arg (TREE_VEC_ELT (args, i)); + write_char ('E'); } else if (TYPE_P (node)) write_type (node); diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index a04d7312216..0da373ce2a6 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3484,7 +3484,6 @@ do_using_directive (tree name_space) if (!toplevel_bindings_p ()) { push_using_directive (name_space); - context = current_scope (); } else { @@ -3492,12 +3491,12 @@ do_using_directive (tree name_space) add_using_namespace (current_namespace, name_space, 0); if (current_namespace != global_namespace) context = current_namespace; - } - /* Emit debugging info. */ - if (!processing_template_decl) - (*debug_hooks->imported_module_or_decl) (name_space, NULL_TREE, - context, false); + /* Emit debugging info. */ + if (!processing_template_decl) + (*debug_hooks->imported_module_or_decl) (name_space, NULL_TREE, + context, false); + } } /* Deal with a using-directive seen by the parser. Currently we only diff --git a/gcc/cp/operators.def b/gcc/cp/operators.def index 9c2dd8b2ca1..20c74d88220 100644 --- a/gcc/cp/operators.def +++ b/gcc/cp/operators.def @@ -125,7 +125,8 @@ DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", 2) DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", 2) DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", 2) DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", 2) -DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", 2) +DEF_SIMPLE_OPERATOR ("->", ARROW_EXPR, "pt", 2) +DEF_SIMPLE_OPERATOR (".", COMPONENT_REF, "dt", 2) DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", 2) DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", 2) DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", 2) @@ -152,4 +153,4 @@ DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", 3) DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", -1) /* Variadic templates extension. */ -DEF_SIMPLE_OPERATOR ("...", EXPR_PACK_EXPANSION, "pu", 1) +DEF_SIMPLE_OPERATOR ("...", EXPR_PACK_EXPANSION, "sp", 1) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 13e9a0f56ab..b1bbb38dfa8 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4109,7 +4109,7 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv, cond = cp_build_binary_op (elocus, TREE_CODE (cond), decl, diff, tf_warning_or_error); - incr = build_modify_expr (decl, PLUS_EXPR, incr); + incr = build_modify_expr (elocus, decl, PLUS_EXPR, incr); orig_body = *body; *body = push_stmt_list (); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 75bcf9c6913..b115e2871d8 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2405,8 +2405,8 @@ build_x_indirect_ref (tree expr, const char *errorstring, /* Helper function called from c-common. */ tree -build_indirect_ref (tree ptr, const char *errorstring, - location_t loc __attribute__ ((__unused__))) +build_indirect_ref (location_t loc __attribute__ ((__unused__)), + tree ptr, const char *errorstring) { return cp_build_indirect_ref (ptr, errorstring, tf_warning_or_error); } @@ -3349,7 +3349,7 @@ cp_build_binary_op (location_t location, { enum tree_code tcode0 = code0, tcode1 = code1; - warn_for_div_by_zero (op1); + warn_for_div_by_zero (location, op1); if (tcode0 == COMPLEX_TYPE || tcode0 == VECTOR_TYPE) tcode0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0))); @@ -3385,7 +3385,7 @@ cp_build_binary_op (location_t location, case TRUNC_MOD_EXPR: case FLOOR_MOD_EXPR: - warn_for_div_by_zero (op1); + warn_for_div_by_zero (location, op1); if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { @@ -4642,7 +4642,8 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, /* Hook for the c-common bits that build a unary op. */ tree -build_unary_op (enum tree_code code, tree xarg, int noconvert) +build_unary_op (location_t location ATTRIBUTE_UNUSED, + enum tree_code code, tree xarg, int noconvert) { return cp_build_unary_op (code, xarg, noconvert, tf_warning_or_error); } @@ -5757,7 +5758,8 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain) /* For use from the C common bits. */ tree -build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) +build_modify_expr (location_t location ATTRIBUTE_UNUSED, + tree lhs, enum tree_code modifycode, tree rhs) { return cp_build_modify_expr (lhs, modifycode, rhs, tf_warning_or_error); } @@ -5940,7 +5942,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, || MAYBE_CLASS_TYPE_P (lhstype))); lhs = stabilize_reference (lhs); - newrhs = cp_build_binary_op (EXPR_LOCATION (lhs), + newrhs = cp_build_binary_op (input_location, modifycode, lhs, rhs, complain); if (newrhs == error_mark_node) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 6d9ebf167b6..b1b8d72bc9b 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -12236,6 +12236,7 @@ The processor names are: @samp{r2000}, @samp{r3000}, @samp{r3900}, @samp{r4000}, @samp{r4400}, @samp{r4600}, @samp{r4650}, @samp{r6000}, @samp{r8000}, @samp{rm7000}, @samp{rm9000}, +@samp{r10000}, @samp{r12000}, @samp{r14000}, @samp{r16000}, @samp{sb1}, @samp{sr71000}, @samp{vr4100}, @samp{vr4111}, @samp{vr4120}, @samp{vr4130}, @samp{vr4300}, diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 148e19ddc9a..a12de2152bb 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -2930,9 +2930,11 @@ constituent instructions might not. When a @code{clobber} expression for a register appears inside a @code{parallel} with other side effects, the register allocator guarantees that the register is unoccupied both before and after that -insn. However, the reload phase may allocate a register used for one of -the inputs unless the @samp{&} constraint is specified for the selected -alternative (@pxref{Modifiers}). You can clobber either a specific hard +insn if it is a hard register clobber or the @samp{&} constraint +is specified for at least one alternative (@pxref{Modifiers}) of the +clobber. However, the reload phase may allocate a register used for +one of the inputs unless the @samp{&} constraint is specified for the +selected alternative. You can clobber either a specific hard register, a pseudo register, or a @code{scratch} expression; in the latter two cases, GCC will allocate a hard register that is available there for use as a temporary. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index e39e687edbb..ed4d74d0e51 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -4489,6 +4489,8 @@ static bool dwarf2out_ignore_block (const_tree); static void dwarf2out_global_decl (tree); static void dwarf2out_type_decl (tree, int); static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool); +static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree, + dw_die_ref); static void dwarf2out_abstract_function (tree); static void dwarf2out_var_location (rtx); static void dwarf2out_begin_function (tree); @@ -4746,6 +4748,10 @@ static GTY((param_is (struct dwarf_file_data))) htab_t file_table; The key is a DECL_UID() which is a unique number identifying each decl. */ static GTY ((param_is (struct die_struct))) htab_t decl_die_table; +/* A hash table of references to DIE's that describe COMMON blocks. + The key is DECL_UID() ^ die_parent. */ +static GTY ((param_is (struct die_struct))) htab_t common_block_die_table; + /* Node of the variable location list. */ struct var_loc_node GTY ((chain_next ("%h.next"))) { @@ -4958,6 +4964,8 @@ static void equate_type_number_to_die (tree, dw_die_ref); static hashval_t decl_die_table_hash (const void *); static int decl_die_table_eq (const void *, const void *); static dw_die_ref lookup_decl_die (tree); +static hashval_t common_block_die_table_hash (const void *); +static int common_block_die_table_eq (const void *, const void *); static hashval_t decl_loc_table_hash (const void *); static int decl_loc_table_eq (const void *, const void *); static var_loc_list *lookup_decl_loc (const_tree); @@ -13810,6 +13818,26 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) } +/* Returns a hash value for X (which really is a die_struct). */ + +static hashval_t +common_block_die_table_hash (const void *x) +{ + const_dw_die_ref d = (const_dw_die_ref) x; + return (hashval_t) d->decl_id ^ htab_hash_pointer (d->die_parent); +} + +/* Return nonzero if decl_id and die_parent of die_struct X is the same + as decl_id and die_parent of die_struct Y. */ + +static int +common_block_die_table_eq (const void *x, const void *y) +{ + const_dw_die_ref d = (const_dw_die_ref) x; + const_dw_die_ref e = (const_dw_die_ref) y; + return d->decl_id == e->decl_id && d->die_parent == e->die_parent; +} + /* Generate a DIE to represent a declared data object. */ static void @@ -13851,6 +13879,7 @@ gen_variable_die (tree decl, dw_die_ref context_die) tree field; dw_die_ref com_die; dw_loc_descr_ref loc; + die_node com_die_arg; var_die = lookup_decl_die (decl); if (var_die) @@ -13861,21 +13890,41 @@ gen_variable_die (tree decl, dw_die_ref context_die) if (loc) { if (off) - add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst, + { + /* Optimize the common case. */ + if (loc->dw_loc_opc == DW_OP_addr + && loc->dw_loc_next == NULL + && GET_CODE (loc->dw_loc_oprnd1.v.val_addr) + == SYMBOL_REF) + loc->dw_loc_oprnd1.v.val_addr + = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off); + else + add_loc_descr (&loc, + new_loc_descr (DW_OP_plus_uconst, off, 0)); + } add_AT_loc (var_die, DW_AT_location, loc); remove_AT (var_die, DW_AT_declaration); } } return; } + + if (common_block_die_table == NULL) + common_block_die_table + = htab_create_ggc (10, common_block_die_table_hash, + common_block_die_table_eq, NULL); + field = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0); - com_die = lookup_decl_die (com_decl); + com_die_arg.decl_id = DECL_UID (com_decl); + com_die_arg.die_parent = context_die; + com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg); loc = loc_descriptor_from_tree (com_decl); if (com_die == NULL) { const char *cnam = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (com_decl)); + void **slot; com_die = new_die (DW_TAG_common_block, context_die, decl); add_name_and_src_coords_attributes (com_die, com_decl); @@ -13889,7 +13938,9 @@ gen_variable_die (tree decl, dw_die_ref context_die) else if (DECL_EXTERNAL (decl)) add_AT_flag (com_die, DW_AT_declaration, 1); add_pubname_string (cnam, com_die); /* ??? needed? */ - equate_decl_number_to_die (com_decl, com_die); + com_die->decl_id = DECL_UID (com_decl); + slot = htab_find_slot (common_block_die_table, com_die, INSERT); + *slot = (void *) com_die; } else if (get_AT (com_die, DW_AT_location) == NULL && loc) { @@ -13905,7 +13956,17 @@ gen_variable_die (tree decl, dw_die_ref context_die) if (loc) { if (off) - add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst, off, 0)); + { + /* Optimize the common case. */ + if (loc->dw_loc_opc == DW_OP_addr + && loc->dw_loc_next == NULL + && GET_CODE (loc->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF) + loc->dw_loc_oprnd1.v.val_addr + = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off); + else + add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst, + off, 0)); + } add_AT_loc (var_die, DW_AT_location, loc); } else if (DECL_EXTERNAL (decl)) @@ -14918,6 +14979,9 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth) if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl) && !(is_fortran () && TREE_PUBLIC (decl))) ; + else if (TREE_CODE (decl) == IMPORTED_DECL) + dwarf2out_imported_module_or_decl_1 (decl, DECL_NAME (decl), + stmt, context_die); else gen_decl_die (decl, context_die); } @@ -15309,6 +15373,7 @@ gen_decl_die (tree decl, dw_die_ref context_die) break; case NAMESPACE_DECL: + case IMPORTED_DECL: gen_namespace_die (decl); break; @@ -15343,44 +15408,20 @@ dwarf2out_type_decl (tree decl, int local) } /* Output debug information for imported module or decl DECL. - NAME is non-NULL name in context if the decl has been renamed. - CHILD is true if decl is one of the renamed decls as part of - importing whole module. */ - + NAME is non-NULL name in the lexical block if the decl has been renamed. + LEXICAL_BLOCK is the lexical block (which TREE_CODE is a BLOCK) + that DECL belongs to. + LEXICAL_BLOCK_DIE is the DIE of LEXICAL_BLOCK. */ static void -dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, - bool child) +dwarf2out_imported_module_or_decl_1 (tree decl, + tree name, + tree lexical_block, + dw_die_ref lexical_block_die) { - dw_die_ref imported_die, at_import_die; - dw_die_ref scope_die; expanded_location xloc; + dw_die_ref imported_die = NULL; + dw_die_ref at_import_die; - if (debug_info_level <= DINFO_LEVEL_TERSE) - return; - - gcc_assert (decl); - - /* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs. - We need decl DIE for reference and scope die. First, get DIE for the decl - itself. */ - - /* Get the scope die for decl context. Use comp_unit_die for global module - or decl. If die is not found for non globals, force new die. */ - if (context - && TYPE_P (context) - && !should_emit_struct_debug (context, DINFO_USAGE_DIR_USE)) - return; - scope_die = get_context_die (context); - - if (child) - { - gcc_assert (scope_die->die_child); - gcc_assert (scope_die->die_child->die_tag == DW_TAG_imported_module); - gcc_assert (TREE_CODE (decl) != NAMESPACE_DECL); - scope_die = scope_die->die_child; - } - - /* For TYPE_DECL or CONST_DECL, lookup TREE_TYPE. */ if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL) { if (is_base_type (TREE_TYPE (decl))) @@ -15398,6 +15439,19 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, gcc_assert (at_import_die); } } + else if (TREE_CODE (decl) == IMPORTED_DECL) + { + tree imported_ns_decl; + /* IMPORTED_DECL nodes that are not imported namespace are just not + supported yet. */ + gcc_assert (DECL_INITIAL (decl) + && TREE_CODE (DECL_INITIAL (decl)) == NAMESPACE_DECL); + imported_ns_decl = DECL_INITIAL (decl); + at_import_die = lookup_decl_die (imported_ns_decl); + if (!at_import_die) + at_import_die = force_decl_die (imported_ns_decl); + gcc_assert (at_import_die); + } else { at_import_die = lookup_decl_die (decl); @@ -15421,20 +15475,66 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, } } - /* OK, now we have DIEs for decl as well as scope. Emit imported die. */ if (TREE_CODE (decl) == NAMESPACE_DECL) - imported_die = new_die (DW_TAG_imported_module, scope_die, context); + imported_die = new_die (DW_TAG_imported_module, + lexical_block_die, + lexical_block); else - imported_die = new_die (DW_TAG_imported_declaration, scope_die, context); + imported_die = new_die (DW_TAG_imported_declaration, + lexical_block_die, + lexical_block); xloc = expand_location (input_location); add_AT_file (imported_die, DW_AT_decl_file, lookup_filename (xloc.file)); add_AT_unsigned (imported_die, DW_AT_decl_line, xloc.line); if (name) - add_AT_string (imported_die, DW_AT_name, IDENTIFIER_POINTER (name)); + add_AT_string (imported_die, DW_AT_name, + IDENTIFIER_POINTER (name)); add_AT_die_ref (imported_die, DW_AT_import, at_import_die); } +/* Output debug information for imported module or decl DECL. + NAME is non-NULL name in context if the decl has been renamed. + CHILD is true if decl is one of the renamed decls as part of + importing whole module. */ + +static void +dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, + bool child) +{ + /* dw_die_ref at_import_die; */ + dw_die_ref scope_die; + + if (debug_info_level <= DINFO_LEVEL_TERSE) + return; + + gcc_assert (decl); + + /* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs. + We need decl DIE for reference and scope die. First, get DIE for the decl + itself. */ + + /* Get the scope die for decl context. Use comp_unit_die for global module + or decl. If die is not found for non globals, force new die. */ + if (context + && TYPE_P (context) + && !should_emit_struct_debug (context, DINFO_USAGE_DIR_USE)) + return; + scope_die = get_context_die (context); + + if (child) + { + gcc_assert (scope_die->die_child); + gcc_assert (scope_die->die_child->die_tag == DW_TAG_imported_module); + gcc_assert (TREE_CODE (decl) != NAMESPACE_DECL); + scope_die = scope_die->die_child; + } + + /* OK, now we have DIEs for decl as well as scope. Emit imported die. */ + dwarf2out_imported_module_or_decl_1 (decl, name, context, scope_die); + +} + /* Write the debugging output for DECL. */ void @@ -15519,6 +15619,7 @@ dwarf2out_decl (tree decl) break; case NAMESPACE_DECL: + case IMPORTED_DECL: if (debug_info_level <= DINFO_LEVEL_TERSE) return; if (lookup_decl_die (decl) != NULL) diff --git a/gcc/expmed.c b/gcc/expmed.c index ae5ad0a2f12..5e8d7f30324 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -3075,7 +3075,8 @@ expand_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, { /* If we are multiplying in DImode, it may still be a win to try to work with shifts and adds. */ - if (CONST_DOUBLE_HIGH (op1) == 0) + if (CONST_DOUBLE_HIGH (op1) == 0 + && CONST_DOUBLE_LOW (op1) > 0) coeff = CONST_DOUBLE_LOW (op1); else if (CONST_DOUBLE_LOW (op1) == 0 && EXACT_POWER_OF_2_OR_ZERO_P (CONST_DOUBLE_HIGH (op1))) diff --git a/gcc/expr.c b/gcc/expr.c index 32c8d01fe7f..277a6e1a33a 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -5021,6 +5021,9 @@ count_type_elements (const_tree type, bool allow_flexarr) case REFERENCE_TYPE: return 1; + case ERROR_MARK: + return 0; + case VOID_TYPE: case METHOD_TYPE: case FUNCTION_TYPE: diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 53f3f0c1526..b0ef1cef8be 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,12 @@ +2008-10-07 Jakub Jelinek <jakub@redhat.com> + + * f95-lang.c (poplevel): Don't clear BLOCK_VARS if functionbody. + * trans-decl.c (gfc_build_qualified_array): Build accurate debug type + even if nest. + (build_entry_thunks, gfc_generate_function_code, + gfc_generate_constructors): Ensure DECL_SAVED_TREE is a BIND_EXPR + with DECL_INITIAL as its BLOCK. + 2008-10-05 Paul Thomas <pault@gcc.gnu.org> PR fortran/35680 diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index cf0dc2d48b7..a7d6c8f66a5 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -430,14 +430,8 @@ poplevel (int keep, int reverse, int functionbody) current_binding_level = current_binding_level->level_chain; if (functionbody) - { - /* This is the top level block of a function. The ..._DECL chain stored - in BLOCK_VARS are the function's parameters (PARM_DECL nodes). Don't - leave them in the BLOCK because they are found in the FUNCTION_DECL - instead. */ - DECL_INITIAL (current_function_decl) = block_node; - BLOCK_VARS (block_node) = 0; - } + /* This is the top level block of a function. */ + DECL_INITIAL (current_function_decl) = block_node; else if (current_binding_level == global_binding_level) /* When using gfc_start_block/gfc_finish_block from middle-end hooks, don't add newly created BLOCKs as subblocks of global_binding_level. */ diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 20253e668ca..1b47f2673e6 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -704,7 +704,7 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym) layout_type (type); } - if (nest || write_symbols == NO_DEBUG) + if (write_symbols == NO_DEBUG) return; if (TYPE_NAME (type) != NULL_TREE @@ -1761,7 +1761,7 @@ build_entry_thunks (gfc_namespace * ns) thunk_fndecl = thunk_sym->backend_decl; - gfc_start_block (&body); + gfc_init_block (&body); /* Pass extra parameter identifying this entry point. */ tmp = build_int_cst (gfc_array_index_type, el->id); @@ -1869,8 +1869,12 @@ build_entry_thunks (gfc_namespace * ns) /* Finish off this function and send it for code generation. */ DECL_SAVED_TREE (thunk_fndecl) = gfc_finish_block (&body); + tmp = getdecls (); poplevel (1, 0, 1); BLOCK_SUPERCONTEXT (DECL_INITIAL (thunk_fndecl)) = thunk_fndecl; + DECL_SAVED_TREE (thunk_fndecl) + = build3_v (BIND_EXPR, tmp, DECL_SAVED_TREE (thunk_fndecl), + DECL_INITIAL (thunk_fndecl)); /* Output the GENERIC tree. */ dump_function (TDI_original, thunk_fndecl); @@ -3652,7 +3656,7 @@ gfc_generate_function_code (gfc_namespace * ns) trans_function_start (sym); - gfc_start_block (&block); + gfc_init_block (&block); if (ns->entries && ns->proc_name->ts.type == BT_CHARACTER) { @@ -3886,11 +3890,16 @@ gfc_generate_function_code (gfc_namespace * ns) saved_function_decls = NULL_TREE; DECL_SAVED_TREE (fndecl) = gfc_finish_block (&block); + decl = getdecls (); /* Finish off this function and send it for code generation. */ poplevel (1, 0, 1); BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; + DECL_SAVED_TREE (fndecl) + = build3_v (BIND_EXPR, decl, DECL_SAVED_TREE (fndecl), + DECL_INITIAL (fndecl)); + /* Output the GENERIC tree. */ dump_function (TDI_original, fndecl); @@ -3969,9 +3978,13 @@ gfc_generate_constructors (void) DECL_SAVED_TREE (fndecl) = build_stmt (EXPR_STMT, tmp); } + decl = getdecls (); poplevel (1, 0, 1); BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; + DECL_SAVED_TREE (fndecl) + = build3_v (BIND_EXPR, decl, DECL_SAVED_TREE (fndecl), + DECL_INITIAL (fndecl)); free_after_parsing (cfun); free_after_compilation (cfun); diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 2befb43ecff..c6a79fbe8b7 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -2238,10 +2238,11 @@ maybe_with_size_expr (tree *expr_p) /* Helper for gimplify_call_expr. Gimplify a single argument *ARG_P - Store any side-effects in PRE_P. */ + Store any side-effects in PRE_P. CALL_LOCATION is the location of + the CALL_EXPR. */ static enum gimplify_status -gimplify_arg (tree *arg_p, gimple_seq *pre_p) +gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location) { bool (*test) (tree); fallback_t fb; @@ -2259,6 +2260,10 @@ gimplify_arg (tree *arg_p, gimple_seq *pre_p) /* If this is a variable sized type, we must remember the size. */ maybe_with_size_expr (arg_p); + /* Make sure arguments have the same location as the function call + itself. */ + protected_set_expr_location (*arg_p, call_location); + /* There is a sequence point before a function call. Side effects in the argument list must occur before the actual call. So, when gimplifying arguments, force gimplify_expr to use an internal @@ -2448,7 +2453,8 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) be the plain PARM_DECL. */ if ((i != 1) || !builtin_va_start_p) { - t = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p); + t = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p, + EXPR_LOCATION (*expr_p)); if (t == GS_ERROR) ret = GS_ERROR; @@ -3095,10 +3101,10 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value, from = TREE_OPERAND (*expr_p, 1); from_ptr = build_fold_addr_expr (from); - gimplify_arg (&from_ptr, seq_p); + gimplify_arg (&from_ptr, seq_p, EXPR_LOCATION (*expr_p)); to_ptr = build_fold_addr_expr (to); - gimplify_arg (&to_ptr, seq_p); + gimplify_arg (&to_ptr, seq_p, EXPR_LOCATION (*expr_p)); t = implicit_built_in_decls[BUILT_IN_MEMCPY]; @@ -3145,7 +3151,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value, to = TREE_OPERAND (*expr_p, 0); to_ptr = build_fold_addr_expr (to); - gimplify_arg (&to_ptr, seq_p); + gimplify_arg (&to_ptr, seq_p, EXPR_LOCATION (*expr_p)); t = implicit_built_in_decls[BUILT_IN_MEMSET]; gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size); diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c index 609708e9069..c1b2bdd6548 100644 --- a/gcc/ira-lives.c +++ b/gcc/ira-lives.c @@ -209,20 +209,15 @@ clear_allocno_live (ira_allocno_t a) sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (a)); } -/* Mark the register referenced by use or def REF as live - Store a 1 in hard_regs_live or allocnos_live for this register or - the corresponding allocno, record how many consecutive hardware - registers it actually needs. */ - +/* Mark the register REG as live. Store a 1 in hard_regs_live or + allocnos_live for this register or the corresponding allocno, + record how many consecutive hardware registers it actually + needs. */ static void -mark_ref_live (struct df_ref *ref) +mark_reg_live (rtx reg) { - rtx reg; int regno; - reg = DF_REF_REG (ref); - if (GET_CODE (reg) == SUBREG) - reg = SUBREG_REG (reg); gcc_assert (REG_P (reg)); regno = REGNO (reg); @@ -269,32 +264,25 @@ mark_ref_live (struct df_ref *ref) } } -/* Return true if the definition described by DEF conflicts with the - instruction's inputs. */ -static bool -def_conflicts_with_inputs_p (struct df_ref *def) +/* Mark the register referenced by use or def REF as live. */ +static void +mark_ref_live (struct df_ref *ref) { - /* Conservatively assume that the condition is true for all clobbers. */ - return DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER); + rtx reg; + + reg = DF_REF_REG (ref); + if (GET_CODE (reg) == SUBREG) + reg = SUBREG_REG (reg); + mark_reg_live (reg); } -/* Mark the register referenced by definition DEF as dead, if the - definition is a total one. Store a 0 in hard_regs_live or +/* Mark the register REG as dead. Store a 0 in hard_regs_live or allocnos_live for the register. */ static void -mark_ref_dead (struct df_ref *def) +mark_reg_dead (rtx reg) { - unsigned int i; - rtx reg; int regno; - if (DF_REF_FLAGS_IS_SET (def, DF_REF_PARTIAL) - || DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL)) - return; - - reg = DF_REF_REG (def); - if (GET_CODE (reg) == SUBREG) - reg = SUBREG_REG (reg); gcc_assert (REG_P (reg)); regno = REGNO (reg); @@ -312,6 +300,7 @@ mark_ref_dead (struct df_ref *def) } else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)) { + unsigned int i; int last = regno + hard_regno_nregs[regno][GET_MODE (reg)]; enum reg_class cover_class; @@ -343,6 +332,80 @@ mark_ref_dead (struct df_ref *def) } } +/* Mark the register referenced by definition DEF as dead, if the + definition is a total one. */ +static void +mark_ref_dead (struct df_ref *def) +{ + rtx reg; + + if (DF_REF_FLAGS_IS_SET (def, DF_REF_PARTIAL) + || DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL)) + return; + + reg = DF_REF_REG (def); + if (GET_CODE (reg) == SUBREG) + reg = SUBREG_REG (reg); + mark_reg_dead (reg); +} + +/* Mark early clobber registers of the current INSN as live (if + LIVE_P) or dead. Return true if there are such registers. */ +static bool +mark_early_clobbers (rtx insn, bool live_p) +{ + int alt; + int def; + struct df_ref **def_rec; + bool set_p = false; + + for (def = 0; def < recog_data.n_operands; def++) + { + rtx dreg = recog_data.operand[def]; + + if (GET_CODE (dreg) == SUBREG) + dreg = SUBREG_REG (dreg); + if (! REG_P (dreg)) + continue; + + for (alt = 0; alt < recog_data.n_alternatives; alt++) + if ((recog_op_alt[def][alt].earlyclobber) + && (recog_op_alt[def][alt].cl != NO_REGS)) + break; + + if (alt >= recog_data.n_alternatives) + continue; + + if (live_p) + mark_reg_live (dreg); + else + mark_reg_dead (dreg); + set_p = true; + } + + for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) + if (DF_REF_FLAGS_IS_SET (*def_rec, DF_REF_MUST_CLOBBER)) + { + rtx dreg = DF_REF_REG (*def_rec); + + if (GET_CODE (dreg) == SUBREG) + dreg = SUBREG_REG (dreg); + if (! REG_P (dreg) || REGNO (dreg) >= FIRST_PSEUDO_REGISTER) + continue; + + /* Hard register clobbers are believed to be early clobber + because there is no way to say that non-operand hard + register clobbers are not early ones. */ + if (live_p) + mark_ref_live (*def_rec); + else + mark_ref_dead (*def_rec); + set_p = true; + } + + return set_p; +} + /* Checks that CONSTRAINTS permits to use only one hard register. If it is so, the function returns the class of the hard register. Otherwise it returns NO_REGS. */ @@ -580,6 +643,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) bitmap_iterator bi; bitmap reg_live_out; unsigned int px; + bool set_p; bb = loop_tree_node->bb; if (bb != NULL) @@ -698,6 +762,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) } extract_insn (insn); + preprocess_constraints (); process_single_reg_class_operands (false, freq); /* See which defined values die here. */ @@ -733,19 +798,20 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) mark_ref_live (*use_rec); - /* If any defined values conflict with the inputs, mark those - defined values as live. */ - for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) - if (def_conflicts_with_inputs_p (*def_rec)) - mark_ref_live (*def_rec); + set_p = mark_early_clobbers (insn, true); process_single_reg_class_operands (true, freq); - /* See which of the defined values we marked as live are dead - before the instruction. */ - for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) - if (def_conflicts_with_inputs_p (*def_rec)) - mark_ref_dead (*def_rec); + if (set_p) + { + mark_early_clobbers (insn, false); + + /* Mark each used value as live again. For example, a + hard register can be in clobber and in an insn + input. */ + for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) + mark_ref_live (*use_rec); + } curr_point++; } diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index fb9b664d2b8..f980814c07b 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,29 @@ +2008-10-06 Aldy Hernandez <aldyh@redhat.com> + + * objc-act.c (objc_build_string_object): Pass location to + build_unary_op. + (init_def_list): Same. + (init_objc_symtab): Same. + (init_module_descriptor): Same. + (build_module_initializer_routine): Same. + (generate_static_references): Same. + (build_typed_selector_reference): Same. + (add_objc_string): Same. + (objc_substitute_decl): Same. + (objc_build_ivar_assignment): Same. + (objc_build_global_assignment): Same. + (objc_build_strong_cast_assignment): Same. + (generate_protocols): Same. + (build_protocol_initializer): Same. + (build_dispatch_table_initializer): Same. + (generate_protocol_list): Same. + (build_category_initializer): Same. + (build_shared_structure_initializer): Same. + (generate_shared_structures): Same. + (objc_build_protocol_expr): Same. + (build_ivar_reference): Same. + (get_super_receiver): Same. + 2008-09-23 Aldy Hernandez <aldyh@redhat.com> * objc-act.c (next_sjlj_build_enter_and_setjmp): Call diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 9ea40eafbec..c23fb9ecba2 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -1940,10 +1940,12 @@ objc_build_string_object (tree string) initlist = build_tree_list (fields, flag_next_runtime - ? build_unary_op (ADDR_EXPR, string_class_decl, 0) + ? build_unary_op (input_location, + ADDR_EXPR, string_class_decl, 0) : build_int_cst (NULL_TREE, 0)); fields = TREE_CHAIN (fields); - initlist = tree_cons (fields, build_unary_op (ADDR_EXPR, string, 1), + initlist = tree_cons (fields, build_unary_op (input_location, + ADDR_EXPR, string, 1), initlist); fields = TREE_CHAIN (fields); initlist = tree_cons (fields, build_int_cst (NULL_TREE, length), @@ -1966,7 +1968,8 @@ objc_build_string_object (tree string) } addr = convert (build_pointer_type (constant_string_type), - build_unary_op (ADDR_EXPR, desc->constructor, 1)); + build_unary_op (input_location, + ADDR_EXPR, desc->constructor, 1)); return addr; } @@ -2104,7 +2107,8 @@ init_def_list (tree type) { if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE) { - expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0); + expr = build_unary_op (input_location, + ADDR_EXPR, impent->class_decl, 0); initlist = tree_cons (NULL_TREE, expr, initlist); } } @@ -2114,7 +2118,8 @@ init_def_list (tree type) { if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE) { - expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0); + expr = build_unary_op (input_location, + ADDR_EXPR, impent->class_decl, 0); initlist = tree_cons (NULL_TREE, expr, initlist); } } @@ -2125,7 +2130,8 @@ init_def_list (tree type) tree expr; if (static_instances_decl) - expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0); + expr = build_unary_op (input_location, + ADDR_EXPR, static_instances_decl, 0); else expr = build_int_cst (NULL_TREE, 0); @@ -2155,7 +2161,7 @@ init_objc_symtab (tree type) initlist = tree_cons (NULL_TREE, convert (build_pointer_type (objc_selector_type), - build_unary_op (ADDR_EXPR, + build_unary_op (input_location, ADDR_EXPR, UOBJC_SELECTOR_TABLE_decl, 1)), initlist); @@ -2262,7 +2268,8 @@ init_module_descriptor (tree type) /* symtab = { ..., _OBJC_SYMBOLS, ... } */ if (UOBJC_SYMBOLS_decl) - expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0); + expr = build_unary_op (input_location, + ADDR_EXPR, UOBJC_SYMBOLS_decl, 0); else expr = build_int_cst (NULL_TREE, 0); initlist = tree_cons (NULL_TREE, expr, initlist); @@ -2345,7 +2352,7 @@ build_module_initializer_routine (void) (execclass_decl, build_tree_list (NULL_TREE, - build_unary_op (ADDR_EXPR, + build_unary_op (input_location, ADDR_EXPR, UOBJC_MODULES_decl, 0)))); add_stmt (c_end_compound_stmt (body, true)); @@ -2440,13 +2447,15 @@ generate_static_references (void) klass = TREE_VALUE (cl_chain); class_name = get_objc_string_decl (OBJC_TYPE_NAME (klass), class_names); initlist = build_tree_list (NULL_TREE, - build_unary_op (ADDR_EXPR, class_name, 1)); + build_unary_op (input_location, + ADDR_EXPR, class_name, 1)); /* Output {..., instance, ...}. */ for (in_chain = TREE_PURPOSE (cl_chain); in_chain; in_chain = TREE_CHAIN (in_chain)) { - expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1); + expr = build_unary_op (input_location, + ADDR_EXPR, TREE_VALUE (in_chain), 1); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -2456,7 +2465,8 @@ generate_static_references (void) expr = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist)); finish_var_decl (decl, expr); decls - = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls); + = tree_cons (NULL_TREE, build_unary_op (input_location, + ADDR_EXPR, decl, 1), decls); } decls = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), decls); @@ -2628,7 +2638,7 @@ build_typed_selector_reference (tree ident, tree prototype) *chain = tree_cons (prototype, ident, NULL_TREE); return_at_index: - expr = build_unary_op (ADDR_EXPR, + expr = build_unary_op (input_location, ADDR_EXPR, build_array_ref (UOBJC_SELECTOR_TABLE_decl, build_int_cst (NULL_TREE, index), input_location), @@ -2801,7 +2811,8 @@ add_objc_string (tree ident, enum string_section section) { if (TREE_VALUE (*chain) == ident) return convert (string_type_node, - build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1)); + build_unary_op (input_location, + ADDR_EXPR, TREE_PURPOSE (*chain), 1)); chain = &TREE_CHAIN (*chain); } @@ -2820,7 +2831,8 @@ add_objc_string (tree ident, enum string_section section) *chain = tree_cons (decl, ident, NULL_TREE); - return convert (string_type_node, build_unary_op (ADDR_EXPR, decl, 1)); + return convert (string_type_node, build_unary_op (input_location, + ADDR_EXPR, decl, 1)); } static GTY(()) int class_names_idx; @@ -3052,10 +3064,10 @@ objc_substitute_decl (tree expr, tree oldexpr, tree newexpr) TREE_OPERAND (expr, 1), input_location); case INDIRECT_REF: - return build_indirect_ref (objc_substitute_decl (TREE_OPERAND (expr, 0), + return build_indirect_ref (input_location, + objc_substitute_decl (TREE_OPERAND (expr, 0), oldexpr, - newexpr), "->", - input_location); + newexpr), "->"); default: return expr; } @@ -3077,7 +3089,8 @@ objc_build_ivar_assignment (tree outervar, tree lhs, tree rhs) ? objc_assign_ivar_fast_decl : objc_assign_ivar_decl); - offs = convert (integer_type_node, build_unary_op (ADDR_EXPR, offs, 0)); + offs = convert (integer_type_node, build_unary_op (input_location, + ADDR_EXPR, offs, 0)); offs = fold (offs); func_params = tree_cons (NULL_TREE, convert (objc_object_type, rhs), @@ -3095,7 +3108,7 @@ objc_build_global_assignment (tree lhs, tree rhs) tree func_params = tree_cons (NULL_TREE, convert (objc_object_type, rhs), tree_cons (NULL_TREE, convert (build_pointer_type (objc_object_type), - build_unary_op (ADDR_EXPR, lhs, 0)), + build_unary_op (input_location, ADDR_EXPR, lhs, 0)), NULL_TREE)); assemble_external (objc_assign_global_decl); @@ -3108,7 +3121,7 @@ objc_build_strong_cast_assignment (tree lhs, tree rhs) tree func_params = tree_cons (NULL_TREE, convert (objc_object_type, rhs), tree_cons (NULL_TREE, convert (build_pointer_type (objc_object_type), - build_unary_op (ADDR_EXPR, lhs, 0)), + build_unary_op (input_location, ADDR_EXPR, lhs, 0)), NULL_TREE)); assemble_external (objc_assign_strong_cast_decl); @@ -4672,7 +4685,8 @@ generate_protocols (void) if (refs_decl) refs_expr = convert (build_pointer_type (build_pointer_type (objc_protocol_template)), - build_unary_op (ADDR_EXPR, refs_decl, 0)); + build_unary_op (input_location, + ADDR_EXPR, refs_decl, 0)); else refs_expr = build_int_cst (NULL_TREE, 0); @@ -4709,7 +4723,8 @@ build_protocol_initializer (tree type, tree protocol_name, else { expr = convert (objc_method_proto_list_ptr, - build_unary_op (ADDR_EXPR, instance_methods, 0)); + build_unary_op (input_location, + ADDR_EXPR, instance_methods, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -4718,7 +4733,8 @@ build_protocol_initializer (tree type, tree protocol_name, else { expr = convert (objc_method_proto_list_ptr, - build_unary_op (ADDR_EXPR, class_methods, 0)); + build_unary_op (input_location, + ADDR_EXPR, class_methods, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -5287,7 +5303,7 @@ build_dispatch_table_initializer (tree type, tree entries) elemlist = tree_cons (NULL_TREE, convert (ptr_type_node, - build_unary_op (ADDR_EXPR, + build_unary_op (input_location, ADDR_EXPR, METHOD_DEFINITION (entries), 1)), elemlist); @@ -5471,7 +5487,8 @@ generate_protocol_list (tree i_or_p) if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE && PROTOCOL_FORWARD_DECL (pval)) { - e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0); + e = build_unary_op (input_location, ADDR_EXPR, + PROTOCOL_FORWARD_DECL (pval), 0); initlist = tree_cons (NULL_TREE, e, initlist); } } @@ -5514,7 +5531,8 @@ build_category_initializer (tree type, tree cat_name, tree class_name, else { expr = convert (objc_method_list_ptr, - build_unary_op (ADDR_EXPR, instance_methods, 0)); + build_unary_op (input_location, ADDR_EXPR, + instance_methods, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } if (!class_methods) @@ -5522,7 +5540,8 @@ build_category_initializer (tree type, tree cat_name, tree class_name, else { expr = convert (objc_method_list_ptr, - build_unary_op (ADDR_EXPR, class_methods, 0)); + build_unary_op (input_location, ADDR_EXPR, + class_methods, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -5534,7 +5553,8 @@ build_category_initializer (tree type, tree cat_name, tree class_name, expr = convert (build_pointer_type (build_pointer_type (objc_protocol_template)), - build_unary_op (ADDR_EXPR, protocol_list, 0)); + build_unary_op (input_location, ADDR_EXPR, + protocol_list, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -5599,7 +5619,8 @@ build_shared_structure_initializer (tree type, tree isa, tree super, else { expr = convert (objc_ivar_list_ptr, - build_unary_op (ADDR_EXPR, ivar_list, 0)); + build_unary_op (input_location, ADDR_EXPR, + ivar_list, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -5609,7 +5630,8 @@ build_shared_structure_initializer (tree type, tree isa, tree super, else { expr = convert (objc_method_list_ptr, - build_unary_op (ADDR_EXPR, dispatch_table, 0)); + build_unary_op (input_location, ADDR_EXPR, + dispatch_table, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -5636,7 +5658,8 @@ build_shared_structure_initializer (tree type, tree isa, tree super, expr = convert (build_pointer_type (build_pointer_type (objc_protocol_template)), - build_unary_op (ADDR_EXPR, protocol_list, 0)); + build_unary_op (input_location, ADDR_EXPR, + protocol_list, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -5790,7 +5813,7 @@ generate_shared_structures (int cls_flags) initlist = build_shared_structure_initializer (TREE_TYPE (decl), - build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0), + build_unary_op (input_location, ADDR_EXPR, UOBJC_METACLASS_decl, 0), super_expr, name_expr, convert (integer_type_node, TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE @@ -6582,7 +6605,8 @@ objc_build_protocol_expr (tree protoname) if (!PROTOCOL_FORWARD_DECL (p)) build_protocol_reference (p); - expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0); + expr = build_unary_op (input_location, + ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0); /* ??? Ideally we'd build the reference with objc_protocol_type directly, if we have it, rather than converting it here. */ @@ -6720,8 +6744,8 @@ build_ivar_reference (tree id) self_decl = convert (objc_instance_type, self_decl); /* cast */ } - return objc_build_component_ref (build_indirect_ref (self_decl, "->", - input_location), id); + return objc_build_component_ref (build_indirect_ref (input_location, + self_decl, "->"), id); } /* Compute a hash value for a given method SEL_NAME. */ @@ -8701,7 +8725,8 @@ get_super_receiver (void) /* Set receiver to self. */ super_expr = objc_build_component_ref (UOBJC_SUPER_decl, self_id); - super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl); + super_expr = build_modify_expr (input_location, + super_expr, NOP_EXPR, self_decl); super_expr_list = super_expr; /* Set class to begin searching. */ @@ -8713,7 +8738,7 @@ get_super_receiver (void) /* [_cls, __cls]Super are "pre-built" in synth_forward_declarations. */ - super_expr = build_modify_expr (super_expr, NOP_EXPR, + super_expr = build_modify_expr (input_location, super_expr, NOP_EXPR, ((TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL) ? ucls_super_ref @@ -8744,8 +8769,9 @@ get_super_receiver (void) "isa" is the first ivar in a class (which it must be). */ super_class = build_indirect_ref - (build_c_cast (build_pointer_type (objc_class_type), - super_class), "unary *", input_location); + (input_location, + build_c_cast (build_pointer_type (objc_class_type), + super_class), "unary *"); } else { @@ -8764,14 +8790,15 @@ get_super_receiver (void) } super_expr - = build_modify_expr (super_expr, NOP_EXPR, + = build_modify_expr (input_location, super_expr, NOP_EXPR, build_c_cast (TREE_TYPE (super_expr), super_class)); } super_expr_list = build_compound_expr (super_expr_list, super_expr); - super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0); + super_expr = build_unary_op (input_location, + ADDR_EXPR, UOBJC_SUPER_decl, 0); super_expr_list = build_compound_expr (super_expr_list, super_expr); return super_expr_list; diff --git a/gcc/opts.c b/gcc/opts.c index bac50b0925f..6e210ea7ceb 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1459,8 +1459,7 @@ common_handle_option (size_t scode, const char *arg, int value, print_specific_help (0, undoc_mask, all_langs_mask); /* Then display any remaining, non-language options. */ for (i = CL_MIN_OPTION_CLASS; i <= CL_MAX_OPTION_CLASS; i <<= 1) - if (i != CL_SAVE) - print_specific_help (i, undoc_mask, 0); + print_specific_help (i, undoc_mask, 0); exit_after_options = true; break; } diff --git a/gcc/opts.h b/gcc/opts.h index 7a51a0e3b52..bc290f6457c 100644 --- a/gcc/opts.h +++ b/gcc/opts.h @@ -65,14 +65,13 @@ extern const unsigned int cl_options_count; extern const char *const lang_names[]; extern const unsigned int cl_lang_count; -#define CL_SAVE (1 << 17) /* Target-specific option for attribute. */ -#define CL_PARAMS (1 << 18) /* Fake entry. Used to display --param info with --help. */ -#define CL_WARNING (1 << 19) /* Enables an (optional) warning message. */ -#define CL_OPTIMIZATION (1 << 20) /* Enables an (optional) optimization. */ -#define CL_TARGET (1 << 21) /* Target-specific option. */ -#define CL_COMMON (1 << 22) /* Language-independent. */ - -#define CL_MIN_OPTION_CLASS CL_SAVE +#define CL_PARAMS (1 << 17) /* Fake entry. Used to display --param info with --help. */ +#define CL_WARNING (1 << 18) /* Enables an (optional) warning message. */ +#define CL_OPTIMIZATION (1 << 19) /* Enables an (optional) optimization. */ +#define CL_TARGET (1 << 20) /* Target-specific option. */ +#define CL_COMMON (1 << 21) /* Language-independent. */ + +#define CL_MIN_OPTION_CLASS CL_PARAMS #define CL_MAX_OPTION_CLASS CL_COMMON /* From here on the bits describe attributes of the options. @@ -80,6 +79,7 @@ extern const unsigned int cl_lang_count; This distinction is important because --help will not list options which only have these higher bits set. */ +#define CL_SAVE (1 << 22) /* Target-specific option for attribute. */ #define CL_DISABLED (1 << 23) /* Disabled in this configuration. */ #define CL_REPORT (1 << 24) /* Report argument with -fverbose-asm */ #define CL_JOINED (1 << 25) /* If takes joined argument. */ diff --git a/gcc/print-tree.c b/gcc/print-tree.c index 16ba3929fab..fb9f12692c6 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -926,6 +926,12 @@ print_node (FILE *file, const char *prefix, tree node, int indent) case TARGET_OPTION_NODE: cl_target_option_print (file, indent + 4, TREE_TARGET_OPTION (node)); break; + case IMPORTED_DECL: + fprintf (file, " imported declaration"); + print_node_brief (file, "associated declaration", + IMPORTED_DECL_ASSOCIATED_DECL (node), + indent + 4); + break; default: if (EXCEPTIONAL_CLASS_P (node)) diff --git a/gcc/profile.c b/gcc/profile.c index 0ece72519d9..976d91cc17b 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -960,10 +960,12 @@ branch_prob (void) && (LOCATION_FILE (e->goto_locus) != LOCATION_FILE (gimple_location (last)) || (LOCATION_LINE (e->goto_locus) - != LOCATION_LINE (gimple_location (last))))) + != LOCATION_LINE (gimple_location (last))))) { basic_block new_bb = split_edge (e); - single_succ_edge (new_bb)->goto_locus = e->goto_locus; + edge ne = single_succ_edge (new_bb); + ne->goto_locus = e->goto_locus; + ne->goto_block = e->goto_block; } if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL)) && e->dest != EXIT_BLOCK_PTR) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index df7ba0b1e96..cc7ec163e07 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,77 @@ +2008-10-07 Simon Martin <simartin@users.sourceforge.net> + + PR c/35437 + * gcc.dg/struct-parse-2.c: New test. + * g++.dg/parse/struct-4.C: New test. + +2008-10-07 Jakub Jelinek <jakub@redhat.com> + + PR debug/29609 + PR debug/36690 + PR debug/37616 + * gcc.dg/debug/pr29609-1.c: New test. + * gcc.dg/debug/pr29609-2.c: New test. + * gcc.dg/debug/pr36690-1.c: New test. + * gcc.dg/debug/pr36690-2.c: New test. + * gcc.dg/debug/pr36690-3.c: New test. + * gcc.dg/debug/pr37616.c: New test. + * gcc.dg/debug/dwarf2/pr29609-1.c: New test. + * gcc.dg/debug/dwarf2/pr29609-2.c: New test. + * gcc.dg/debug/dwarf2/pr36690-1.c: New test. + * gcc.dg/debug/dwarf2/pr36690-2.c: New test. + * gcc.dg/debug/dwarf2/pr36690-3.c: New test. + * gcc.dg/debug/dwarf2/pr37616.c: New test. + +2008-10-07 H.J. Lu <hongjiu.lu@intel.com> + + PR middle-end/37731 + * gcc.dg/torture/pr37731-1.c: New. + * gcc.dg/torture/pr37731-2.c: Likewise. + +2008-10-07 Jakub Jelinek <jakub@redhat.com> + + PR debug/37738 + * gfortran.dg/debug/pr37738.f: New test. + +2008-10-07 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/loop_optimization4.adb: New test. + * gnat.dg/loop_optimization4_pkg.ad[sb]: New helper. + +2008-10-07 Bob Wilson <bob.wilson@acm.org> + + * gcc.dg/compat/struct-layout-1_generate.c (dg_options): New. Moved + dg-options lines to this array, and added options for xtensa*-*-*. + (NDG_OPTIONS): Define. + (switchfiles): Print dg-options lines from new dg_options array. + * g++.dg/compat/struct-layout-1_generate.c (dg_options): Add options + for xtensa*-*-* targets. + +2008-10-07 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/addr4.adb: New test. + * gnat.dg/addr5.adb: Likewise. + +2008-10-06 Adam Nemet <anemet@caviumnetworks.com> + + * gcc.target/mips/mips.exp (dg-mips-options): Set mips_new_gp to + 32 when -march=r3900 is passed. + * testsuite/gcc.target/mips/r3900-mult.c: New test. + +2008-10-06 Aldy Hernandez <aldyh@redhat.com> + + * gcc.dg/gomp/for-1.c: Test column. + * gcc.dg/misc-column.c: Add column tests for unary arguments. + +2008-10-06 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/unchecked_convert2.adb: New test. + +2008-10-05 Dodji Seketeli <dodji@redhat.com> + + PR c++/37410 + * g++.dg/debug/dwarf2/imported-module.C: New test. + 2008-10-05 Paul Thomas <pault@gcc.gnu.org> PR fortran/35680 diff --git a/gcc/testsuite/g++.dg/abi/mangle30.C b/gcc/testsuite/g++.dg/abi/mangle30.C new file mode 100644 index 00000000000..f0b83dbe929 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle30.C @@ -0,0 +1,22 @@ +// Test for mangling of template args in a typename type. + +struct A +{ + template <class T> + struct B + { + typedef T myT; + }; +}; + +struct C {}; + +template <class T> +void f (T t, typename T::template B<C>::myT u, typename T::template B<int>::myT v); + +int main() +{ + f (A(), C(), 1); +} + +// { dg-final { scan-assembler "_Z1fI1AEvT_NS1_1BI1CE3myTENS2_IiE3myTE" } } diff --git a/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c b/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c index 8535022b7fc..589cc787fd8 100644 --- a/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c +++ b/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c @@ -46,7 +46,8 @@ const char *dg_options[] = { "/* { dg-options \"%s-I%s\" } */\n", "/* { dg-options \"%s-I%s -mno-mmx\" { target i?86-*-* x86_64-*-* } } */\n", "/* { dg-options \"%s-I%s -fno-common\" { target hppa*-*-hpux* } } */\n", -"/* { dg-options \"%s-I%s -mno-base-addresses\" { target mmix-*-* } } */\n" +"/* { dg-options \"%s-I%s -mno-base-addresses\" { target mmix-*-* } } */\n", +"/* { dg-options \"%s-I%s -mlongcalls -mtext-section-literals\" { target xtensa*-*-* } } */\n" #define NDG_OPTIONS (sizeof (dg_options) / sizeof (dg_options[0])) }; diff --git a/gcc/testsuite/g++.dg/cpp0x/auto6.C b/gcc/testsuite/g++.dg/cpp0x/auto6.C index 713583a1a48..d2bcfedb63c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto6.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto6.C @@ -1,3 +1,4 @@ +// Tests for late-specified return type. // { dg-options "-std=c++0x" } auto f() -> int @@ -12,17 +13,81 @@ auto add(T t, U u) -> decltype (t+u) } template<class T, class U> -decltype(T()+U()) add2(T t, U u); +decltype(T()+U()) add2(T t, U u) +{ + return t+u; +} template <class T, class U> -U g (T, U); +U ag (T, U) +{ + return U(); +} template<class T, class U> -auto add3(T t, U u) -> decltype (g(t,u)); +auto add3(T t, U u) -> decltype (ag(t,u)) +{ + return ag(t,u); +} + +template <class T> +struct A +{ + T f() {} + template <class U> + T g() {} + template <class V> + struct B + { + int MEM; + }; +}; + +template <class T> +auto f(T* t) -> decltype (t->f()) +{ + return t->f(); +} + +template <class T> +auto g(T t) -> decltype (t.f()) +{ + return t.f(); +} + +template <class T, class U> +auto h(T t, U u) -> decltype (t.template g<U>()) +{ + return t.template g<U>(); +} + +struct D { }; +struct C: public A<int>::B<D> +{ +}; + +template <class T, class U, class V> +auto k(T t, U u, V v) -> decltype (t.U::template B<V>::MEM) +{ + return t.U::template B<V>::MEM; +} + +A<int> a, *p; int main() { + // { dg-final { scan-assembler "_Z3addIidEDTplsTT_sTT0_ES0_S1_" } } auto i = add(1, 2.0); + // { dg-final { scan-assembler "_Z4add2IidEDTplcvT_vcvT0_vES0_S1_" } } auto i2 = add2(1, 2.0); + // { dg-final { scan-assembler "_Z4add3IidEDTclL_Z2agEsTT_sTT0_EES0_S1_" } } auto i3 = add3(1, 2.0); + // { dg-final { scan-assembler "_Z1fI1AIiEEDTclptsTPT_1fEES3_" } } + f(p); + // { dg-final { scan-assembler "_Z1gI1AIiEEDTcldtsTT_1fEES2_" } } + g(a); + // { dg-final { scan-assembler "_Z1hI1AIiEdEDTcldtsTT_1gIT0_EEES2_S3_" } } + h(a,1.0); + // { dg-final { scan-assembler "_Z1kI1C1AIiE1DEDtdtsTT_srNT0_1BIT1_EE3MEMES4_S5_S7_" } } + k( C(), A<int>(), D() ); } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic4.C b/gcc/testsuite/g++.dg/cpp0x/variadic4.C index 6c15a6de92d..9257a92d5b9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic4.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic4.C @@ -9,7 +9,7 @@ void f_two(tuple<int, float>) {} void f_nested(tuple<int, tuple<double, char>, float>) { } -// { dg-final { scan-assembler "_Z6f_none5tupleIE" } } -// { dg-final { scan-assembler "_Z5f_one5tupleIiE" } } -// { dg-final { scan-assembler "_Z5f_two5tupleIifE" } } -// { dg-final { scan-assembler "_Z8f_nested5tupleIiS_IdcEfE" } } +// { dg-final { scan-assembler "_Z6f_none5tupleIIEE" } } +// { dg-final { scan-assembler "_Z5f_one5tupleIIiEE" } } +// { dg-final { scan-assembler "_Z5f_two5tupleIIifEE" } } +// { dg-final { scan-assembler "_Z8f_nested5tupleIIiS_IIdcEEfEE" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic42.C b/gcc/testsuite/g++.dg/cpp0x/variadic42.C index 4c6c7673d80..47d9b66da58 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic42.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic42.C @@ -8,5 +8,5 @@ void g() f<int*, float*, double*>(0, 0, 0); f<int*>(0,0,0); } -// { dg-final { scan-assembler "_Z1fIPiPfPdEvU10__variadicT_" } } -// { dg-final { scan-assembler "_Z1fIPiiiEvU10__variadicT_" } } +// { dg-final { scan-assembler "_Z1fIIPiPfPdEEvDpT_" } } +// { dg-final { scan-assembler "_Z1fIIPiiiEEvDpT_" } } diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/imported-module.C b/gcc/testsuite/g++.dg/debug/dwarf2/imported-module.C new file mode 100644 index 00000000000..7b25233f1ab --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/imported-module.C @@ -0,0 +1,35 @@ +// Contributed by Dodji Seketeli <dodji@redhat.com> +// Origin: PR debug/37410 +// { dg-do compile } + +namespace A1 + { + int aaa = 1; + }; +namespace A2 + { + int aaa = 2; + }; + +int +foo (void) +{ + int x; + + { + int block_create; + using namespace A1; + + block_create = aaa; /* break1 */ + } + + { + int block_create; + using namespace A2; + + block_create = aaa; /* break2 */ + } + + return x = 0; +} + diff --git a/gcc/testsuite/g++.dg/ext/utf-mangle.C b/gcc/testsuite/g++.dg/ext/utf-mangle.C index bb5e3822adc..a131887882a 100644 --- a/gcc/testsuite/g++.dg/ext/utf-mangle.C +++ b/gcc/testsuite/g++.dg/ext/utf-mangle.C @@ -8,7 +8,7 @@ void f1 (char32_t c) {} void f2 (char16_t *s) {} void f3 (char32_t *s) {} -// { dg-final { scan-assembler "_Z2f0u8char16_t:" } } -// { dg-final { scan-assembler "_Z2f1u8char32_t:" } } -// { dg-final { scan-assembler "_Z2f2Pu8char16_t:" } } -// { dg-final { scan-assembler "_Z2f3Pu8char32_t:" } } +// { dg-final { scan-assembler "_Z2f0Ds:" } } +// { dg-final { scan-assembler "_Z2f1Di:" } } +// { dg-final { scan-assembler "_Z2f2PDs:" } } +// { dg-final { scan-assembler "_Z2f3PDi:" } } diff --git a/gcc/testsuite/g++.dg/parse/struct-4.C b/gcc/testsuite/g++.dg/parse/struct-4.C new file mode 100644 index 00000000000..559411a19cf --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/struct-4.C @@ -0,0 +1,13 @@ +/* PR c/35437 */ +/* { dg-do "compile" } */ + +struct A +{ + int i; + struct A a; /* { dg-error "has incomplete type" } */ +}; + +void foo() +{ + struct A b = { 0 }; +} diff --git a/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c b/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c index 097ef5053a8..d50322c9f87 100644 --- a/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c +++ b/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c @@ -1,5 +1,5 @@ /* Structure layout test generator. - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. Contributed by Jakub Jelinek <jakub@redhat.com>. This file is part of GCC. @@ -42,6 +42,14 @@ along with GCC; see the file COPYING3. If not see #define COMPAT_PRLL "ll" #endif +const char *dg_options[] = { +"/* { dg-options \"%s-I%s\" } */\n", +"/* { dg-options \"%s-I%s -fno-common\" { target hppa*-*-hpux* *-*-darwin* *-*-mingw32* *-*-cygwin* } } */\n", +"/* { dg-options \"%s-I%s -mno-base-addresses\" { target mmix-*-* } } */\n", +"/* { dg-options \"%s-I%s -mlongcalls -mtext-section-literals\" { target xtensa*-*-* } } */\n" +#define NDG_OPTIONS (sizeof (dg_options) / sizeof (dg_options[0])) +}; + typedef unsigned int hashval_t; enum TYPE @@ -747,6 +755,8 @@ switchfiles (int fields) { static int filecnt; static char *destbuf, *destptr; + int i; + ++filecnt; if (outfile) fclose (outfile); @@ -774,11 +784,10 @@ switchfiles (int fields) fputs ("failed to create test files\n", stderr); exit (1); } + fprintf (outfile, "/* { dg-require-effective-target int32plus } */\n"); + for (i = 0; i < NDG_OPTIONS; i++) + fprintf (outfile, dg_options[i], "", srcdir_safe); fprintf (outfile, "\ -/* { dg-require-effective-target int32plus } */\n\ -/* { dg-options \"-I%s\" } */\n\ -/* { dg-options \"-I%s -fno-common\" { target hppa*-*-hpux* *-*-darwin* *-*-mingw32* *-*-cygwin* } } */\n\ -/* { dg-options \"-I%s -mno-base-addresses\" { target mmix-*-* } } */\n\ #include \"struct-layout-1.h\"\n\ \n\ #define TX(n, type, attrs, fields, ops) extern void test##n (void);\n\ @@ -796,33 +805,31 @@ int main (void)\n\ abort ();\n\ }\n\ exit (0);\n\ -}\n", srcdir_safe, srcdir_safe, srcdir_safe, filecnt, filecnt); +}\n", filecnt, filecnt); fclose (outfile); sprintf (destptr, "t%03d_x.c", filecnt); outfile = fopen (destbuf, "w"); if (outfile == NULL) goto fail; + for (i = 0; i < NDG_OPTIONS; i++) + fprintf (outfile, dg_options[i], "-w ", srcdir_safe); fprintf (outfile, "\ -/* { dg-options \"-w -I%s\" } */\n\ -/* { dg-options \"-w -I%s -fno-common\" { target hppa*-*-hpux* *-*-darwin* *-*-mingw32* *-*-cygwin* } } */\n\ -/* { dg-options \"-w -I%s -mno-base-addresses\" { target mmix-*-* } } */\n\ #include \"struct-layout-1_x1.h\"\n\ #include \"t%03d_test.h\"\n\ #include \"struct-layout-1_x2.h\"\n\ -#include \"t%03d_test.h\"\n", srcdir_safe, srcdir_safe, srcdir_safe, filecnt, filecnt); +#include \"t%03d_test.h\"\n", filecnt, filecnt); fclose (outfile); sprintf (destptr, "t%03d_y.c", filecnt); outfile = fopen (destbuf, "w"); if (outfile == NULL) goto fail; + for (i = 0; i < NDG_OPTIONS; i++) + fprintf (outfile, dg_options[i], "-w ", srcdir_safe); fprintf (outfile, "\ -/* { dg-options \"-w -I%s\" } */\n\ -/* { dg-options \"-w -I%s -fno-common\" { target hppa*-*-hpux* *-*-darwin* *-*-mingw32* *-*-cygwin* } } */\n\ -/* { dg-options \"-w -I%s -mno-base-addresses\" { target mmix-*-* } } */\n\ #include \"struct-layout-1_y1.h\"\n\ #include \"t%03d_test.h\"\n\ #include \"struct-layout-1_y2.h\"\n\ -#include \"t%03d_test.h\"\n", srcdir_safe, srcdir_safe, srcdir_safe, filecnt, filecnt); +#include \"t%03d_test.h\"\n", filecnt, filecnt); fclose (outfile); sprintf (destptr, "t%03d_test.h", filecnt); outfile = fopen (destbuf, "w"); diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr29609-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr29609-1.c new file mode 100644 index 00000000000..5476aac0afd --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr29609-1.c @@ -0,0 +1,32 @@ +/* PR debug/29609 */ +/* Verify that breakpoint on the break is hit. */ +/* { dg-do compile } */ +/* { dg-options "-O0 -gdwarf-2 -dA" } */ + +void abort (void); + +int +foo (void) +{ + int a, i; + + for (i = 1; i <= 10; i++) + { + if (i < 3) + a = 1; + else + break; + a = 5; + } + return a; +} + +int +main (void) +{ + if (foo () != 5) + abort (); + return 0; +} + +/* { dg-final { scan-assembler "pr29609-1.c:18" } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr29609-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr29609-2.c new file mode 100644 index 00000000000..43bc54524a9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr29609-2.c @@ -0,0 +1,53 @@ +/* PR debug/29609 */ +/* Verify that breakpoint on both goto failure; stmts is hit. */ +/* { dg-do compile } */ +/* { dg-options "-O0 -gdwarf-2 -dA" } */ + +extern void abort (void); +int x; + +int +foo (void) +{ + return 0 ^ x; +} + +int +bar (void) +{ + return 1 ^ x; +} + +int +baz (void) +{ + int c; + + if (!foo ()) + goto failure; + + if (!bar ()) + goto failure; + + return 0; + +failure: + return 1; +} + +int +main (void) +{ + if (baz () != 1) + abort (); + x = 1; + if (baz () != 1) + abort (); + x = 2; + if (baz () != 0) + abort (); + return 0; +} + +/* { dg-final { scan-assembler "pr29609-2.c:27" } } */ +/* { dg-final { scan-assembler "pr29609-2.c:30" } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr36690-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr36690-1.c new file mode 100644 index 00000000000..de90acb81bf --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr36690-1.c @@ -0,0 +1,22 @@ +/* PR debug/36690 */ +/* Verify that break func is hit. */ +/* { dg-do compile } */ +/* { dg-options "-O0 -gdwarf-2 -dA" } */ + +int i; + +void +func (void) +{ + while (i == 1) + i = 0; +} + +int +main (void) +{ + func (); + return 0; +} + +/* { dg-final { scan-assembler "pr36690-1.c:11" } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr36690-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr36690-2.c new file mode 100644 index 00000000000..2330f53858e --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr36690-2.c @@ -0,0 +1,39 @@ +/* PR debug/36690 */ +/* Verify that breakpoint can be put on goto f1, it is hit and + varz at that spot is defined and contains 5. Nowhere else + in the function should be varz in the scope. */ +/* { dg-do compile } */ +/* { dg-options "-O0 -gdwarf-2 -dA" } */ + +int cnt; + +void +bar (int i) +{ + cnt += i; +} + +void +foo (int i) +{ + if (!i) + bar (0); + else + { + static int varz = 5; + goto f1; + } + bar (1); +f1: + bar (2); +} + +int +main (void) +{ + foo (0); + foo (1); + return 0; +} + +/* { dg-final { scan-assembler "pr36690-2.c:24" } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr36690-3.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr36690-3.c new file mode 100644 index 00000000000..234ad1263b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr36690-3.c @@ -0,0 +1,53 @@ +/* PR debug/36690 */ +/* { dg-do compile } */ +/* { dg-options "-O0 -gdwarf-2 -dA" } */ + +int cnt; + +void +bar (int i) +{ + cnt += i; +} + +void +foo (int i, int j) +{ + if (j) + { + bar (i + 1); + goto f1; + } + bar (i + 2); + goto f2; +f1: + if (i > 10) + goto f3; +f2: + if (i > 40) + goto f4; + else + goto f5; +f3: + bar (i); +f4: + bar (i); +f5: + bar (i); +} + +int +main (void) +{ + foo (0, 1); + foo (11, 1); + foo (21, 0); + foo (41, 0); + return 0; +} + +/* { dg-final { scan-assembler "pr36690-3.c:19" } } */ +/* { dg-final { scan-assembler "pr36690-3.c:22" } } */ +/* { dg-final { scan-assembler "pr36690-3.c:25" } } */ +/* { dg-final { scan-assembler "pr36690-3.c:28" } } */ +/* { dg-final { scan-assembler "pr36690-3.c:30" } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr37616.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr37616.c new file mode 100644 index 00000000000..badff447a8b --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr37616.c @@ -0,0 +1,41 @@ +/* PR debug/37616 */ +/* Test that one can put breakpoints onto continue, exitlab and break + and actually see program reaching those breakpoints. */ +/* { dg-do compile } */ +/* { dg-options "-O0 -gdwarf-2 -dA" } */ + +extern void abort (void); + +int +foo (int parm) +{ + int varj, varm; + + for (varj = 0; varj < 10; varj++) + { + if (varj == 5) + continue; + if (varj == 7 && !parm) + goto exitlab; + if (varj == 9) + break; + varm = varj; + } + +exitlab: + return varm; +} + +int +main (void) +{ + if (foo (0) != 6) + abort (); + if (foo (1) != 8) + abort (); + return 0; +} + +/* { dg-final { scan-assembler "pr37616.c:17" } } */ +/* { dg-final { scan-assembler "pr37616.c:19" } } */ +/* { dg-final { scan-assembler "pr37616.c:21" } } */ diff --git a/gcc/testsuite/gcc.dg/debug/pr29609-1.c b/gcc/testsuite/gcc.dg/debug/pr29609-1.c new file mode 100644 index 00000000000..85069ebd650 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/pr29609-1.c @@ -0,0 +1,33 @@ +/* PR debug/29609 */ +/* Verify that breakpoint on the break is hit. + This version of the test just checks that it can be compiled, linked + and executed, further testing is done in corresponding gcc.dg/dwarf2/ + test and hopefully in gdb testsuite. */ +/* { dg-do run } */ +/* { dg-options "-O0 -g -dA" } */ + +extern void abort (void); + +int +foo (void) +{ + int a, i; + + for (i = 1; i <= 10; i++) + { + if (i < 3) + a = 1; + else + break; + a = 5; + } + return a; +} + +int +main (void) +{ + if (foo () != 5) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/debug/pr29609-2.c b/gcc/testsuite/gcc.dg/debug/pr29609-2.c new file mode 100644 index 00000000000..1ae1a738d97 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/pr29609-2.c @@ -0,0 +1,53 @@ +/* PR debug/29609 */ +/* Verify that breakpoint on both goto failure; stmts is hit. + This version of the test just checks that it can be compiled, linked + and executed, further testing is done in corresponding gcc.dg/dwarf2/ + test and hopefully in gdb testsuite. */ +/* { dg-do run } */ +/* { dg-options "-O0 -g -dA" } */ + +extern void abort (void); +int x; + +int +foo (void) +{ + return 0 ^ x; +} + +int +bar (void) +{ + return 1 ^ x; +} + +int +baz (void) +{ + int c; + + if (!foo ()) + goto failure; + + if (!bar ()) + goto failure; + + return 0; + +failure: + return 1; +} + +int +main (void) +{ + if (baz () != 1) + abort (); + x = 1; + if (baz () != 1) + abort (); + x = 2; + if (baz () != 0) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/debug/pr36690-1.c b/gcc/testsuite/gcc.dg/debug/pr36690-1.c new file mode 100644 index 00000000000..e3c913b6bb0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/pr36690-1.c @@ -0,0 +1,23 @@ +/* PR debug/36690 */ +/* Verify that break func is hit. + This version of the test just checks that it can be compiled, linked + and executed, further testing is done in corresponding gcc.dg/dwarf2/ + test and hopefully in gdb testsuite. */ +/* { dg-do run } */ +/* { dg-options "-O0 -g -dA" } */ + +int i; + +void +func (void) +{ + while (i == 1) + i = 0; +} + +int +main (void) +{ + func (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/debug/pr36690-2.c b/gcc/testsuite/gcc.dg/debug/pr36690-2.c new file mode 100644 index 00000000000..ddda18cf73c --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/pr36690-2.c @@ -0,0 +1,40 @@ +/* PR debug/36690 */ +/* Verify that breakpoint can be put on goto f1, it is hit and + varz at that spot is defined and contains 5. Nowhere else + in the function should be varz in the scope. + This version of the test just checks that it can be compiled, linked + and executed, further testing is done in corresponding gcc.dg/dwarf2/ + test and hopefully in gdb testsuite. */ +/* { dg-do run } */ +/* { dg-options "-O0 -g -dA" } */ + +int cnt; + +void +bar (int i) +{ + cnt += i; +} + +void +foo (int i) +{ + if (!i) + bar (0); + else + { + static int varz = 5; + goto f1; + } + bar (1); +f1: + bar (2); +} + +int +main (void) +{ + foo (0); + foo (1); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/debug/pr36690-3.c b/gcc/testsuite/gcc.dg/debug/pr36690-3.c new file mode 100644 index 00000000000..62d3494dacd --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/pr36690-3.c @@ -0,0 +1,47 @@ +/* PR debug/36690 */ +/* { dg-do run } */ +/* { dg-options "-O0 -g -dA" } */ + +int cnt; + +void +bar (int i) +{ + cnt += i; +} + +void +foo (int i, int j) +{ + if (j) + { + bar (i + 1); + goto f1; + } + bar (i + 2); + goto f2; +f1: + if (i > 10) + goto f3; +f2: + if (i > 40) + goto f4; + else + goto f5; +f3: + bar (i); +f4: + bar (i); +f5: + bar (i); +} + +int +main (void) +{ + foo (0, 1); + foo (11, 1); + foo (21, 0); + foo (41, 0); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/debug/pr37616.c b/gcc/testsuite/gcc.dg/debug/pr37616.c new file mode 100644 index 00000000000..3bbaebbdf78 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/pr37616.c @@ -0,0 +1,40 @@ +/* PR debug/37616 */ +/* Test that one can put breakpoints onto continue, exitlab and break + and actually see program reaching those breakpoints. + This version of the test just checks that it can be compiled, linked + and executed, further testing is done in corresponding gcc.dg/dwarf2/ + test and hopefully in gdb testsuite. */ +/* { dg-do run } */ +/* { dg-options "-O0 -g -dA" } */ + +extern void abort (void); + +int +foo (int parm) +{ + int varj, varm; + + for (varj = 0; varj < 10; varj++) + { + if (varj == 5) + continue; + if (varj == 7 && !parm) + goto exitlab; + if (varj == 9) + break; + varm = varj; + } + +exitlab: + return varm; +} + +int +main (void) +{ + if (foo (0) != 6) + abort (); + if (foo (1) != 8) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/gomp/for-1.c b/gcc/testsuite/gcc.dg/gomp/for-1.c index bf50f25f458..840f9478499 100644 --- a/gcc/testsuite/gcc.dg/gomp/for-1.c +++ b/gcc/testsuite/gcc.dg/gomp/for-1.c @@ -44,6 +44,6 @@ void foo (int j, int k) baz (i); #pragma omp for - for (i = 0; i < 10; i-=3, j+=2) /* { dg-error "invalid increment expression" } */ + for (i = 0; i < 10; i-=3, j+=2) /* { dg-error "23:invalid increment expression" } */ baz (i); } diff --git a/gcc/testsuite/gcc.dg/misc-column.c b/gcc/testsuite/gcc.dg/misc-column.c index f84a553959d..a24427e4baa 100644 --- a/gcc/testsuite/gcc.dg/misc-column.c +++ b/gcc/testsuite/gcc.dg/misc-column.c @@ -1,5 +1,6 @@ /* { dg-options "-fshow-column -Wall -Wfloat-equal -pedantic" } */ +int i, j; float a, b; int *p; @@ -26,4 +27,14 @@ void foo (void) if (p < 0) /* { dg-warning "9:ordered comparison of pointer with" } */ bar(); + + -q; /* { dg-error "3:wrong type argument to unary" } */ + + ~q; /* { dg-error "3:wrong type argument to bit" } */ + + ++*q; /* { dg-error "3:wrong type argument to increment" } */ + + i = j / 0; /* { dg-warning "9:division by zero" } */ + + i /= 0; /* { dg-warning "5:division by zero" } */ } diff --git a/gcc/testsuite/gcc.dg/struct-parse-2.c b/gcc/testsuite/gcc.dg/struct-parse-2.c new file mode 100644 index 00000000000..559411a19cf --- /dev/null +++ b/gcc/testsuite/gcc.dg/struct-parse-2.c @@ -0,0 +1,13 @@ +/* PR c/35437 */ +/* { dg-do "compile" } */ + +struct A +{ + int i; + struct A a; /* { dg-error "has incomplete type" } */ +}; + +void foo() +{ + struct A b = { 0 }; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr37731-1.c b/gcc/testsuite/gcc.dg/torture/pr37731-1.c new file mode 100644 index 00000000000..5c156b1f9a6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr37731-1.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ + +extern void abort (); + +unsigned long long xh = 1; + +int +main () +{ + unsigned long long yh = 0xffffffffull; + unsigned long long z = xh * yh; + + if (z != yh) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr37731-2.c b/gcc/testsuite/gcc.dg/torture/pr37731-2.c new file mode 100644 index 00000000000..a7f8f1e02e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr37731-2.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ + +extern void abort (); + +long long xh = 1; + +int +main () +{ + long long yh = 0xffffffffll; + long long z = xh * yh; + + if (z != yh) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp index 832633900c9..8e66e0a1901 100644 --- a/gcc/testsuite/gcc.target/mips/mips.exp +++ b/gcc/testsuite/gcc.target/mips/mips.exp @@ -261,6 +261,7 @@ proc dg-mips-options {args} { -mips[12] - -mips32* - -march=mips32* - + -march=r3900 - -march=24k* - -mabi=32 - -mgp32 { diff --git a/gcc/testsuite/gcc.target/mips/r3900-mult.c b/gcc/testsuite/gcc.target/mips/r3900-mult.c new file mode 100644 index 00000000000..393f1086e07 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/r3900-mult.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-mips-options "-march=r3900" } */ +/* { dg-final { scan-assembler "\tmult\t\[^\n\]*,\[^\n\]*," } } */ + +NOMIPS16 int +f (int a, int b) +{ + return a * b; +} diff --git a/gcc/testsuite/gfortran.dg/debug/pr37738.f b/gcc/testsuite/gfortran.dg/debug/pr37738.f new file mode 100644 index 00000000000..b0a787b2e52 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/debug/pr37738.f @@ -0,0 +1,30 @@ +C PR debug/37738 +C { dg-do compile } +C { dg-skip-if "DWARF-2 only" { "*-*-*" } { "*" } { "-gdwarf-2" } } +C { dg-options "-dA" } + + subroutine a + integer*4 a_i, c_i + common /block/a_i, c_i + a_i = 1 + c_i = 4 + end subroutine a + subroutine b + integer*4 b_i + common /block/b_i, d_i + b_i = 2 + d_i = 5 + end subroutine b + subroutine c + integer*4 a_i, c_i + common /block/a_i, c_i + if (a_i .ne. 2) call abort + if (c_i .ne. 5) call abort + end subroutine c + program abc + call a + call b + call c + end program abc + +C { dg-final { scan-assembler-times "DIE\[^\n\]*DW_TAG_common_block" 3 } } diff --git a/gcc/testsuite/gnat.dg/addr4.adb b/gcc/testsuite/gnat.dg/addr4.adb new file mode 100644 index 00000000000..8bb3f2c9723 --- /dev/null +++ b/gcc/testsuite/gnat.dg/addr4.adb @@ -0,0 +1,12 @@ +-- { dg-do compile } +-- { dg-options "-g" } + +procedure Addr4 is + function F return String is begin return ""; end F; + S1 : String renames F; + subtype ST is String (1 .. S1'Length); + S2 : ST; + for S2'Address use S1'Address; +begin + null; +end; diff --git a/gcc/testsuite/gnat.dg/addr5.adb b/gcc/testsuite/gnat.dg/addr5.adb new file mode 100644 index 00000000000..e331dfdc09e --- /dev/null +++ b/gcc/testsuite/gnat.dg/addr5.adb @@ -0,0 +1,10 @@ +-- { dg-do compile } +-- { dg-options "-g" } + +procedure Addr5 (Len : Integer) is + S : aliased String (1 .. Len) := (others => ' '); + C : Character; + for C'Address use S'Address; +begin + null; +end; diff --git a/gcc/testsuite/gnat.dg/loop_optimization4.adb b/gcc/testsuite/gnat.dg/loop_optimization4.adb new file mode 100644 index 00000000000..a6799f393e7 --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization4.adb @@ -0,0 +1,9 @@ +-- { dg-do run } +-- { dg-options "-O2" } + +with Loop_Optimization4_Pkg; use Loop_Optimization4_Pkg; + +procedure Loop_Optimization4 is +begin + Add ("Nothing"); +end; diff --git a/gcc/testsuite/gnat.dg/loop_optimization4_pkg.adb b/gcc/testsuite/gnat.dg/loop_optimization4_pkg.adb new file mode 100644 index 00000000000..ba372f6bddd --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization4_pkg.adb @@ -0,0 +1,17 @@ +package body Loop_Optimization4_Pkg is + + procedure Add (Phrase : String) is + begin + if Debug_Buffer_Len = Max_Debug_Buffer_Len then + return; + end if; + for I in Phrase'Range loop + Debug_Buffer_Len := Debug_Buffer_Len + 1; + Debug_Buffer (Debug_Buffer_Len) := Phrase (I); + if Debug_Buffer_Len = Max_Debug_Buffer_Len then + exit; + end if; + end loop; + end Add; + +end Loop_Optimization4_Pkg; diff --git a/gcc/testsuite/gnat.dg/loop_optimization4_pkg.ads b/gcc/testsuite/gnat.dg/loop_optimization4_pkg.ads new file mode 100644 index 00000000000..a07c4e568c6 --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization4_pkg.ads @@ -0,0 +1,9 @@ +package Loop_Optimization4_Pkg is + + Max_Debug_Buffer_Len : Natural := 8 * 1024; + Debug_Buffer : String (1 .. Max_Debug_Buffer_Len); + Debug_Buffer_Len : Natural range 0 .. Max_Debug_Buffer_Len; + + procedure Add (Phrase : String); + +end Loop_Optimization4_Pkg; diff --git a/gcc/testsuite/gnat.dg/unchecked_convert2.adb b/gcc/testsuite/gnat.dg/unchecked_convert2.adb new file mode 100644 index 00000000000..f542af7c343 --- /dev/null +++ b/gcc/testsuite/gnat.dg/unchecked_convert2.adb @@ -0,0 +1,34 @@ +-- { dg-do run } + +with Ada.Unchecked_Conversion; +with Ada.Streams; use Ada.Streams; +with Ada.Text_IO; use Ada.Text_IO; + +procedure Unchecked_Convert2 is + + subtype Day_Number is Integer range 0 .. 31; + + subtype Byte_Array_Of_Integer is Stream_Element_Array + (1 .. Integer'Size / Stream_Element_Array'Component_Size); + + function To_Byte_Array is + new Ada.Unchecked_Conversion (Integer, Byte_Array_Of_Integer); + + Day_Now : Day_Number; + Pragma Volatile (Day_Now); + + Arr : Stream_Element_Array (1 .. 12) := (others => 16#ff#); + + procedure Test (Arr : Stream_Element_Array) is + begin + if Arr(5) /= 0 or Arr(6) /= 0 or Arr(7) /= 0 or Arr(8) /= 0 then + raise Program_Error; + end if; + end; + +begin + Day_Now := 0; + Arr (5 .. 8) := To_Byte_Array (Day_Now); + Test (Arr); + Arr (1) := 16#ff#; +end Unchecked_Convert2; diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index e9f315c53a2..505ee700057 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -658,9 +658,13 @@ make_cond_expr_edges (basic_block bb) e = make_edge (bb, then_bb, EDGE_TRUE_VALUE); e->goto_locus = gimple_location (then_stmt); + e->goto_block = gimple_block (then_stmt); e = make_edge (bb, else_bb, EDGE_FALSE_VALUE); if (e) - e->goto_locus = gimple_location (else_stmt); + { + e->goto_locus = gimple_location (else_stmt); + e->goto_block = gimple_block (else_stmt); + } /* We do not need the labels anymore. */ gimple_cond_set_true_label (entry, NULL_TREE); @@ -849,6 +853,7 @@ make_goto_expr_edges (basic_block bb) tree dest = gimple_goto_dest (goto_t); edge e = make_edge (bb, label_to_block (dest), EDGE_FALLTHRU); e->goto_locus = gimple_location (goto_t); + e->goto_block = gimple_block (goto_t); gsi_remove (&last, true); return; } @@ -5743,6 +5748,23 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb, update_stmt (stmt); pop_cfun (); } + + FOR_EACH_EDGE (e, ei, bb->succs) + if (e->goto_locus) + { + tree block = e->goto_block; + if (d->orig_block == NULL_TREE + || block == d->orig_block) + e->goto_block = d->new_block; +#ifdef ENABLE_CHECKING + else if (block != d->new_block) + { + while (block && block != d->orig_block) + block = BLOCK_SUPERCONTEXT (block); + gcc_assert (block); + } +#endif + } } /* Examine the statements in BB (which is in SRC_CFUN); find and return diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 4639588a162..c924a7631db 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -1558,7 +1558,7 @@ may_be_nonaddressable_p (tree expr) non-addressability may be uncovered again, causing ADDR_EXPRs of inappropriate objects to be built. */ if (is_gimple_reg (TREE_OPERAND (expr, 0)) - || is_gimple_min_invariant (TREE_OPERAND (expr, 0))) + || !is_gimple_addressable (TREE_OPERAND (expr, 0))) return true; /* ... fall through ... */ diff --git a/gcc/tree.c b/gcc/tree.c index 4b178d5073f..33ab8b7078b 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -343,6 +343,8 @@ init_ttree (void) tree_contains_struct[CONST_DECL][TS_CONST_DECL] = 1; tree_contains_struct[TYPE_DECL][TS_TYPE_DECL] = 1; tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL] = 1; + tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON] = 1; lang_hooks.init_ts (); } diff --git a/gcc/tree.def b/gcc/tree.def index ef103cdba50..bde59b7016c 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -371,6 +371,17 @@ DEFTREECODE (MEMORY_PARTITION_TAG, "memory_partition_tag", tcc_declaration, 0) _DECLs, providing a hierarchy of names. */ DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0) +/* A declaration import. + The C++ FE uses this to represent a using-directive; eg: + "using namespace foo". + But it could be used to represent any declaration import construct. + Whenever a declaration import appears in a lexical block, the BLOCK node + representing that lexical block in GIMPLE will contain an IMPORTED_DECL + node, linked via BLOCK_VARS accessor of the said BLOCK. + For a given NODE which code is IMPORTED_DECL, + IMPORTED_DECL_ASSOCIATED_DECL (NODE) accesses the imported declaration. */ +DEFTREECODE (IMPORTED_DECL, "imported_decl", tcc_declaration, 0) + /* A translation unit. This is not technically a declaration, since it can't be looked up, but it's close enough. */ DEFTREECODE (TRANSLATION_UNIT_DECL, "translation_unit_decl",\ diff --git a/gcc/tree.h b/gcc/tree.h index 4c046c29d64..44bc3f0f282 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2559,7 +2559,7 @@ struct tree_memory_partition_tag GTY(()) /* For a FUNCTION_DECL, holds the tree of BINDINGs. For a TRANSLATION_UNIT_DECL, holds the namespace's BLOCK. For a VAR_DECL, holds the initial value. - For a PARM_DECL, not used--default + For a PARM_DECL, used for DECL_ARG_TYPE--default values for parameters are encoded in the type of the function, not in the PARM_DECL slot. For a FIELD_DECL, this is used for enumeration values and the C @@ -3334,6 +3334,11 @@ struct tree_function_decl GTY(()) #define TYPE_DECL_SUPPRESS_DEBUG(NODE) \ (TYPE_DECL_CHECK (NODE)->decl_common.decl_flag_2) +/* Getter of the imported declaration associated to the + IMPORTED_DECL node. */ +#define IMPORTED_DECL_ASSOCIATED_DECL(NODE) \ +(DECL_INITIAL (IMPORTED_DECL_CHECK (NODE))) + struct tree_type_decl GTY(()) { struct tree_decl_non_common common; diff --git a/include/ChangeLog b/include/ChangeLog index 64b0a6caeeb..20da6186ff0 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2008-10-06 Jason Merrill <jason@redhat.com> + + * demangle.h (enum demangle_component_type): Add + DEMANGLE_COMPONENT_PACK_EXPANSION. + 2008-09-09 Jason Merrill <jason@redhat.com> * demangle.h (enum demangle_component_type): Add diff --git a/include/demangle.h b/include/demangle.h index 146d778e097..0ea639d62ba 100644 --- a/include/demangle.h +++ b/include/demangle.h @@ -372,7 +372,9 @@ enum demangle_component_type /* A name formed by a single character. */ DEMANGLE_COMPONENT_CHARACTER, /* A decltype type. */ - DEMANGLE_COMPONENT_DECLTYPE + DEMANGLE_COMPONENT_DECLTYPE, + /* A pack expansion. */ + DEMANGLE_COMPONENT_PACK_EXPANSION }; /* Types which are only used internally. */ diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index e6980aea132..c79b3b75098 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,28 @@ +2008-10-07 Jan Kratochvil <jan.kratochvil@redhat.com> + + * configure.ac: Call AC_SYS_LARGEFILE. + * config.in: Regenerated. + * configure: Likewise. + +2008-10-06 Jason Merrill <jason@redhat.com> + + * cp-demangle.c (struct d_print_info): Add pack_index. + (d_dump): Add DEMANGLE_COMPONENT_PACK_EXPANSION. + (d_make_comp): Likewise. DEMANGLE_COMPONENT_ARGLIST and + DEMANGLE_COMPONENT_TEMPLATE_ARGLIST can have two null args. + (cplus_demangle_builtin_types): Add char16/32_t. + (cplus_demangle_type): Recognize them. + (d_template_args): Handle empty argument packs. + (d_template_arg): Handle argument packs. + (d_expression): Handle dependent name. + (d_index_template_argument): New fn. + (d_lookup_template_argument): New fn. + (d_find_pack, d_pack_length): New fn. + (d_print_subexpr): Split out... + (d_print_comp): ...from here. Use d_*_template_argument. + Handle empty arg lists. Support pack expansions. + * cp-demangle.h (D_BUILTIN_TYPE_COUNT): Increase to 32. + 2008-09-09 Jason Merrill <jason@redhat.com> * cp-demangle.c (d_dump): Handle DEMANGLE_COMPONENT_DECLTYPE. diff --git a/libiberty/config.in b/libiberty/config.in index 436a58d7e79..9260d560a6e 100644 --- a/libiberty/config.in +++ b/libiberty/config.in @@ -425,6 +425,12 @@ first (like Motorola and SPARC, unlike Intel and VAX). */ #undef WORDS_BIGENDIAN +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + /* Define to empty if `const' does not conform to ANSI C. */ #undef const diff --git a/libiberty/configure b/libiberty/configure index 50e9ba3699e..71b6ccd95b5 100755 --- a/libiberty/configure +++ b/libiberty/configure @@ -849,6 +849,7 @@ Optional Features: enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-multilib build many library versions (default) + --disable-largefile omit support for large files --enable-install-libiberty Install headers for end users Optional Packages: @@ -2741,6 +2742,371 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu + +# Check whether --enable-largefile or --disable-largefile was given. +if test "${enable_largefile+set}" = set; then + enableval="$enable_largefile" + +fi; +if test "$enable_largefile" != no; then + + echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5 +echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_largefile_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext + CC="$CC -n32" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_largefile_CC=' -n32'; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5 +echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6 + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi + + echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_file_offset_bits+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + while :; do + ac_cv_sys_file_offset_bits=no + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_file_offset_bits=64; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + break +done +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5 +echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6 +if test "$ac_cv_sys_file_offset_bits" != no; then + +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF + +fi +rm -f conftest* + echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5 +echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_large_files+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + while :; do + ac_cv_sys_large_files=no + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_large_files=1; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + break +done +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5 +echo "${ECHO_T}$ac_cv_sys_large_files" >&6 +if test "$ac_cv_sys_large_files" != no; then + +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF + +fi +rm -f conftest* +fi + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -2980,7 +3346,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_c_preproc_warn_flag=yes - ac_libiberty_warn_cflags= save_CFLAGS="$CFLAGS" for option in -W -Wall -Wwrite-strings -Wc++-compat \ diff --git a/libiberty/configure.ac b/libiberty/configure.ac index 419351bbb93..ff0ae6a81e4 100644 --- a/libiberty/configure.ac +++ b/libiberty/configure.ac @@ -130,6 +130,7 @@ fi GCC_NO_EXECUTABLES AC_PROG_CC +AC_SYS_LARGEFILE AC_PROG_CPP_WERROR ACX_PROG_CC_WARNING_OPTS([-W -Wall -Wwrite-strings -Wc++-compat \ diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 3d292f07d0a..3fa5f1f21d3 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -299,6 +299,9 @@ struct d_print_info struct d_print_mod *modifiers; /* Set to 1 if we saw a demangling error. */ int demangle_failure; + /* The current index into any template argument packs we are using + for printing. */ + int pack_index; }; #ifdef CP_DEMANGLE_DEBUG @@ -663,6 +666,9 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_DECLTYPE: printf ("decltype\n"); break; + case DEMANGLE_COMPONENT_PACK_EXPANSION: + printf ("pack expansion\n"); + break; } d_dump (d_left (dc), indent + 2); @@ -806,11 +812,10 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_COMPLEX: case DEMANGLE_COMPONENT_IMAGINARY: case DEMANGLE_COMPONENT_VENDOR_TYPE: - case DEMANGLE_COMPONENT_ARGLIST: - case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: case DEMANGLE_COMPONENT_CAST: case DEMANGLE_COMPONENT_JAVA_RESOURCE: case DEMANGLE_COMPONENT_DECLTYPE: + case DEMANGLE_COMPONENT_PACK_EXPANSION: if (left == NULL) return NULL; break; @@ -831,6 +836,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_RESTRICT_THIS: case DEMANGLE_COMPONENT_VOLATILE_THIS: case DEMANGLE_COMPONENT_CONST_THIS: + case DEMANGLE_COMPONENT_ARGLIST: + case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: break; /* Other types should not be seen here. */ @@ -1433,6 +1440,7 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "da", NL ("delete[]"), 1 }, { "de", NL ("*"), 1 }, { "dl", NL ("delete"), 1 }, + { "dt", NL ("."), 2 }, { "dv", NL ("/"), 2 }, { "eO", NL ("^="), 2 }, { "eo", NL ("^"), 2 }, @@ -1875,21 +1883,24 @@ cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] = /* n */ { NL ("__int128"), NL ("__int128"), D_PRINT_DEFAULT }, /* o */ { NL ("unsigned __int128"), NL ("unsigned __int128"), D_PRINT_DEFAULT }, - /* The decimal floating point and half-precision floating point types - don't use the normal builtin type encoding, they're just stuck into - holes in the table for convenience. */ - /* p */ { NL ("decimal32"), NL ("decimal32"), D_PRINT_DEFAULT }, - /* q */ { NL ("decimal64"), NL ("decimal64"), D_PRINT_DEFAULT }, - /* r */ { NL ("decimal128"), NL ("decimal128"), D_PRINT_DEFAULT }, + /* p */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, + /* q */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, + /* r */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, /* s */ { NL ("short"), NL ("short"), D_PRINT_DEFAULT }, /* t */ { NL ("unsigned short"), NL ("unsigned short"), D_PRINT_DEFAULT }, - /* u */ { NL ("half"), NL ("half"), D_PRINT_FLOAT }, + /* u */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, /* v */ { NL ("void"), NL ("void"), D_PRINT_VOID }, /* w */ { NL ("wchar_t"), NL ("char"), D_PRINT_DEFAULT }, /* x */ { NL ("long long"), NL ("long"), D_PRINT_LONG_LONG }, /* y */ { NL ("unsigned long long"), NL ("unsigned long long"), D_PRINT_UNSIGNED_LONG_LONG }, /* z */ { NL ("..."), NL ("..."), D_PRINT_DEFAULT }, + /* 26 */ { NL ("decimal32"), NL ("decimal32"), D_PRINT_DEFAULT }, + /* 27 */ { NL ("decimal64"), NL ("decimal64"), D_PRINT_DEFAULT }, + /* 28 */ { NL ("decimal128"), NL ("decimal128"), D_PRINT_DEFAULT }, + /* 29 */ { NL ("half"), NL ("half"), D_PRINT_FLOAT }, + /* 30 */ { NL ("char16_t"), NL ("char16_t"), D_PRINT_DEFAULT }, + /* 31 */ { NL ("char32_t"), NL ("char32_t"), D_PRINT_DEFAULT }, }; CP_STATIC_IF_GLIBCPP_V3 @@ -2070,30 +2081,38 @@ cplus_demangle_type (struct d_info *di) case 'p': /* Pack expansion. */ - return NULL; + ret = d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION, + cplus_demangle_type (di), NULL); + break; case 'f': - /* 32-bit DFP */ - ret = d_make_builtin_type (di, - &cplus_demangle_builtin_types['p' - 'a']); + /* 32-bit decimal floating point */ + ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[26]); di->expansion += ret->u.s_builtin.type->len; break; case 'd': - /* 64-bit decimal floating point */ - ret = d_make_builtin_type (di, - &cplus_demangle_builtin_types['q' - 'a']); + /* 64-bit DFP */ + ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[27]); di->expansion += ret->u.s_builtin.type->len; break; case 'e': /* 128-bit DFP */ - ret = d_make_builtin_type (di, - &cplus_demangle_builtin_types['r' - 'a']); + ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[28]); di->expansion += ret->u.s_builtin.type->len; break; case 'h': /* 16-bit half-precision FP */ - ret = d_make_builtin_type (di, - &cplus_demangle_builtin_types['u' - 'a']); + ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[29]); + di->expansion += ret->u.s_builtin.type->len; + break; + case 's': + /* char16_t */ + ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[30]); + di->expansion += ret->u.s_builtin.type->len; + break; + case 'i': + /* char32_t */ + ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[31]); di->expansion += ret->u.s_builtin.type->len; break; } @@ -2390,6 +2409,13 @@ d_template_args (struct d_info *di) if (! d_check_char (di, 'I')) return NULL; + if (d_peek_char (di) == 'E') + { + /* An argument pack can be empty. */ + d_advance (di, 1); + return d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, NULL, NULL); + } + al = NULL; pal = &al; while (1) @@ -2439,6 +2465,10 @@ d_template_arg (struct d_info *di) case 'L': return d_expr_primary (di); + case 'I': + /* An argument pack. */ + return d_template_args (di); + default: return cplus_demangle_type (di); } @@ -2452,6 +2482,12 @@ d_exprlist (struct d_info *di) struct demangle_component *list = NULL; struct demangle_component **p = &list; + if (d_peek_char (di) == 'E') + { + d_advance (di, 1); + return d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, NULL, NULL); + } + while (1) { struct demangle_component *arg = d_expression (di); @@ -2515,6 +2551,19 @@ d_expression (struct d_info *di) d_advance (di, 2); return cplus_demangle_type (di); } + else if (IS_DIGIT (peek)) + { + /* We can get an unqualified name as an expression in the case of + a dependent member access, i.e. decltype(T().i). */ + struct demangle_component *name = d_unqualified_name (di); + if (name == NULL) + return NULL; + if (d_peek_char (di) == 'I') + return d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, + d_template_args (di)); + else + return name; + } else { struct demangle_component *op; @@ -3067,6 +3116,123 @@ cplus_demangle_print (int options, const struct demangle_component *dc, return dgs.buf; } +/* Returns the I'th element of the template arglist ARGS, or NULL on + failure. */ + +static struct demangle_component * +d_index_template_argument (struct demangle_component *args, int i) +{ + struct demangle_component *a; + + for (a = args; + a != NULL; + a = d_right (a)) + { + if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) + return NULL; + if (i <= 0) + break; + --i; + } + if (i != 0 || a == NULL) + return NULL; + + return d_left (a); +} + +/* Returns the template argument from the current context indicated by DC, + which is a DEMANGLE_COMPONENT_TEMPLATE_PARAM, or NULL. */ + +static struct demangle_component * +d_lookup_template_argument (struct d_print_info *dpi, + const struct demangle_component *dc) +{ + if (dpi->templates == NULL) + { + d_print_error (dpi); + return NULL; + } + + return d_index_template_argument + (d_right (dpi->templates->template_decl), + dc->u.s_number.number); +} + +/* Returns a template argument pack used in DC (any will do), or NULL. */ + +static struct demangle_component * +d_find_pack (struct d_print_info *dpi, + const struct demangle_component *dc) +{ + struct demangle_component *a; + if (dc == NULL) + return NULL; + + switch (dc->type) + { + case DEMANGLE_COMPONENT_TEMPLATE_PARAM: + a = d_lookup_template_argument (dpi, dc); + if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) + return a; + return NULL; + + case DEMANGLE_COMPONENT_PACK_EXPANSION: + return NULL; + + case DEMANGLE_COMPONENT_NAME: + case DEMANGLE_COMPONENT_OPERATOR: + case DEMANGLE_COMPONENT_BUILTIN_TYPE: + case DEMANGLE_COMPONENT_SUB_STD: + case DEMANGLE_COMPONENT_CHARACTER: + return NULL; + + case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: + return d_find_pack (dpi, dc->u.s_extended_operator.name); + case DEMANGLE_COMPONENT_CTOR: + return d_find_pack (dpi, dc->u.s_ctor.name); + case DEMANGLE_COMPONENT_DTOR: + return d_find_pack (dpi, dc->u.s_dtor.name); + + default: + a = d_find_pack (dpi, d_left (dc)); + if (a) + return a; + return d_find_pack (dpi, d_right (dc)); + } +} + +/* Returns the length of the template argument pack DC. */ + +static int +d_pack_length (const struct demangle_component *dc) +{ + int count = 0; + while (dc && dc->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST + && d_left (dc) != NULL) + { + ++count; + dc = d_right (dc); + } + return count; +} + +/* DC is a component of a mangled expression. Print it, wrapped in parens + if needed. */ + +static void +d_print_subexpr (struct d_print_info *dpi, + const struct demangle_component *dc) +{ + int simple = 0; + if (dc->type == DEMANGLE_COMPONENT_NAME) + simple = 1; + if (!simple) + d_append_char (dpi, '('); + d_print_comp (dpi, dc); + if (!simple) + d_append_char (dpi, ')'); +} + /* Subroutine to handle components. */ static void @@ -3252,30 +3418,13 @@ d_print_comp (struct d_print_info *dpi, case DEMANGLE_COMPONENT_TEMPLATE_PARAM: { - long i; - struct demangle_component *a; struct d_print_template *hold_dpt; + struct demangle_component *a = d_lookup_template_argument (dpi, dc); - if (dpi->templates == NULL) - { - d_print_error (dpi); - return; - } - i = dc->u.s_number.number; - for (a = d_right (dpi->templates->template_decl); - a != NULL; - a = d_right (a)) - { - if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) - { - d_print_error (dpi); - return; - } - if (i <= 0) - break; - --i; - } - if (i != 0 || a == NULL) + if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) + a = d_index_template_argument (a, dpi->pack_index); + + if (a == NULL) { d_print_error (dpi); return; @@ -3289,7 +3438,7 @@ d_print_comp (struct d_print_info *dpi, hold_dpt = dpi->templates; dpi->templates = hold_dpt->next; - d_print_comp (dpi, d_left (a)); + d_print_comp (dpi, a); dpi->templates = hold_dpt; @@ -3578,7 +3727,8 @@ d_print_comp (struct d_print_info *dpi, case DEMANGLE_COMPONENT_ARGLIST: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: - d_print_comp (dpi, d_left (dc)); + if (d_left (dc) != NULL) + d_print_comp (dpi, d_left (dc)); if (d_right (dc) != NULL) { d_append_string (dpi, ", "); @@ -3618,11 +3768,12 @@ d_print_comp (struct d_print_info *dpi, d_print_cast (dpi, d_left (dc)); d_append_char (dpi, ')'); } - d_append_char (dpi, '('); - if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST - || d_right (dc)->type != DEMANGLE_COMPONENT_BUILTIN_TYPE) - d_print_comp (dpi, d_right (dc)); - d_append_char (dpi, ')'); + if (d_left (dc)->type == DEMANGLE_COMPONENT_CAST + && d_right (dc)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE) + /* type() -- FIXME what about type(multiple,args) */ + d_append_string (dpi, "()"); + else + d_print_subexpr (dpi, d_right (dc)); return; case DEMANGLE_COMPONENT_BINARY: @@ -3632,15 +3783,6 @@ d_print_comp (struct d_print_info *dpi, return; } - if (!strcmp (d_left (dc)->u.s_operator.op->code, "cl")) - { - d_print_comp (dpi, d_left (d_right (dc))); - d_append_string (dpi, " ("); - d_print_comp (dpi, d_right (d_right (dc))); - d_append_char (dpi, ')'); - return; - } - /* We wrap an expression which uses the greater-than operator in an extra layer of parens so that it does not get confused with the '>' which ends the template parameters. */ @@ -3649,13 +3791,10 @@ d_print_comp (struct d_print_info *dpi, && d_left (dc)->u.s_operator.op->name[0] == '>') d_append_char (dpi, '('); - d_append_char (dpi, '('); - d_print_comp (dpi, d_left (d_right (dc))); - d_append_string (dpi, ") "); - d_print_expr_op (dpi, d_left (dc)); - d_append_string (dpi, " ("); - d_print_comp (dpi, d_right (d_right (dc))); - d_append_char (dpi, ')'); + d_print_subexpr (dpi, d_left (d_right (dc))); + if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") != 0) + d_print_expr_op (dpi, d_left (dc)); + d_print_subexpr (dpi, d_right (d_right (dc))); if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR && d_left (dc)->u.s_operator.op->len == 1 @@ -3676,15 +3815,11 @@ d_print_comp (struct d_print_info *dpi, d_print_error (dpi); return; } - d_append_char (dpi, '('); - d_print_comp (dpi, d_left (d_right (dc))); - d_append_string (dpi, ") "); + d_print_subexpr (dpi, d_left (d_right (dc))); d_print_expr_op (dpi, d_left (dc)); - d_append_string (dpi, " ("); - d_print_comp (dpi, d_left (d_right (d_right (dc)))); - d_append_string (dpi, ") : ("); - d_print_comp (dpi, d_right (d_right (d_right (dc)))); - d_append_char (dpi, ')'); + d_print_subexpr (dpi, d_left (d_right (d_right (dc)))); + d_append_string (dpi, " : "); + d_print_subexpr (dpi, d_right (d_right (d_right (dc)))); return; case DEMANGLE_COMPONENT_TRINARY_ARG1: @@ -3797,6 +3932,23 @@ d_print_comp (struct d_print_info *dpi, d_append_char (dpi, ')'); return; + case DEMANGLE_COMPONENT_PACK_EXPANSION: + { + struct demangle_component *a = d_find_pack (dpi, d_left (dc)); + int len = d_pack_length (a); + int i; + + dc = d_left (dc); + for (i = 0; i < len; ++i) + { + dpi->pack_index = i; + d_print_comp (dpi, dc); + if (i < len-1) + d_append_string (dpi, ", "); + } + } + return; + default: d_print_error (dpi); return; diff --git a/libiberty/cp-demangle.h b/libiberty/cp-demangle.h index 8622f29ca89..aad37437400 100644 --- a/libiberty/cp-demangle.h +++ b/libiberty/cp-demangle.h @@ -147,7 +147,7 @@ struct d_info extern const struct demangle_operator_info cplus_demangle_operators[]; #endif -#define D_BUILTIN_TYPE_COUNT (26) +#define D_BUILTIN_TYPE_COUNT (32) CP_STATIC_IF_GLIBCPP_V3 const struct demangle_builtin_type_info diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 9358204d2bd..d9efbc0d24e 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -3345,7 +3345,7 @@ f<X> # --format=gnu-v3 --no-params _ZngILi42EEvN1AIXplT_Li2EEE1TE -void operator-<42>(A<(42) + (2)>::T) +void operator-<42>(A<(42)+(2)>::T) operator-<42> # --format=gnu-v3 --no-params @@ -3385,7 +3385,7 @@ int* const volatile restrict _far # --format=gnu-v3 --no-params _Z3fooILi2EEvRAplT_Li1E_i -void foo<2>(int (&) [(2) + (1)]) +void foo<2>(int (&) [(2)+(1)]) foo<2> # --format=gnu-v3 --no-params @@ -3612,13 +3612,13 @@ hairyfunc5 # This is from gcc PR 8861 --format=gnu-v3 --no-params _Z1fILi1ELc120EEv1AIXplT_cviLd810000000000000000703DAD7A370C5EEE -void f<1, (char)120>(A<(1) + ((int)((double)[810000000000000000703DAD7A370C5]))>) +void f<1, (char)120>(A<(1)+((int)((double)[810000000000000000703DAD7A370C5]))>) f<1, (char)120> # # This is also from gcc PR 8861 --format=gnu-v3 --no-params _Z1fILi1EEv1AIXplT_cvingLf3f800000EEE -void f<1>(A<(1) + ((int)(-((float)[3f800000])))>) +void f<1>(A<(1)+((int)(-((float)[3f800000])))>) f<1> # # This is from a libstdc++ debug mode patch. @@ -3643,7 +3643,7 @@ f # confusion with the '>' which ends the template parameters. --format=gnu-v3 --no-params _Z4dep9ILi3EEvP3fooIXgtT_Li2EEE -void dep9<3>(foo<((3) > (2))>*) +void dep9<3>(foo<((3)>(2))>*) dep9<3> # # Watch out for templated version of `operator<'--it needs an extra @@ -3885,16 +3885,20 @@ java resource java/util/iso4217.properties # decltype/param placeholder test --format=gnu-v3 _Z3addIidEDTplsTT_sTT0_ES0_S1_ -decltype ((int) + (double)) add<int, double>(int, double) -# decltype/T() test ---format=gnu-v3 -_Z4add2IidEDTplcvT_vcvT0_vES0_S1_ -decltype (((int)()) + ((double)())) add2<int, double>(int, double) +decltype ((int)+(double)) add<int, double>(int, double) # decltype/fn call test --format=gnu-v3 _Z4add3IidEDTclL_Z1gEsTT_sTT0_EES0_S1_ -decltype (g (int, double)) add3<int, double>(int, double) -# Extended floating point types test +decltype (g(int, double)) add3<int, double>(int, double) +# new (2008) built in types test +--format=gnu-v3 +_Z1fDfDdDeDhDsDi +f(decimal32, decimal64, decimal128, half, char16_t, char32_t) +# pack expansion test +--format=gnu-v3 +_Z1fIIPiPfPdEEvDpT_ +void f<int*, float*, double*>(int*, float*, double*) +# '.' test --format=gnu-v3 -_Z1fDfDdDeDh -f(decimal32, decimal64, decimal128, half) +_Z1hI1AIiEdEDTcldtsTT_1gIT0_EEES2_S3_ +decltype (((A<int>).(g<double>))()) h<A<int>, double>(A<int>, double) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 153e6947eb7..3b2762620f7 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,22 @@ +2008-10-07 Jason Merrill <jason@redhat.com> + + PR libstdc++/37761 + * testsuite/abi/demangle/abi_examples/20.cc: Adjust expected spacing. + * testsuite/abi/demangle/abi_text/02.cc: Likewise. + * testsuite/abi/demangle/regression/cw-16.cc: Likewise. + +2008-10-07 Paolo Carlini <paolo.carlini@oracle.com> + + * include/bits/stl_iterator.h (operator-(const reverse_iterator<>&, + const reverse_iterator<>&), operator-(const __normal_iterator<>&, + const __normal_iterator<>&), operator-(const move_iterator<>&, + const move_iterator<>&)): Use the auto -> return type syntax, + implement DR 685. + +2008-10-06 Jason Merrill <jason@redhat.com> + + * config/abi/pre/gnu.ver: Update char16/32_t manglings. + 2008-10-05 Paolo Carlini <paolo.carlini@oracle.com> * testsuite/20_util/reference_wrapper/invoke.cc: New. diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 56fa9be3e6e..024fcfd4086 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -1104,12 +1104,12 @@ CXXABI_1.3.2 { CXXABI_1.3.3 { # typeinfo for char16_t and char32_t - _ZTIu8char16_t; - _ZTIPu8char16_t; - _ZTIPKu8char16_t; - _ZTIu8char32_t; - _ZTIPu8char32_t; - _ZTIPKu8char32_t; + _ZTIDs; + _ZTIPDs; + _ZTIPKDs; + _ZTIDi; + _ZTIPDi; + _ZTIPKDi; # exception_ptr _ZNSt15__exception_ptr13exception_ptrC1Ev; diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 0d66129fb80..d161e303e30 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -365,9 +365,17 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { return !(__x < __y); } template<typename _IteratorL, typename _IteratorR> +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + // DR 685. + inline auto + operator-(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + -> decltype(__y.base() - __x.base()) +#else inline typename reverse_iterator<_IteratorL>::difference_type operator-(const reverse_iterator<_IteratorL>& __x, const reverse_iterator<_IteratorR>& __y) +#endif { return __y.base() - __x.base(); } //@} @@ -835,9 +843,17 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) // operators but also operator- must accept mixed iterator/const_iterator // parameters. template<typename _IteratorL, typename _IteratorR, typename _Container> +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + // DR 685. + inline auto + operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + -> decltype(__lhs.base() - __rhs.base()) +#else inline typename __normal_iterator<_IteratorL, _Container>::difference_type operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, const __normal_iterator<_IteratorR, _Container>& __rhs) +#endif { return __lhs.base() - __rhs.base(); } template<typename _Iterator, typename _Container> @@ -1001,10 +1017,12 @@ _GLIBCXX_BEGIN_NAMESPACE(std) const move_iterator<_IteratorR>& __y) { return !(__x < __y); } + // DR 685. template<typename _IteratorL, typename _IteratorR> - inline typename move_iterator<_IteratorL>::difference_type + inline auto operator-(const move_iterator<_IteratorL>& __x, const move_iterator<_IteratorR>& __y) + -> decltype(__x.base() - __y.base()) { return __x.base() - __y.base(); } template<typename _Iterator> diff --git a/libstdc++-v3/testsuite/abi/demangle/abi_examples/20.cc b/libstdc++-v3/testsuite/abi/demangle/abi_examples/20.cc index eaa5db0430f..1bef745b197 100644 --- a/libstdc++-v3/testsuite/abi/demangle/abi_examples/20.cc +++ b/libstdc++-v3/testsuite/abi/demangle/abi_examples/20.cc @@ -29,7 +29,7 @@ int main() using namespace __gnu_test; verify_demangle("_ZngILi42EEvN1AIXplT_Li2EEE1TE", - "void operator-<42>(A<(42) + (2)>::T)"); + "void operator-<42>(A<(42)+(2)>::T)"); return 0; } diff --git a/libstdc++-v3/testsuite/abi/demangle/abi_text/02.cc b/libstdc++-v3/testsuite/abi/demangle/abi_text/02.cc index 28a617aef7d..9a41fe55c20 100644 --- a/libstdc++-v3/testsuite/abi/demangle/abi_text/02.cc +++ b/libstdc++-v3/testsuite/abi/demangle/abi_text/02.cc @@ -33,7 +33,7 @@ int main() // Equivalent, but formatting difference in void argument and parentheses. // icc, __cxa_demangle verify_demangle("_Z3fooILi2EEvRAplT_Li1E_i", - "void foo<2>(int (&) [(2) + (1)])"); + "void foo<2>(int (&) [(2)+(1)])"); // cplus-dem // verify_demangle("_Z3fooILi2EEvRAplT_Li1E_i", // "void foo<(int)2>(int (&) [((int)2)+((int)1)])"); diff --git a/libstdc++-v3/testsuite/abi/demangle/regression/cw-16.cc b/libstdc++-v3/testsuite/abi/demangle/regression/cw-16.cc index 0c8c29f28af..0db740e991a 100644 --- a/libstdc++-v3/testsuite/abi/demangle/regression/cw-16.cc +++ b/libstdc++-v3/testsuite/abi/demangle/regression/cw-16.cc @@ -32,9 +32,9 @@ verify_demangle("_Z3fooIA6_KiEvA9_KT_rVPrS4_", "void foo<int const [6]>(int const [9][6], int restrict const (* volatile restrict) [9][6])"); // 2003/11/12, libstdc++/12947 verify_demangle("_Z1fILi5E1AEvN1CIXqugtT_Li0ELi1ELi2EEE1qE", - "void f<5, A>(C<(((5) > (0))) ? (1) : (2)>::q)"); + "void f<5, A>(C<(((5)>(0)))?(1) : (2)>::q)"); verify_demangle("_Z1fILi5EEvN1AIXcvimlT_Li22EEE1qE", - "void f<5>(A<(int)((5) * (22))>::q)"); + "void f<5>(A<(int)((5)*(22))>::q)"); verify_demangle("_Z1fPFYPFiiEiE", "f(int (*(*)(int))(int))"); verify_demangle("_Z1fI1XENT_1tES2_", @@ -43,9 +43,9 @@ verify_demangle("_Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE", "void f<5, A>(C<sizeof (T::t), sizeof (T::t)>::q)"); // 2003/12/03, libstdc++/13045 verify_demangle("_Z1fILi1ELc120EEv1AIXplT_cviLd4028ae147ae147aeEEE", - "void f<1, (char)120>(A<(1) + ((int)((double)[4028ae147ae147ae]))>)"); + "void f<1, (char)120>(A<(1)+((int)((double)[4028ae147ae147ae]))>)"); verify_demangle("_Z1fILi1ELc120EEv1AIXplT_cviLf3f800000EEE", - "void f<1, (char)120>(A<(1) + ((int)((float)[3f800000]))>)"); + "void f<1, (char)120>(A<(1)+((int)((float)[3f800000]))>)"); verify_demangle("_Z9hairyfuncM1YKFPVPFrPA2_PM1XKFKPA3_ilEPcEiE", "hairyfunc(int (* const (X::** (* restrict (* volatile* (Y::*)(int) const)(char*)) [2])(long) const) [3])"); |