diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-02-11 17:53:16 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-02-11 17:53:16 +0000 |
commit | 4b678f58022a436a25225112a17efbab107bcce3 (patch) | |
tree | c4ffe81a9561a1053191a0c104581fc27cefb9d9 | |
parent | 78cce47cff6efdfc96821cc3d94e789abca1c39a (diff) | |
parent | e5a6b70e88b852b5a1932d4cefd619b6d82a02ba (diff) | |
download | gcc-4b678f58022a436a25225112a17efbab107bcce3.zip gcc-4b678f58022a436a25225112a17efbab107bcce3.tar.gz gcc-4b678f58022a436a25225112a17efbab107bcce3.tar.bz2 |
Merge from trunk revision 257559.
From-SVN: r257563
113 files changed, 3118 insertions, 353 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d9c45c9..677c316 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,299 @@ +2018-02-10 John David Anglin <danglin@gcc.gnu.org> + + * config/pa/pa.c (hppa_profile_hook): Mark SYMBOL_REF for _mcount as + function label. + +2018-02-10 Alan Modra <amodra@gmail.com> + + PR target/84300 + * config/rs6000/rs6000.md (split_stack_return): Remove (use ..). + Specify LR as an input. + +2018-02-10 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/83987 + * omp-low.c (maybe_remove_omp_member_access_dummy_vars, + remove_member_access_dummy_vars): New functions. + (lower_omp_for, lower_omp_taskreg, lower_omp_target, + lower_omp_1, execute_lower_omp): Use them. + + PR rtl-optimization/84308 + * shrink-wrap.c (spread_components): Release todo vector. + +2018-02-09 Vladimir Makarov <vmakarov@redhat.com> + + PR rtl-optimization/57193 + * ira-color.c (struct allocno_color_data): Add member + conflict_allocno_hard_prefs. + (update_conflict_allocno_hard_prefs): New. + (bucket_allocno_compare_func): Add a preference based on + conflict_allocno_hard_prefs. + (push_allocno_to_stack): Update conflict_allocno_hard_prefs. + (color_allocnos): Remove a dead code. Initiate + conflict_allocno_hard_prefs. Call update_costs_from_prefs. + +2018-02-09 Jakub Jelinek <jakub@redhat.com> + + PR target/84226 + * config/rs6000/vsx.md (p9_xxbrq_v16qi): Change input operand + constraint from =wa to wa. Avoid a subreg on the output operand, + instead use a pseudo and subreg it in a move. + (p9_xxbrd_<mode>): Changed to ... + (p9_xxbrd_v2di): ... this insn, without VSX_D iterator. + (p9_xxbrd_v2df): New expander. + (p9_xxbrw_<mode>): Changed to ... + (p9_xxbrw_v4si): ... this insn, without VSX_W iterator. + (p9_xxbrw_v4sf): New expander. + +2018-02-09 Sebastian Perta <sebastian.perta@renesas.com> + + * config/rx.md: updated "movsicc" expand to be matched by GCC + * testsuite/gcc.target/rx/movsicc.c: new test case + +2018-02-09 Peter Bergner <bergner@vnet.ibm.com> + + PR target/83926 + * config/rs6000/vsx.md (vsx_mul_v2di): Handle generating a 64-bit + multiply in 32-bit mode. + (vsx_div_v2di): Handle generating a 64-bit signed divide in 32-bit mode. + (vsx_udiv_v2di): Handle generating a 64-bit unsigned divide in 32-bit + mode. + +2018-02-09 Sebastian Perta <sebastian.perta@renesas.com> + + * config/rx/constraints.md: added new constraint CALL_OP_SYMBOL_REF + to allow or block "symbol_ref" depending on value of TARGET_JSR + * config/rx/rx.md: use CALL_OP_SYMBOL_REF in call_internal and + call_value_internal insns + +2018-02-09 Pierre-Marie de Rodat <derodat@adacore.com> + + PR lto/84213 + * dwarf2out.c (is_trivial_indirect_ref): New function. + (dwarf2out_late_global_decl): Do not generate a location + attribute for variables that have a non-trivial DECL_VALUE_EXPR + and that are not defined in the current unit. + +2018-02-09 Eric Botcazou <ebotcazou@adacore.com> + + * optabs.c (prepare_cmp_insn): Try harder to emit a direct comparison + instead of a libcall for UNORDERED. + +2018-02-09 Tamar Christina <tamar.christina@arm.com> + + PR target/82641 + * config/arm/arm-c.c (arm_cpu_builtins): Un-define __ARM_FEATURE_LDREX, + __ARM_ARCH_PROFILE, __ARM_ARCH_ISA_THUMB, __ARM_FP and __ARM_NEON_FP. + +2018-02-09 Andreas Krebbel <krebbel@linux.vnet.ibm.com> + + PR target/PR84295 + * config/s390/s390.c (s390_set_current_function): Invoke + s390_indirect_branch_settings also if fndecl didn't change. + +2018-02-09 Alexandre Oliva <aoliva@redhat.com> + + * config/rs6000/rs6000.md (blockage): Set length to zero. + +2018-02-09 Eric Botcazou <ebotcazou@adacore.com> + + * expr.c (optimize_bitfield_assignment_op): Remove obsolete assertion. + +2018-02-09 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/84285 + * gcc.c (STATIC_LIBASAN_LIBS, STATIC_LIBTSAN_LIBS, + STATIC_LIBLSAN_LIBS, STATIC_LIBUBSAN_LIBS): Handle -static like + -static-lib*san. + + PR debug/84252 + * var-tracking.c (vt_add_function_parameter): Punt for non-onepart + PARALLEL incoming that failed vt_get_decl_and_offset check. + + PR middle-end/84237 + * output.h (bss_initializer_p): Add NAMED argument, defaulted to false. + * varasm.c (bss_initializer_p): Add NAMED argument, if true, ignore + TREE_READONLY bit. + (get_variable_section): For decls in named .bss* sections pass true as + second argument to bss_initializer_p. + +2018-02-09 Marek Polacek <polacek@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + PR c++/83659 + * fold-const.c (fold_indirect_ref_1): Use VECTOR_TYPE_P macro. + Formatting fixes. Verify first that tree_fits_poly_int64_p (op01). + Sync some changes from cxx_fold_indirect_ref. + +2018-02-09 Alexandre Oliva <aoliva@redhat.com> + + * cfgexpand.c (expand_gimple_basic_block): Handle inline entry + markers. + * dwarf2out.c (dwarf2_debug_hooks): Enable inline_entry hook. + (BLOCK_INLINE_ENTRY_LABEL): New. + (dwarf2out_var_location): Disregard inline entry markers. + (inline_entry_data): New struct. + (inline_entry_data_hasher): New hashtable type. + (inline_entry_data_hasher::hash): New. + (inline_entry_data_hasher::equal): New. + (inline_entry_data_table): New variable. + (add_high_low_attributes): Add DW_AT_entry_pc and + DW_AT_GNU_entry_view attributes if a pending entry is found + in inline_entry_data_table. Add old entry_pc attribute only + if debug nonbinding markers are disabled. + (gen_inlined_subroutine_die): Set BLOCK_DIE if nonbinding + markers are enabled. + (block_within_block_p, dwarf2out_inline_entry): New. + (dwarf2out_finish): Check that no entries remained in + inline_entry_data_table. + * final.c (reemit_insn_block_notes): Handle inline entry notes. + (final_scan_insn, notice_source_line): Likewise. + (rest_of_clean_state): Skip inline entry markers. + * gimple-pretty-print.c (dump_gimple_debug): Handle inline entry + markers. + * gimple.c (gimple_build_debug_inline_entry): New. + * gimple.h (enum gimple_debug_subcode): Add + GIMPLE_DEBUG_INLINE_ENTRY. + (gimple_build_debug_inline_entry): Declare. + (gimple_debug_inline_entry_p): New. + (gimple_debug_nonbind_marker_p): Adjust. + * insn-notes.def (INLINE_ENTRY): New. + * print-rtl.c (rtx_writer::print_rtx_operand_code_0): Handle + inline entry marker notes. + (print_insn): Likewise. + * rtl.h (NOTE_MARKER_P): Add INLINE_ENTRY support. + (INSN_DEBUG_MARKER_KIND): Likewise. + (GEN_RTX_DEBUG_MARKER_INLINE_ENTRY_PAT): New. + * tree-inline.c (expand_call_inline): Build and insert + debug_inline_entry stmt. + * tree-ssa-live.c (remove_unused_scope_block_p): Preserve + inline entry blocks early, if nonbind markers are enabled. + (dump_scope_block): Dump fragment info. + * var-tracking.c (reemit_marker_as_note): Handle inline entry note. + * doc/gimple.texi (gimple_debug_inline_entry_p): New. + (gimple_build_debug_inline_entry): New. + * doc/invoke.texi (gstatement-frontiers, gno-statement-frontiers): + Enable/disable inline entry points too. + * doc/rtl.texi (NOTE_INSN_INLINE_ENTRY): New. + (DEBUG_INSN): Describe inline entry markers. + + * common.opt (gvariable-location-views): New. + (gvariable-location-views=incompat5): New. + * config.in: Rebuilt. + * configure: Rebuilt. + * configure.ac: Test assembler for view support. + * dwarf2asm.c (dw2_asm_output_symname_uleb128): New. + * dwarf2asm.h (dw2_asm_output_symname_uleb128): Declare. + * dwarf2out.c (var_loc_view): New typedef. + (struct dw_loc_list_struct): Add vl_symbol, vbegin, vend. + (dwarf2out_locviews_in_attribute): New. + (dwarf2out_locviews_in_loclist): New. + (dw_val_equal_p): Compare val_view_list of dw_val_class_view_lists. + (enum dw_line_info_opcode): Add LI_adv_address. + (struct dw_line_info_table): Add view. + (RESET_NEXT_VIEW, RESETTING_VIEW_P): New macros. + (DWARF2_ASM_VIEW_DEBUG_INFO): Define default. + (zero_view_p): New variable. + (ZERO_VIEW_P): New macro. + (output_asm_line_debug_info): New. + (struct var_loc_node): Add view. + (add_AT_view_list, AT_loc_list): New. + (add_var_loc_to_decl): Add view param. Test it against last. + (new_loc_list): Add view params. Record them. + (AT_loc_list_ptr): Handle loc and view lists. + (view_list_to_loc_list_val_node): New. + (print_dw_val): Handle dw_val_class_view_list. + (size_of_die): Likewise. + (value_format): Likewise. + (loc_list_has_views): New. + (gen_llsym): Set vl_symbol too. + (maybe_gen_llsym, skip_loc_list_entry): New. + (dwarf2out_maybe_output_loclist_view_pair): New. + (output_loc_list): Output view list or entries too. + (output_view_list_offset): New. + (output_die): Handle dw_val_class_view_list. + (output_dwarf_version): New. + (output_compilation_unit_header): Use it. + (output_skeleton_debug_sections): Likewise. + (output_rnglists, output_line_info): Likewise. + (output_pubnames, output_aranges): Update version comments. + (output_one_line_info_table): Output view numbers in asm comments. + (dw_loc_list): Determine current endview, pass it to new_loc_list. + Call maybe_gen_llsym. + (loc_list_from_tree_1): Adjust. + (add_AT_location_description): Create view list attribute if + needed, check it's absent otherwise. + (convert_cfa_to_fb_loc_list): Adjust. + (maybe_emit_file): Call output_asm_line_debug_info for test. + (dwarf2out_var_location): Reset views as needed. Precompute + add_var_loc_to_decl args. Call get_attr_min_length only if we have the + attribute. Set view. + (new_line_info_table): Reset next view. + (set_cur_line_info_table): Call output_asm_line_debug_info for test. + (dwarf2out_source_line): Likewise. Output view resets and labels to + the assembler, or select appropriate line info opcodes. + (prune_unused_types_walk_attribs): Handle dw_val_class_view_list. + (optimize_string_length): Catch it. Adjust. + (resolve_addr): Copy vl_symbol along with ll_symbol. Handle + dw_val_class_view_list, and remove it if no longer needed. + (hash_loc_list): Hash view numbers. + (loc_list_hasher::equal): Compare them. + (optimize_location_lists): Check whether a view list symbol is + needed, and whether the locview attribute is present, and + whether they match. Remove the locview attribute if no longer + needed. + (index_location_lists): Call skip_loc_list_entry for test. + (dwarf2out_finish): Call output_asm_line_debug_info for test. + Use output_dwarf_version. + * dwarf2out.h (enum dw_val_class): Add dw_val_class_view_list. + (struct dw_val_node): Add val_view_list. + * final.c (SEEN_NEXT_VIEW): New. + (set_next_view_needed): New. + (clear_next_view_needed): New. + (maybe_output_next_view): New. + (final_start_function): Rename to... + (final_start_function_1): ... this. Take pointer to FIRST, + add SEEN parameter. Emit param bindings in the initial view. + (final_start_function): Reintroduce SEEN-less interface. + (final): Rename to... + (final_1): ... this. Take SEEN parameter. Output final pending + next view at the end. + (final): Reintroduce seen-less interface. + (final_scan_insn): Output pending next view before switching + sections or ending a block. Mark the next view as needed when + outputting variable locations. Notify debug backend of section + changes, and of location view changes. + (rest_of_handle_final): Adjust. + * toplev.c (process_options): Autodetect value for debug variable + location views option. Warn on incompat5 without -gdwarf-5. + * doc/invoke.texi (gvariable-location-views): New. + (gvariable-location-views=incompat5): New. + (gno-variable-location-views): New. + +2018-02-08 David Malcolm <dmalcolm@redhat.com> + + PR tree-optimization/84136 + * tree-cfg.c (find_taken_edge_computed_goto): Remove assertion + that the result of find_edge is non-NULL. + +2018-02-08 Sergey Shalnov <sergey.shalnov@intel.com> + + PR target/83008 + * config/i386/x86-tune-costs.h (skylake_cost): Fix cost of + storing integer register in SImode. Fix cost of 256 and 512 + byte aligned SSE register store. + +2018-02-08 Sergey Shalnov <sergey.shalnov@intel.com> + + * config/i386/i386.c (ix86_multiplication_cost): Fix + multiplication cost for TARGET_AVX512DQ. + +2018-02-08 Marek Polacek <polacek@redhat.com> + + PR tree-optimization/84238 + * tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Verify the result of + get_range_strlen. + 2018-02-08 Richard Sandiford <richard.sandiford@linaro.org> PR tree-optimization/84265 @@ -149,6 +445,7 @@ 2018-02-07 Iain Sandoe <iain@codesourcery.com> + PR target/84113 * config/rs6000/altivec.md (*restore_world): Remove LR use. * config/rs6000/predicates.md (restore_world_operation): Adjust op count, remove one USE. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 3a0b1e3..d1c73de 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20180208 +20180211 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 02b2b1a..1f536d1 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,25 @@ +2018-02-09 Nathan Sidwell <nathan@acm.org> + + PR c/84293 + * c-common.h (strict_aliasing_warning): Drop OTYPE arg, insert LOC + arg. + * c-warn.c (strict_aliasing_warning): Drop OTYPE arg, require LOC + arg. Adjust. + +2018-02-09 Martin Sebor <msebor@redhat.com> + + PR lto/84212 + * c.opt (-Wstringop-overflow, -Warray-bounds): Add LTO. + (-Walloc-size-larger-than, -Wformat-truncation=): Same. + (-Wmaybe-uninitialized, -Wnonnull, -Wrestrict): Same. + (-Wstrict-overflow, -Wsuggest-attribute): Same. + (-Wuninitialized): Same. + +2018-02-09 Eric Botcazou <ebotcazou@adacore.com> + + * c-ada-spec.c (dump_ada_declaration): Do not generate the 'constant' + keyword for components. + 2018-02-02 Paolo Carlini <paolo.carlini@oracle.com> * c-common.h (DECL_UNNAMED_BIT_FIELD): New. diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c index 914ded9..1c1cadc 100644 --- a/gcc/c-family/c-ada-spec.c +++ b/gcc/c-family/c-ada-spec.c @@ -3131,7 +3131,7 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) { pp_string (buffer, "aliased "); - if (TREE_READONLY (t)) + if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL) pp_string (buffer, "constant "); if (TYPE_NAME (TREE_TYPE (t))) @@ -3147,7 +3147,7 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) || TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE)) pp_string (buffer, "aliased "); - if (TREE_READONLY (t)) + if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL) pp_string (buffer, "constant "); dump_generic_ada_node diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 775d468..95bb0fd 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1260,7 +1260,7 @@ extern void warn_tautological_cmp (location_t, enum tree_code, tree, tree); extern void warn_logical_not_parentheses (location_t, enum tree_code, tree, tree); extern bool warn_if_unused_value (const_tree, location_t); -extern bool strict_aliasing_warning (tree, tree, tree); +extern bool strict_aliasing_warning (location_t, tree, tree); extern void sizeof_pointer_memaccess_warning (location_t *, tree, vec<tree, va_gc> *, tree *, bool (*) (tree, tree)); diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 7d87c45..f3fb62c 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -599,17 +599,21 @@ warn_if_unused_value (const_tree exp, location_t locus) } } -/* Print a warning about casts that might indicate violation - of strict aliasing rules if -Wstrict-aliasing is used and - strict aliasing mode is in effect. OTYPE is the original - TREE_TYPE of EXPR, and TYPE the type we're casting to. */ +/* Print a warning about casts that might indicate violation of strict + aliasing rules if -Wstrict-aliasing is used and strict aliasing + mode is in effect. LOC is the location of the expression being + cast, EXPR might be from inside it. TYPE is the type we're casting + to. */ bool -strict_aliasing_warning (tree otype, tree type, tree expr) +strict_aliasing_warning (location_t loc, tree type, tree expr) { + if (loc == UNKNOWN_LOCATION) + loc = input_location; + /* Strip pointer conversion chains and get to the correct original type. */ STRIP_NOPS (expr); - otype = TREE_TYPE (expr); + tree otype = TREE_TYPE (expr); if (!(flag_strict_aliasing && POINTER_TYPE_P (type) @@ -628,8 +632,9 @@ strict_aliasing_warning (tree otype, tree type, tree expr) if the cast breaks type based aliasing. */ if (!COMPLETE_TYPE_P (TREE_TYPE (type)) && warn_strict_aliasing == 2) { - warning (OPT_Wstrict_aliasing, "type-punning to incomplete type " - "might break strict-aliasing rules"); + warning_at (loc, OPT_Wstrict_aliasing, + "type-punning to incomplete type " + "might break strict-aliasing rules"); return true; } else @@ -645,15 +650,17 @@ strict_aliasing_warning (tree otype, tree type, tree expr) && !alias_set_subset_of (set2, set1) && !alias_sets_conflict_p (set1, set2)) { - warning (OPT_Wstrict_aliasing, "dereferencing type-punned " - "pointer will break strict-aliasing rules"); + warning_at (loc, OPT_Wstrict_aliasing, + "dereferencing type-punned " + "pointer will break strict-aliasing rules"); return true; } else if (warn_strict_aliasing == 2 && !alias_sets_must_conflict_p (set1, set2)) { - warning (OPT_Wstrict_aliasing, "dereferencing type-punned " - "pointer might break strict-aliasing rules"); + warning_at (loc, OPT_Wstrict_aliasing, + "dereferencing type-punned " + "pointer might break strict-aliasing rules"); return true; } } @@ -669,8 +676,9 @@ strict_aliasing_warning (tree otype, tree type, tree expr) if (!COMPLETE_TYPE_P (type) || !alias_sets_must_conflict_p (set1, set2)) { - warning (OPT_Wstrict_aliasing, "dereferencing type-punned " - "pointer might break strict-aliasing rules"); + warning_at (loc, OPT_Wstrict_aliasing, + "dereferencing type-punned " + "pointer might break strict-aliasing rules"); return true; } } diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 9c71726..7fb386d 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -304,7 +304,7 @@ C ObjC C++ ObjC++ Var(warn_alloca) Warning Warn on any use of alloca. Walloc-size-larger-than= -C ObjC C++ ObjC++ Var(warn_alloc_size_limit) Warning Joined LangEnabledBy(C ObjC C++ ObjC++,Wall) +C ObjC C++ LTO ObjC++ Var(warn_alloc_size_limit) Warning Joined LangEnabledBy(C ObjC C++ LTO ObjC++,Wall) -Walloc-size-larger-than=<bytes> Warn for calls to allocation functions that attempt to allocate objects larger than the specified number of bytes. @@ -319,11 +319,11 @@ alloca, and on bounded uses of alloca whose bound can be larger than <number> bytes. Warray-bounds -LangEnabledBy(C ObjC C++ ObjC++,Wall) +LangEnabledBy(C ObjC C++ LTO ObjC++,Wall) ; in common.opt Warray-bounds= -LangEnabledBy(C ObjC C++ ObjC++,Wall,1,0) +LangEnabledBy(C ObjC C++ LTO ObjC++,Wall,1,0) ; in common.opt Wassign-intercept @@ -575,12 +575,12 @@ C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format) Warning LangEn Warn about printf/scanf/strftime/strfmon format string anomalies. Wformat-overflow= -C ObjC C++ LTO ObjC++ Joined RejectNegative UInteger Var(warn_format_overflow) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0) IntegerRange(0, 2) +C ObjC C++ LTO ObjC++ Joined RejectNegative UInteger Var(warn_format_overflow) Warning LangEnabledBy(C ObjC C++ LTO ObjC++,Wformat=, warn_format >= 1, 0) IntegerRange(0, 2) Warn about function calls with format strings that write past the end of the destination region. Wformat-truncation= -C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format_trunc) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0) IntegerRange(0, 2) +C ObjC C++ LTO ObjC++ Joined RejectNegative UInteger Var(warn_format_trunc) Warning LangEnabledBy(C ObjC C++ LTO ObjC++,Wformat=, warn_format >= 1, 0) IntegerRange(0, 2) Warn about calls to snprintf and similar functions that truncate output. Wif-not-aligned @@ -739,17 +739,17 @@ C ObjC C++ ObjC++ Var(warn_sizeof_array_argument) Warning Init(1) Warn when sizeof is applied on a parameter declared as an array. Wstringop-overflow -C ObjC C++ ObjC++ Warning Alias(Wstringop-overflow=, 2, 0) +C ObjC C++ LTO ObjC++ Warning Alias(Wstringop-overflow=, 2, 0) Warn about buffer overflow in string manipulation functions like memcpy and strcpy. Wstringop-overflow= -C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_stringop_overflow) Init(2) Warning LangEnabledBy(C ObjC C++ ObjC++, Wall, 2, 0) IntegerRange(0, 4) +C ObjC C++ LTO ObjC++ Joined RejectNegative UInteger Var(warn_stringop_overflow) Init(2) Warning LangEnabledBy(C ObjC C++ LTO ObjC++, Wall, 2, 0) IntegerRange(0, 4) Under the control of Object Size type, warn about buffer overflow in string manipulation functions like memcpy and strcpy. Wstringop-truncation -C ObjC C++ ObjC++ Var(warn_stringop_truncation) Warning Init (1) LangEnabledBy(C ObjC C++ ObjC++, Wall) +C ObjC C++ LTO ObjC++ Var(warn_stringop_truncation) Warning Init (1) LangEnabledBy(C ObjC C++ LTO ObjC++, Wall) Warn about truncation in string manipulation functions like strncat and strncpy. Wsuggest-attribute=format @@ -833,11 +833,11 @@ C++ ObjC++ Var(warn_nonvdtor) Warning LangEnabledBy(C++ ObjC++,Weffc++) Warn about non-virtual destructors. Wnonnull -C ObjC C++ ObjC++ Var(warn_nonnull) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=,warn_format >= 1,0) +C ObjC C++ LTO ObjC++ Var(warn_nonnull) Warning LangEnabledBy(C ObjC C++ LTO ObjC++,Wformat=,warn_format >= 1,0) Warn about NULL being passed to argument slots marked as requiring non-NULL. Wnonnull -C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall) +C ObjC C++ LTO ObjC++ LangEnabledBy(C ObjC C++ LTO ObjC++,Wall) ; Wnonnull-compare @@ -1084,11 +1084,11 @@ C ObjC C++ ObjC++ CPP(warn_undef) CppReason(CPP_W_UNDEF) Var(cpp_warn_undef) Ini Warn if an undefined macro is used in an #if directive. Wuninitialized -C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall) +C ObjC C++ ObjC++ LTO LangEnabledBy(C ObjC C++ ObjC++ LTO,Wall) ; Wmaybe-uninitialized -C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall) +C ObjC C++ ObjC++ LTO LangEnabledBy(C ObjC C++ ObjC++ LTO,Wall) ; Wunknown-pragmas diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 97ae43c..bca7268 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2018-02-09 Nathan Sidwell <nathan@acm.org> + + PR c/84293 + * c-typeck.c (build_indirect_ref, build_c_cast): Pass expr location + to strict_aliasing_warning. + 2018-02-02 Paolo Carlini <paolo.carlini@oracle.com> * c-typeck.c (really_start_incremental_init, push_init_level, diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index b35c2c0..1eae4ea 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -2524,7 +2524,7 @@ build_indirect_ref (location_t loc, tree ptr, ref_operator errstring) the backend. This only needs to be done at warn_strict_aliasing > 2. */ if (warn_strict_aliasing > 2) - if (strict_aliasing_warning (TREE_TYPE (TREE_OPERAND (pointer, 0)), + if (strict_aliasing_warning (EXPR_LOCATION (pointer), type, TREE_OPERAND (pointer, 0))) TREE_NO_WARNING (pointer) = 1; } @@ -5696,7 +5696,7 @@ build_c_cast (location_t loc, tree type, tree expr) "of different size"); if (warn_strict_aliasing <= 2) - strict_aliasing_warning (otype, type, expr); + strict_aliasing_warning (EXPR_LOCATION (value), type, expr); /* If pedantic, warn for conversions between function and object pointer types, except for converting a null pointer constant diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 2ee6fba..deab929 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -5731,6 +5731,15 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) goto delink_debug_stmt; else if (gimple_debug_begin_stmt_p (stmt)) val = GEN_RTX_DEBUG_MARKER_BEGIN_STMT_PAT (); + else if (gimple_debug_inline_entry_p (stmt)) + { + tree block = gimple_block (stmt); + + if (block) + val = GEN_RTX_DEBUG_MARKER_INLINE_ENTRY_PAT (); + else + goto delink_debug_stmt; + } else gcc_unreachable (); diff --git a/gcc/common.opt b/gcc/common.opt index 3e9e310..40ec008 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2956,6 +2956,13 @@ gtoggle Common Driver Report Var(flag_gtoggle) Toggle debug information generation. +gvariable-location-views +Common Driver Var(debug_variable_location_views, 1) Init(2) +Augment variable location lists with progressive views. + +gvariable-location-views=incompat5 +Common Driver RejectNegative Var(debug_variable_location_views, -1) Init(2) + gvms Common Driver JoinedOrMissing Negative(gxcoff) Generate debug information in VMS format. diff --git a/gcc/config.in b/gcc/config.in index 8dc4531..5bccb40 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -358,6 +358,12 @@ #endif +/* Define if your assembler supports views in dwarf2 .loc directives. */ +#ifndef USED_FOR_TARGET +#undef HAVE_AS_DWARF2_DEBUG_VIEW +#endif + + /* Define if your assembler supports the R_PPC64_ENTRY relocation. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_ENTRY_MARKERS diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c index 9a16172..7c741e9 100644 --- a/gcc/config/arm/arm-c.c +++ b/gcc/config/arm/arm-c.c @@ -87,11 +87,10 @@ arm_cpu_builtins (struct cpp_reader* pfile) builtin_define ("__ARM_FEATURE_CMSE"); } + cpp_undef (pfile, "__ARM_FEATURE_LDREX"); if (TARGET_ARM_FEATURE_LDREX) builtin_define_with_int_value ("__ARM_FEATURE_LDREX", TARGET_ARM_FEATURE_LDREX); - else - cpp_undef (pfile, "__ARM_FEATURE_LDREX"); def_or_undef_macro (pfile, "__ARM_FEATURE_CLZ", ((TARGET_ARM_ARCH >= 5 && !TARGET_THUMB) @@ -105,6 +104,8 @@ arm_cpu_builtins (struct cpp_reader* pfile) builtin_define_with_int_value ("__ARM_SIZEOF_MINIMAL_ENUM", flag_short_enums ? 1 : 4); builtin_define_type_sizeof ("__ARM_SIZEOF_WCHAR_T", wchar_type_node); + + cpp_undef (pfile, "__ARM_ARCH_PROFILE"); if (TARGET_ARM_ARCH_PROFILE) builtin_define_with_int_value ("__ARM_ARCH_PROFILE", TARGET_ARM_ARCH_PROFILE); @@ -128,6 +129,7 @@ arm_cpu_builtins (struct cpp_reader* pfile) else def_or_undef_macro (pfile, "__THUMBEL__", TARGET_THUMB); + cpp_undef (pfile, "__ARM_ARCH_ISA_THUMB"); if (TARGET_ARM_ARCH_ISA_THUMB) builtin_define_with_int_value ("__ARM_ARCH_ISA_THUMB", TARGET_ARM_ARCH_ISA_THUMB); @@ -147,10 +149,9 @@ arm_cpu_builtins (struct cpp_reader* pfile) builtin_define ("__VFP_FP__"); + cpp_undef (pfile, "__ARM_FP"); if (TARGET_ARM_FP) builtin_define_with_int_value ("__ARM_FP", TARGET_ARM_FP); - else - cpp_undef (pfile, "__ARM_FP"); def_or_undef_macro (pfile, "__ARM_FP16_FORMAT_IEEE", arm_fp16_format == ARM_FP16_FORMAT_IEEE); @@ -169,10 +170,9 @@ arm_cpu_builtins (struct cpp_reader* pfile) def_or_undef_macro (pfile, "__ARM_NEON__", TARGET_NEON); def_or_undef_macro (pfile, "__ARM_NEON", TARGET_NEON); + cpp_undef (pfile, "__ARM_NEON_FP"); if (TARGET_NEON_FP) builtin_define_with_int_value ("__ARM_NEON_FP", TARGET_NEON_FP); - else - cpp_undef (pfile, "__ARM_NEON_FP"); /* Add a define for interworking. Needed when building libgcc.a. */ if (arm_cpp_interwork) diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index fc3d6f0..a870997 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -40402,6 +40402,10 @@ ix86_multiplication_cost (const struct processor_costs *cost, ? cost->mulsd : cost->mulss, true); else if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) { + /* vpmullq is used in this case. No emulation is needed. */ + if (TARGET_AVX512DQ) + return ix86_vec_cost (mode, cost->mulss, true); + /* V*QImode is emulated with 7-13 insns. */ if (mode == V16QImode || mode == V32QImode) { diff --git a/gcc/config/i386/x86-tune-costs.h b/gcc/config/i386/x86-tune-costs.h index e943d13..8409a5f 100644 --- a/gcc/config/i386/x86-tune-costs.h +++ b/gcc/config/i386/x86-tune-costs.h @@ -1557,7 +1557,7 @@ struct processor_costs skylake_cost = { {4, 4, 4}, /* cost of loading integer registers in QImode, HImode and SImode. Relative to reg-reg move (2). */ - {6, 6, 6}, /* cost of storing integer registers */ + {6, 6, 3}, /* cost of storing integer registers */ 2, /* cost of reg,reg fld/fst */ {6, 6, 8}, /* cost of loading fp registers in SFmode, DFmode and XFmode */ @@ -1572,7 +1572,7 @@ struct processor_costs skylake_cost = { {6, 6, 6, 10, 20}, /* cost of loading SSE registers in 32,64,128,256 and 512-bit */ {6, 6, 6, 10, 20}, /* cost of unaligned loads. */ - {8, 8, 8, 8, 16}, /* cost of storing SSE registers + {8, 8, 8, 12, 24}, /* cost of storing SSE registers in 32,64,128,256 and 512-bit */ {8, 8, 8, 8, 16}, /* cost of unaligned stores. */ 2, 2, /* SSE->integer and integer->SSE moves */ diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 0809a79..13d5777 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -4578,13 +4578,17 @@ hppa_profile_hook (int label_no) lcla2 and load_offset_label_address insn patterns. */ rtx reg = gen_reg_rtx (SImode); rtx_code_label *label_rtx = gen_label_rtx (); - rtx mcount = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (Pmode, "_mcount")); int reg_parm_stack_space = REG_PARM_STACK_SPACE (NULL_TREE); - rtx arg_bytes, begin_label_rtx; + rtx arg_bytes, begin_label_rtx, mcount, sym; rtx_insn *call_insn; char begin_label_name[16]; bool use_mcount_pcrel_call; + /* Set up call destination. */ + sym = gen_rtx_SYMBOL_REF (Pmode, "_mcount"); + pa_encode_label (sym); + mcount = gen_rtx_MEM (Pmode, sym); + /* If we can reach _mcount with a pc-relative call, we can optimize loading the address of the current function. This requires linker long branch stub support. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 33f0d95..5f44d80 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -11063,7 +11063,8 @@ (define_insn "blockage" [(unspec_volatile [(const_int 0)] UNSPECV_BLOCK)] "" - "") + "" + [(set_attr "length" "0")]) (define_expand "probe_stack_address" [(use (match_operand 0 "address_operand"))] @@ -13359,7 +13360,7 @@ ;; Use r0 to stop regrename twiddling with lr restore insns emitted ;; after the call to __morestack. (define_insn "split_stack_return" - [(unspec_volatile [(use (reg:SI 0))] UNSPECV_SPLIT_STACK_RETURN)] + [(unspec_volatile [(reg:SI 0) (reg:SI LR_REGNO)] UNSPECV_SPLIT_STACK_RETURN)] "" "blr" [(set_attr "type" "jmpreg")]) diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index c2016f1..6f0bd09 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -1650,10 +1650,22 @@ rtx op5 = gen_reg_rtx (DImode); emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0))); emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0))); - emit_insn (gen_muldi3 (op5, op3, op4)); + if (TARGET_POWERPC64) + emit_insn (gen_muldi3 (op5, op3, op4)); + else + { + rtx ret = expand_mult (DImode, op3, op4, NULL, 0, false); + emit_move_insn (op5, ret); + } emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1))); emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1))); - emit_insn (gen_muldi3 (op3, op3, op4)); + if (TARGET_POWERPC64) + emit_insn (gen_muldi3 (op3, op3, op4)); + else + { + rtx ret = expand_mult (DImode, op3, op4, NULL, 0, false); + emit_move_insn (op3, ret); + } emit_insn (gen_vsx_concat_v2di (op0, op5, op3)); DONE; }" @@ -1688,10 +1700,30 @@ rtx op5 = gen_reg_rtx (DImode); emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0))); emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0))); - emit_insn (gen_divdi3 (op5, op3, op4)); + if (TARGET_POWERPC64) + emit_insn (gen_divdi3 (op5, op3, op4)); + else + { + rtx libfunc = optab_libfunc (sdiv_optab, DImode); + rtx target = emit_library_call_value (libfunc, + op5, LCT_NORMAL, DImode, + op3, DImode, + op4, DImode); + emit_move_insn (op5, target); + } emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1))); emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1))); - emit_insn (gen_divdi3 (op3, op3, op4)); + if (TARGET_POWERPC64) + emit_insn (gen_divdi3 (op3, op3, op4)); + else + { + rtx libfunc = optab_libfunc (sdiv_optab, DImode); + rtx target = emit_library_call_value (libfunc, + op3, LCT_NORMAL, DImode, + op3, DImode, + op4, DImode); + emit_move_insn (op3, target); + } emit_insn (gen_vsx_concat_v2di (op0, op5, op3)); DONE; }" @@ -1716,10 +1748,30 @@ rtx op5 = gen_reg_rtx (DImode); emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0))); emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0))); - emit_insn (gen_udivdi3 (op5, op3, op4)); + if (TARGET_POWERPC64) + emit_insn (gen_udivdi3 (op5, op3, op4)); + else + { + rtx libfunc = optab_libfunc (udiv_optab, DImode); + rtx target = emit_library_call_value (libfunc, + op5, LCT_NORMAL, DImode, + op3, DImode, + op4, DImode); + emit_move_insn (op5, target); + } emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1))); emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1))); - emit_insn (gen_udivdi3 (op3, op3, op4)); + if (TARGET_POWERPC64) + emit_insn (gen_udivdi3 (op3, op3, op4)); + else + { + rtx libfunc = optab_libfunc (udiv_optab, DImode); + rtx target = emit_library_call_value (libfunc, + op3, LCT_NORMAL, DImode, + op3, DImode, + op4, DImode); + emit_move_insn (op3, target); + } emit_insn (gen_vsx_concat_v2di (op0, op5, op3)); DONE; }" @@ -5311,35 +5363,60 @@ (define_expand "p9_xxbrq_v16qi" [(use (match_operand:V16QI 0 "vsx_register_operand" "=wa")) - (use (match_operand:V16QI 1 "vsx_register_operand" "=wa"))] + (use (match_operand:V16QI 1 "vsx_register_operand" "wa"))] "TARGET_P9_VECTOR" { - rtx op0 = gen_lowpart (V1TImode, operands[0]); + rtx op0 = gen_reg_rtx (V1TImode); rtx op1 = gen_lowpart (V1TImode, operands[1]); emit_insn (gen_p9_xxbrq_v1ti (op0, op1)); + emit_move_insn (operands[0], gen_lowpart (V16QImode, op0)); DONE; }) ;; Swap all bytes in each 64-bit element -(define_insn "p9_xxbrd_<mode>" - [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa") - (bswap:VSX_D (match_operand:VSX_D 1 "vsx_register_operand" "wa")))] +(define_insn "p9_xxbrd_v2di" + [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa") + (bswap:V2DI (match_operand:V2DI 1 "vsx_register_operand" "wa")))] "TARGET_P9_VECTOR" "xxbrd %x0,%x1" [(set_attr "type" "vecperm")]) +(define_expand "p9_xxbrd_v2df" + [(use (match_operand:V2DF 0 "vsx_register_operand" "=wa")) + (use (match_operand:V2DF 1 "vsx_register_operand" "wa"))] + "TARGET_P9_VECTOR" +{ + rtx op0 = gen_reg_rtx (V2DImode); + rtx op1 = gen_lowpart (V2DImode, operands[1]); + emit_insn (gen_p9_xxbrd_v2di (op0, op1)); + emit_move_insn (operands[0], gen_lowpart (V2DFmode, op0)); + DONE; +}) + ;; Swap all bytes in each 32-bit element -(define_insn "p9_xxbrw_<mode>" - [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa") - (bswap:VSX_W (match_operand:VSX_W 1 "vsx_register_operand" "wa")))] +(define_insn "p9_xxbrw_v4si" + [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa") + (bswap:V4SI (match_operand:V4SI 1 "vsx_register_operand" "wa")))] "TARGET_P9_VECTOR" "xxbrw %x0,%x1" [(set_attr "type" "vecperm")]) +(define_expand "p9_xxbrw_v4sf" + [(use (match_operand:V4SF 0 "vsx_register_operand" "=wa")) + (use (match_operand:V4SF 1 "vsx_register_operand" "wa"))] + "TARGET_P9_VECTOR" +{ + rtx op0 = gen_reg_rtx (V4SImode); + rtx op1 = gen_lowpart (V4SImode, operands[1]); + emit_insn (gen_p9_xxbrw_v4si (op0, op1)); + emit_move_insn (operands[0], gen_lowpart (V4SFmode, op0)); + DONE; +}) + ;; Swap all bytes in each element of vector (define_expand "revb_<mode>" - [(set (match_operand:VEC_REVB 0 "vsx_register_operand") - (bswap:VEC_REVB (match_operand:VEC_REVB 1 "vsx_register_operand")))] + [(use (match_operand:VEC_REVB 0 "vsx_register_operand")) + (use (match_operand:VEC_REVB 1 "vsx_register_operand"))] "" { if (TARGET_P9_VECTOR) diff --git a/gcc/config/rx/constraints.md b/gcc/config/rx/constraints.md index 448fc46..d981f66 100644 --- a/gcc/config/rx/constraints.md +++ b/gcc/config/rx/constraints.md @@ -106,3 +106,9 @@ ) ) ) + +(define_constraint "CALL_OP_SYMBOL_REF" +"constraint for call instructions using symbol ref" +(and (match_test "!TARGET_JSR") + (match_code "symbol_ref")) +) diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index e642d73..3fb2ac8 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -438,7 +438,7 @@ ) (define_insn "call_internal" - [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol")) + [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,CALL_OP_SYMBOL_REF")) (const_int 0)) (clobber (reg:CC CC_REG))] "" @@ -466,7 +466,7 @@ (define_insn "call_value_internal" [(set (match_operand 0 "register_operand" "=r,r") - (call (mem:QI (match_operand:SI 1 "rx_call_operand" "r,Symbol")) + (call (mem:QI (match_operand:SI 1 "rx_call_operand" "r,CALL_OP_SYMBOL_REF")) (const_int 0))) (clobber (reg:CC CC_REG))] "" @@ -733,12 +733,17 @@ (define_expand "movsicc" [(parallel [(set (match_operand:SI 0 "register_operand") - (if_then_else:SI (match_operand:SI 1 "comparison_operator") + (if_then_else:SI (match_operand 1 "comparison_operator") (match_operand:SI 2 "nonmemory_operand") (match_operand:SI 3 "nonmemory_operand"))) (clobber (reg:CC CC_REG))])] "" { + /* Make sure that we have an integer comparison... */ + if (GET_MODE (XEXP (operands[1], 0)) != CCmode + && GET_MODE (XEXP (operands[1], 0)) != SImode) + FAIL; + /* One operand must be a constant or a register, the other must be a register. */ if ( ! CONSTANT_P (operands[2]) && ! CONSTANT_P (operands[3]) diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 62a60e2..298fdd1 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -16135,7 +16135,10 @@ s390_set_current_function (tree fndecl) several times in the course of compiling a function, and we don't want to slow things down too much or call target_reinit when it isn't safe. */ if (fndecl == s390_previous_fndecl) - return; + { + s390_indirect_branch_settings (fndecl); + return; + } tree old_tree; if (s390_previous_fndecl == NULL_TREE) diff --git a/gcc/configure b/gcc/configure index 3360209..b126287 100755 --- a/gcc/configure +++ b/gcc/configure @@ -27825,6 +27825,52 @@ $as_echo "$gcc_cv_as_dwarf2_file_buggy" >&6; } $as_echo "#define HAVE_AS_DWARF2_DEBUG_LINE 1" >>confdefs.h + + if test $gcc_cv_as_leb128 = yes; then + conftest_s="\ + .file 1 \"conftest.s\" + .loc 1 3 0 view .LVU1 + $insn + .data + .uleb128 .LVU1 + .uleb128 .LVU1 +" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for dwarf2 debug_view support" >&5 +$as_echo_n "checking assembler for dwarf2 debug_view support... " >&6; } +if test "${gcc_cv_as_dwarf2_debug_view+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + gcc_cv_as_dwarf2_debug_view=no + if test $in_tree_gas = yes; then + if test $in_tree_gas_is_elf = yes \ + && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 27 \) \* 1000 + 0` + then gcc_cv_as_dwarf2_debug_view=yes +fi + elif test x$gcc_cv_as != x; then + $as_echo "$conftest_s" > conftest.s + if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + gcc_cv_as_dwarf2_debug_view=yes + else + echo "configure: failed program was" >&5 + cat conftest.s >&5 + fi + rm -f conftest.o conftest.s + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_dwarf2_debug_view" >&5 +$as_echo "$gcc_cv_as_dwarf2_debug_view" >&6; } +if test $gcc_cv_as_dwarf2_debug_view = yes; then + +$as_echo "#define HAVE_AS_DWARF2_DEBUG_VIEW 1" >>confdefs.h + +fi + fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for --gdwarf2 option" >&5 diff --git a/gcc/configure.ac b/gcc/configure.ac index 1019b31..140c804 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -4902,9 +4902,25 @@ if test x"$insn" != x; then if test $gcc_cv_as_dwarf2_debug_line = yes \ && test $gcc_cv_as_dwarf2_file_buggy = no; then - AC_DEFINE(HAVE_AS_DWARF2_DEBUG_LINE, 1, + AC_DEFINE(HAVE_AS_DWARF2_DEBUG_LINE, 1, [Define if your assembler supports dwarf2 .file/.loc directives, and preserves file table indices exactly as given.]) + + if test $gcc_cv_as_leb128 = yes; then + conftest_s="\ + .file 1 \"conftest.s\" + .loc 1 3 0 view .LVU1 + $insn + .data + .uleb128 .LVU1 + .uleb128 .LVU1 +" + gcc_GAS_CHECK_FEATURE([dwarf2 debug_view support], + gcc_cv_as_dwarf2_debug_view, + [elf,2,27,0],,[$conftest_s],, + [AC_DEFINE(HAVE_AS_DWARF2_DEBUG_VIEW, 1, + [Define if your assembler supports views in dwarf2 .loc directives.])]) + fi fi gcc_GAS_CHECK_FEATURE([--gdwarf2 option], diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b898ba1..e01e73b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,55 @@ +2018-02-10 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/83987 + * tree.c (cp_free_lang_data): Revert 2018-01-23 change. + +2018-02-09 Jason Merrill <jason@redhat.com> + + PR c++/81917 - ICE with void_t and partial specialization. + * pt.c (instantiate_class_template_1): Set TYPE_BEING_DEFINED before + calling most_specialized_partial_spec. + +2018-02-09 Nathan Sidwell <nathan@acm.org> + + PR c/84293 + * typeck.c (cp_build_indirect_ref_1, build_reinterpret_cast_1): + Pass expr location to strict_aliasing_warning. + +2018-02-09 Jason Merrill <jason@redhat.com> + + PR c++/84296 - ICE with qualified-id in template. + PR c++/83714 + * pt.c (unknown_base_ref_p): New. + (instantiation_dependent_scope_ref_p): Use it instead of + any_dependent_bases_p. + +2018-02-09 Marek Polacek <polacek@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + PR c++/83659 + * constexpr.c (cxx_fold_indirect_ref): Sync some changes from + fold_indirect_ref_1, including poly_*int64. Verify first that + tree_fits_poly_int64_p (op01). Formatting fixes. + +2018-02-08 Paolo Carlini <paolo.carlini@oracle.com> + + * constexpr.c (cxx_eval_component_reference): Use INDIRECT_REF_P. + * lambda.c (build_capture_proxy): Likewise. + * search.c (field_access_p): Likewise. + * semantics.c (omp_clause_decl, omp_privatize_field, + finish_omp_clauses): Likewise. + +2018-02-08 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/83806 + * typeck.c (decay_conversion): Use mark_rvalue_use for the special + case of nullptr too. + +2018-02-08 Nathan Sidwell <nathan@acm.org> + + * class.c (finish_struct): Fix std:initializer_list diagnostic + formatting. + 2018-02-08 Paolo Carlini <paolo.carlini@oracle.com> PR c++/83204 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4417020..e48a04a 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -7062,7 +7062,7 @@ finish_struct (tree t, tree attributes) /* People keep complaining that the compiler crashes on an invalid definition of initializer_list, so I guess we should explicitly reject it. What the compiler internals care about is that it's a - template and has a pointer field followed by an integer field. */ + template and has a pointer field followed by size_type field. */ bool ok = false; if (processing_template_decl) { @@ -7075,9 +7075,8 @@ finish_struct (tree t, tree attributes) } } if (!ok) - fatal_error (input_location, - "definition of std::initializer_list does not match " - "#include <initializer_list>"); + fatal_error (input_location, "definition of %qD does not match " + "%<#include <initializer_list>%>", TYPE_NAME (t)); } input_location = saved_loc; diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 93dd8ae..7292441 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -2463,7 +2463,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, tree whole = cxx_eval_constant_expression (ctx, orig_whole, lval, non_constant_p, overflow_p); - if (TREE_CODE (whole) == INDIRECT_REF + if (INDIRECT_REF_P (whole) && integer_zerop (TREE_OPERAND (whole, 0)) && !ctx->quiet) error ("dereferencing a null pointer in %qE", orig_whole); @@ -3025,9 +3025,10 @@ cxx_eval_vec_init (const constexpr_ctx *ctx, tree t, static tree cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) { - tree sub, subtype; + tree sub = op0; + tree subtype; + poly_uint64 const_op01; - sub = op0; STRIP_NOPS (sub); subtype = TREE_TYPE (sub); if (!POINTER_TYPE_P (subtype)) @@ -3082,7 +3083,8 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) { tree part_width = TYPE_SIZE (type); tree index = bitsize_int (0); - return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, index); + return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, + index); } /* Also handle conversion to an empty base class, which is represented with a NOP_EXPR. */ @@ -3107,7 +3109,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) } } else if (TREE_CODE (sub) == POINTER_PLUS_EXPR - && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST) + && poly_int_tree_p (TREE_OPERAND (sub, 1), &const_op01)) { tree op00 = TREE_OPERAND (sub, 0); tree op01 = TREE_OPERAND (sub, 1); @@ -3121,29 +3123,37 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */ if (VECTOR_TYPE_P (op00type) - && (same_type_ignoring_top_level_qualifiers_p - (type, TREE_TYPE (op00type)))) + && same_type_ignoring_top_level_qualifiers_p + (type, TREE_TYPE (op00type)) + /* POINTER_PLUS_EXPR second operand is sizetype, unsigned, + but we want to treat offsets with MSB set as negative. + For the code below negative offsets are invalid and + TYPE_SIZE of the element is something unsigned, so + check whether op01 fits into poly_int64, which implies + it is from 0 to INTTYPE_MAXIMUM (HOST_WIDE_INT), and + then just use poly_uint64 because we want to treat the + value as unsigned. */ + && tree_fits_poly_int64_p (op01)) { - HOST_WIDE_INT offset = tree_to_shwi (op01); tree part_width = TYPE_SIZE (type); - unsigned HOST_WIDE_INT part_widthi = tree_to_shwi (part_width)/BITS_PER_UNIT; - unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; - tree index = bitsize_int (indexi); - - if (known_lt (offset / part_widthi, - TYPE_VECTOR_SUBPARTS (op00type))) - return fold_build3_loc (loc, - BIT_FIELD_REF, type, op00, - part_width, index); - + poly_uint64 max_offset + = (tree_to_uhwi (part_width) / BITS_PER_UNIT + * TYPE_VECTOR_SUBPARTS (op00type)); + if (known_lt (const_op01, max_offset)) + { + tree index = bitsize_int (const_op01 * BITS_PER_UNIT); + return fold_build3_loc (loc, + BIT_FIELD_REF, type, op00, + part_width, index); + } } /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */ else if (TREE_CODE (op00type) == COMPLEX_TYPE && (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (op00type)))) { - tree size = TYPE_SIZE_UNIT (type); - if (tree_int_cst_equal (size, op01)) + if (known_eq (wi::to_poly_offset (TYPE_SIZE_UNIT (type)), + const_op01)) return fold_build1_loc (loc, IMAGPART_EXPR, type, op00); } /* ((foo *)&fooarray)[1] => fooarray[1] */ @@ -3198,7 +3208,8 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) { tree type_domain; tree min_val = size_zero_node; - tree newsub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL); + tree newsub + = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL); if (newsub) sub = newsub; else diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index ff8236a..2545eae 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -450,7 +450,7 @@ build_capture_proxy (tree member, tree init) { if (PACK_EXPANSION_P (init)) init = PACK_EXPANSION_PATTERN (init); - if (TREE_CODE (init) == INDIRECT_REF) + if (INDIRECT_REF_P (init)) init = TREE_OPERAND (init, 0); STRIP_NOPS (init); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index a9e4770..2816045 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10347,14 +10347,14 @@ instantiate_class_template_1 (tree type) templ = most_general_template (CLASSTYPE_TI_TEMPLATE (type)); gcc_assert (TREE_CODE (templ) == TEMPLATE_DECL); + /* Mark the type as in the process of being defined. */ + TYPE_BEING_DEFINED (type) = 1; + /* Determine what specialization of the original template to instantiate. */ t = most_specialized_partial_spec (type, tf_warning_or_error); if (t == error_mark_node) - { - TYPE_BEING_DEFINED (type) = 1; - return error_mark_node; - } + return error_mark_node; else if (t) { /* This TYPE is actually an instantiation of a partial @@ -10379,16 +10379,16 @@ instantiate_class_template_1 (tree type) /* If the template we're instantiating is incomplete, then clearly there's nothing we can do. */ if (!COMPLETE_TYPE_P (pattern)) - return type; + { + /* We can try again later. */ + TYPE_BEING_DEFINED (type) = 0; + return type; + } /* If we've recursively instantiated too many templates, stop. */ if (! push_tinst_level (type)) return type; - /* Now we're really doing the instantiation. Mark the type as in - the process of being defined. */ - TYPE_BEING_DEFINED (type) = 1; - /* We may be in the middle of deferred access check. Disable it now. */ push_deferring_access_checks (dk_no_deferred); @@ -24012,6 +24012,30 @@ dependent_scope_p (tree scope) && !currently_open_class (scope)); } +/* T is a SCOPE_REF. Return whether it represents a non-static member of + an unknown base of 'this' (and is therefore instantiation-dependent). */ + +static bool +unknown_base_ref_p (tree t) +{ + if (!current_class_ptr) + return false; + + tree mem = TREE_OPERAND (t, 1); + if (shared_member_p (mem)) + return false; + + tree cur = current_nonlambda_class_type (); + if (!any_dependent_bases_p (cur)) + return false; + + tree ctx = TREE_OPERAND (t, 0); + if (DERIVED_FROM_P (ctx, cur)) + return false; + + return true; +} + /* T is a SCOPE_REF; return whether we need to consider it instantiation-dependent so that we can check access at instantiation time even though we know which member it resolves to. */ @@ -24021,9 +24045,7 @@ instantiation_dependent_scope_ref_p (tree t) { if (DECL_P (TREE_OPERAND (t, 1)) && CLASS_TYPE_P (TREE_OPERAND (t, 0)) - /* A dependent base could make a member inaccessible in the current - class. */ - && !any_dependent_bases_p () + && !unknown_base_ref_p (t) && accessible_in_template_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1))) return false; diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 920fc15..796209f 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1636,7 +1636,7 @@ field_access_p (tree component_ref, tree field_decl, tree field_type) return false; tree indirect_ref = TREE_OPERAND (component_ref, 0); - if (TREE_CODE (indirect_ref) != INDIRECT_REF) + if (!INDIRECT_REF_P (indirect_ref)) return false; tree ptr = STRIP_NOPS (TREE_OPERAND (indirect_ref, 0)); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index ea92da3..f0cee68 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4391,7 +4391,7 @@ omp_clause_decl_field (tree decl) && DECL_OMP_PRIVATIZED_MEMBER (decl)) { tree f = DECL_VALUE_EXPR (decl); - if (TREE_CODE (f) == INDIRECT_REF) + if (INDIRECT_REF_P (f)) f = TREE_OPERAND (f, 0); if (TREE_CODE (f) == COMPONENT_REF) { @@ -4446,7 +4446,7 @@ omp_privatize_field (tree t, bool shared) omp_private_member_map = new hash_map<tree, tree>; if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE) { - gcc_assert (TREE_CODE (m) == INDIRECT_REF); + gcc_assert (INDIRECT_REF_P (m)); m = TREE_OPERAND (m, 0); } tree vb = NULL_TREE; @@ -5864,7 +5864,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (TREE_CODE (t) == POINTER_PLUS_EXPR) t = TREE_OPERAND (t, 0); if (TREE_CODE (t) == ADDR_EXPR - || TREE_CODE (t) == INDIRECT_REF) + || INDIRECT_REF_P (t)) t = TREE_OPERAND (t, 0); } tree n = omp_clause_decl_field (t); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index d85f934..a53bddf 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -5273,16 +5273,6 @@ cp_free_lang_data (tree t) /* We do not need the leftover chaining of namespaces from the binding level. */ DECL_CHAIN (t) = NULL_TREE; - /* Set DECL_VALUE_EXPRs of OpenMP privatized member artificial - decls to error_mark_node. These are DECL_IGNORED_P and after - OpenMP lowering they aren't useful anymore. Clearing DECL_VALUE_EXPR - doesn't work, as expansion could then consider them as something - to be expanded. */ - if (VAR_P (t) - && DECL_LANG_SPECIFIC (t) - && DECL_OMP_PRIVATIZED_MEMBER (t) - && DECL_IGNORED_P (t)) - SET_DECL_VALUE_EXPR (t, error_mark_node); } /* Stub for c-common. Please keep in sync with c-decl.c. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 83e7678..dfcf716 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2009,7 +2009,10 @@ decay_conversion (tree exp, return error_mark_node; if (NULLPTR_TYPE_P (type) && !TREE_SIDE_EFFECTS (exp)) - return nullptr_node; + { + mark_rvalue_use (exp, loc, reject_builtin); + return nullptr_node; + } /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Leave such NOP_EXPRs, since RHS is being used in non-lvalue context. */ @@ -3133,7 +3136,7 @@ cp_build_indirect_ref_1 (tree ptr, ref_operator errorstring, the backend. This only needs to be done at warn_strict_aliasing > 2. */ if (warn_strict_aliasing > 2) - if (strict_aliasing_warning (TREE_TYPE (TREE_OPERAND (ptr, 0)), + if (strict_aliasing_warning (EXPR_LOCATION (ptr), type, TREE_OPERAND (ptr, 0))) TREE_NO_WARNING (ptr) = 1; } @@ -7331,7 +7334,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, expr = cp_build_addr_expr (expr, complain); if (warn_strict_aliasing > 2) - strict_aliasing_warning (TREE_TYPE (expr), type, expr); + strict_aliasing_warning (EXPR_LOCATION (expr), type, expr); if (expr != error_mark_node) expr = build_reinterpret_cast_1 @@ -7425,8 +7428,6 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype)) || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype))) { - tree sexpr = expr; - if (!c_cast_p && check_for_casting_away_constness (intype, type, REINTERPRET_CAST_EXPR, @@ -7444,11 +7445,9 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, warning (OPT_Wcast_align, "cast from %qH to %qI " "increases required alignment of target type", intype, type); - /* We need to strip nops here, because the front end likes to - create (int *)&a for array-to-pointer decay, instead of &a[0]. */ - STRIP_NOPS (sexpr); if (warn_strict_aliasing <= 2) - strict_aliasing_warning (intype, type, sexpr); + /* strict_aliasing_warning STRIP_NOPs its expr. */ + strict_aliasing_warning (EXPR_LOCATION (expr), type, expr); return build_nop (type, expr); } diff --git a/gcc/doc/gimple.texi b/gcc/doc/gimple.texi index 6d920ae..1f9449f 100644 --- a/gcc/doc/gimple.texi +++ b/gcc/doc/gimple.texi @@ -836,6 +836,11 @@ Return true if g is a @code{GIMPLE_DEBUG} that marks the beginning of a source statement. @end deftypefn +@deftypefn {GIMPLE function} gimple_debug_inline_entry_p (gimple g) +Return true if g is a @code{GIMPLE_DEBUG} that marks the entry +point of an inlined function. +@end deftypefn + @deftypefn {GIMPLE function} gimple_debug_nonbind_marker_p (gimple g) Return true if g is a @code{GIMPLE_DEBUG} that marks a program location, without any variable binding. @@ -1541,6 +1546,7 @@ Set the conditional @code{COND_STMT} to be of the form 'if (1 == 1)'. @cindex @code{GIMPLE_DEBUG} @cindex @code{GIMPLE_DEBUG_BIND} @cindex @code{GIMPLE_DEBUG_BEGIN_STMT} +@cindex @code{GIMPLE_DEBUG_INLINE_ENTRY} @deftypefn {GIMPLE function} gdebug *gimple_build_debug_bind (tree var, @ tree value, gimple stmt) @@ -1626,6 +1632,18 @@ observable, and that none of the side effects of subsequent user statements are. @end deftypefn +@deftypefn {GIMPLE function} gimple gimple_build_debug_inline_entry (tree block, location_t location) +Build a @code{GIMPLE_DEBUG} statement with +@code{GIMPLE_DEBUG_INLINE_ENTRY} @code{subcode}. The effect of this +statement is to tell debug information generation machinery that a +function call at @code{location} underwent inline substitution, that +@code{block} is the enclosing lexical block created for the +substitution, and that at the point of the program in which the stmt is +inserted, all parameters for the inlined function are bound to the +respective arguments, and none of the side effects of its stmts are +observable. +@end deftypefn + @node @code{GIMPLE_EH_FILTER} @subsection @code{GIMPLE_EH_FILTER} @cindex @code{GIMPLE_EH_FILTER} diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 367b99b..df357be 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -348,6 +348,7 @@ Objective-C and Objective-C++ Dialects}. -gstabs -gstabs+ -gstrict-dwarf -gno-strict-dwarf @gol -gcolumn-info -gno-column-info @gol -gstatement-frontiers -gno-statement-frontiers @gol +-gvariable-location-views -gno-variable-location-views @gol -gvms -gxcoff -gxcoff+ -gz@r{[}=@var{type}@r{]} @gol -fdebug-prefix-map=@var{old}=@var{new} -fdebug-types-section @gol -fno-eliminate-unused-debug-types @gol @@ -7255,6 +7256,34 @@ markers in the line number table. This is enabled by default when compiling with optimization (@option{-Os}, @option{-O}, @option{-O2}, @dots{}), and outputting DWARF 2 debug information at the normal level. +@item -gvariable-location-views +@item -gvariable-location-views=incompat5 +@item -gno-variable-location-views +@opindex gvariable-location-views +@opindex gvariable-location-views=incompat5 +@opindex gno-variable-location-views +Augment variable location lists with progressive view numbers implied +from the line number table. This enables debug information consumers to +inspect state at certain points of the program, even if no instructions +associated with the corresponding source locations are present at that +point. If the assembler lacks support for view numbers in line number +tables, this will cause the compiler to emit the line number table, +which generally makes them somewhat less compact. The augmented line +number tables and location lists are fully backward-compatible, so they +can be consumed by debug information consumers that are not aware of +these augmentations, but they won't derive any benefit from them either. +This is enabled by default when outputting DWARF 2 debug information at +the normal level, as long as @option{-fvar-tracking-assignments} is +enabled and @option{-gstrict-dwarf} is not. + +There is a proposed representation for view numbers that is not backward +compatible with the location list format introduced in DWARF 5, that can +be enabled with @option{-gvariable-location-views=incompat5}. This +option may be removed in the future, is only provided as a reference +implementation of the proposed representation. Debug information +consumers are not expected to support this extended format, and they +would be rendered unable to decode location lists using it. + @item -gz@r{[}=@var{type}@r{]} @opindex gz Produce compressed debug sections in DWARF format, if that is supported. diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 2523f63..43d5405 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -3670,7 +3670,10 @@ Refers to a parameter that was completely optimized out. @item (debug_marker:@var{mode}) Marks a program location. With @code{VOIDmode}, it stands for the beginning of a statement, a recommended inspection point logically after -all prior side effects, and before any subsequent side effects. +all prior side effects, and before any subsequent side effects. With +@code{BLKmode}, it indicates an inline entry point: the lexical block +encoded in the @code{INSN_LOCATION} is the enclosing block that encloses +the inlined function. @end table @@ -3954,6 +3957,13 @@ This note is used to generate @code{is_stmt} markers in line number debuggign information. It indicates the beginning of a user statement. +@findex NOTE_INSN_INLINE_ENTRY +@item NOTE_INSN_INLINE_ENTRY +This note is used to generate @code{entry_pc} for inlined subroutines in +debugging information. It indicates an inspection point at which all +arguments for the inlined function have been bound, and before its first +statement. + @end table These codes are printed symbolically when they appear in debugging dumps. @@ -3971,8 +3981,12 @@ binds a user variable tree to an RTL representation of the it stands for the value bound to the corresponding @code{DEBUG_EXPR_DECL}. -@code{GIMPLE_DEBUG_BEGIN_STMT} is expanded to RTL as a @code{DEBUG_INSN} -with a @code{VOIDmode} @code{DEBUG_MARKER} @code{PATTERN}. These +@code{GIMPLE_DEBUG_BEGIN_STMT} and @code{GIMPLE_DEBUG_INLINE_ENTRY} are +expanded to RTL as a @code{DEBUG_INSN} with a @code{DEBUG_MARKER} +@code{PATTERN}; the difference is the RTL mode: the former's +@code{DEBUG_MARKER} is @code{VOIDmode}, whereas the latter is +@code{BLKmode}; information about the inlined function can be taken from +the lexical block encoded in the @code{INSN_LOCATION}. These @code{DEBUG_INSN}s, that do not carry @code{VAR_LOCATION} information, just @code{DEBUG_MARKER}s, can be detected by testing @code{DEBUG_MARKER_INSN_P}, whereas those that do can be recognized as @@ -3983,8 +3997,8 @@ with respect to each other, particularly during scheduling. Binding information is kept in pseudo-instruction form, so that, unlike notes, it gets the same treatment and adjustments that regular instructions would. It is the variable tracking pass that turns these -pseudo-instructions into @code{NOTE_INSN_VAR_LOCATION} and -@code{NOTE_INSN_BEGIN_STMT} notes, +pseudo-instructions into @code{NOTE_INSN_VAR_LOCATION}, +@code{NOTE_INSN_BEGIN_STMT} and @code{NOTE_INSN_INLINE_ENTRY} notes, analyzing control flow, value equivalences and changes to registers and memory referenced in value expressions, propagating the values of debug temporaries and determining expressions that can be used to compute the diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c index 9952e0a..e9b18b8 100644 --- a/gcc/dwarf2asm.c +++ b/gcc/dwarf2asm.c @@ -767,6 +767,35 @@ dw2_asm_output_data_sleb128 (HOST_WIDE_INT value, va_end (ap); } +/* Output symbol LAB1 as an unsigned LEB128 quantity. LAB1 should be + an assembler-computed constant, e.g. a view number, because we + can't have relocations in LEB128 quantities. */ + +void +dw2_asm_output_symname_uleb128 (const char *lab1 ATTRIBUTE_UNUSED, + const char *comment, ...) +{ + va_list ap; + + va_start (ap, comment); + +#ifdef HAVE_AS_LEB128 + fputs ("\t.uleb128 ", asm_out_file); + assemble_name (asm_out_file, lab1); +#else + gcc_unreachable (); +#endif + + if (flag_debug_asm && comment) + { + fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); + vfprintf (asm_out_file, comment, ap); + } + fputc ('\n', asm_out_file); + + va_end (ap); +} + void dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED, const char *lab2 ATTRIBUTE_UNUSED, diff --git a/gcc/dwarf2asm.h b/gcc/dwarf2asm.h index b5ed449..1b76909 100644 --- a/gcc/dwarf2asm.h +++ b/gcc/dwarf2asm.h @@ -70,6 +70,10 @@ extern void dw2_asm_output_data_sleb128 (HOST_WIDE_INT, const char *, ...) ATTRIBUTE_NULL_PRINTF_2; +extern void dw2_asm_output_symname_uleb128 (const char *, + const char *, ...) + ATTRIBUTE_NULL_PRINTF_2; + extern void dw2_asm_output_delta_uleb128 (const char *, const char *, const char *, ...) ATTRIBUTE_NULL_PRINTF_3; diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 948b3cb..984df9f 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -1291,6 +1291,8 @@ struct GTY((for_user)) addr_table_entry { GTY ((desc ("%1.kind"))) addr; }; +typedef unsigned int var_loc_view; + /* Location lists are ranges + location descriptions for that range, so you can track variables that are in different places over their entire life. */ @@ -1300,9 +1302,11 @@ typedef struct GTY(()) dw_loc_list_struct { addr_table_entry *begin_entry; const char *end; /* Label for end of range */ char *ll_symbol; /* Label for beginning of location list. - Only on head of list */ + Only on head of list. */ + char *vl_symbol; /* Label for beginning of view list. Ditto. */ const char *section; /* Section this loclist is relative to */ dw_loc_descr_ref expr; + var_loc_view vbegin, vend; hashval_t hash; /* True if all addresses in this and subsequent lists are known to be resolved. */ @@ -1339,6 +1343,29 @@ dwarf_stack_op_name (unsigned int op) return "OP_<unknown>"; } +/* Return TRUE iff we're to output location view lists as a separate + attribute next to the location lists, as an extension compatible + with DWARF 2 and above. */ + +static inline bool +dwarf2out_locviews_in_attribute () +{ + return debug_variable_location_views == 1; +} + +/* Return TRUE iff we're to output location view lists as part of the + location lists, as proposed for standardization after DWARF 5. */ + +static inline bool +dwarf2out_locviews_in_loclist () +{ +#ifndef DW_LLE_view_pair + return false; +#else + return debug_variable_location_views == -1; +#endif +} + /* Return a pointer to a newly allocated location description. Location descriptions are simple expression terms that can be strung together to form more complicated location (address) descriptions. */ @@ -1401,6 +1428,8 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b) return a->v.val_loc == b->v.val_loc; case dw_val_class_loc_list: return a->v.val_loc_list == b->v.val_loc_list; + case dw_val_class_view_list: + return a->v.val_view_list == b->v.val_view_list; case dw_val_class_die_ref: return a->v.val_die_ref.die == b->v.val_die_ref.die; case dw_val_class_fde_ref: @@ -2718,6 +2747,7 @@ 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_insn *); +static void dwarf2out_inline_entry (tree); static void dwarf2out_size_function (tree); static void dwarf2out_begin_function (tree); static void dwarf2out_end_function (unsigned int); @@ -2771,7 +2801,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = debug_nothing_rtx_code_label, /* label */ debug_nothing_int, /* handle_pch */ dwarf2out_var_location, - debug_nothing_tree, /* inline_entry */ + dwarf2out_inline_entry, /* inline_entry */ dwarf2out_size_function, /* size_function */ dwarf2out_switch_text_section, dwarf2out_set_name, @@ -2875,7 +2905,15 @@ enum dw_line_info_opcode { LI_set_epilogue_begin, /* Emit a DW_LNE_set_discriminator. */ - LI_set_discriminator + LI_set_discriminator, + + /* Output a Fixed Advance PC; the target PC is the label index; the + base PC is the previous LI_adv_address or LI_set_address entry. + We only use this when emitting debug views without assembler + support, at explicit user request. Ideally, we should only use + it when the offset might be zero but we can't tell: it's the only + way to maybe change the PC without resetting the view number. */ + LI_adv_address }; typedef struct GTY(()) dw_line_info_struct { @@ -2897,6 +2935,25 @@ struct GTY(()) dw_line_info_table { bool is_stmt; bool in_use; + /* This denotes the NEXT view number. + + If it is 0, it is known that the NEXT view will be the first view + at the given PC. + + If it is -1, we've advanced PC but we haven't emitted a line location yet, + so we shouldn't use this view number. + + The meaning of other nonzero values depends on whether we're + computing views internally or leaving it for the assembler to do + so. If we're emitting them internally, view denotes the view + number since the last known advance of PC. If we're leaving it + for the assembler, it denotes the LVU label number that we're + going to ask the assembler to assign. */ + var_loc_view view; + +#define RESET_NEXT_VIEW(x) ((x) = (var_loc_view)0) +#define RESETTING_VIEW_P(x) ((x) == (var_loc_view)0) + vec<dw_line_info_entry, va_gc> *entries; }; @@ -3098,6 +3155,71 @@ skeleton_chain_node; #endif #endif +/* Use assembler views in line directives if available. */ +#ifndef DWARF2_ASM_VIEW_DEBUG_INFO +#ifdef HAVE_AS_DWARF2_DEBUG_VIEW +#define DWARF2_ASM_VIEW_DEBUG_INFO 1 +#else +#define DWARF2_ASM_VIEW_DEBUG_INFO 0 +#endif +#endif + +/* A bit is set in ZERO_VIEW_P if we are using the assembler-supported + view computation, and it refers to a view identifier for which we + will not emit a label because it is known to map to a view number + zero. We won't allocate the bitmap if we're not using assembler + support for location views, but we have to make the variable + visible for GGC and for code that will be optimized out for lack of + support but that's still parsed and compiled. We could abstract it + out with macros, but it's not worth it. */ +static GTY(()) bitmap zero_view_p; + +/* Evaluate to TRUE iff N is known to identify the first location view + at its PC. When not using assembler location view computation, + that must be view number zero. Otherwise, ZERO_VIEW_P is allocated + and views label numbers recorded in it are the ones known to be + zero. */ +#define ZERO_VIEW_P(N) (zero_view_p \ + ? bitmap_bit_p (zero_view_p, (N)) \ + : (N) == 0) + +/* Return true iff we're to emit .loc directives for the assembler to + generate line number sections. + + When we're not emitting views, all we need from the assembler is + support for .loc directives. + + If we are emitting views, we can only use the assembler's .loc + support if it also supports views. + + When the compiler is emitting the line number programs and + computing view numbers itself, it resets view numbers at known PC + changes and counts from that, and then it emits view numbers as + literal constants in locviewlists. There are cases in which the + compiler is not sure about PC changes, e.g. when extra alignment is + requested for a label. In these cases, the compiler may not reset + the view counter, and the potential PC advance in the line number + program will use an opcode that does not reset the view counter + even if the PC actually changes, so that compiler and debug info + consumer can keep view numbers in sync. + + When the compiler defers view computation to the assembler, it + emits symbolic view numbers in locviewlists, with the exception of + views known to be zero (forced resets, or reset after + compiler-visible PC changes): instead of emitting symbols for + these, we emit literal zero and assert the assembler agrees with + the compiler's assessment. We could use symbolic views everywhere, + instead of special-casing zero views, but then we'd be unable to + optimize out locviewlists that contain only zeros. */ + +static bool +output_asm_line_debug_info (void) +{ + return (DWARF2_ASM_VIEW_DEBUG_INFO + || (DWARF2_ASM_LINE_DEBUG_INFO + && !debug_variable_location_views)); +} + /* Minimum line offset in a special line info. opcode. This value was chosen to give a reasonable range of values. */ #define DWARF_LINE_BASE -10 @@ -3207,6 +3329,7 @@ struct GTY ((chain_next ("%h.next"))) var_loc_node { rtx GTY (()) loc; const char * GTY (()) label; struct var_loc_node * GTY (()) next; + var_loc_view view; }; /* Variable location list. */ @@ -3415,6 +3538,8 @@ static inline dw_loc_descr_ref AT_loc (dw_attr_node *); static void add_AT_loc_list (dw_die_ref, enum dwarf_attribute, dw_loc_list_ref); static inline dw_loc_list_ref AT_loc_list (dw_attr_node *); +static void add_AT_view_list (dw_die_ref, enum dwarf_attribute); +static inline dw_loc_list_ref AT_loc_list (dw_attr_node *); static addr_table_entry *add_addr_table_entry (void *, enum ate_kind); static void remove_addr_table_entry (addr_table_entry *); static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx, bool); @@ -3451,7 +3576,7 @@ static void equate_type_number_to_die (tree, dw_die_ref); static dw_die_ref lookup_decl_die (tree); static var_loc_list *lookup_decl_loc (const_tree); static void equate_decl_number_to_die (tree, dw_die_ref); -static struct var_loc_node *add_var_loc_to_decl (tree, rtx, const char *); +static struct var_loc_node *add_var_loc_to_decl (tree, rtx, const char *, var_loc_view); static void print_spaces (FILE *); static void print_die (dw_die_ref, FILE *); static void loc_checksum (dw_loc_descr_ref, struct md5_ctx *); @@ -3651,8 +3776,8 @@ static void gen_tagged_type_die (tree, dw_die_ref, enum debug_info_usage); static void gen_type_die_with_usage (tree, dw_die_ref, enum debug_info_usage); static void splice_child_die (dw_die_ref, dw_die_ref); static int file_info_cmp (const void *, const void *); -static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *, - const char *, const char *); +static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *, var_loc_view, + const char *, var_loc_view, const char *); static void output_loc_list (dw_loc_list_ref); static char *gen_internal_sym (const char *); static bool want_pubnames (void); @@ -3944,6 +4069,9 @@ static char ranges_base_label[2 * MAX_ARTIFICIAL_LABEL_BYTES]; #ifndef BLOCK_BEGIN_LABEL #define BLOCK_BEGIN_LABEL "LBB" #endif +#ifndef BLOCK_INLINE_ENTRY_LABEL +#define BLOCK_INLINE_ENTRY_LABEL "LBI" +#endif #ifndef BLOCK_END_LABEL #define BLOCK_END_LABEL "LBE" #endif @@ -4648,11 +4776,65 @@ AT_loc_list (dw_attr_node *a) return a->dw_attr_val.v.val_loc_list; } +/* Add a view list attribute to DIE. It must have a DW_AT_location + attribute, because the view list complements the location list. */ + +static inline void +add_AT_view_list (dw_die_ref die, enum dwarf_attribute attr_kind) +{ + dw_attr_node attr; + + if (XCOFF_DEBUGGING_INFO && !HAVE_XCOFF_DWARF_EXTRAS) + return; + + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_view_list; + attr.dw_attr_val.val_entry = NULL; + attr.dw_attr_val.v.val_view_list = die; + add_dwarf_attr (die, &attr); + gcc_checking_assert (get_AT (die, DW_AT_location)); + gcc_assert (have_location_lists); +} + +/* Return a pointer to the location list referenced by the attribute. + If the named attribute is a view list, look up the corresponding + DW_AT_location attribute and return its location list. */ + static inline dw_loc_list_ref * AT_loc_list_ptr (dw_attr_node *a) { - gcc_assert (a && AT_class (a) == dw_val_class_loc_list); - return &a->dw_attr_val.v.val_loc_list; + gcc_assert (a); + switch (AT_class (a)) + { + case dw_val_class_loc_list: + return &a->dw_attr_val.v.val_loc_list; + case dw_val_class_view_list: + { + dw_attr_node *l; + l = get_AT (a->dw_attr_val.v.val_view_list, DW_AT_location); + if (!l) + return NULL; + gcc_checking_assert (l + 1 == a); + return AT_loc_list_ptr (l); + } + default: + gcc_unreachable (); + } +} + +/* Return the location attribute value associated with a view list + attribute value. */ + +static inline dw_val_node * +view_list_to_loc_list_val_node (dw_val_node *val) +{ + gcc_assert (val->val_class == dw_val_class_view_list); + dw_attr_node *loc = get_AT (val->v.val_view_list, DW_AT_location); + if (!loc) + return NULL; + gcc_checking_assert (&(loc + 1)->dw_attr_val == val); + gcc_assert (AT_class (loc) == dw_val_class_loc_list); + return &loc->dw_attr_val; } struct addr_hasher : ggc_ptr_hash<addr_table_entry> @@ -5907,7 +6089,7 @@ adjust_piece_list (rtx *dest, rtx *src, rtx *inner, /* Add a variable location node to the linked list for DECL. */ static struct var_loc_node * -add_var_loc_to_decl (tree decl, rtx loc_note, const char *label) +add_var_loc_to_decl (tree decl, rtx loc_note, const char *label, var_loc_view view) { unsigned int decl_id; var_loc_list *temp; @@ -5996,7 +6178,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label) /* TEMP->LAST here is either pointer to the last but one or last element in the chained list, LAST is pointer to the last element. */ - if (label && strcmp (last->label, label) == 0) + if (label && strcmp (last->label, label) == 0 && last->view == view) { /* For SRA optimized variables if there weren't any real insns since last note, just modify the last node. */ @@ -6012,7 +6194,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label) temp->last->next = NULL; unused = last; last = temp->last; - gcc_assert (strcmp (last->label, label) != 0); + gcc_assert (strcmp (last->label, label) != 0 || last->view != view); } else { @@ -6147,6 +6329,12 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile) fprintf (outfile, "location list -> label:%s", val->v.val_loc_list->ll_symbol); break; + case dw_val_class_view_list: + val = view_list_to_loc_list_val_node (val); + fprintf (outfile, "location list with views -> labels:%s and %s", + val->v.val_loc_list->ll_symbol, + val->v.val_loc_list->vl_symbol); + break; case dw_val_class_range_list: fprintf (outfile, "range list"); break; @@ -9007,6 +9195,7 @@ size_of_die (dw_die_ref die) } break; case dw_val_class_loc_list: + case dw_val_class_view_list: if (dwarf_split_debug_info && dwarf_version >= 5) { gcc_assert (AT_loc_list (a)->num_assigned); @@ -9378,6 +9567,7 @@ value_format (dw_attr_node *a) gcc_unreachable (); } case dw_val_class_loc_list: + case dw_val_class_view_list: if (dwarf_split_debug_info && dwarf_version >= 5 && AT_loc_list (a)->num_assigned) @@ -9652,7 +9842,8 @@ output_abbrev_section (void) expression. */ static inline dw_loc_list_ref -new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end, +new_loc_list (dw_loc_descr_ref expr, const char *begin, var_loc_view vbegin, + const char *end, var_loc_view vend, const char *section) { dw_loc_list_ref retlist = ggc_cleared_alloc<dw_loc_list_node> (); @@ -9662,10 +9853,28 @@ new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end, retlist->end = end; retlist->expr = expr; retlist->section = section; + retlist->vbegin = vbegin; + retlist->vend = vend; return retlist; } +/* Return true iff there's any nonzero view number in the loc list. */ + +static bool +loc_list_has_views (dw_loc_list_ref list) +{ + if (!debug_variable_location_views) + return false; + + for (dw_loc_list_ref loc = list; + loc != NULL; loc = loc->dw_loc_next) + if (!ZERO_VIEW_P (loc->vbegin) || !ZERO_VIEW_P (loc->vend)) + return true; + + return false; +} + /* Generate a new internal symbol for this location list node, if it hasn't got one yet. */ @@ -9674,6 +9883,98 @@ gen_llsym (dw_loc_list_ref list) { gcc_assert (!list->ll_symbol); list->ll_symbol = gen_internal_sym ("LLST"); + + if (!loc_list_has_views (list)) + return; + + if (dwarf2out_locviews_in_attribute ()) + { + /* Use the same label_num for the view list. */ + label_num--; + list->vl_symbol = gen_internal_sym ("LVUS"); + } + else + list->vl_symbol = list->ll_symbol; +} + +/* Generate a symbol for the list, but only if we really want to emit + it as a list. */ + +static inline void +maybe_gen_llsym (dw_loc_list_ref list) +{ + if (!list || (!list->dw_loc_next && !loc_list_has_views (list))) + return; + + gen_llsym (list); +} + +/* Determine whether or not to skip loc_list entry CURR. If we're not + to skip it, and SIZEP is non-null, store the size of CURR->expr's + representation in *SIZEP. */ + +static bool +skip_loc_list_entry (dw_loc_list_ref curr, unsigned long *sizep = 0) +{ + /* Don't output an entry that starts and ends at the same address. */ + if (strcmp (curr->begin, curr->end) == 0 + && curr->vbegin == curr->vend && !curr->force) + return true; + + unsigned long size = size_of_locs (curr->expr); + + /* If the expression is too large, drop it on the floor. We could + perhaps put it into DW_TAG_dwarf_procedure and refer to that + in the expression, but >= 64KB expressions for a single value + in a single range are unlikely very useful. */ + if (dwarf_version < 5 && size > 0xffff) + return true; + + if (sizep) + *sizep = size; + + return false; +} + +/* Output a view pair loclist entry for CURR, if it requires one. */ + +static void +dwarf2out_maybe_output_loclist_view_pair (dw_loc_list_ref curr) +{ + if (!dwarf2out_locviews_in_loclist ()) + return; + + if (ZERO_VIEW_P (curr->vbegin) && ZERO_VIEW_P (curr->vend)) + return; + +#ifdef DW_LLE_view_pair + dw2_asm_output_data (1, DW_LLE_view_pair, "DW_LLE_view_pair"); + +# if DWARF2_ASM_VIEW_DEBUG_INFO + if (ZERO_VIEW_P (curr->vbegin)) + dw2_asm_output_data_uleb128 (0, "Location view begin"); + else + { + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + ASM_GENERATE_INTERNAL_LABEL (label, "LVU", curr->vbegin); + dw2_asm_output_symname_uleb128 (label, "Location view begin"); + } + + if (ZERO_VIEW_P (curr->vend)) + dw2_asm_output_data_uleb128 (0, "Location view end"); + else + { + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + ASM_GENERATE_INTERNAL_LABEL (label, "LVU", curr->vend); + dw2_asm_output_symname_uleb128 (label, "Location view end"); + } +# else /* !DWARF2_ASM_VIEW_DEBUG_INFO */ + dw2_asm_output_data_uleb128 (curr->vbegin, "Location view begin"); + dw2_asm_output_data_uleb128 (curr->vend, "Location view end"); +# endif /* DWARF2_ASM_VIEW_DEBUG_INFO */ +#endif /* DW_LLE_view_pair */ + + return; } /* Output the location list given to us. */ @@ -9681,34 +9982,85 @@ gen_llsym (dw_loc_list_ref list) static void output_loc_list (dw_loc_list_ref list_head) { + int vcount = 0, lcount = 0; + if (list_head->emitted) return; list_head->emitted = true; + if (list_head->vl_symbol && dwarf2out_locviews_in_attribute ()) + { + ASM_OUTPUT_LABEL (asm_out_file, list_head->vl_symbol); + + for (dw_loc_list_ref curr = list_head; curr != NULL; + curr = curr->dw_loc_next) + { + if (skip_loc_list_entry (curr)) + continue; + + vcount++; + + /* ?? dwarf_split_debug_info? */ +#if DWARF2_ASM_VIEW_DEBUG_INFO + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + + if (!ZERO_VIEW_P (curr->vbegin)) + { + ASM_GENERATE_INTERNAL_LABEL (label, "LVU", curr->vbegin); + dw2_asm_output_symname_uleb128 (label, + "View list begin (%s)", + list_head->vl_symbol); + } + else + dw2_asm_output_data_uleb128 (0, + "View list begin (%s)", + list_head->vl_symbol); + + if (!ZERO_VIEW_P (curr->vend)) + { + ASM_GENERATE_INTERNAL_LABEL (label, "LVU", curr->vend); + dw2_asm_output_symname_uleb128 (label, + "View list end (%s)", + list_head->vl_symbol); + } + else + dw2_asm_output_data_uleb128 (0, + "View list end (%s)", + list_head->vl_symbol); +#else /* !DWARF2_ASM_VIEW_DEBUG_INFO */ + dw2_asm_output_data_uleb128 (curr->vbegin, + "View list begin (%s)", + list_head->vl_symbol); + dw2_asm_output_data_uleb128 (curr->vend, + "View list end (%s)", + list_head->vl_symbol); +#endif + } + } + ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol); - dw_loc_list_ref curr = list_head; const char *last_section = NULL; const char *base_label = NULL; /* Walk the location list, and output each range + expression. */ - for (curr = list_head; curr != NULL; curr = curr->dw_loc_next) + for (dw_loc_list_ref curr = list_head; curr != NULL; + curr = curr->dw_loc_next) { unsigned long size; - /* Don't output an entry that starts and ends at the same address. */ - if (strcmp (curr->begin, curr->end) == 0 && !curr->force) - continue; - size = size_of_locs (curr->expr); - /* If the expression is too large, drop it on the floor. We could - perhaps put it into DW_TAG_dwarf_procedure and refer to that - in the expression, but >= 64KB expressions for a single value - in a single range are unlikely very useful. */ - if (dwarf_version < 5 && size > 0xffff) + + /* Skip this entry? If we skip it here, we must skip it in the + view list above as well. */ + if (skip_loc_list_entry (curr, &size)) continue; + + lcount++; + if (dwarf_version >= 5) { if (dwarf_split_debug_info) { + dwarf2out_maybe_output_loclist_view_pair (curr); /* For -gsplit-dwarf, emit DW_LLE_starx_length, which has uleb128 index into .debug_addr and uleb128 length. */ dw2_asm_output_data (1, DW_LLE_startx_length, @@ -9726,6 +10078,7 @@ output_loc_list (dw_loc_list_ref list_head) } else if (!have_multiple_function_sections && HAVE_AS_LEB128) { + dwarf2out_maybe_output_loclist_view_pair (curr); /* If all code is in .text section, the base address is already provided by the CU attributes. Use DW_LLE_offset_pair where both addresses are uleb128 encoded @@ -9776,6 +10129,7 @@ output_loc_list (dw_loc_list_ref list_head) length. */ if (last_section == NULL) { + dwarf2out_maybe_output_loclist_view_pair (curr); dw2_asm_output_data (1, DW_LLE_start_length, "DW_LLE_start_length (%s)", list_head->ll_symbol); @@ -9790,6 +10144,7 @@ output_loc_list (dw_loc_list_ref list_head) DW_LLE_base_address. */ else { + dwarf2out_maybe_output_loclist_view_pair (curr); dw2_asm_output_data (1, DW_LLE_offset_pair, "DW_LLE_offset_pair (%s)", list_head->ll_symbol); @@ -9805,6 +10160,7 @@ output_loc_list (dw_loc_list_ref list_head) DW_LLE_start_end with a pair of absolute addresses. */ else { + dwarf2out_maybe_output_loclist_view_pair (curr); dw2_asm_output_data (1, DW_LLE_start_end, "DW_LLE_start_end (%s)", list_head->ll_symbol); @@ -9883,6 +10239,9 @@ output_loc_list (dw_loc_list_ref list_head) "Location list terminator end (%s)", list_head->ll_symbol); } + + gcc_assert (!list_head->vl_symbol + || vcount == lcount * (dwarf2out_locviews_in_attribute () ? 1 : 0)); } /* Output a range_list offset into the .debug_ranges or .debug_rnglists @@ -9947,6 +10306,22 @@ output_loc_list_offset (dw_attr_node *a) "%s", dwarf_attr_name (a->dw_attr)); } +/* Output the offset into the debug_loc section. */ + +static void +output_view_list_offset (dw_attr_node *a) +{ + char *sym = (*AT_loc_list_ptr (a))->vl_symbol; + + gcc_assert (sym); + if (dwarf_split_debug_info) + dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label, + "%s", dwarf_attr_name (a->dw_attr)); + else + dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, debug_loc_section, + "%s", dwarf_attr_name (a->dw_attr)); +} + /* Output an attribute's index or value appropriately. */ static void @@ -10172,6 +10547,10 @@ output_die (dw_die_ref die) output_loc_list_offset (a); break; + case dw_val_class_view_list: + output_view_list_offset (a); + break; + case dw_val_class_die_ref: if (AT_ref_external (a)) { @@ -10356,6 +10735,28 @@ output_die (dw_die_ref die) (unsigned long) die->die_offset); } +/* Output the dwarf version number. */ + +static void +output_dwarf_version () +{ + /* ??? For now, if -gdwarf-6 is specified, we output version 5 with + views in loclist. That will change eventually. */ + if (dwarf_version == 6) + { + static bool once; + if (!once) + { + warning (0, + "-gdwarf-6 is output as version 5 with incompatibilities"); + once = true; + } + dw2_asm_output_data (2, 5, "DWARF version number"); + } + else + dw2_asm_output_data (2, dwarf_version, "DWARF version number"); +} + /* Output the compilation unit that appears at the beginning of the .debug_info section, and precedes the DIE descriptions. */ @@ -10372,7 +10773,7 @@ output_compilation_unit_header (enum dwarf_unit_type ut) "Length of Compilation Unit Info"); } - dw2_asm_output_data (2, dwarf_version, "DWARF version number"); + output_dwarf_version (); if (dwarf_version >= 5) { const char *name; @@ -10584,7 +10985,7 @@ output_skeleton_debug_sections (dw_die_ref comp_unit, - DWARF_INITIAL_LENGTH_SIZE + size_of_die (comp_unit), "Length of Compilation Unit Info"); - dw2_asm_output_data (2, dwarf_version, "DWARF version number"); + output_dwarf_version (); if (dwarf_version >= 5) { dw2_asm_output_data (1, DW_UT_skeleton, "DW_UT_skeleton"); @@ -10883,7 +11284,7 @@ output_pubnames (vec<pubname_entry, va_gc> *names) } /* Version number for pubnames/pubtypes is independent of dwarf version. */ - dw2_asm_output_data (2, 2, "DWARF Version"); + dw2_asm_output_data (2, 2, "DWARF pubnames/pubtypes version"); if (dwarf_split_debug_info) dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label, @@ -10965,7 +11366,7 @@ output_aranges (void) } /* Version number for aranges is still 2, even up to DWARF5. */ - dw2_asm_output_data (2, 2, "DWARF Version"); + dw2_asm_output_data (2, 2, "DWARF aranges version"); if (dwarf_split_debug_info) dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label, debug_skeleton_info_section, @@ -11230,7 +11631,7 @@ output_rnglists (unsigned generation) dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1, "Length of Range Lists"); ASM_OUTPUT_LABEL (asm_out_file, l1); - dw2_asm_output_data (2, dwarf_version, "DWARF Version"); + output_dwarf_version (); dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size"); dw2_asm_output_data (1, 0, "Segment Size"); /* Emit the offset table only for -gsplit-dwarf. If we don't care @@ -11864,8 +12265,11 @@ output_one_line_info_table (dw_line_info_table *table) char line_label[MAX_ARTIFICIAL_LABEL_BYTES]; unsigned int current_line = 1; bool current_is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START; - dw_line_info_entry *ent; + dw_line_info_entry *ent, *prev_addr; size_t i; + unsigned int view; + + view = 0; FOR_EACH_VEC_SAFE_ELT (table->entries, i, ent) { @@ -11880,14 +12284,36 @@ output_one_line_info_table (dw_line_info_table *table) to determine when it is safe to use DW_LNS_fixed_advance_pc. */ ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, ent->val); + view = 0; + /* This can handle any delta. This takes 4+DWARF2_ADDR_SIZE bytes. */ - dw2_asm_output_data (1, 0, "set address %s", line_label); + dw2_asm_output_data (1, 0, "set address %s%s", line_label, + debug_variable_location_views + ? ", reset view to 0" : ""); dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); dw2_asm_output_data (1, DW_LNE_set_address, NULL); dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); + + prev_addr = ent; break; + case LI_adv_address: + { + ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, ent->val); + char prev_label[MAX_ARTIFICIAL_LABEL_BYTES]; + ASM_GENERATE_INTERNAL_LABEL (prev_label, LINE_CODE_LABEL, prev_addr->val); + + view++; + + dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, "fixed advance PC, increment view to %i", view); + dw2_asm_output_delta (2, line_label, prev_label, + "from %s to %s", prev_label, line_label); + + prev_addr = ent; + break; + } + case LI_set_line: if (ent->val == current_line) { @@ -11995,7 +12421,7 @@ output_line_info (bool prologue_only) ASM_OUTPUT_LABEL (asm_out_file, l1); - dw2_asm_output_data (2, dwarf_version, "DWARF Version"); + output_dwarf_version (); if (dwarf_version >= 5) { dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size"); @@ -16453,6 +16879,7 @@ static dw_loc_list_ref dw_loc_list (var_loc_list *loc_list, tree decl, int want_address) { const char *endname, *secname; + var_loc_view endview; rtx varloc; enum var_init_status initialized; struct var_loc_node *node; @@ -16517,24 +16944,27 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address) && current_function_decl) { endname = cfun->fde->dw_fde_end; + endview = 0; range_across_switch = true; } /* The variable has a location between NODE->LABEL and NODE->NEXT->LABEL. */ else if (node->next) - endname = node->next->label; + endname = node->next->label, endview = node->next->view; /* If the variable has a location at the last label it keeps its location until the end of function. */ else if (!current_function_decl) - endname = text_end_label; + endname = text_end_label, endview = 0; else { ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL, current_function_funcdef_no); endname = ggc_strdup (label_id); + endview = 0; } - *listp = new_loc_list (descr, node->label, endname, secname); + *listp = new_loc_list (descr, node->label, node->view, + endname, endview, secname); if (TREE_CODE (decl) == PARM_DECL && node == loc_list->first && NOTE_P (node->loc) @@ -16569,11 +16999,11 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address) /* The variable has a location between NODE->LABEL and NODE->NEXT->LABEL. */ if (node->next) - endname = node->next->label; + endname = node->next->label, endview = node->next->view; else - endname = cfun->fde->dw_fde_second_end; - *listp = new_loc_list (descr, cfun->fde->dw_fde_second_begin, - endname, secname); + endname = cfun->fde->dw_fde_second_end, endview = 0; + *listp = new_loc_list (descr, cfun->fde->dw_fde_second_begin, 0, + endname, endview, secname); listp = &(*listp)->dw_loc_next; } } @@ -16584,8 +17014,7 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address) representable, we don't want to pretend a single entry that was applies to the entire scope in which the variable is available. */ - if (list && loc_list->first->next) - gen_llsym (list); + maybe_gen_llsym (list); return list; } @@ -17404,7 +17833,7 @@ loc_list_from_tree_1 (tree loc, int want_address, { if (dwarf_version >= 3 || !dwarf_strict) return new_loc_list (new_loc_descr (DW_OP_push_object_address, 0, 0), - NULL, NULL, NULL); + NULL, 0, NULL, 0, NULL); else return NULL; } @@ -18220,7 +18649,7 @@ loc_list_from_tree_1 (tree loc, int want_address, add_loc_descr_to_each (list_ret, new_loc_descr (op, size, 0)); } if (ret) - list_ret = new_loc_list (ret, NULL, NULL, NULL); + list_ret = new_loc_list (ret, NULL, 0, NULL, 0, NULL); return list_ret; } @@ -18544,12 +18973,25 @@ static inline void add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref descr) { + bool check_no_locviews = true; if (descr == 0) return; if (single_element_loc_list_p (descr)) add_AT_loc (die, attr_kind, descr->expr); else - add_AT_loc_list (die, attr_kind, descr); + { + add_AT_loc_list (die, attr_kind, descr); + gcc_assert (descr->ll_symbol); + if (attr_kind == DW_AT_location && descr->vl_symbol + && dwarf2out_locviews_in_attribute ()) + { + add_AT_view_list (die, DW_AT_GNU_locviews); + check_no_locviews = false; + } + } + + if (check_no_locviews) + gcc_assert (!get_AT (die, DW_AT_GNU_locviews)); } /* Add DW_AT_accessibility attribute to DIE if needed. */ @@ -19738,7 +20180,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset) /* If the first partition contained no CFI adjustments, the CIE opcodes apply to the whole first partition. */ *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - fde->dw_fde_begin, fde->dw_fde_end, section); + fde->dw_fde_begin, 0, fde->dw_fde_end, 0, section); list_tail =&(*list_tail)->dw_loc_next; start_label = last_label = fde->dw_fde_second_begin; } @@ -19754,7 +20196,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset) if (!cfa_equal_p (&last_cfa, &next_cfa)) { *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - start_label, last_label, section); + start_label, 0, last_label, 0, section); list_tail = &(*list_tail)->dw_loc_next; last_cfa = next_cfa; @@ -19776,14 +20218,14 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset) if (!cfa_equal_p (&last_cfa, &next_cfa)) { *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - start_label, last_label, section); + start_label, 0, last_label, 0, section); list_tail = &(*list_tail)->dw_loc_next; last_cfa = next_cfa; start_label = last_label; } *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - start_label, fde->dw_fde_end, section); + start_label, 0, fde->dw_fde_end, 0, section); list_tail = &(*list_tail)->dw_loc_next; start_label = last_label = fde->dw_fde_second_begin; } @@ -19792,19 +20234,18 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset) if (!cfa_equal_p (&last_cfa, &next_cfa)) { *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - start_label, last_label, section); + start_label, 0, last_label, 0, section); list_tail = &(*list_tail)->dw_loc_next; start_label = last_label; } *list_tail = new_loc_list (build_cfa_loc (&next_cfa, offset), - start_label, + start_label, 0, fde->dw_fde_second_begin - ? fde->dw_fde_second_end : fde->dw_fde_end, + ? fde->dw_fde_second_end : fde->dw_fde_end, 0, section); - if (list && list->dw_loc_next) - gen_llsym (list); + maybe_gen_llsym (list); return list; } @@ -22778,6 +23219,48 @@ block_die_hasher::equal (die_struct *x, die_struct *y) return x->decl_id == y->decl_id && x->die_parent == y->die_parent; } +/* Hold information about markers for inlined entry points. */ +struct GTY ((for_user)) inline_entry_data +{ + /* The block that's the inlined_function_outer_scope for an inlined + function. */ + tree block; + + /* The label at the inlined entry point. */ + const char *label_pfx; + unsigned int label_num; + + /* The view number to be used as the inlined entry point. */ + var_loc_view view; +}; + +struct inline_entry_data_hasher : ggc_ptr_hash <inline_entry_data> +{ + typedef tree compare_type; + static inline hashval_t hash (const inline_entry_data *); + static inline bool equal (const inline_entry_data *, const_tree); +}; + +/* Hash table routines for inline_entry_data. */ + +inline hashval_t +inline_entry_data_hasher::hash (const inline_entry_data *data) +{ + return htab_hash_pointer (data->block); +} + +inline bool +inline_entry_data_hasher::equal (const inline_entry_data *data, + const_tree block) +{ + return data->block == block; +} + +/* Inlined entry points pending DIE creation in this compilation unit. */ + +static GTY(()) hash_table<inline_entry_data_hasher> *inline_entry_data_table; + + /* Return TRUE if DECL, which may have been previously generated as OLD_DIE, is a candidate for a DW_AT_specification. DECLARATION is true if decl (or its origin) is either an extern declaration or a @@ -23230,6 +23713,42 @@ add_high_low_attributes (tree stmt, dw_die_ref die) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; + if (inline_entry_data **iedp + = !inline_entry_data_table ? NULL + : inline_entry_data_table->find_slot_with_hash (stmt, + htab_hash_pointer (stmt), + NO_INSERT)) + { + inline_entry_data *ied = *iedp; + gcc_assert (MAY_HAVE_DEBUG_MARKER_INSNS); + gcc_assert (inlined_function_outer_scope_p (stmt)); + ASM_GENERATE_INTERNAL_LABEL (label, ied->label_pfx, ied->label_num); + add_AT_lbl_id (die, DW_AT_entry_pc, label); + + if (debug_variable_location_views && !ZERO_VIEW_P (ied->view)) + { + if (!output_asm_line_debug_info ()) + add_AT_unsigned (die, DW_AT_GNU_entry_view, ied->view); + else + { + ASM_GENERATE_INTERNAL_LABEL (label, "LVU", ied->view); + /* FIXME: this will resolve to a small number. Could we + possibly emit smaller data? Ideally we'd emit a + uleb128, but that would make the size of DIEs + impossible for the compiler to compute, since it's + the assembler that computes the value of the view + label in this case. Ideally, we'd have a single form + encompassing both the address and the view, and + indirecting them through a table might make things + easier, but even that would be more wasteful, + space-wise, than what we have now. */ + add_AT_lbl_id (die, DW_AT_GNU_entry_view, label); + } + } + + inline_entry_data_table->clear_slot (iedp); + } + if (BLOCK_FRAGMENT_CHAIN (stmt) && (dwarf_version >= 3 || !dwarf_strict)) { @@ -23237,7 +23756,7 @@ add_high_low_attributes (tree stmt, dw_die_ref die) dw_die_ref pdie; dw_attr_node *attr = NULL; - if (inlined_function_outer_scope_p (stmt)) + if (!MAY_HAVE_DEBUG_MARKER_INSNS && inlined_function_outer_scope_p (stmt)) { ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, BLOCK_NUMBER (stmt)); @@ -23402,7 +23921,7 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die) dw_die_ref subr_die = new_die (DW_TAG_inlined_subroutine, context_die, stmt); - if (call_arg_locations) + if (call_arg_locations || MAY_HAVE_DEBUG_MARKER_INSNS) BLOCK_DIE (stmt) = subr_die; add_abstract_origin_attribute (subr_die, decl); if (TREE_ASM_WRITTEN (stmt)) @@ -25716,6 +26235,23 @@ dwarf2out_early_global_decl (tree decl) symtab->global_info_ready = save; } +/* Return whether EXPR is an expression with the following pattern: + INDIRECT_REF (NOP_EXPR (INTEGER_CST)). */ + +static bool +is_trivial_indirect_ref (tree expr) +{ + if (expr == NULL_TREE || TREE_CODE (expr) != INDIRECT_REF) + return false; + + tree nop = TREE_OPERAND (expr, 0); + if (nop == NULL_TREE || TREE_CODE (nop) != NOP_EXPR) + return false; + + tree int_cst = TREE_OPERAND (nop, 0); + return int_cst != NULL_TREE && TREE_CODE (int_cst) == INTEGER_CST; +} + /* Output debug information for global decl DECL. Called from toplev.c after compilation proper has finished. */ @@ -25740,11 +26276,17 @@ dwarf2out_late_global_decl (tree decl) if (die) { /* We get called via the symtab code invoking late_global_decl - for symbols that are optimized out. Do not add locations - for those, except if they have a DECL_VALUE_EXPR, in which case - they are relevant for debuggers. */ + for symbols that are optimized out. + + Do not add locations for those, except if they have a + DECL_VALUE_EXPR, in which case they are relevant for debuggers. + Still don't add a location if the DECL_VALUE_EXPR is not a trivial + INDIRECT_REF expression, as this could generate relocations to + text symbols in LTO object files, which is invalid. */ varpool_node *node = varpool_node::get (decl); - if ((! node || ! node->definition) && ! DECL_HAS_VALUE_EXPR_P (decl)) + if ((! node || ! node->definition) + && ! (DECL_HAS_VALUE_EXPR_P (decl) + && is_trivial_indirect_ref (DECL_VALUE_EXPR (decl)))) tree_add_const_value_attribute_for_decl (die, decl); else add_location_or_const_value_attribute (die, decl, false); @@ -26164,7 +26706,7 @@ maybe_emit_file (struct dwarf_file_data * fd) fd->emitted_number = 1; last_emitted_file = fd; - if (DWARF2_ASM_LINE_DEBUG_INFO) + if (output_asm_line_debug_info ()) { fprintf (asm_out_file, "\t.file %u ", fd->emitted_number); output_quoted_string (asm_out_file, @@ -26358,11 +26900,13 @@ dwarf2out_var_location (rtx_insn *loc_note) static rtx_insn *expected_next_loc_note; tree decl; bool var_loc_p; + var_loc_view view = 0; if (!NOTE_P (loc_note)) { if (CALL_P (loc_note)) { + RESET_NEXT_VIEW (cur_line_info_table->view); call_site_count++; if (SIBLING_CALL_P (loc_note)) tail_call_site_count++; @@ -26396,6 +26940,18 @@ dwarf2out_var_location (rtx_insn *loc_note) } } } + else if (!debug_variable_location_views) + gcc_unreachable (); + else if (JUMP_TABLE_DATA_P (loc_note)) + RESET_NEXT_VIEW (cur_line_info_table->view); + else if (GET_CODE (loc_note) == USE + || GET_CODE (loc_note) == CLOBBER + || GET_CODE (loc_note) == ASM_INPUT + || asm_noperands (loc_note) >= 0) + ; + else if (get_attr_min_length (loc_note) > 0) + RESET_NEXT_VIEW (cur_line_info_table->view); + return; } @@ -26420,6 +26976,7 @@ dwarf2out_var_location (rtx_insn *loc_note) || ! NOTE_P (next_note) || (NOTE_KIND (next_note) != NOTE_INSN_VAR_LOCATION && NOTE_KIND (next_note) != NOTE_INSN_BEGIN_STMT + && NOTE_KIND (next_note) != NOTE_INSN_INLINE_ENTRY && NOTE_KIND (next_note) != NOTE_INSN_CALL_ARG_LOCATION)) next_note = NULL; @@ -26459,10 +27016,11 @@ create_label: if (var_loc_p) { + const char *label + = NOTE_DURING_CALL_P (loc_note) ? last_postcall_label : last_label; + view = cur_line_info_table->view; decl = NOTE_VAR_LOCATION_DECL (loc_note); - newloc = add_var_loc_to_decl (decl, loc_note, - NOTE_DURING_CALL_P (loc_note) - ? last_postcall_label : last_label); + newloc = add_var_loc_to_decl (decl, loc_note, label, view); if (newloc == NULL) return; } @@ -26503,8 +27061,8 @@ create_label: else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0) continue; -#ifdef HAVE_attr_length - else if (get_attr_min_length (insn) == 0) +#ifdef HAVE_ATTR_length /* ??? We don't include insn-attr.h. */ + else if (HAVE_ATTR_length && get_attr_min_length (insn) == 0) continue; #endif else @@ -26572,7 +27130,10 @@ create_label: call_arg_loc_last = ca_loc; } else if (loc_note != NULL_RTX && !NOTE_DURING_CALL_P (loc_note)) - newloc->label = last_label; + { + newloc->label = last_label; + newloc->view = view; + } else { if (!last_postcall_label) @@ -26581,6 +27142,7 @@ create_label: last_postcall_label = ggc_strdup (loclabel); } newloc->label = last_postcall_label; + newloc->view = view; } if (var_loc_p && flag_debug_asm) @@ -26608,6 +27170,113 @@ create_label: last_in_cold_section_p = in_cold_section_p; } +/* Check whether BLOCK, a lexical block, is nested within OUTER, or is + OUTER itself. If BOTHWAYS, check not only that BLOCK can reach + OUTER through BLOCK_SUPERCONTEXT links, but also that there is a + path from OUTER to BLOCK through BLOCK_SUBBLOCKs and + BLOCK_FRAGMENT_ORIGIN links. */ +static bool +block_within_block_p (tree block, tree outer, bool bothways) +{ + if (block == outer) + return true; + + /* Quickly check that OUTER is up BLOCK's supercontext chain. */ + for (tree context = BLOCK_SUPERCONTEXT (block); + context != outer; + context = BLOCK_SUPERCONTEXT (context)) + if (!context || TREE_CODE (context) != BLOCK) + return false; + + if (!bothways) + return true; + + /* Now check that each block is actually referenced by its + parent. */ + for (tree context = BLOCK_SUPERCONTEXT (block); ; + context = BLOCK_SUPERCONTEXT (context)) + { + if (BLOCK_FRAGMENT_ORIGIN (context)) + { + gcc_assert (!BLOCK_SUBBLOCKS (context)); + context = BLOCK_FRAGMENT_ORIGIN (context); + } + for (tree sub = BLOCK_SUBBLOCKS (context); + sub != block; + sub = BLOCK_CHAIN (sub)) + if (!sub) + return false; + if (context == outer) + return true; + else + block = context; + } +} + +/* Called during final while assembling the marker of the entry point + for an inlined function. */ + +static void +dwarf2out_inline_entry (tree block) +{ + /* If we can't represent it, don't bother. */ + if (!(dwarf_version >= 3 || !dwarf_strict)) + return; + + gcc_assert (DECL_P (block_ultimate_origin (block))); + + /* Sanity check the block tree. This would catch a case in which + BLOCK got removed from the tree reachable from the outermost + lexical block, but got retained in markers. It would still link + back to its parents, but some ancestor would be missing a link + down the path to the sub BLOCK. If the block got removed, its + BLOCK_NUMBER will not be a usable value. */ + if (flag_checking) + gcc_assert (block_within_block_p (block, + DECL_INITIAL (current_function_decl), + true)); + + gcc_assert (inlined_function_outer_scope_p (block)); + gcc_assert (!BLOCK_DIE (block)); + + if (BLOCK_FRAGMENT_ORIGIN (block)) + block = BLOCK_FRAGMENT_ORIGIN (block); + /* Can the entry point ever not be at the beginning of an + unfragmented lexical block? */ + else if (!(BLOCK_FRAGMENT_CHAIN (block) + || (cur_line_info_table + && !ZERO_VIEW_P (cur_line_info_table->view)))) + return; + + if (!inline_entry_data_table) + inline_entry_data_table + = hash_table<inline_entry_data_hasher>::create_ggc (10); + + + inline_entry_data **iedp + = inline_entry_data_table->find_slot_with_hash (block, + htab_hash_pointer (block), + INSERT); + if (*iedp) + /* ??? Ideally, we'd record all entry points for the same inlined + function (some may have been duplicated by e.g. unrolling), but + we have no way to represent that ATM. */ + return; + + inline_entry_data *ied = *iedp = ggc_cleared_alloc<inline_entry_data> (); + ied->block = block; + ied->label_pfx = BLOCK_INLINE_ENTRY_LABEL; + ied->label_num = BLOCK_NUMBER (block); + if (cur_line_info_table) + ied->view = cur_line_info_table->view; + + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + + ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_INLINE_ENTRY_LABEL, + BLOCK_NUMBER (block)); + ASM_OUTPUT_LABEL (asm_out_file, label); +} + /* Called from finalize_size_functions for size functions so that their body can be encoded in the debug info to describe the layout of variable-length structures. */ @@ -26652,6 +27321,7 @@ new_line_info_table (void) table->file_num = 1; table->line_num = 1; table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START; + RESET_NEXT_VIEW (table->view); return table; } @@ -26700,7 +27370,7 @@ set_cur_line_info_table (section *sec) vec_safe_push (separate_line_info, table); } - if (DWARF2_ASM_LINE_DEBUG_INFO) + if (output_asm_line_debug_info ()) table->is_stmt = (cur_line_info_table ? cur_line_info_table->is_stmt : DWARF_LINE_DEFAULT_IS_STMT_START); @@ -26881,7 +27551,7 @@ dwarf2out_source_line (unsigned int line, unsigned int column, filename, line); } - if (DWARF2_ASM_LINE_DEBUG_INFO) + if (output_asm_line_debug_info ()) { /* Emit the .loc directive understood by GNU as. */ /* "\t.loc %u %u 0 is_stmt %u discriminator %u", @@ -26904,6 +27574,50 @@ dwarf2out_source_line (unsigned int line, unsigned int column, fputs (" discriminator ", asm_out_file); fprint_ul (asm_out_file, (unsigned long) discriminator); } + if (debug_variable_location_views) + { + static var_loc_view lvugid; + if (!lvugid) + { + gcc_assert (!zero_view_p); + zero_view_p = BITMAP_GGC_ALLOC (); + bitmap_set_bit (zero_view_p, 0); + } + if (!RESETTING_VIEW_P (table->view)) + { + /* When we're using the assembler to compute view + numbers, we output symbolic labels after "view" in + .loc directives, and the assembler will set them for + us, so that we can refer to the view numbers in + location lists. The only exceptions are when we know + a view will be zero: "-0" is a forced reset, used + e.g. in the beginning of functions, whereas "0" tells + the assembler to check that there was a PC change + since the previous view, in a way that implicitly + resets the next view. */ + fputs (" view ", asm_out_file); + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + ASM_GENERATE_INTERNAL_LABEL (label, "LVU", table->view); + assemble_name (asm_out_file, label); + table->view = ++lvugid; + } + else + { + if (!table->in_use) + fputs (" view -0", asm_out_file); + else + fputs (" view 0", asm_out_file); + /* Mark the present view as a zero view. Earlier debug + binds may have already added its id to loclists to be + emitted later, so we can't reuse the id for something + else. However, it's good to know whether a view is + known to be zero, because then we may be able to + optimize out locviews that are all zeros, so take + note of it in zero_view_p. */ + bitmap_set_bit (zero_view_p, lvugid); + table->view = ++lvugid; + } + } putc ('\n', asm_out_file); } else @@ -26912,7 +27626,19 @@ dwarf2out_source_line (unsigned int line, unsigned int column, targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL, label_num); - push_dw_line_info_entry (table, LI_set_address, label_num); + if (debug_variable_location_views && table->view) + push_dw_line_info_entry (table, LI_adv_address, label_num); + else + push_dw_line_info_entry (table, LI_set_address, label_num); + if (debug_variable_location_views) + { + if (flag_debug_asm) + fprintf (asm_out_file, "\t%s view %s%d\n", + ASM_COMMENT_START, + table->in_use ? "" : "-", + table->view); + table->view++; + } if (file_num != table->file_num) push_dw_line_info_entry (table, LI_set_file, file_num); if (discriminator != table->discrim_num) @@ -27588,9 +28314,10 @@ init_sections_and_labels (bool early_lto_debug) SECTION_DEBUG, NULL); debug_str_section = get_section (DEBUG_STR_SECTION, DEBUG_STR_SECTION_FLAGS, NULL); - if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO) + if (!dwarf_split_debug_info && !output_asm_line_debug_info ()) debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION, DEBUG_STR_SECTION_FLAGS, NULL); + debug_ranges_section = get_section (dwarf_version >= 5 ? DEBUG_RNGLISTS_SECTION : DEBUG_RANGES_SECTION, @@ -27976,6 +28703,11 @@ prune_unused_types_walk_attribs (dw_die_ref die) prune_unused_types_walk_loc_descr (list->expr); break; + case dw_val_class_view_list: + /* This points to a loc_list in another attribute, so it's + already covered. */ + break; + case dw_val_class_die_ref: /* A reference to another DIE. Make sure that it will get emitted. @@ -29075,6 +29807,8 @@ optimize_string_length (dw_attr_node *a) if (d->expr && non_dwarf_expression (d->expr)) non_dwarf_expr = true; break; + case dw_val_class_view_list: + gcc_unreachable (); case dw_val_class_loc: lv = AT_loc (av); if (lv == NULL) @@ -29119,7 +29853,7 @@ optimize_string_length (dw_attr_node *a) lv = copy_deref_exprloc (d->expr); if (lv) { - *p = new_loc_list (lv, d->begin, d->end, d->section); + *p = new_loc_list (lv, d->begin, d->vbegin, d->end, d->vend, d->section); p = &(*p)->dw_loc_next; } else if (!dwarf_strict && d->expr) @@ -29189,6 +29923,7 @@ resolve_addr (dw_die_ref die) { gcc_assert (!next->ll_symbol); next->ll_symbol = (*curr)->ll_symbol; + next->vl_symbol = (*curr)->vl_symbol; } if (dwarf_split_debug_info) remove_loc_list_addr_table_entries (l); @@ -29214,6 +29949,21 @@ resolve_addr (dw_die_ref die) ix--; } break; + case dw_val_class_view_list: + { + gcc_checking_assert (a->dw_attr == DW_AT_GNU_locviews); + gcc_checking_assert (dwarf2out_locviews_in_attribute ()); + dw_val_node *llnode + = view_list_to_loc_list_val_node (&a->dw_attr_val); + /* If we no longer have a loclist, or it no longer needs + views, drop this attribute. */ + if (!llnode || !llnode->v.val_loc_list->vl_symbol) + { + remove_AT (die, a->dw_attr); + ix--; + } + break; + } case dw_val_class_loc: { dw_loc_descr_ref l = AT_loc (a); @@ -29610,6 +30360,8 @@ hash_loc_list (dw_loc_list_ref list_head) { hstate.add (curr->begin, strlen (curr->begin) + 1); hstate.add (curr->end, strlen (curr->end) + 1); + hstate.add_object (curr->vbegin); + hstate.add_object (curr->vend); if (curr->section) hstate.add (curr->section, strlen (curr->section) + 1); hash_locs (curr->expr, hstate); @@ -29831,6 +30583,7 @@ loc_list_hasher::equal (const dw_loc_list_struct *a, || strcmp (a->end, b->end) != 0 || (a->section == NULL) != (b->section == NULL) || (a->section && strcmp (a->section, b->section) != 0) + || a->vbegin != b->vbegin || a->vend != b->vend || !compare_locs (a->expr, b->expr)) break; return a == NULL && b == NULL; @@ -29849,6 +30602,8 @@ optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type *htab) dw_attr_node *a; unsigned ix; dw_loc_list_struct **slot; + bool drop_locviews = false; + bool has_locviews = false; FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a) if (AT_class (a) == dw_val_class_loc_list) @@ -29859,10 +30614,32 @@ optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type *htab) hash_loc_list (list); slot = htab->find_slot_with_hash (list, list->hash, INSERT); if (*slot == NULL) - *slot = list; + { + *slot = list; + if (loc_list_has_views (list)) + gcc_assert (list->vl_symbol); + else if (list->vl_symbol) + { + drop_locviews = true; + list->vl_symbol = NULL; + } + } else - a->dw_attr_val.v.val_loc_list = *slot; + { + if (list->vl_symbol && !(*slot)->vl_symbol) + drop_locviews = true; + a->dw_attr_val.v.val_loc_list = *slot; + } } + else if (AT_class (a) == dw_val_class_view_list) + { + gcc_checking_assert (a->dw_attr == DW_AT_GNU_locviews); + has_locviews = true; + } + + + if (drop_locviews && has_locviews) + remove_AT (die, DW_AT_GNU_locviews); FOR_EACH_CHILD (die, c, optimize_location_lists_1 (c, htab)); } @@ -29888,7 +30665,7 @@ index_location_lists (dw_die_ref die) /* Don't index an entry that has already been indexed or won't be output. */ if (curr->begin_entry != NULL - || (strcmp (curr->begin, curr->end) == 0 && !curr->force)) + || skip_loc_list_entry (curr)) continue; curr->begin_entry @@ -29996,6 +30773,9 @@ dwarf2out_finish (const char *) /* Flush out any latecomers to the limbo party. */ flush_limbo_die_list (); + if (inline_entry_data_table) + gcc_assert (inline_entry_data_table->elements () == 0); + if (flag_checking) { verify_die (comp_unit_die ()); @@ -30312,7 +31092,7 @@ dwarf2out_finish (const char *) dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1, "Length of Location Lists"); ASM_OUTPUT_LABEL (asm_out_file, l1); - dw2_asm_output_data (2, dwarf_version, "DWARF Version"); + output_dwarf_version (); dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size"); dw2_asm_output_data (1, 0, "Segment Size"); dw2_asm_output_data (4, dwarf_split_debug_info ? loc_list_idx : 0, @@ -30371,7 +31151,7 @@ dwarf2out_finish (const char *) used by the debug_info section are marked as 'used'. */ switch_to_section (debug_line_section); ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label); - if (! DWARF2_ASM_LINE_DEBUG_INFO) + if (! output_asm_line_debug_info ()) output_line_info (false); if (dwarf_split_debug_info && info_section_emitted) diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h index bc2ae4d..a1856a5 100644 --- a/gcc/dwarf2out.h +++ b/gcc/dwarf2out.h @@ -160,7 +160,8 @@ enum dw_val_class dw_val_class_discr_list, dw_val_class_const_implicit, dw_val_class_unsigned_const_implicit, - dw_val_class_file_implicit + dw_val_class_file_implicit, + dw_val_class_view_list }; /* Describe a floating point constant value, or a vector constant value. */ @@ -203,6 +204,7 @@ struct GTY(()) dw_val_node { rtx GTY ((tag ("dw_val_class_addr"))) val_addr; unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_offset"))) val_offset; dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list; + dw_die_ref GTY ((tag ("dw_val_class_view_list"))) val_view_list; dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc; HOST_WIDE_INT GTY ((default)) val_int; unsigned HOST_WIDE_INT @@ -4726,8 +4726,6 @@ optimize_bitfield_assignment_op (poly_uint64 pbitsize, } else if (!REG_P (str_rtx) && GET_CODE (str_rtx) != SUBREG) return false; - else - gcc_assert (!reverse); /* If the bit field covers the whole REG/MEM, store_field will likely generate better code. */ diff --git a/gcc/final.c b/gcc/final.c index 578e5d6..99a7cad 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -110,6 +110,7 @@ along with GCC; see the file COPYING3. If not see /* Bitflags used by final_scan_insn. */ #define SEEN_NOTE 1 #define SEEN_EMITTED 2 +#define SEEN_NEXT_VIEW 4 /* Last insn processed by final_scan_insn. */ static rtx_insn *debug_insn; @@ -1610,6 +1611,7 @@ reemit_insn_block_notes (void) break; case NOTE_INSN_BEGIN_STMT: + case NOTE_INSN_INLINE_ENTRY: this_block = LOCATION_BLOCK (NOTE_MARKER_LOCATION (insn)); goto set_cur_block_to_this_block; @@ -1692,6 +1694,67 @@ get_some_local_dynamic_name () return 0; } +/* Arrange for us to emit a source location note before any further + real insns or section changes, by setting the SEEN_NEXT_VIEW bit in + *SEEN, as long as we are keeping track of location views. The bit + indicates we have referenced the next view at the current PC, so we + have to emit it. This should be called next to the var_location + debug hook. */ + +static inline void +set_next_view_needed (int *seen) +{ + if (debug_variable_location_views) + *seen |= SEEN_NEXT_VIEW; +} + +/* Clear the flag in *SEEN indicating we need to emit the next view. + This should be called next to the source_line debug hook. */ + +static inline void +clear_next_view_needed (int *seen) +{ + *seen &= ~SEEN_NEXT_VIEW; +} + +/* Test whether we have a pending request to emit the next view in + *SEEN, and emit it if needed, clearing the request bit. */ + +static inline void +maybe_output_next_view (int *seen) +{ + if ((*seen & SEEN_NEXT_VIEW) != 0) + { + clear_next_view_needed (seen); + (*debug_hooks->source_line) (last_linenum, last_columnnum, + last_filename, last_discriminator, + false); + } +} + +/* We want to emit param bindings (before the first begin_stmt) in the + initial view, if we are emitting views. To that end, we may + consume initial notes in the function, processing them in + final_start_function, before signaling the beginning of the + prologue, rather than in final. + + We don't test whether the DECLs are PARM_DECLs: the assumption is + that there will be a NOTE_INSN_BEGIN_STMT marker before any + non-parameter NOTE_INSN_VAR_LOCATION. It's ok if the marker is not + there, we'll just have more variable locations bound in the initial + view, which is consistent with their being bound without any code + that would give them a value. */ + +static inline bool +in_initial_view_p (rtx_insn *insn) +{ + return (!DECL_IGNORED_P (current_function_decl) + && debug_variable_location_views + && insn && GET_CODE (insn) == NOTE + && (NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION + || NOTE_KIND (insn) == NOTE_INSN_DELETED)); +} + /* Output assembler code for the start of a function, and initialize some of the variables in this file for the new function. The label for the function and associated @@ -1699,12 +1762,15 @@ get_some_local_dynamic_name () FIRST is the first insn of the rtl for the function being compiled. FILE is the file to write assembler code to. + SEEN should be initially set to zero, and it may be updated to + indicate we have references to the next location view, that would + require us to emit it at the current PC. OPTIMIZE_P is nonzero if we should eliminate redundant test and compare insns. */ -void -final_start_function (rtx_insn *first, FILE *file, - int optimize_p ATTRIBUTE_UNUSED) +static void +final_start_function_1 (rtx_insn **firstp, FILE *file, int *seen, + int optimize_p ATTRIBUTE_UNUSED) { block_depth = 0; @@ -1722,8 +1788,21 @@ final_start_function (rtx_insn *first, FILE *file, if (flag_sanitize & SANITIZE_ADDRESS) asan_function_start (); + rtx_insn *first = *firstp; + if (in_initial_view_p (first)) + { + do + { + final_scan_insn (first, file, 0, 0, seen); + first = NEXT_INSN (first); + } + while (in_initial_view_p (first)); + *firstp = first; + } + if (!DECL_IGNORED_P (current_function_decl)) - debug_hooks->begin_prologue (last_linenum, last_columnnum, last_filename); + debug_hooks->begin_prologue (last_linenum, last_columnnum, + last_filename); if (!dwarf2_debug_info_emitted_p (current_function_decl)) dwarf2out_begin_prologue (0, 0, NULL); @@ -1799,6 +1878,17 @@ final_start_function (rtx_insn *first, FILE *file, profile_after_prologue (file); } +/* This is an exported final_start_function_1, callable without SEEN. */ + +void +final_start_function (rtx_insn *first, FILE *file, + int optimize_p ATTRIBUTE_UNUSED) +{ + int seen = 0; + final_start_function_1 (&first, file, &seen, optimize_p); + gcc_assert (seen == 0); +} + static void profile_after_prologue (FILE *file ATTRIBUTE_UNUSED) { @@ -1928,11 +2018,10 @@ dump_basic_block_info (FILE *file, rtx_insn *insn, basic_block *start_to_bb, /* Output assembler code for some insns: all or part of a function. For description of args, see `final_start_function', above. */ -void -final (rtx_insn *first, FILE *file, int optimize_p) +static void +final_1 (rtx_insn *first, FILE *file, int seen, int optimize_p) { rtx_insn *insn, *next; - int seen = 0; /* Used for -dA dump. */ basic_block *start_to_bb = NULL; @@ -1999,6 +2088,8 @@ final (rtx_insn *first, FILE *file, int optimize_p) insn = final_scan_insn (insn, file, optimize_p, 0, &seen); } + maybe_output_next_view (&seen); + if (flag_debug_asm) { free (start_to_bb); @@ -2015,6 +2106,23 @@ final (rtx_insn *first, FILE *file, int optimize_p) delete_insn (insn); } } + +/* This is an exported final_1, callable without SEEN. */ + +void +final (rtx_insn *first, FILE *file, int optimize_p) +{ + /* Those that use the internal final_start_function_1/final_1 API + skip initial debug bind notes in final_start_function_1, and pass + the modified FIRST to final_1. But those that use the public + final_start_function/final APIs, final_start_function can't move + FIRST because it's not passed by reference, so if they were + skipped there, skip them again here. */ + while (in_initial_view_p (first)) + first = NEXT_INSN (first); + + final_1 (first, file, 0, optimize_p); +} const char * get_insn_template (int code, rtx insn) @@ -2155,6 +2263,8 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, break; case NOTE_INSN_SWITCH_TEXT_SECTIONS: + maybe_output_next_view (seen); + in_cold_section_p = !in_cold_section_p; if (in_cold_section_p) @@ -2301,6 +2411,8 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, break; case NOTE_INSN_BLOCK_END: + maybe_output_next_view (seen); + if (debug_info_level == DINFO_LEVEL_NORMAL || debug_info_level == DINFO_LEVEL_VERBOSE || write_symbols == DWARF2_DEBUG @@ -2357,7 +2469,10 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, case NOTE_INSN_VAR_LOCATION: case NOTE_INSN_CALL_ARG_LOCATION: if (!DECL_IGNORED_P (current_function_decl)) - debug_hooks->var_location (insn); + { + debug_hooks->var_location (insn); + set_next_view_needed (seen); + } break; case NOTE_INSN_BEGIN_STMT: @@ -2365,9 +2480,23 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, if (!DECL_IGNORED_P (current_function_decl) && notice_source_line (insn, NULL)) { + output_source_line: (*debug_hooks->source_line) (last_linenum, last_columnnum, last_filename, last_discriminator, true); + clear_next_view_needed (seen); + } + break; + + case NOTE_INSN_INLINE_ENTRY: + gcc_checking_assert (cfun->debug_nonbind_markers); + if (!DECL_IGNORED_P (current_function_decl)) + { + if (!notice_source_line (insn, NULL)) + break; + (*debug_hooks->inline_entry) (LOCATION_BLOCK + (NOTE_MARKER_LOCATION (insn))); + goto output_source_line; } break; @@ -2563,6 +2692,10 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, switch_to_section (current_function_section ()); + if (debug_variable_location_views + && !DECL_IGNORED_P (current_function_decl)) + debug_hooks->var_location (insn); + break; } /* Output this line note if it is the first or the last line @@ -2575,7 +2708,12 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, (*debug_hooks->source_line) (last_linenum, last_columnnum, last_filename, last_discriminator, is_stmt); + clear_next_view_needed (seen); } + else + maybe_output_next_view (seen); + + gcc_checking_assert (!DEBUG_INSN_P (insn)); if (GET_CODE (body) == PARALLEL && GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT) @@ -3042,7 +3180,8 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, /* Let the debug info back-end know about this call. We do this only after the instruction has been emitted because labels that may be created to reference the call instruction must appear after it. */ - if (call_insn != NULL && !DECL_IGNORED_P (current_function_decl)) + if ((debug_variable_location_views || call_insn != NULL) + && !DECL_IGNORED_P (current_function_decl)) debug_hooks->var_location (insn); current_output_insn = debug_insn = 0; @@ -3064,6 +3203,17 @@ notice_source_line (rtx_insn *insn, bool *is_stmt) if (NOTE_MARKER_P (insn)) { location_t loc = NOTE_MARKER_LOCATION (insn); + /* The inline entry markers (gimple, insn, note) carry the + location of the call, because that's what we want to carry + during compilation, but the location we want to output in + debug information for the inline entry point is the location + of the function itself. */ + if (NOTE_KIND (insn) == NOTE_INSN_INLINE_ENTRY) + { + tree block = LOCATION_BLOCK (loc); + tree fn = block_ultimate_origin (block); + loc = DECL_SOURCE_LOCATION (fn); + } expanded_location xloc = expand_location (loc); if (xloc.line == 0) { @@ -4481,8 +4631,10 @@ rest_of_handle_final (void) delete_vta_debug_insns (false); assemble_start_function (current_function_decl, fnname); - final_start_function (get_insns (), asm_out_file, optimize); - final (get_insns (), asm_out_file, optimize); + rtx_insn *first = get_insns (); + int seen = 0; + final_start_function_1 (&first, asm_out_file, &seen, optimize); + final_1 (first, asm_out_file, seen, optimize); if (flag_ipa_ra && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl))) collect_fn_hard_reg_usage (); @@ -4668,6 +4820,7 @@ rest_of_clean_state (void) && (!NOTE_P (insn) || (NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION && NOTE_KIND (insn) != NOTE_INSN_BEGIN_STMT + && NOTE_KIND (insn) != NOTE_INSN_INLINE_ENTRY && NOTE_KIND (insn) != NOTE_INSN_CALL_ARG_LOCATION && NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END diff --git a/gcc/fold-const.c b/gcc/fold-const.c index c86c3f9..87d00a5 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -14115,6 +14115,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) { tree op = TREE_OPERAND (sub, 0); tree optype = TREE_TYPE (op); + /* *&CONST_DECL -> to the value of the const decl. */ if (TREE_CODE (op) == CONST_DECL) return DECL_INITIAL (op); @@ -14148,12 +14149,13 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) && type == TREE_TYPE (optype)) return fold_build1_loc (loc, REALPART_EXPR, type, op); /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */ - else if (TREE_CODE (optype) == VECTOR_TYPE + else if (VECTOR_TYPE_P (optype) && type == TREE_TYPE (optype)) { tree part_width = TYPE_SIZE (type); tree index = bitsize_int (0); - return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, index); + return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, + index); } } @@ -14171,8 +14173,17 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) op00type = TREE_TYPE (op00); /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */ - if (TREE_CODE (op00type) == VECTOR_TYPE - && type == TREE_TYPE (op00type)) + if (VECTOR_TYPE_P (op00type) + && type == TREE_TYPE (op00type) + /* POINTER_PLUS_EXPR second operand is sizetype, unsigned, + but we want to treat offsets with MSB set as negative. + For the code below negative offsets are invalid and + TYPE_SIZE of the element is something unsigned, so + check whether op01 fits into poly_int64, which implies + it is from 0 to INTTYPE_MAXIMUM (HOST_WIDE_INT), and + then just use poly_uint64 because we want to treat the + value as unsigned. */ + && tree_fits_poly_int64_p (op01)) { tree part_width = TYPE_SIZE (type); poly_uint64 max_offset @@ -14199,16 +14210,16 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) && type == TREE_TYPE (op00type)) { tree type_domain = TYPE_DOMAIN (op00type); - tree min = size_zero_node; + tree min_val = size_zero_node; if (type_domain && TYPE_MIN_VALUE (type_domain)) - min = TYPE_MIN_VALUE (type_domain); + min_val = TYPE_MIN_VALUE (type_domain); offset_int off = wi::to_offset (op01); offset_int el_sz = wi::to_offset (TYPE_SIZE_UNIT (type)); offset_int remainder; off = wi::divmod_trunc (off, el_sz, SIGNED, &remainder); - if (remainder == 0 && TREE_CODE (min) == INTEGER_CST) + if (remainder == 0 && TREE_CODE (min_val) == INTEGER_CST) { - off = off + wi::to_offset (min); + off = off + wi::to_offset (min_val); op01 = wide_int_to_tree (sizetype, off); return build4_loc (loc, ARRAY_REF, type, op00, op01, NULL_TREE, NULL_TREE); diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index a87c48a..b0bd14f 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,17 @@ +2018-02-10 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/84141 + PR fortran/84155 + * trans-array.c (gfc_array_init_size): Revert the change made + in revision 257356 setting the dtype. + * trans-types.c (gfc_get_dtype): Do not use the cached dtype. + Call gfc_get_dtype_rank_type every time. + + PR fortran/56691 + * trans-array.c (gfc_conv_expr_descriptor): If the source array + is a descriptor type, use its offset, removing the condition + that is be a class expression. + 2018-02-07 Steven G. Kargl <kargl@gcc.gnu.org> PR fortran/82994 diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index c845bef..d8b4381 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -5354,8 +5354,8 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset, } else { - tmp = gfc_get_dtype_rank_type (rank, gfc_get_element_type (type)); - gfc_add_modify (pblock, gfc_conv_descriptor_dtype (descriptor), tmp); + tmp = gfc_conv_descriptor_dtype (descriptor); + gfc_add_modify (pblock, tmp, gfc_get_dtype (type)); } or_expr = logical_false_node; @@ -7529,9 +7529,9 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) : base; gfc_conv_descriptor_offset_set (&loop.pre, parm, tmp); } - else if (IS_CLASS_ARRAY (expr) && !se->data_not_needed - && (!rank_remap || se->use_offset) - && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))) + else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)) + && !se->data_not_needed + && (!rank_remap || se->use_offset)) { gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_conv_descriptor_offset_get (desc)); diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c index b15a4b2..697b735 100644 --- a/gcc/fortran/trans-types.c +++ b/gcc/fortran/trans-types.c @@ -1593,9 +1593,6 @@ gfc_get_dtype (tree type) gcc_assert (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type)); - if (GFC_TYPE_ARRAY_DTYPE (type)) - return GFC_TYPE_ARRAY_DTYPE (type); - rank = GFC_TYPE_ARRAY_RANK (type); etype = gfc_get_element_type (type); dtype = gfc_get_dtype_rank_type (rank, etype); @@ -684,7 +684,7 @@ proper position among the other output files. */ #ifndef LIBASAN_SPEC #define STATIC_LIBASAN_LIBS \ - " %{static-libasan:%:include(libsanitizer.spec)%(link_libasan)}" + " %{static-libasan|static:%:include(libsanitizer.spec)%(link_libasan)}" #ifdef LIBASAN_EARLY_SPEC #define LIBASAN_SPEC STATIC_LIBASAN_LIBS #elif defined(HAVE_LD_STATIC_DYNAMIC) @@ -702,7 +702,7 @@ proper position among the other output files. */ #ifndef LIBTSAN_SPEC #define STATIC_LIBTSAN_LIBS \ - " %{static-libtsan:%:include(libsanitizer.spec)%(link_libtsan)}" + " %{static-libtsan|static:%:include(libsanitizer.spec)%(link_libtsan)}" #ifdef LIBTSAN_EARLY_SPEC #define LIBTSAN_SPEC STATIC_LIBTSAN_LIBS #elif defined(HAVE_LD_STATIC_DYNAMIC) @@ -720,7 +720,7 @@ proper position among the other output files. */ #ifndef LIBLSAN_SPEC #define STATIC_LIBLSAN_LIBS \ - " %{static-liblsan:%:include(libsanitizer.spec)%(link_liblsan)}" + " %{static-liblsan|static:%:include(libsanitizer.spec)%(link_liblsan)}" #ifdef LIBLSAN_EARLY_SPEC #define LIBLSAN_SPEC STATIC_LIBLSAN_LIBS #elif defined(HAVE_LD_STATIC_DYNAMIC) @@ -738,7 +738,7 @@ proper position among the other output files. */ #ifndef LIBUBSAN_SPEC #define STATIC_LIBUBSAN_LIBS \ - " %{static-libubsan:%:include(libsanitizer.spec)%(link_libubsan)}" + " %{static-libubsan|static:%:include(libsanitizer.spec)%(link_libubsan)}" #ifdef HAVE_LD_STATIC_DYNAMIC #define LIBUBSAN_SPEC "%{static-libubsan:" LD_STATIC_OPTION \ "} -lubsan %{static-libubsan:" LD_DYNAMIC_OPTION "}" \ diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 374bd45..6695526 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -1371,6 +1371,19 @@ dump_gimple_debug (pretty_printer *buffer, gdebug *gs, int spc, dump_gimple_fmt (buffer, spc, flags, "# DEBUG BEGIN_STMT"); break; + case GIMPLE_DEBUG_INLINE_ENTRY: + if (flags & TDF_RAW) + dump_gimple_fmt (buffer, spc, flags, "%G INLINE_ENTRY %T", gs, + gimple_block (gs) + ? block_ultimate_origin (gimple_block (gs)) + : NULL_TREE); + else + dump_gimple_fmt (buffer, spc, flags, "# DEBUG INLINE_ENTRY %T", + gimple_block (gs) + ? block_ultimate_origin (gimple_block (gs)) + : NULL_TREE); + break; + default: gcc_unreachable (); } diff --git a/gcc/gimple.c b/gcc/gimple.c index c1b7229..9dc4911 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -874,6 +874,27 @@ gimple_build_debug_begin_stmt (tree block, location_t location } +/* Build a new GIMPLE_DEBUG_INLINE_ENTRY statement in BLOCK at + LOCATION. The BLOCK links to the inlined function. */ + +gdebug * +gimple_build_debug_inline_entry (tree block, location_t location + MEM_STAT_DECL) +{ + gdebug *p + = as_a <gdebug *> ( + gimple_build_with_ops_stat (GIMPLE_DEBUG, + (unsigned)GIMPLE_DEBUG_INLINE_ENTRY, 0 + PASS_MEM_STAT)); + + gimple_set_location (p, location); + gimple_set_block (p, block); + cfun->debug_marker_count++; + + return p; +} + + /* Build a GIMPLE_OMP_CRITICAL statement. BODY is the sequence of statements for which only one thread can execute. diff --git a/gcc/gimple.h b/gcc/gimple.h index 7460586..265e3e2 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -202,7 +202,8 @@ enum gf_mask { enum gimple_debug_subcode { GIMPLE_DEBUG_BIND = 0, GIMPLE_DEBUG_SOURCE_BIND = 1, - GIMPLE_DEBUG_BEGIN_STMT = 2 + GIMPLE_DEBUG_BEGIN_STMT = 2, + GIMPLE_DEBUG_INLINE_ENTRY = 3 }; /* Masks for selecting a pass local flag (PLF) to work on. These @@ -1454,6 +1455,7 @@ geh_dispatch *gimple_build_eh_dispatch (int); gdebug *gimple_build_debug_bind (tree, tree, gimple * CXX_MEM_STAT_INFO); gdebug *gimple_build_debug_source_bind (tree, tree, gimple * CXX_MEM_STAT_INFO); gdebug *gimple_build_debug_begin_stmt (tree, location_t CXX_MEM_STAT_INFO); +gdebug *gimple_build_debug_inline_entry (tree, location_t CXX_MEM_STAT_INFO); gomp_critical *gimple_build_omp_critical (gimple_seq, tree, tree); gomp_for *gimple_build_omp_for (gimple_seq, int, tree, size_t, gimple_seq); gomp_parallel *gimple_build_omp_parallel (gimple_seq, tree, tree, tree); @@ -4784,13 +4786,25 @@ gimple_debug_begin_stmt_p (const gimple *s) return false; } +/* Return true if S is a GIMPLE_DEBUG INLINE_ENTRY statement. */ + +static inline bool +gimple_debug_inline_entry_p (const gimple *s) +{ + if (is_gimple_debug (s)) + return s->subcode == GIMPLE_DEBUG_INLINE_ENTRY; + + return false; +} + /* Return true if S is a GIMPLE_DEBUG non-binding marker statement. */ static inline bool gimple_debug_nonbind_marker_p (const gimple *s) { if (is_gimple_debug (s)) - return s->subcode == GIMPLE_DEBUG_BEGIN_STMT; + return s->subcode == GIMPLE_DEBUG_BEGIN_STMT + || s->subcode == GIMPLE_DEBUG_INLINE_ENTRY; return false; } diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index edffc11..3d73330 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -7e94bac5676afc8188677c98ecb263c78c1a7f8d +89105404f94005ffa8e2b08df78015dc9ac91362 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index ab0c27b..11ac338 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -5189,17 +5189,24 @@ Function::defer_stack(Location location) void Function::export_func(Export* exp, const std::string& name) const { - Function::export_func_with_type(exp, name, this->type_); + Function::export_func_with_type(exp, name, this->type_, + this->is_method() && this->nointerface()); } // Export a function with a type. void Function::export_func_with_type(Export* exp, const std::string& name, - const Function_type* fntype) + const Function_type* fntype, bool nointerface) { exp->write_c_string("func "); + if (nointerface) + { + go_assert(fntype->is_method()); + exp->write_c_string("/*nointerface*/ "); + } + if (fntype->is_method()) { exp->write_c_string("("); @@ -5280,10 +5287,21 @@ Function::import_func(Import* imp, std::string* pname, Typed_identifier** preceiver, Typed_identifier_list** pparameters, Typed_identifier_list** presults, - bool* is_varargs) + bool* is_varargs, + bool* nointerface) { imp->require_c_string("func "); + *nointerface = false; + if (imp->match_c_string("/*")) + { + imp->require_c_string("/*nointerface*/ "); + *nointerface = true; + + // Only a method can be nointerface. + go_assert(imp->peek_char() == '('); + } + *preceiver = NULL; if (imp->peek_char() == '(') { @@ -6213,6 +6231,32 @@ Bindings_snapshot::check_goto_defs(Location loc, const Block* block, // Class Function_declaration. +// Whether this declares a method. + +bool +Function_declaration::is_method() const +{ + return this->fntype_->is_method(); +} + +// Whether this method should not be included in the type descriptor. + +bool +Function_declaration::nointerface() const +{ + go_assert(this->is_method()); + return (this->pragmas_ & GOPRAGMA_NOINTERFACE) != 0; +} + +// Record that this method should not be included in the type +// descriptor. + +void +Function_declaration::set_nointerface() +{ + this->pragmas_ |= GOPRAGMA_NOINTERFACE; +} + // Return the function descriptor. Expression* diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index dfff5c1..139df17 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -1476,13 +1476,14 @@ class Function // Export a function with a type. static void export_func_with_type(Export*, const std::string& name, - const Function_type*); + const Function_type*, bool nointerface); // Import a function. static void import_func(Import*, std::string* pname, Typed_identifier** receiver, Typed_identifier_list** pparameters, - Typed_identifier_list** presults, bool* is_varargs); + Typed_identifier_list** presults, bool* is_varargs, + bool* nointerface); private: // Type for mapping from label names to Label objects. @@ -1607,6 +1608,10 @@ class Function_declaration location() const { return this->location_; } + // Return whether this function declaration is a method. + bool + is_method() const; + const std::string& asm_name() const { return this->asm_name_; } @@ -1628,6 +1633,16 @@ class Function_declaration this->pragmas_ = pragmas; } + // Whether this method should not be included in the type + // descriptor. + bool + nointerface() const; + + // Record that this method should not be included in the type + // descriptor. + void + set_nointerface(); + // Return an expression for the function descriptor, given the named // object for this function. This may only be called for functions // without a closure. This will be an immutable struct with one @@ -1652,7 +1667,10 @@ class Function_declaration // Export a function declaration. void export_func(Export* exp, const std::string& name) const - { Function::export_func_with_type(exp, name, this->fntype_); } + { + Function::export_func_with_type(exp, name, this->fntype_, + this->is_method() && this->nointerface()); + } // Check that the types used in this declaration's signature are defined. void diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc index 2a3ea83..7e06a3c 100644 --- a/gcc/go/gofrontend/import.cc +++ b/gcc/go/gofrontend/import.cc @@ -607,8 +607,9 @@ Import::import_func(Package* package) Typed_identifier_list* parameters; Typed_identifier_list* results; bool is_varargs; + bool nointerface; Function::import_func(this, &name, &receiver, - ¶meters, &results, &is_varargs); + ¶meters, &results, &is_varargs, &nointerface); Function_type *fntype = Type::make_function_type(receiver, parameters, results, this->location_); if (is_varargs) @@ -648,6 +649,10 @@ Import::import_func(Package* package) if (this->add_to_globals_) this->gogo_->add_dot_import_object(no); } + + if (nointerface) + no->func_declaration_value()->set_nointerface(); + return no; } diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index eb04fe1..40eccfc 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -9742,7 +9742,12 @@ bool Named_method::do_nointerface() const { Named_object* no = this->named_object_; - return no->is_function() && no->func_value()->nointerface(); + if (no->is_function()) + return no->func_value()->nointerface(); + else if (no->is_function_declaration()) + return no->func_declaration_value()->nointerface(); + else + go_unreachable(); } // Class Interface_method. diff --git a/gcc/insn-notes.def b/gcc/insn-notes.def index 5186d58..9cac5f1 100644 --- a/gcc/insn-notes.def +++ b/gcc/insn-notes.def @@ -71,6 +71,10 @@ INSN_NOTE (CALL_ARG_LOCATION) /* The beginning of a statement. */ INSN_NOTE (BEGIN_STMT) +/* The entry point for an inlined function. Its NOTE_BLOCK references + the lexical block whose abstract origin is the inlined function. */ +INSN_NOTE (INLINE_ENTRY) + /* Record the struct for the following basic block. Uses NOTE_BASIC_BLOCK. FIXME: Redundant with the basic block pointer now included in every insn. NOTE: If there's no CFG anymore, in other words, diff --git a/gcc/ira-color.c b/gcc/ira-color.c index 26b18f3..7087fb9 100644 --- a/gcc/ira-color.c +++ b/gcc/ira-color.c @@ -112,6 +112,9 @@ struct allocno_color_data available for the allocno allocation. It is number of the profitable hard regs. */ int available_regs_num; + /* Sum of frequencies of hard register preferences of all + conflicting allocnos which are not the coloring stack yet. */ + int conflict_allocno_hard_prefs; /* Allocnos in a bucket (used in coloring) chained by the following two members. */ ira_allocno_t next_bucket_allocno; @@ -1435,6 +1438,36 @@ update_costs_from_copies (ira_allocno_t allocno, bool decr_p, bool record_p) update_costs_from_allocno (allocno, hard_regno, 1, decr_p, record_p); } +/* Update conflict_allocno_hard_prefs of allocnos conflicting with + ALLOCNO. */ +static void +update_conflict_allocno_hard_prefs (ira_allocno_t allocno) +{ + int l, nr = ALLOCNO_NUM_OBJECTS (allocno); + + for (l = 0; l < nr; l++) + { + ira_object_t conflict_obj, obj = ALLOCNO_OBJECT (allocno, l); + ira_object_conflict_iterator oci; + + FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci) + { + ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj); + allocno_color_data_t conflict_data = ALLOCNO_COLOR_DATA (conflict_a); + ira_pref_t pref; + + if (!(hard_reg_set_intersect_p + (ALLOCNO_COLOR_DATA (allocno)->profitable_hard_regs, + conflict_data->profitable_hard_regs))) + continue; + for (pref = ALLOCNO_PREFS (allocno); + pref != NULL; + pref = pref->next_pref) + conflict_data->conflict_allocno_hard_prefs += pref->freq; + } + } +} + /* Restore costs of allocnos connected to ALLOCNO by copies as it was before updating costs of these allocnos from given allocno. This is a wise thing to do as if given allocno did not get an expected @@ -2223,7 +2256,7 @@ bucket_allocno_compare_func (const void *v1p, const void *v2p) { ira_allocno_t a1 = *(const ira_allocno_t *) v1p; ira_allocno_t a2 = *(const ira_allocno_t *) v2p; - int diff, freq1, freq2, a1_num, a2_num; + int diff, freq1, freq2, a1_num, a2_num, pref1, pref2; ira_allocno_t t1 = ALLOCNO_COLOR_DATA (a1)->first_thread_allocno; ira_allocno_t t2 = ALLOCNO_COLOR_DATA (a2)->first_thread_allocno; int cl1 = ALLOCNO_CLASS (a1), cl2 = ALLOCNO_CLASS (a2); @@ -2253,6 +2286,11 @@ bucket_allocno_compare_func (const void *v1p, const void *v2p) a2_num = ALLOCNO_COLOR_DATA (a2)->available_regs_num; if ((diff = a2_num - a1_num) != 0) return diff; + /* Push allocnos with minimal conflict_allocno_hard_prefs first. */ + pref1 = ALLOCNO_COLOR_DATA (a1)->conflict_allocno_hard_prefs; + pref2 = ALLOCNO_COLOR_DATA (a2)->conflict_allocno_hard_prefs; + if ((diff = pref1 - pref2) != 0) + return diff; return ALLOCNO_NUM (a2) - ALLOCNO_NUM (a1); } @@ -2339,7 +2377,8 @@ delete_allocno_from_bucket (ira_allocno_t allocno, ira_allocno_t *bucket_ptr) /* Put allocno A onto the coloring stack without removing it from its bucket. Pushing allocno to the coloring stack can result in moving conflicting allocnos from the uncolorable bucket to the colorable - one. */ + one. Update conflict_allocno_hard_prefs of the conflicting + allocnos which are not on stack yet. */ static void push_allocno_to_stack (ira_allocno_t a) { @@ -2369,15 +2408,19 @@ push_allocno_to_stack (ira_allocno_t a) FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci) { ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj); - + ira_pref_t pref; + conflict_data = ALLOCNO_COLOR_DATA (conflict_a); - if (conflict_data->colorable_p - || ! conflict_data->in_graph_p + if (! conflict_data->in_graph_p || ALLOCNO_ASSIGNED_P (conflict_a) || !(hard_reg_set_intersect_p (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs, conflict_data->profitable_hard_regs))) continue; + for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = pref->next_pref) + conflict_data->conflict_allocno_hard_prefs -= pref->freq; + if (conflict_data->colorable_p) + continue; ira_assert (bitmap_bit_p (coloring_allocno_bitmap, ALLOCNO_NUM (conflict_a))); if (update_left_conflict_sizes_p (conflict_a, a, size)) @@ -3048,21 +3091,12 @@ color_allocnos (void) setup_profitable_hard_regs (); EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi) { - int l, nr; - HARD_REG_SET conflict_hard_regs; allocno_color_data_t data; ira_pref_t pref, next_pref; a = ira_allocnos[i]; - nr = ALLOCNO_NUM_OBJECTS (a); - CLEAR_HARD_REG_SET (conflict_hard_regs); - for (l = 0; l < nr; l++) - { - ira_object_t obj = ALLOCNO_OBJECT (a, l); - IOR_HARD_REG_SET (conflict_hard_regs, - OBJECT_CONFLICT_HARD_REGS (obj)); - } data = ALLOCNO_COLOR_DATA (a); + data->conflict_allocno_hard_prefs = 0; for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = next_pref) { next_pref = pref->next_pref; @@ -3072,6 +3106,7 @@ color_allocnos (void) ira_remove_pref (pref); } } + if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY) { n = 0; @@ -3134,6 +3169,7 @@ color_allocnos (void) { ALLOCNO_COLOR_DATA (a)->in_graph_p = true; update_costs_from_prefs (a); + update_conflict_allocno_hard_prefs (a); } else { diff --git a/gcc/omp-low.c b/gcc/omp-low.c index ebbf88e..d8588b9 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3208,6 +3208,43 @@ scan_omp (gimple_seq *body_p, omp_context *ctx) /* Re-gimplification and code generation routines. */ +/* Remove omp_member_access_dummy_var variables from gimple_bind_vars + of BIND if in a method. */ + +static void +maybe_remove_omp_member_access_dummy_vars (gbind *bind) +{ + if (DECL_ARGUMENTS (current_function_decl) + && DECL_ARTIFICIAL (DECL_ARGUMENTS (current_function_decl)) + && (TREE_CODE (TREE_TYPE (DECL_ARGUMENTS (current_function_decl))) + == POINTER_TYPE)) + { + tree vars = gimple_bind_vars (bind); + for (tree *pvar = &vars; *pvar; ) + if (omp_member_access_dummy_var (*pvar)) + *pvar = DECL_CHAIN (*pvar); + else + pvar = &DECL_CHAIN (*pvar); + gimple_bind_set_vars (bind, vars); + } +} + +/* Remove omp_member_access_dummy_var variables from BLOCK_VARS of + block and its subblocks. */ + +static void +remove_member_access_dummy_vars (tree block) +{ + for (tree *pvar = &BLOCK_VARS (block); *pvar; ) + if (omp_member_access_dummy_var (*pvar)) + *pvar = DECL_CHAIN (*pvar); + else + pvar = &DECL_CHAIN (*pvar); + + for (block = BLOCK_SUBBLOCKS (block); block; block = BLOCK_CHAIN (block)) + remove_member_access_dummy_vars (block); +} + /* If a context was created for STMT when it was scanned, return it. */ static omp_context * @@ -6961,6 +6998,7 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx) pop_gimplify_context (new_stmt); gimple_bind_append_vars (new_stmt, ctx->block_vars); + maybe_remove_omp_member_access_dummy_vars (new_stmt); BLOCK_VARS (block) = gimple_bind_vars (new_stmt); if (BLOCK_VARS (block)) TREE_USED (block) = 1; @@ -7413,6 +7451,7 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx) /* Declare all the variables created by mapping and the variables declared in the scope of the parallel body. */ record_vars_into (ctx->block_vars, child_fn); + maybe_remove_omp_member_access_dummy_vars (par_bind); record_vars_into (gimple_bind_vars (par_bind), child_fn); if (ctx->record_type) @@ -7781,6 +7820,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) /* Declare all the variables created by mapping and the variables declared in the scope of the target body. */ record_vars_into (ctx->block_vars, child_fn); + maybe_remove_omp_member_access_dummy_vars (tgt_bind); record_vars_into (gimple_bind_vars (tgt_bind), child_fn); } @@ -8772,6 +8812,7 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx) break; case GIMPLE_BIND: lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx); + maybe_remove_omp_member_access_dummy_vars (as_a <gbind *> (stmt)); break; case GIMPLE_OMP_PARALLEL: case GIMPLE_OMP_TASK: @@ -8976,6 +9017,16 @@ execute_lower_omp (void) all_contexts = NULL; } BITMAP_FREE (task_shared_vars); + + /* If current function is a method, remove artificial dummy VAR_DECL created + for non-static data member privatization, they aren't needed for + debuginfo nor anything else, have been already replaced everywhere in the + IL and cause problems with LTO. */ + if (DECL_ARGUMENTS (current_function_decl) + && DECL_ARTIFICIAL (DECL_ARGUMENTS (current_function_decl)) + && (TREE_CODE (TREE_TYPE (DECL_ARGUMENTS (current_function_decl))) + == POINTER_TYPE)) + remove_member_access_dummy_vars (DECL_INITIAL (current_function_decl)); return 0; } diff --git a/gcc/optabs.c b/gcc/optabs.c index daac545..5f61e4e 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -3935,7 +3935,20 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, if (methods != OPTAB_LIB_WIDEN) goto fail; - if (!SCALAR_FLOAT_MODE_P (mode)) + if (SCALAR_FLOAT_MODE_P (mode)) + { + /* Small trick if UNORDERED isn't implemented by the hardware. */ + if (comparison == UNORDERED && rtx_equal_p (x, y)) + { + prepare_cmp_insn (x, y, UNLT, NULL_RTX, unsignedp, OPTAB_WIDEN, + ptest, pmode); + if (*ptest) + return; + } + + prepare_float_lib_cmp (x, y, comparison, ptest, pmode); + } + else { rtx result; machine_mode ret_mode; @@ -3982,8 +3995,6 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, prepare_cmp_insn (x, y, comparison, NULL_RTX, unsignedp, methods, ptest, pmode); } - else - prepare_float_lib_cmp (x, y, comparison, ptest, pmode); return; diff --git a/gcc/output.h b/gcc/output.h index 51ac149..f708cc7 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -552,7 +552,7 @@ extern void output_file_directive (FILE *, const char *); extern unsigned int default_section_type_flags (tree, const char *, int); extern bool have_global_bss_p (void); -extern bool bss_initializer_p (const_tree); +extern bool bss_initializer_p (const_tree, bool = false); extern void default_no_named_section (const char *, unsigned int, tree); extern void default_elf_asm_named_section (const char *, unsigned int, tree); diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c index c26e46c..3ad11dc 100644 --- a/gcc/print-rtl.c +++ b/gcc/print-rtl.c @@ -276,6 +276,7 @@ rtx_writer::print_rtx_operand_code_0 (const_rtx in_rtx ATTRIBUTE_UNUSED, break; case NOTE_INSN_BEGIN_STMT: + case NOTE_INSN_INLINE_ENTRY: #ifndef GENERATOR_FILE { expanded_location xloc @@ -1879,6 +1880,10 @@ print_insn (pretty_printer *pp, const rtx_insn *x, int verbose) pp_string (pp, "debug begin stmt marker"); break; + case NOTE_INSN_INLINE_ENTRY: + pp_string (pp, "debug inline entry marker"); + break; + default: gcc_unreachable (); } @@ -1654,7 +1654,8 @@ extern const char * const reg_note_name[]; for which NOTE_MARKER_LOCATION can be used. */ #define NOTE_MARKER_P(INSN) \ (NOTE_P (INSN) && \ - (NOTE_KIND (INSN) == NOTE_INSN_BEGIN_STMT)) + (NOTE_KIND (INSN) == NOTE_INSN_BEGIN_STMT \ + || NOTE_KIND (INSN) == NOTE_INSN_INLINE_ENTRY)) /* Variable declaration and the location of a variable. */ #define PAT_VAR_LOCATION_DECL(PAT) (XCTREE ((PAT), 0, VAR_LOCATION)) @@ -1692,6 +1693,8 @@ extern const char * const reg_note_name[]; (GET_CODE (PATTERN (INSN)) == DEBUG_MARKER \ ? (GET_MODE (PATTERN (INSN)) == VOIDmode \ ? NOTE_INSN_BEGIN_STMT \ + : GET_MODE (PATTERN (INSN)) == BLKmode \ + ? NOTE_INSN_INLINE_ENTRY \ : (enum insn_note)-1) \ : (enum insn_note)-1) /* Create patterns for debug markers. These and the above abstract @@ -1701,6 +1704,8 @@ extern const char * const reg_note_name[]; wouldn't be a problem. */ #define GEN_RTX_DEBUG_MARKER_BEGIN_STMT_PAT() \ gen_rtx_DEBUG_MARKER (VOIDmode) +#define GEN_RTX_DEBUG_MARKER_INLINE_ENTRY_PAT() \ + gen_rtx_DEBUG_MARKER (BLKmode) /* The VAR_LOCATION rtx in a DEBUG_INSN. */ #define INSN_VAR_LOCATION(INSN) \ diff --git a/gcc/shrink-wrap.c b/gcc/shrink-wrap.c index eda0f06..fd19ace 100644 --- a/gcc/shrink-wrap.c +++ b/gcc/shrink-wrap.c @@ -1370,6 +1370,8 @@ spread_components (sbitmap components) bitmap_clear_bit (seen, bb->index); } + todo.release (); + /* Finally, mark everything not not needed both forwards and backwards. */ FOR_EACH_BB_FN (bb, cfun) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e989c94..a14db69 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,135 @@ +2018-02-10 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/56691 + * gfortran.dg/type_to_class_4.f03: New test. + +2018-02-10 Alan Modra <amodra@gmail.com> + + PR target/84300 + * gcc.dg/pr84300.c: New. + +2018-02-10 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/83987 + * g++.dg/ubsan/pr83987-2.C: New test. + +2018-02-09 Peter Bergner <bergner@vnet.ibm.com> + + PR target/83926 + * gcc.target/powerpc/pr83926.c: Filter out gimple folding disabled + message. + +2018-02-09 Will Schmidt <will_schmidt@vnet.ibm.com> + + * gcc.target/powerpc/vsx-vector-6-le.c: Update CPU target. + * gcc.target/powerpc/vsx-vector-6-le.p9.c: New. + +2018-02-09 Nathan Sidwell <nathan@acm.org> + + PR c/84293 + * c-c++-common/pr84293.h: New. + * c-c++-common/pr84293.c: New. + +2018-02-09 Vladimir Makarov <vmakarov@redhat.com> + + PR rtl-optimization/57193 + * gcc.target/i386/57193.c: New. + +2018-02-09 Jakub Jelinek <jakub@redhat.com> + + PR target/84226 + * gcc.target/powerpc/pr84226.c: New test. + +2018-02-09 Peter Bergner <bergner@vnet.ibm.com> + + * gcc.target/powerpc/builtins-1-be.c <vclzb>: Rename duplicate test + from this to... + <vclzd>: ...this. + +2018-02-09 Martin Sebor <msebor@redhat.com> + + PR lto/84212 + * gcc.dg/lto/pr84212_0.c: New test file. + * gcc.dg/lto/pr84212_1.c: Same. + +2018-02-09 Peter Bergner <bergner@vnet.ibm.com> + + PR target/83926 + * gcc.target/powerpc/pr83926.c: New test. + * gcc.target/powerpc/builtins-1-be.c: Filter out gimple folding disabled + message. Fix test for running in 32-bit mode. + +2018-02-09 Tamar Christina <tamar.christina@arm.com> + + PR target/82641 + * gcc.target/arm/pragma_arch_switch_2.c: Use armv6 and armv5t. + +2018-02-09 Andreas Krebbel <krebbel@linux.vnet.ibm.com> + + PR target/PR84295 + * gcc.target/s390/pr84295.c: New test. + +2018-02-09 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/77522 + * g++.dg/cpp1y/lambda-init16.C: New. + +2018-02-09 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/sso8.adb: New test. + * gnat.dg/sso8_pkg.ads: New helper. + +2018-02-09 Richard Biener <rguenther@suse.de> + + PR tree-optimization/84278 + * gcc.target/i386/pr84278.c: Adjust regex. + +2018-02-09 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/84232 + * gcc.dg/tree-ssa/ssa-dom-cse-2.c: Add -mtune-generic on x86. + + PR debug/84252 + * gcc.target/aarch64/pr84252.c: New test. + + PR middle-end/84237 + * gcc.dg/pr84237.c: New test. + +2018-02-09 Marek Polacek <polacek@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + PR c++/83659 + * g++.dg/torture/pr83659.C: New test. + +2018-02-08 David Malcolm <dmalcolm@redhat.com> + + PR tree-optimization/84136 + * gcc.c-torture/compile/pr84136.c: New test. + +2018-02-08 Sergey Shalnov <sergey.shalnov@intel.com> + + PR target/83008 + * gcc.target/i386/pr83008.c: New test. + +2018-02-08 Peter Bergner <bergner@vnet.ibm.com> + + PR target/81143 + * gcc.target/powerpc/pr79799-2.c: Use __LITTLE_ENDIAN__. + +2018-02-08 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/83806 + * g++.dg/warn/Wunused-parm-11.C: New. + +2018-02-08 Marek Polacek <polacek@redhat.com> + + PR tree-optimization/84238 + * gcc.dg/Wstringop-overflow-3.c: New test. + +2018-02-08 Nathan Sidwell <nathan@acm.org> + + * g++.dg/cpp0x/initlist93.C: Adjust diagnostic. + 2018-02-08 Richard Sandiford <richard.sandiford@linaro.org> PR tree-optimization/84265 diff --git a/gcc/testsuite/c-c++-common/pr84293.c b/gcc/testsuite/c-c++-common/pr84293.c new file mode 100644 index 0000000..dfcc859 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr84293.c @@ -0,0 +1,10 @@ +/* PR c/84293 unexpected warning from system header. */ +#include "./pr84293.h" +struct typeobject thing; + +#pragma GCC diagnostic warning "-Wstrict-aliasing" +void __attribute__ ((optimize (2))) init () +{ + INCREF_TDEF (&thing); + INCREF_STAG (&thing); +} diff --git a/gcc/testsuite/c-c++-common/pr84293.h b/gcc/testsuite/c-c++-common/pr84293.h new file mode 100644 index 0000000..c129896 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr84293.h @@ -0,0 +1,7 @@ +/* PR c/84293 unexpected warning from system header expansion. */ +#pragma GCC system_header +struct typeobject { unsigned refs; }; +typedef struct object { unsigned refs; } Object; + +#define INCREF_TDEF(op) (((Object*)(op))->refs++) +#define INCREF_STAG(op) (((struct object*)(op))->refs++) diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-62.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-62.C new file mode 100644 index 0000000..6f1fa45 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-62.C @@ -0,0 +1,22 @@ +// PR c++/81917 +// { dg-do compile { target c++11 } } + +template <typename> using a = void; +template <typename, typename = void> struct b +{ + typedef int c; +}; +template <typename d> class b<d, a<typename d::e>>; +template <typename d, typename = typename b<d>::c> class f; +template <typename> class g { }; +template <typename, typename> class h +{ + class i; + typedef g<f<i>> j; + class i + { + j k; // { dg-error "incomplete" } + }; +}; +h<int, int> H; + diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-template2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-template2.C index 40e3075..0df0d4e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist-template2.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-template2.C @@ -1,6 +1,5 @@ // PR c++/71747 // { dg-do compile { target c++11 } } -// { dg-options -ftemplate-depth=20 } template < bool > struct A { @@ -14,10 +13,8 @@ template < bool > struct A template < bool, typename = int > struct F; template < bool X > // should be: struct F < X, typename A < A < X > {} () >::type > -struct F < X, typename A < F < X > {} () >::type > // { dg-error "" } +struct F < X, typename A < F < X > {} () >::type > { }; -F < true > f; - -// { dg-prune-output "compilation terminated" } +F < true > f; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist93.C b/gcc/testsuite/g++.dg/cpp0x/initlist93.C index 84a4738..7a0b021 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist93.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist93.C @@ -3,7 +3,7 @@ namespace std { -template <class> class initializer_list // { dg-error "definition of std::initializer_list does not match" } +template <class> class initializer_list // { dg-error "definition of .*std::initializer_list.* does not match" } { int *_M_array; int _M_len; diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-init16.C b/gcc/testsuite/g++.dg/cpp1y/lambda-init16.C new file mode 100644 index 0000000..0a40ebb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-init16.C @@ -0,0 +1,13 @@ +// PR c++/77522 +// { dg-do compile { target c++14 } } + +template < class T = int > void f (T) +{ + auto g = [&a = f] () {}; // { dg-error "invalid initialization" } +} + +int main () +{ + f (0); + return 0; +} diff --git a/gcc/testsuite/g++.dg/template/crash125.C b/gcc/testsuite/g++.dg/template/crash125.C index 448f746..de41b99 100644 --- a/gcc/testsuite/g++.dg/template/crash125.C +++ b/gcc/testsuite/g++.dg/template/crash125.C @@ -13,6 +13,4 @@ struct TraitCheckImpl<Swappable<T> > { typedef void Complete; }; -Swappable<int> s; // { dg-error "depth" } - -// { dg-prune-output "compilation terminated" } +Swappable<int> s; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/template/pr51488.C b/gcc/testsuite/g++.dg/template/pr51488.C index 4979a22..794a6cf 100644 --- a/gcc/testsuite/g++.dg/template/pr51488.C +++ b/gcc/testsuite/g++.dg/template/pr51488.C @@ -2,6 +2,4 @@ template<class T,class U=void> struct s; template<class T> struct s<T,typename s<T>::a> {}; -s<int> ca; // { dg-error "depth" } - -// { dg-prune-output "compilation terminated" } +s<int> ca; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/template/pr55843.C b/gcc/testsuite/g++.dg/template/pr55843.C index 467dd82..04079ed 100644 --- a/gcc/testsuite/g++.dg/template/pr55843.C +++ b/gcc/testsuite/g++.dg/template/pr55843.C @@ -1,5 +1,3 @@ -// { dg-options "-ftemplate-depth-8" } - template< typename T > struct type_wrapper { }; typedef char (&yes_tag)[2]; @@ -7,11 +5,11 @@ template<bool b> struct if_c { }; template< typename T > struct has_type { struct gcc_3_2_wknd { - template< typename U > static yes_tag test( type_wrapper<U> const volatile* // { dg-message "required" } + template< typename U > static yes_tag test( type_wrapper<U> const volatile* // { dg-message "" } , type_wrapper<typename U::type>* = 0 ); }; typedef type_wrapper<T> t_; - static const bool value = sizeof(gcc_3_2_wknd::test(static_cast<t_*>(0))) == // { dg-message "required" } + static const bool value = sizeof(gcc_3_2_wknd::test(static_cast<t_*>(0))) == // { dg-message "" } sizeof(yes_tag); }; template <class K, class T, class=void> struct Get_type { @@ -22,7 +20,4 @@ template <class K> struct Get_type<K, RT_tag, typename if_c< !has_type<Get_type<K, FT_tag> >::value >::type> { }; // { dg-message "required" } template <class K> struct Get_type<K, FT_tag, typename if_c< !has_type<Get_type<K, RT_tag> >::value >::type> { }; // { dg-message "required" } -typedef Get_type<int, FT_tag>::type P; - -// { dg-prune-output "-ftemplate-depth" } -// { dg-prune-output "compilation terminated" } +typedef Get_type<int, FT_tag>::type P; // { dg-message "" } diff --git a/gcc/testsuite/g++.dg/template/scope5.C b/gcc/testsuite/g++.dg/template/scope5.C new file mode 100644 index 0000000..629225c --- /dev/null +++ b/gcc/testsuite/g++.dg/template/scope5.C @@ -0,0 +1,66 @@ +// PR c++/84296 + +namespace b {} +namespace c { +using namespace b; +} +namespace b { +template <int d> struct e { static const int f = d; }; +} +template <typename> struct g; +template <typename h, typename i, typename aa, typename j> +struct g<h(i, aa, j)> : h::template ab<i, aa, j> {}; +struct k { + template <typename l> struct m { typedef typename g<l>::n o; }; +}; +template <typename> struct ac; +struct r { + typedef ac<int> p; +}; +template <typename q> struct s : k { + template <typename i, typename, typename> + struct ab : q::template t<typename i::u>::template ab<i, int, int> {}; +}; +struct ad { + typedef int u; +}; +template <typename> struct ae; +template <typename, typename ag> struct ah { + typedef ae<ag> ai; + typedef typename ai::template w<ai(r, int)>::o n; +}; +struct x { + template <typename i, typename, typename> struct ab : ah<i, int> {}; +}; +struct y { + struct z { + template <typename> struct t : x {}; + }; + struct aj : s<z> {}; +}; +template <typename i> struct ak { + typedef y::aj al; + typedef typename al::m<al(i, int, int)>::o o; +}; +struct am { + enum { an }; +}; +template <typename> struct ao {}; +template <typename af> struct ap : af::aq {}; +template <> struct ae<int> { + template <typename> struct w; + template <typename ar, typename as, typename at> struct w<ar(as, at)> { + typedef typename as::p o; + }; +}; +enum { a = b::e<0>::f }; +template <typename> class au; +template <typename av> struct ac : ao<av> { typedef c::e<am::an> aq; }; +template <typename aw, typename i, typename ax> void ay(aw, i, ax) { + au<c::e<ap<typename ak<i>::o>::f> > az(); +} +void v() { + ad a; + void az(); + ay(az, a, v); +} diff --git a/gcc/testsuite/g++.dg/torture/pr83659.C b/gcc/testsuite/g++.dg/torture/pr83659.C new file mode 100644 index 0000000..bdcdca2 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr83659.C @@ -0,0 +1,18 @@ +// PR c++/83659 +// { dg-do compile } + +typedef int V __attribute__ ((__vector_size__ (16))); +V a; +V b[2]; + +int +foo () +{ + return reinterpret_cast <int *> (&a)[-1] += 1; +} + +int +bar () +{ + return reinterpret_cast <int *> (&a[1])[-1]; +} diff --git a/gcc/testsuite/g++.dg/ubsan/pr83987-2.C b/gcc/testsuite/g++.dg/ubsan/pr83987-2.C new file mode 100644 index 0000000..a70b7b2 --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/pr83987-2.C @@ -0,0 +1,24 @@ +// PR sanitizer/83987 +// { dg-do compile { target fopenmp } } +// { dg-options "-fopenmp -fsanitize=vptr" } + +struct A +{ + int i; +}; + +struct B : virtual A +{ + void foo(); +}; + +void B::foo() +{ +#pragma omp parallel + { + #pragma omp sections lastprivate (i) + { + i = 0; + } + } +} diff --git a/gcc/testsuite/g++.dg/warn/Wunused-parm-11.C b/gcc/testsuite/g++.dg/warn/Wunused-parm-11.C new file mode 100644 index 0000000..35896df --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wunused-parm-11.C @@ -0,0 +1,13 @@ +// PR c++/83806 +// { dg-do compile { target c++11 } } +// { dg-options "-Wunused-but-set-parameter" } + +template <class X, class Y> +bool equals(X x, Y y) { + return (x == y); +} + +int main() { + const char* p = nullptr; + equals(p, nullptr); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr84136.c b/gcc/testsuite/gcc.c-torture/compile/pr84136.c new file mode 100644 index 0000000..0a70e4e --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr84136.c @@ -0,0 +1,15 @@ +void* a; + +void foo() { + if ((a = &&l)) + return; + + l:; +} + +int main() { + foo(); + goto *a; + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-3.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-3.c new file mode 100644 index 0000000..5901844 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-3.c @@ -0,0 +1,13 @@ +/* PR tree-optimization/84238 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +char a[1]; +int b; +char *strncpy (char *, char *, __SIZE_TYPE__); +void +c () +{ + char d[b]; + strncpy (a, &d[3], 3); /* { dg-warning "writing 3 bytes into a region of size 1" } */ +} diff --git a/gcc/testsuite/gcc.dg/lto/pr84212_0.c b/gcc/testsuite/gcc.dg/lto/pr84212_0.c new file mode 100644 index 0000000..859b2fa --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/pr84212_0.c @@ -0,0 +1,11 @@ +/* PR lto/84212 - -Wno-stringop-verflow does not disable warnings from + -flto link stage + { dg-lto-do link } + { dg-lto-options { { -O2 -Werror -Wno-stringop-overflow -flto } } } */ + +#include <string.h> + +void clear (char *p, unsigned n) +{ + memset (p, 0, n); +} diff --git a/gcc/testsuite/gcc.dg/lto/pr84212_1.c b/gcc/testsuite/gcc.dg/lto/pr84212_1.c new file mode 100644 index 0000000..7ad8a7d --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/pr84212_1.c @@ -0,0 +1,11 @@ +/* PR lto/84212 - -Wno-stringop-verflow does not disable warnings from + -flto link stage */ + +extern void clear (char*, unsigned); + +int main (void) +{ + char x[3]; + + clear (x, 4); +} diff --git a/gcc/testsuite/gcc.dg/pr84237.c b/gcc/testsuite/gcc.dg/pr84237.c new file mode 100644 index 0000000..5a2697f --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr84237.c @@ -0,0 +1,5 @@ +/* PR middle-end/84237 */ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "" } */ + +const char __attribute__((__section__(".bss.page_aligned.const"), __aligned__(4096))) zero_page[4096]; diff --git a/gcc/testsuite/gcc.dg/pr84300.c b/gcc/testsuite/gcc.dg/pr84300.c new file mode 100644 index 0000000..6016799 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr84300.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target split_stack } */ +/* { dg-options "-g -O2 -fsplit-stack -fno-omit-frame-pointer" } */ + +void trap () { __builtin_trap (); } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c index 8606969..e4daa9d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c @@ -2,8 +2,10 @@ /* { dg-options "-O3 -fno-tree-fre -fno-tree-pre -fdump-tree-optimized --param sra-max-scalarization-size-Ospeed=32" } */ /* System Z needs hardware vector support for this to work (the optimization gets too complex without it. - { dg-additional-options "-march=z13" { target { s390x-*-* } } } */ - + { dg-additional-options "-march=z13" { target s390x-*-* } } */ +/* Use generic tuning on x86 for the same reasons as why alpha, powerpc etc. are + xfailed below. + { dg-additional-options "-mtune=generic" { target i?86-*-* x86_64-*-* } } */ int foo () diff --git a/gcc/testsuite/gcc.target/aarch64/pr84252.c b/gcc/testsuite/gcc.target/aarch64/pr84252.c new file mode 100644 index 0000000..fc66a26 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr84252.c @@ -0,0 +1,10 @@ +/* PR debug/84252 */ +/* { dg-do compile } */ +/* { dg-options "-g -O2" } */ + +struct S { __Int32x4_t b[2]; }; + +void +foo (struct S x) +{ +} diff --git a/gcc/testsuite/gcc.target/arm/pragma_arch_switch_2.c b/gcc/testsuite/gcc.target/arm/pragma_arch_switch_2.c index fe52191..7f29755 100644 --- a/gcc/testsuite/gcc.target/arm/pragma_arch_switch_2.c +++ b/gcc/testsuite/gcc.target/arm/pragma_arch_switch_2.c @@ -2,16 +2,16 @@ /* { dg-skip-if "instruction not valid on thumb" { *-*-* } { "-mthumb" } { "" } } */ /* { dg-do assemble } */ /* { dg-require-effective-target arm_arm_ok } */ -/* { dg-additional-options "-Wall -O2 -march=armv4t -std=gnu99 -marm" } */ +/* { dg-additional-options "-Wall -O2 -march=armv5t -std=gnu99 -marm" } */ -#pragma GCC target ("arch=armv5te") -void cpu_has_iwmmxt (void) +#pragma GCC target ("arch=armv6") +int test_assembly (int hi, int lo) { - int lo; - int hi; + int res; __asm__ __volatile__ ( - "mcrr p0, 0, %2, %3, c0\n" - : "=r" (lo), "=r" (hi) - : "r" (0), "r" (0x100)); + "uxtah %0, %1, %2\n" + : "=r" (res) + : "r" (hi), "r" (lo)); + return res; } diff --git a/gcc/testsuite/gcc.target/i386/pr57193.c b/gcc/testsuite/gcc.target/i386/pr57193.c new file mode 100644 index 0000000..70e2612 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr57193.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-times "movdqa" 2 } } */ + +#include <emmintrin.h> + +void test1(const __m128i* in1, const __m128i* in2, __m128i* out, + __m128i f, __m128i zero) +{ + __m128i c = _mm_avg_epu8(*in1, *in2); + __m128i l = _mm_unpacklo_epi8(c, zero); + __m128i h = _mm_unpackhi_epi8(c, zero); + __m128i m = _mm_mulhi_epu16(l, f); + __m128i n = _mm_mulhi_epu16(h, f); + *out = _mm_packus_epi16(m, n); +} diff --git a/gcc/testsuite/gcc.target/i386/pr83008.c b/gcc/testsuite/gcc.target/i386/pr83008.c new file mode 100644 index 0000000..87a4bea --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr83008.c @@ -0,0 +1,40 @@ +/* PR target/83008 */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -funroll-loops -march=skylake-avx512 -mfpmath=sse" } */ +/* { dg-final { scan-assembler-not "vmovdq(a|u)(32|64)" } } */ + +int +pr83008 (unsigned char *pix1, int i_pix1, unsigned char *pix2, int i_pix2) +{ + unsigned int tmp[4][4]; + unsigned int a0, a1, a2, a3; + int sum = 0; + for (int i = 0; i < 4; i++, pix1 += i_pix1, pix2 += i_pix2) + { + a0 = (pix1[0] - pix2[0]) + ((pix1[4] - pix2[4]) << 16); + a1 = (pix1[1] - pix2[1]) + ((pix1[5] - pix2[5]) << 16); + a2 = (pix1[2] - pix2[2]) + ((pix1[6] - pix2[6]) << 16); + a3 = (pix1[3] - pix2[3]) + ((pix1[7] - pix2[7]) << 16); + int t0 = a0 + a1; + int t1 = a0 - a1; + int t2 = a2 + a3; + int t3 = a2 - a3; + tmp[i][0] = t0 + t2; + tmp[i][2] = t0 - t2; + tmp[i][1] = t1 + t3; + tmp[i][3] = t1 - t3; + } + for (int i = 0; i < 4; i++) + { + int t0 = tmp[0][i] + tmp[1][i]; + int t1 = tmp[0][i] - tmp[1][i]; + int t2 = tmp[2][i] + tmp[3][i]; + int t3 = tmp[2][i] - tmp[3][i]; + a0 = t0 + t2; + a2 = t0 - t2; + a1 = t1 + t3; + a3 = t1 - t3; + sum += (a0) + (a1) + (a2) + (a3); + } + return (sum + ((unsigned int) sum >> 16)) >> 1; +} diff --git a/gcc/testsuite/gcc.target/i386/pr84278.c b/gcc/testsuite/gcc.target/i386/pr84278.c index 31e6288..d100dff 100644 --- a/gcc/testsuite/gcc.target/i386/pr84278.c +++ b/gcc/testsuite/gcc.target/i386/pr84278.c @@ -15,4 +15,4 @@ void foo(void) } } -/* { dg-final { scan-assembler-not "\(%.sp\)" } } */ +/* { dg-final { scan-assembler-not "\\\(%.sp\\\)" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-1-be.c b/gcc/testsuite/gcc.target/powerpc/builtins-1-be.c index aaaf79d..9de8baf 100644 --- a/gcc/testsuite/gcc.target/powerpc/builtins-1-be.c +++ b/gcc/testsuite/gcc.target/powerpc/builtins-1-be.c @@ -1,6 +1,7 @@ /* { dg-do compile { target { powerpc64-*-* } } } */ /* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */ -/* { dg-options "-mcpu=power8 -O0 -mno-fold-gimple" } */ +/* { dg-options "-mcpu=power8 -O0 -mno-fold-gimple -dp" } */ +/* { dg-prune-output "gimple folding of rs6000 builtins has been disabled." } */ /* Test that a number of newly added builtin overloads are accepted by the compiler. */ @@ -22,10 +23,10 @@ vec_ctf xvmuldp vec_cts xvcvdpsxds, vctsxs vec_ctu xvcvdpuxds, vctuxs - vec_div divd, divdu + vec_div divd, divdu | __divdi3(), __udivdi3() vec_mergel vmrghb, vmrghh, xxmrghw vec_mergeh xxmrglw, vmrglh - vec_mul mulld + vec_mul mulld | mullw, mulhwu vec_nor xxlnor vec_or xxlor vec_packsu vpksdus @@ -36,34 +37,39 @@ vec_rsqrt xvrsqrtesp vec_rsqrte xvrsqrtesp */ -/* { dg-final { scan-assembler-times "vcmpequd." 4 } } */ -/* { dg-final { scan-assembler-times "vcmpgtud." 8 } } */ -/* { dg-final { scan-assembler-times "xxland" 29 } } */ -/* { dg-final { scan-assembler-times "vclzb" 2 } } */ -/* { dg-final { scan-assembler-times "vclzb" 2 } } */ -/* { dg-final { scan-assembler-times "vclzw" 2 } } */ -/* { dg-final { scan-assembler-times "vclzh" 2 } } */ -/* { dg-final { scan-assembler-times "xvcpsgnsp" 1 } } */ -/* { dg-final { scan-assembler-times "xvmuldp" 6 } } */ -/* { dg-final { scan-assembler-times "xvcvdpsxds" 1 } } */ -/* { dg-final { scan-assembler-times "vctsxs" 1 } } */ -/* { dg-final { scan-assembler-times "xvcvdpuxds" 1 } } */ -/* { dg-final { scan-assembler-times "vctuxs" 1 } } */ -/* { dg-final { scan-assembler-times "divd" 4 } } */ -/* { dg-final { scan-assembler-times "divdu" 2 } } */ -/* { dg-final { scan-assembler-times "vmrghb" 0 } } */ -/* { dg-final { scan-assembler-times "vmrghh" 3 } } */ -/* { dg-final { scan-assembler-times "xxmrghw" 1 } } */ -/* { dg-final { scan-assembler-times "xxmrglw" 4 } } */ -/* { dg-final { scan-assembler-times "vmrglh" 4 } } */ -/* { dg-final { scan-assembler-times "mulld" 4 } } */ -/* { dg-final { scan-assembler-times "xxlnor" 19 } } */ -/* { dg-final { scan-assembler-times "xxlor" 14 } } */ -/* { dg-final { scan-assembler-times "vpksdus" 1 } } */ -/* { dg-final { scan-assembler-times "vperm" 2 } } */ -/* { dg-final { scan-assembler-times "xvrdpi" 1 } } */ -/* { dg-final { scan-assembler-times "xxsel" 6 } } */ -/* { dg-final { scan-assembler-times "xxlxor" 6 } } */ +/* { dg-final { scan-assembler-times {\mvcmpequd\M\.} 4 } } */ +/* { dg-final { scan-assembler-times {\mvcmpgtud\M\.} 8 } } */ +/* { dg-final { scan-assembler-times {\mxxland\M} 16 } } */ +/* { dg-final { scan-assembler-times {\mxxlandc\M} 13 } } */ +/* { dg-final { scan-assembler-times {\mvclzb\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mvclzd\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mvclzw\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mvclzh\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mxvcpsgnsp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvmuldp\M} 6 } } */ +/* { dg-final { scan-assembler-times {\mxvcvdpsxds\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvctsxs\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvcvdpuxds\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvctuxs\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvmrghb\M} 0 } } */ +/* { dg-final { scan-assembler-times {\mvmrghh\M} 3 } } */ +/* { dg-final { scan-assembler-times {\mxxmrghw\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxxmrglw\M} 4 } } */ +/* { dg-final { scan-assembler-times {\mvmrglh\M} 4 } } */ +/* { dg-final { scan-assembler-times {\mxxlnor\M} 6 } } */ +/* { dg-final { scan-assembler-times {(?n)\mxxlor\M.*\mboolv4si3_internal\M} 6 } } */ +/* { dg-final { scan-assembler-times {\mvpksdus\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvperm\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mxvrdpi\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxxsel\M} 6 } } */ +/* { dg-final { scan-assembler-times {\mxxlxor\M} 6 } } */ +/* { dg-final { scan-assembler-times {\mdivd\M} 2 { target lp64 } } } */ +/* { dg-final { scan-assembler-times {\mdivdu\M} 2 { target lp64 } } } */ +/* { dg-final { scan-assembler-times {\mmulld\M} 4 { target lp64 } } } */ +/* { dg-final { scan-assembler-times {\mbl __divdi3\M} 2 { target ilp32 } } } */ +/* { dg-final { scan-assembler-times {\mbl __udivdi3\M} 2 { target ilp32 } } } */ +/* { dg-final { scan-assembler-times {\mmullw\M} 12 { target ilp32 } } } */ +/* { dg-final { scan-assembler-times {\mmulhwu\M} 4 { target ilp32 } } } */ /* The source code for the test is in builtins-1.h. */ #include "builtins-1.h" diff --git a/gcc/testsuite/gcc.target/powerpc/pr79799-2.c b/gcc/testsuite/gcc.target/powerpc/pr79799-2.c index 793e3b9..b1a0b09 100644 --- a/gcc/testsuite/gcc.target/powerpc/pr79799-2.c +++ b/gcc/testsuite/gcc.target/powerpc/pr79799-2.c @@ -8,7 +8,7 @@ /* Optimize x = vec_insert (vec_extract (v2, N), v1, M) for SFmode if N is the default scalar position. */ -#if __ORDER_LITTLE_ENDIAN__ +#if __LITTLE_ENDIAN__ #define ELE 2 #else #define ELE 1 diff --git a/gcc/testsuite/gcc.target/powerpc/pr83926.c b/gcc/testsuite/gcc.target/powerpc/pr83926.c new file mode 100644 index 0000000..8accb2d --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr83926.c @@ -0,0 +1,23 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */ +/* { dg-options "-O2 -mcpu=power8 -mno-fold-gimple" } */ +/* { dg-prune-output "gimple folding of rs6000 builtins has been disabled." } */ + +__attribute__ ((altivec(vector__))) long long +sdiv (__attribute__ ((altivec(vector__))) long long a, + __attribute__ ((altivec(vector__))) long long b) +{ + return __builtin_vsx_div_2di (a, b); +} +__attribute__ ((altivec(vector__))) unsigned long long +udiv (__attribute__ ((altivec(vector__))) unsigned long long a, + __attribute__ ((altivec(vector__))) unsigned long long b) +{ + return __builtin_vsx_udiv_2di (a, b); +} +__attribute__ ((altivec(vector__))) long long +smul (__attribute__ ((altivec(vector__))) long long a, + __attribute__ ((altivec(vector__))) long long b) +{ + return __builtin_vsx_mul_2di (a, b); +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr84226.c b/gcc/testsuite/gcc.target/powerpc/pr84226.c new file mode 100644 index 0000000..aae922b --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr84226.c @@ -0,0 +1,6 @@ +/* PR target/84226 */ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mpower9-misc -O1" } */ + +#include "builtins-revb-runnable.c" diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-vector-6-le.c b/gcc/testsuite/gcc.target/powerpc/vsx-vector-6-le.c index ddb0089..c3f795c 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsx-vector-6-le.c +++ b/gcc/testsuite/gcc.target/powerpc/vsx-vector-6-le.c @@ -1,9 +1,10 @@ /* { dg-do compile { target { powerpc64le-*-* && lp64 } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } } */ /* { dg-require-effective-target powerpc_vsx_ok } */ -/* { dg-options "-mvsx -O2" } */ +/* { dg-options "-mvsx -O2 -mcpu=power8" } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */ -/* Expected instruction counts for Little Endian */ +/* Expected instruction counts for Little Endian targeting Power8. */ /* { dg-final { scan-assembler-times "xvabsdp" 1 } } */ /* { dg-final { scan-assembler-times "xvadddp" 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-vector-6-le.p9.c b/gcc/testsuite/gcc.target/powerpc/vsx-vector-6-le.p9.c new file mode 100644 index 0000000..290d4b4 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/vsx-vector-6-le.p9.c @@ -0,0 +1,33 @@ +/* { dg-do compile { target { powerpc64le-*-* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mvsx -O2 -mcpu=power9" } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */ + +/* Expected instruction counts for Little Endian targeting Power9. */ + +/* { dg-final { scan-assembler-times "xvabsdp" 1 } } */ +/* { dg-final { scan-assembler-times "xvadddp" 1 } } */ +/* { dg-final { scan-assembler-times "xxlnor" 7 } } */ +/* { dg-final { scan-assembler-times "xxlor" 20 } } */ +/* { dg-final { scan-assembler-times "xvcmpeqdp" 5 } } */ +/* { dg-final { scan-assembler-times "xvcmpgtdp" 8 } } */ +/* { dg-final { scan-assembler-times "xvcmpgedp" 8 } } */ +/* { dg-final { scan-assembler-times "xvrdpim" 1 } } */ +/* { dg-final { scan-assembler-times "xvmaddadp" 1 } } */ +/* { dg-final { scan-assembler-times "xvmsubadp" 1 } } */ +/* { dg-final { scan-assembler-times "xvsubdp" 1 } } */ +/* { dg-final { scan-assembler-times "xvmaxdp" 1 } } */ +/* { dg-final { scan-assembler-times "xvmindp" 1 } } */ +/* { dg-final { scan-assembler-times "xvmuldp" 1 } } */ +/* { dg-final { scan-assembler-times "vperm" 1 } } */ +/* { dg-final { scan-assembler-times "xvrdpic" 1 } } */ +/* { dg-final { scan-assembler-times "xvsqrtdp" 1 } } */ +/* { dg-final { scan-assembler-times "xvrdpiz" 1 } } */ +/* { dg-final { scan-assembler-times "xvmsubasp" 1 } } */ +/* { dg-final { scan-assembler-times "xvnmaddasp" 1 } } */ +/* { dg-final { scan-assembler-times "vmsumshs" 1 } } */ +/* { dg-final { scan-assembler-times "xxland" 13 } } */ + +/* Source code for the test in vsx-vector-6.h */ +#include "vsx-vector-6.h" diff --git a/gcc/testsuite/gcc.target/rx/mjsr.c b/gcc/testsuite/gcc.target/rx/mjsr.c new file mode 100644 index 0000000..c73a01b --- /dev/null +++ b/gcc/testsuite/gcc.target/rx/mjsr.c @@ -0,0 +1,134 @@ +/* { dg-do compile } */
+/* { dg-options "-O2 -mjsr" } */
+
+void *malloc (__SIZE_TYPE__);
+void *realloc (void *, __SIZE_TYPE__);
+
+struct A { double x, y; };
+struct B { double x0, y0, x1, y1; };
+struct C { int n_points; int dir; struct B bbox; struct A *points; };
+struct D { int n_segs; struct C segs[1]; };
+
+void foo (int, int, int *, int, int *, struct A **, int *, int *,
+ struct D *, int *, struct D **, int *, int **);
+int baz (struct A, struct A, struct A, struct A);
+
+static void
+bar (struct D *svp, int *n_points_max,
+ struct A p, int *seg_map, int *active_segs, int i)
+{
+ int asi, n_points;
+ struct C *seg;
+
+ asi = seg_map[active_segs[i]];
+ seg = &svp->segs[asi];
+ n_points = seg->n_points;
+ seg->points = ((struct A *)
+ realloc (seg->points, (n_points_max[asi] <<= 1) * sizeof (struct A)));
+ seg->points[n_points] = p;
+ seg->bbox.y1 = p.y;
+ seg->n_points++;
+}
+
+struct D *
+test (struct D *vp)
+{
+ int *active_segs, n_active_segs, *cursor, seg_idx;
+ double y, share_x;
+ int tmp1, tmp2, asi, i, j, *n_ips, *n_ips_max, n_segs_max;
+ struct A **ips, p_curs, *pts;
+ struct D *new_vp;
+ int *n_points_max, *seg_map, first_share;
+
+ n_segs_max = 16;
+ new_vp = (struct D *) malloc (sizeof (struct D) +
+ (n_segs_max - 1) * sizeof (struct C));
+ new_vp->n_segs = 0;
+
+ if (vp->n_segs == 0)
+ return new_vp;
+
+ active_segs = ((int *) malloc ((vp->n_segs) * sizeof (int)));
+ cursor = ((int *) malloc ((vp->n_segs) * sizeof (int)));
+
+ seg_map = ((int *) malloc ((vp->n_segs) * sizeof (int)));
+ n_ips = ((int *) malloc ((vp->n_segs) * sizeof (int)));
+ n_ips_max = ((int *) malloc ((vp->n_segs) * sizeof (int)));
+ ips = ((struct A * *) malloc ((vp->n_segs) * sizeof (struct A *)));
+
+ n_points_max = ((int *) malloc ((n_segs_max) * sizeof (int)));
+
+ n_active_segs = 0;
+ seg_idx = 0;
+ y = vp->segs[0].points[0].y;
+ while (seg_idx < vp->n_segs || n_active_segs > 0)
+ {
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ if (vp->segs[asi].n_points - 1 == cursor[asi] &&
+ vp->segs[asi].points[cursor[asi]].y == y)
+ i--;
+ }
+
+ while (seg_idx < vp->n_segs && y == vp->segs[seg_idx].points[0].y)
+ {
+ cursor[seg_idx] = 0;
+ n_ips[seg_idx] = 1;
+ n_ips_max[seg_idx] = 2;
+ ips[seg_idx] =
+ ((struct A *) malloc ((n_ips_max[seg_idx]) * sizeof (struct A)));
+ ips[seg_idx][0] = vp->segs[seg_idx].points[0];
+ pts = ((struct A *) malloc ((16) * sizeof (struct A)));
+ pts[0] = vp->segs[seg_idx].points[0];
+ tmp1 = seg_idx;
+ for (j = i; j < n_active_segs; j++)
+ {
+ tmp2 = active_segs[j];
+ active_segs[j] = tmp1;
+ tmp1 = tmp2;
+ }
+ active_segs[n_active_segs] = tmp1;
+ n_active_segs++;
+ seg_idx++;
+ }
+ first_share = -1;
+ share_x = 0;
+
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ p_curs = ips[asi][1];
+ if (p_curs.y == y)
+ {
+ bar (new_vp, n_points_max,
+ p_curs, seg_map, active_segs, i);
+
+ n_ips[asi]--;
+ for (j = 0; j < n_ips[asi]; j++)
+ ips[asi][j] = ips[asi][j + 1];
+
+ if (first_share < 0 || p_curs.x != share_x)
+ {
+ foo (first_share, i,
+ active_segs, n_active_segs,
+ cursor, ips, n_ips, n_ips_max, vp, seg_map,
+ &new_vp, &n_segs_max, &n_points_max);
+ first_share = i;
+ share_x = p_curs.x;
+ }
+ }
+ else
+ {
+ foo (first_share, i,
+ active_segs, n_active_segs,
+ cursor, ips, n_ips, n_ips_max, vp, seg_map,
+ &new_vp, &n_segs_max, &n_points_max);
+ first_share = -1;
+ }
+ }
+ }
+ return new_vp;
+}
+
+/* { dg-final { scan-assembler-not "bsr" } } */
diff --git a/gcc/testsuite/gcc.target/rx/movsicc.c b/gcc/testsuite/gcc.target/rx/movsicc.c new file mode 100644 index 0000000..d8e6bcc --- /dev/null +++ b/gcc/testsuite/gcc.target/rx/movsicc.c @@ -0,0 +1,94 @@ +/* { dg-do compile } */ +/* { dg-options "-Os" } */ + +typedef unsigned char u8; +typedef unsigned short u16; +signed int Xa, Xb; + +signed int stzreg_beq(int i, int a, int b) +{ + signed int x; + x = a; + if (i) + x = b; + return x; +} + +/* { dg-final { scan-assembler "bne 1f" } } */ + +signed int stzreg_bge(int i, int a, int b, int c) +{ + signed int x; + x = a; + if (i<c) + x = b; + return x; +} + +/* { dg-final { scan-assembler "blt 1f" } } */ + +signed int stzreg_bgt(int i, int a, int b) +{ + signed int x; + x = a; + if (i<10) + x = b; + return x; +} + +/* { dg-final { scan-assembler "ble 1f" } } */ + +signed int stzreg_ble(int i, int a, int b) +{ + signed int x; + x = a; + if (i>0) + x = b; + return x; +} + +/* { dg-final { scan-assembler "bgt 1f" } } */ + +signed int stzreg_blt(int i, int a, int b) +{ + signed int x; + x = a; + if (i<0) + x = b; + return x; +} + +/* { dg-final { scan-assembler "blt 1f" } } */ + +signed int stzreg_bne(int i, int a, int b) +{ + signed int x; + x = a; + if (!i) + x = b; + return x; +} + +/* { dg-final { scan-assembler "beq 1f" } } */ + +signed int stzimm_le( int i, int a ) +{ + signed int x; + x = a; + if (i>0) + x = 5; + return x; +} + +/* { dg-final { scan-assembler "ble 1f" } } */ + +signed int stzimm_le_r( int i, int a ) +{ + signed int x; + x = a; + if (i<0) + x = 5; + return x; +} + +/* { dg-final { scan-assembler "bge 1f" } } */ diff --git a/gcc/testsuite/gcc.target/s390/pr84295.c b/gcc/testsuite/gcc.target/s390/pr84295.c new file mode 100644 index 0000000..4da43c3 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/pr84295.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z900 -fgnu89-inline --save-temps -mfunction-return-reg=thunk -mindirect-branch-table" } */ + +extern void foo (void); +extern __inline void foo (void) {} +void foo (void) {} + +/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 1 } } */ +/* { dg-final { scan-assembler "ex\t" } } */ + +/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */ +/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */ +/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */ +/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */ diff --git a/gcc/testsuite/gfortran.dg/type_to_class_4.f03 b/gcc/testsuite/gfortran.dg/type_to_class_4.f03 new file mode 100644 index 0000000..196e448 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/type_to_class_4.f03 @@ -0,0 +1,35 @@ +! { dg-do run } +! +! Test the fix for PR56691 comment #7 (and comment #0). +! +! Reduced from the original of Marco Restelli <mrestelli@gmail.com> +! by Janus Weil <janus@gcc.gnu.org> +! +module m2 + implicit none + type :: t_stv + real :: f1 + end type +contains + subroutine lcb(y) + class(t_stv), intent(in) :: y(:) + integer :: k + do k=1,size(y) + if (int(y(k)%f1) .ne. k) call abort + enddo + end subroutine +end module + +program test + use m2 + implicit none + + type(t_stv), allocatable :: work(:) + + allocate(work(4)) + work(:)%f1 = (/ 1.,2.,3.,4./) + + call lcb(work) + call lcb(work(:4)) ! Indexing used to be offset by 1. + +end program diff --git a/gcc/testsuite/gnat.dg/sso8.adb b/gcc/testsuite/gnat.dg/sso8.adb new file mode 100644 index 0000000..003077c --- /dev/null +++ b/gcc/testsuite/gnat.dg/sso8.adb @@ -0,0 +1,15 @@ +-- { dg-do run } +-- { dg-options "-O" } + +with Interfaces; use Interfaces; +with SSO8_Pkg; use SSO8_Pkg; + +procedure SSO8 is + Data : Rec; +begin + Data.Array_Data (2) := True; + Val8 := Conv (Data); + if Val8 /= 32 then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/sso8_pkg.ads b/gcc/testsuite/gnat.dg/sso8_pkg.ads new file mode 100644 index 0000000..e9227e6 --- /dev/null +++ b/gcc/testsuite/gnat.dg/sso8_pkg.ads @@ -0,0 +1,32 @@ +with Interfaces; +with System; +with Unchecked_Conversion; + +package SSO8_Pkg is + + Val8 : Interfaces.Unsigned_8; + + type Two_Bit_Int is range 0 .. 3; + for Two_Bit_Int'size use 2; + + type Arr is array (1 .. 5) of Boolean; + for Arr'scalar_storage_order use System.High_Order_First; + pragma Pack (Arr); + + type Rec is record + Boolean_Data : Boolean; + Array_Data : Arr; + Two_Bit_Data : Two_Bit_Int; + end record; + for Rec use record + Boolean_Data at 0 range 0 .. 0; + Array_Data at 0 range 1 .. 5; + Two_Bit_Data at 0 range 6 .. 7; + end record; + for Rec'size use 8; + for Rec'bit_order use System.High_Order_First; + for Rec'scalar_storage_order use System.High_Order_First; + + function Conv is new Unchecked_Conversion (Rec, Interfaces.Unsigned_8); + +end SSO8_Pkg; diff --git a/gcc/toplev.c b/gcc/toplev.c index 35d7968..23db063 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1558,6 +1558,22 @@ process_options (void) || write_symbols == VMS_AND_DWARF2_DEBUG) && !(flag_selective_scheduling || flag_selective_scheduling2)); + if (debug_variable_location_views == AUTODETECT_VALUE) + { + debug_variable_location_views = flag_var_tracking + && debug_info_level >= DINFO_LEVEL_NORMAL + && (write_symbols == DWARF2_DEBUG + || write_symbols == VMS_AND_DWARF2_DEBUG) + && !dwarf_strict; + } + else if (debug_variable_location_views == -1 && dwarf_version != 5) + { + warning_at (UNKNOWN_LOCATION, 0, + "without -gdwarf-5, -gvariable-location-views=incompat5 " + "is equivalent to -gvariable-location-views"); + debug_variable_location_views = 1; + } + if (flag_tree_cselim == AUTODETECT_VALUE) { if (HAVE_conditional_move) diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index c5318b9..b87e48d 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -2379,10 +2379,14 @@ find_taken_edge_computed_goto (basic_block bb, tree val) dest = label_to_block (val); if (dest) - { - e = find_edge (bb, dest); - gcc_assert (e != NULL); - } + e = find_edge (bb, dest); + + /* It's possible for find_edge to return NULL here on invalid code + that abuses the labels-as-values extension (e.g. code that attempts to + jump *between* functions via stored labels-as-values; PR 84136). + If so, then we simply return that NULL for the edge. + We don't currently have a way of detecting such invalid code, so we + can't assert that it was the case when a NULL edge occurs here. */ return e; } diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index b0d9beb..7f9ec77 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -4605,6 +4605,13 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id) GSI_NEW_STMT); } initialize_inlined_parameters (id, stmt, fn, bb); + if (debug_nonbind_markers_p && id->block + && inlined_function_outer_scope_p (id->block)) + { + gimple_stmt_iterator si = gsi_last_bb (bb); + gsi_insert_after (&si, gimple_build_debug_inline_entry + (id->block, input_location), GSI_NEW_STMT); + } if (DECL_INITIAL (fn)) { diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index 08ac678..26da31f 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -520,6 +520,11 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block) else if (!BLOCK_SUPERCONTEXT (scope) || TREE_CODE (BLOCK_SUPERCONTEXT (scope)) == FUNCTION_DECL) unused = false; + /* Preserve the block, it is referenced by at least the inline + entry point marker. */ + else if (debug_nonbind_markers_p + && inlined_function_outer_scope_p (scope)) + unused = false; /* Innermost blocks with no live variables nor statements can be always eliminated. */ else if (!nsubblocks) @@ -548,11 +553,13 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block) } else if (BLOCK_VARS (scope) || BLOCK_NUM_NONLOCALIZED_VARS (scope)) unused = false; - /* See if this block is important for representation of inlined function. - Inlined functions are always represented by block with - block_ultimate_origin being set to FUNCTION_DECL and DECL_SOURCE_LOCATION - set... */ - else if (inlined_function_outer_scope_p (scope)) + /* See if this block is important for representation of inlined + function. Inlined functions are always represented by block + with block_ultimate_origin being set to FUNCTION_DECL and + DECL_SOURCE_LOCATION set, unless they expand to nothing... But + see above for the case of statement frontiers. */ + else if (!debug_nonbind_markers_p + && inlined_function_outer_scope_p (scope)) unused = false; else /* Verfify that only blocks with source location set @@ -640,6 +647,16 @@ dump_scope_block (FILE *file, int indent, tree scope, dump_flags_t flags) fprintf (file, "#%i", BLOCK_NUMBER (origin)); } } + if (BLOCK_FRAGMENT_ORIGIN (scope)) + fprintf (file, " Fragment of : #%i", + BLOCK_NUMBER (BLOCK_FRAGMENT_ORIGIN (scope))); + else if (BLOCK_FRAGMENT_CHAIN (scope)) + { + fprintf (file, " Fragment chain :"); + for (t = BLOCK_FRAGMENT_CHAIN (scope); t ; + t = BLOCK_FRAGMENT_CHAIN (t)) + fprintf (file, " #%i", BLOCK_NUMBER (t)); + } fprintf (file, " \n"); for (var = BLOCK_VARS (scope); var; var = DECL_CHAIN (var)) { diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index f0f6535..94ed2be 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -1899,7 +1899,10 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt) { tree range[2]; get_range_strlen (src, range); - if (range[0]) + if (range[0] != NULL_TREE + && TREE_CODE (range[0]) == INTEGER_CST + && range[1] != NULL_TREE + && TREE_CODE (range[1]) == INTEGER_CST) { lenrange[0] = wi::to_wide (range[0], prec); lenrange[1] = wi::to_wide (range[1], prec); diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index fbb63db..fb30ec2 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -9653,6 +9653,7 @@ vt_add_function_parameter (tree parm) poly_int64 offset; dataflow_set *out; decl_or_value dv; + bool incoming_ok = true; if (TREE_CODE (parm) != PARM_DECL) return; @@ -9743,6 +9744,7 @@ vt_add_function_parameter (tree parm) if (!vt_get_decl_and_offset (incoming, &decl, &offset)) { + incoming_ok = false; if (MEM_P (incoming)) { /* This means argument is passed by invisible reference. */ @@ -9861,6 +9863,10 @@ vt_add_function_parameter (tree parm) { int i; + /* The following code relies on vt_get_decl_and_offset returning true for + incoming, which might not be always the case. */ + if (!incoming_ok) + return; for (i = 0; i < XVECLEN (incoming, 0); i++) { rtx reg = XEXP (XVECEXP (incoming, 0, i), 0); @@ -9959,6 +9965,7 @@ reemit_marker_as_note (rtx_insn *insn) switch (kind) { case NOTE_INSN_BEGIN_STMT: + case NOTE_INSN_INLINE_ENTRY: { rtx_insn *note = NULL; if (cfun->debug_nonbind_markers) diff --git a/gcc/varasm.c b/gcc/varasm.c index b045efa..6e345d3 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -983,11 +983,11 @@ decode_reg_name (const char *name) /* Return true if DECL's initializer is suitable for a BSS section. */ bool -bss_initializer_p (const_tree decl) +bss_initializer_p (const_tree decl, bool named) { /* Do not put non-common constants into the .bss section, they belong in - a readonly section. */ - return ((!TREE_READONLY (decl) || DECL_COMMON (decl)) + a readonly section, except when NAMED is true. */ + return ((!TREE_READONLY (decl) || DECL_COMMON (decl) || named) && (DECL_INITIAL (decl) == NULL /* In LTO we have no errors in program; error_mark_node is used to mark offlined constructors. */ @@ -1165,7 +1165,8 @@ get_variable_section (tree decl, bool prefer_noswitch_p) { section *sect = get_named_section (decl, NULL, reloc); - if ((sect->common.flags & SECTION_BSS) && !bss_initializer_p (decl)) + if ((sect->common.flags & SECTION_BSS) + && !bss_initializer_p (decl, true)) { error_at (DECL_SOURCE_LOCATION (decl), "only zero initializers are allowed in section %qs", diff --git a/gotools/ChangeLog b/gotools/ChangeLog index 77bd206..ec09f94 100644 --- a/gotools/ChangeLog +++ b/gotools/ChangeLog @@ -1,3 +1,7 @@ +2018-02-09 Ian Lance Taylor <iant@golang.org> + + * Makefile.am (GOTOOLS_TEST_TIMEOUT): Double value. + 2018-02-08 Ian Lance Taylor <iant@golang.org> * Makefile.am (check-gccgo, check-gcc): Add options to pick up diff --git a/gotools/Makefile.am b/gotools/Makefile.am index d0d8850..2019497 100644 --- a/gotools/Makefile.am +++ b/gotools/Makefile.am @@ -162,7 +162,7 @@ uninstall-local: GOTESTFLAGS = # Number of seconds before tests time out. -GOTOOLS_TEST_TIMEOUT = 240 +GOTOOLS_TEST_TIMEOUT = 480 # Run tests using the go tool, and frob the output to look like that # generated by DejaGNU. The main output of this is two files: diff --git a/gotools/Makefile.in b/gotools/Makefile.in index dfef748..4d42d5e 100644 --- a/gotools/Makefile.in +++ b/gotools/Makefile.in @@ -348,7 +348,7 @@ MOSTLYCLEANFILES = \ @NATIVE_TRUE@GOTESTFLAGS = # Number of seconds before tests time out. -@NATIVE_TRUE@GOTOOLS_TEST_TIMEOUT = 240 +@NATIVE_TRUE@GOTOOLS_TEST_TIMEOUT = 480 # CHECK_ENV sets up the environment to run the newly built go tool. # If you change this, change ECHO_ENV, below. @@ -635,8 +635,8 @@ distclean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -@NATIVE_FALSE@install-exec-local: @NATIVE_FALSE@uninstall-local: +@NATIVE_FALSE@install-exec-local: clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \ diff --git a/include/ChangeLog b/include/ChangeLog index e36e227..73d6b64 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,12 @@ +2018-02-09 Alexandre Oliva <aoliva@redhat.com> + + * dwarf2.def (DW_AT_GNU_entry_view): New. + + * dwarf2.def (DW_AT_GNU_locviews): New. + * dwarf2.h (enum dwarf_location_list_entry_type): Add + DW_LLE_GNU_view_pair. + (DW_LLE_view_pair): Define. + 2018-01-03 Jakub Jelinek <jakub@redhat.com> Update copyright years. diff --git a/include/dwarf2.def b/include/dwarf2.def index f0ad0ca..3becd7f 100644 --- a/include/dwarf2.def +++ b/include/dwarf2.def @@ -443,6 +443,8 @@ DW_AT (DW_AT_GNU_pubtypes, 0x2135) /* Attribute for discriminator. See http://gcc.gnu.org/wiki/Discriminator */ DW_AT (DW_AT_GNU_discriminator, 0x2136) +DW_AT (DW_AT_GNU_locviews, 0x2137) +DW_AT (DW_AT_GNU_entry_view, 0x2138) /* VMS extensions. */ DW_AT (DW_AT_VMS_rtnbeg_pd_address, 0x2201) /* GNAT extensions. */ diff --git a/include/dwarf2.h b/include/dwarf2.h index 882e286..cf0039a 100644 --- a/include/dwarf2.h +++ b/include/dwarf2.h @@ -298,6 +298,14 @@ enum dwarf_location_list_entry_type DW_LLE_start_end = 0x07, DW_LLE_start_length = 0x08, + /* <http://lists.dwarfstd.org/private.cgi/dwarf-discuss-dwarfstd.org/2017-April/004347.html> + has the proposal for now; only available to list members. + + A (possibly updated) copy of the proposal is available at + <http://people.redhat.com/aoliva/papers/sfn/dwarf6-sfn-lvu.txt>. */ + DW_LLE_GNU_view_pair = 0x09, +#define DW_LLE_view_pair DW_LLE_GNU_view_pair + /* Former extension for Fission. See http://gcc.gnu.org/wiki/DebugFission. */ DW_LLE_GNU_end_of_list_entry = 0x00, |