On Fri, Nov 10, 2017 at 3:34 AM, Alexandre Oliva <aol...@redhat.com> wrote: > This patch introduces an option to enable the generation of location > views along with location lists. The exact format depends on the > DWARF version: it can be a separate attribute (DW_AT_GNU_locviews) or > (DW_LLE_view_pair) entries in DWARF5+ loclists. > > Line number tables are also affected. If the assembler is found, at > compiler build time, to support .loc views, we use them and > assembler-computed view labels, otherwise we output compiler-generated > line number programs with conservatively-computed view labels. In > either case, we output view information next to line number changes > when verbose assembly output is requested. > > This patch requires an LVU patch that modifies the exported API of > final_scan_insn. It also expects the entire SFN patchset to be > installed first, although SFN is not a requirement for LVU.
What does final.c need langhooks for? Asking because needing langhooks at that point in time is bad (LTO, etc.). I'd appreciate a DWARF person reviewing the dwarf bits, some new static fns seem to lack their toplevel comment. The middle-end pieces are ok. Thanks, Richard. > for include/ChangeLog > > * 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. > > for gcc/ChangeLog > > * common.opt (gvariable-location-views): 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: Include langhooks.h. > (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. > * opts.c (common_handle_option): Accept -gdwarf version 6. > * toplev.c (process_options): Autodetect value for debug variable > location views option. > * doc/invoke.texi (gvariable-location-views): New. > (gno-variable-location-views): New. > --- > gcc/common.opt | 4 + > gcc/config.in | 6 + > gcc/configure | 46 ++++ > gcc/configure.ac | 18 +- > gcc/doc/invoke.texi | 19 ++ > gcc/dwarf2asm.c | 25 ++ > gcc/dwarf2asm.h | 4 + > gcc/dwarf2out.c | 646 > ++++++++++++++++++++++++++++++++++++++++++++++------ > gcc/dwarf2out.h | 4 +- > gcc/final.c | 149 +++++++++++- > gcc/opts.c | 2 +- > gcc/toplev.c | 8 + > include/dwarf2.def | 1 + > include/dwarf2.h | 8 + > 14 files changed, 858 insertions(+), 82 deletions(-) > > diff --git a/gcc/common.opt b/gcc/common.opt > index 421b4a2ce2a1..f37bafce3f48 100644 > --- a/gcc/common.opt > +++ b/gcc/common.opt > @@ -2948,6 +2948,10 @@ gtoggle > Common Driver Report Var(flag_gtoggle) > Toggle debug information generation. > > +gvariable-location-views > +Common Driver Var(debug_variable_location_views) Init(2) > +Augment variable location lists with progressive views. > + > gvms > Common Driver JoinedOrMissing Negative(gxcoff) > Generate debug information in VMS format. > diff --git a/gcc/config.in b/gcc/config.in > index 5651bcba431c..e4154f666f96 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/configure b/gcc/configure > index fb40ead92046..5992d8b75ffe 100755 > --- a/gcc/configure > +++ b/gcc/configure > @@ -27777,6 +27777,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 0e5167695a23..c6761832071f 100644 > --- a/gcc/configure.ac > +++ b/gcc/configure.ac > @@ -4862,9 +4862,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/doc/invoke.texi b/gcc/doc/invoke.texi > index 9509c95acf14..2d574ad3d496 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -347,6 +347,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 > @@ -7093,6 +7094,24 @@ 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 -gno-variable-location-views > +@opindex gvariable-location-views > +@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 @code{-fvar-tracking-assignments} is > +enabled and @code{-gstrict-dwarf} is not. > + > @item -gz@r{[}=@var{type}@r{]} > @opindex gz > Produce compressed debug sections in DWARF format, if that is supported. > diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c > index 8e3e86f224c1..f19e6d65020e 100644 > --- a/gcc/dwarf2asm.c > +++ b/gcc/dwarf2asm.c > @@ -768,6 +768,31 @@ dw2_asm_output_data_sleb128 (HOST_WIDE_INT value, > } > > 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, > const char *comment, ...) > diff --git a/gcc/dwarf2asm.h b/gcc/dwarf2asm.h > index 7fc87a0b0c94..d8370df0ac71 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 4f808b95519c..1d92a6eed5dd 100644 > --- a/gcc/dwarf2out.c > +++ b/gcc/dwarf2out.c > @@ -1276,6 +1276,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. */ > @@ -1285,9 +1287,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. */ > @@ -1324,6 +1328,31 @@ 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 > + && dwarf_version <= 5; > +} > + > +/* 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 > + && dwarf_version >= 6; > +#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. */ > @@ -1399,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: > @@ -2844,7 +2875,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 { > @@ -2866,6 +2905,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; > }; > > @@ -3067,6 +3125,41 @@ 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 is refers to a view identifier for which > + 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) > + > +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 > @@ -3176,6 +3269,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. */ > @@ -3384,6 +3478,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); > @@ -3420,7 +3516,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 *); > @@ -3620,8 +3716,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); > @@ -4617,11 +4713,55 @@ AT_loc_list (dw_attr_node *a) > return a->dw_attr_val.v.val_loc_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); > +} > + > 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 (); > + } > +} > + > +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> > @@ -5891,7 +6031,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; > @@ -5982,7 +6122,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. */ > @@ -5998,7 +6138,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 > { > @@ -6133,6 +6273,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; > @@ -8993,6 +9139,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); > @@ -9364,6 +9511,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) > @@ -9638,7 +9786,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> (); > @@ -9648,10 +9797,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. */ > > @@ -9660,6 +9827,99 @@ 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. */ > @@ -9667,34 +9927,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, > @@ -9712,6 +10023,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 > @@ -9762,6 +10074,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); > @@ -9776,6 +10089,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); > @@ -9791,6 +10105,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); > @@ -9869,6 +10184,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 > @@ -9933,6 +10251,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 > @@ -10158,6 +10492,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)) > { > @@ -10342,6 +10680,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. */ > > @@ -10358,7 +10718,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; > @@ -10570,7 +10930,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"); > @@ -10869,7 +11229,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, > @@ -10951,7 +11311,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, > @@ -11212,7 +11572,7 @@ output_rnglists (void) > 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 > @@ -11846,8 +12206,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) > { > @@ -11862,14 +12225,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) > { > @@ -11977,7 +12362,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"); > @@ -16343,6 +16728,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; > @@ -16398,24 +16784,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) > @@ -16438,12 +16827,12 @@ 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; > + endname = cfun->fde->dw_fde_second_end, endview = 0; > *listp = new_loc_list (descr, > - cfun->fde->dw_fde_second_begin, > - endname, secname); > + cfun->fde->dw_fde_second_begin, 0, > + endname, endview, secname); > listp = &(*listp)->dw_loc_next; > } > } > @@ -16455,8 +16844,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; > } > @@ -17276,7 +17664,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; > } > @@ -18089,7 +18477,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; > } > @@ -18413,12 +18801,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. */ > @@ -19600,7 +20001,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; > } > @@ -19616,7 +20017,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; > @@ -19638,14 +20039,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; > } > @@ -19654,19 +20055,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; > } > @@ -26029,7 +26429,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, > @@ -26223,11 +26623,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++; > @@ -26261,6 +26663,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; > } > > @@ -26324,10 +26738,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; > } > @@ -26368,8 +26783,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 > @@ -26437,7 +26852,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) > @@ -26446,6 +26864,7 @@ create_label: > last_postcall_label = ggc_strdup (loclabel); > } > newloc->label = last_postcall_label; > + newloc->view = view; > } > > if (var_loc_p && flag_debug_asm) > @@ -26512,6 +26931,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; > } > @@ -26560,7 +26980,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); > @@ -26741,7 +27161,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", > @@ -26764,6 +27184,33 @@ 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)) > + { > + if (!table->in_use) > + fputs (" view -0", asm_out_file); > + else > + fputs (" view 0", asm_out_file); > + bitmap_set_bit (zero_view_p, lvugid); > + table->view = ++lvugid; > + } > + else > + { > + 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; > + } > + } > putc ('\n', asm_out_file); > } > else > @@ -26772,7 +27219,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) > @@ -27447,9 +27906,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, > @@ -27828,6 +28288,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. > @@ -28927,6 +29392,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) > @@ -28971,7 +29438,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) > @@ -29041,6 +29508,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); > @@ -29066,6 +29534,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); > @@ -29462,6 +29945,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); > @@ -29683,6 +30168,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; > @@ -29701,6 +30187,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) > @@ -29711,11 +30199,33 @@ 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)); > } > > @@ -29740,7 +30250,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 > @@ -30164,7 +30674,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, > @@ -30223,7 +30733,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 940247316d39..a7653ceb6182 100644 > --- a/gcc/dwarf2out.h > +++ b/gcc/dwarf2out.h > @@ -157,7 +157,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. */ > @@ -200,6 +201,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 > diff --git a/gcc/final.c b/gcc/final.c > index b343063faa6d..c6a1d5b7e05a 100644 > --- a/gcc/final.c > +++ b/gcc/final.c > @@ -81,6 +81,7 @@ along with GCC; see the file COPYING3. If not see > #include "asan.h" > #include "rtl-iter.h" > #include "print-rtl.h" > +#include "langhooks.h" > > #ifdef XCOFF_DEBUGGING_INFO > #include "xcoffout.h" /* Needed for external data declarations. */ > @@ -110,6 +111,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; > @@ -1752,6 +1754,66 @@ 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; > +} > + > /* 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 > @@ -1759,12 +1821,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; > > @@ -1782,8 +1847,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); > @@ -1858,6 +1936,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) > { > @@ -1987,11 +2076,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; > @@ -2058,6 +2146,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); > @@ -2074,6 +2164,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) > @@ -2214,6 +2321,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 (dwarf2out_do_frame ()) > @@ -2353,6 +2462,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 > @@ -2409,7 +2520,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: > @@ -2420,6 +2534,7 @@ 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, > true); > + clear_next_view_needed (seen); > } > break; > > @@ -2615,6 +2730,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 > @@ -2627,7 +2746,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) > @@ -3094,7 +3218,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; > @@ -4525,8 +4650,10 @@ rest_of_handle_final (void) > variable_tracking_main (); > > 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 (); > diff --git a/gcc/opts.c b/gcc/opts.c > index ac383d48ec18..2abae2da47e5 100644 > --- a/gcc/opts.c > +++ b/gcc/opts.c > @@ -2364,7 +2364,7 @@ common_handle_option (struct gcc_options *opts, > > /* FALLTHRU */ > case OPT_gdwarf_: > - if (value < 2 || value > 5) > + if (value < 2 || value > 6) > error_at (loc, "dwarf version %d is not supported", value); > else > opts->x_dwarf_version = value; > diff --git a/gcc/toplev.c b/gcc/toplev.c > index 0b9f1f546279..55d6f21aaeb7 100644 > --- a/gcc/toplev.c > +++ b/gcc/toplev.c > @@ -1541,6 +1541,14 @@ process_options (void) > debug_nonbind_markers_p = optimize && debug_info_level >= > DINFO_LEVEL_NORMAL > && (write_symbols == DWARF2_DEBUG || write_symbols == > VMS_AND_DWARF2_DEBUG); > > + 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; > + } > + > if (flag_tree_cselim == AUTODETECT_VALUE) > { > if (HAVE_conditional_move) > diff --git a/include/dwarf2.def b/include/dwarf2.def > index 2a3b23fef873..f3fa4009207b 100644 > --- a/include/dwarf2.def > +++ b/include/dwarf2.def > @@ -443,6 +443,7 @@ 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) > /* VMS extensions. */ > DW_AT (DW_AT_VMS_rtnbeg_pd_address, 0x2201) > /* GNAT extensions. */ > diff --git a/include/dwarf2.h b/include/dwarf2.h > index a2e022dbdb35..fd76d82e6eb7 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, > -- > 2.13.6 >