@@ -120,6 +120,11 @@ enum debug_info_type write_symbols = NO_DEBUG
Variable
enum debug_info_levels debug_info_level = DINFO_LEVEL_NONE
+; Whether to generate line number table. Normally set at DINFO_LEVEL_NORMAL
+; or above; can also be set for DINFO_LEVEL_TERSE with -gmlt.
+Variable
+bool generate_debug_line_table = false
+
; Nonzero means use GNU-only extensions in the generated symbolic
; debugging information. Currently, this only has an effect when
; write_symbols is set to DBX_DEBUG, XCOFF_DEBUG, or DWARF_DEBUG.
@@ -2150,6 +2155,10 @@ ggdb
Common JoinedOrMissing
Generate debug information in default extended format
+gmlt
+Common RejectNegative
+Generate debug information at level 1 with minimal line table
+
gstabs
Common JoinedOrMissing Negative(gstabs+)
Generate debug information in STABS format
@@ -320,7 +320,7 @@ Objective-C and Objective-C++ Dialects}.
-fstack-usage -ftest-coverage -ftime-report -fvar-tracking @gol
-fvar-tracking-assignments -fvar-tracking-assignments-toggle @gol
-g -g@var{level} -gtoggle -gcoff -gdwarf-@var{version} @gol
--ggdb -gstabs -gstabs+ -gstrict-dwarf -gno-strict-dwarf @gol
+-ggdb -gmlt -gstabs -gstabs+ -gstrict-dwarf -gno-strict-dwarf @gol
-gvms -gxcoff -gxcoff+ @gol
-fno-merge-debug-strings -fno-dwarf2-cfi-asm @gol
-fdebug-prefix-map=@var{old}=@var{new} @gol
@@ -4679,6 +4679,11 @@ debug format is long obsolete, but the option cannot be changed now.
Instead use an additional @option{-g@var{level}} option to change the
debug level for DWARF.
+@item -gmlt
+@opindex gmlt
+Produce a minimal line table, with level 1 debugging information plus
+information about inlined functions and line numbers.
+
@item -gtoggle
@opindex gtoggle
Turn off generation of debug info, if leaving out this option would have
@@ -113,6 +113,10 @@ int vms_file_stats_name (const char *, long long *, long *, char *, int *);
#define DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET 0
#endif
+/* True if generating only the minimum line table (-gmlt). */
+#define GENERATE_MINIMUM_LINE_TABLE (debug_info_level == DINFO_LEVEL_TERSE \
+ && generate_debug_line_table)
+
/* ??? Poison these here until it can be done generically. They've been
totally replaced in this file; make sure it stays that way. */
#undef DWARF2_UNWIND_INFO
@@ -11639,7 +11643,7 @@ dwarf2_name (tree decl, int scope)
static void
add_pubname_string (const char *str, dw_die_ref die)
{
- if (targetm.want_debug_pub_sections)
+ if (!GENERATE_MINIMUM_LINE_TABLE && targetm.want_debug_pub_sections)
{
pubname_entry e;
@@ -11652,7 +11656,9 @@ add_pubname_string (const char *str, dw_die_ref die)
static void
add_pubname (tree decl, dw_die_ref die)
{
- if (targetm.want_debug_pub_sections && TREE_PUBLIC (decl))
+ if (!GENERATE_MINIMUM_LINE_TABLE
+ && targetm.want_debug_pub_sections
+ && TREE_PUBLIC (decl))
{
const char *name = dwarf2_name (decl, 1);
if (name)
@@ -17837,11 +17843,12 @@ add_src_coords_attributes (dw_die_ref die, tree decl)
static void
add_linkage_name (dw_die_ref die, tree decl)
{
- if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
- && TREE_PUBLIC (decl)
- && !DECL_ABSTRACT (decl)
- && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
- && die->die_tag != DW_TAG_member)
+ if (!GENERATE_MINIMUM_LINE_TABLE
+ && (TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
+ && TREE_PUBLIC (decl)
+ && !DECL_ABSTRACT (decl)
+ && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+ && die->die_tag != DW_TAG_member)
{
/* Defer until we have an assembler name set. */
if (!DECL_ASSEMBLER_NAME_SET_P (decl))
@@ -20911,14 +20918,18 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
declared directly within this block but not within any nested
sub-blocks. Also, nested function and tag DIEs have been
generated with a parent of NULL; fix that up now. */
- for (decl = BLOCK_VARS (stmt); decl != NULL; decl = DECL_CHAIN (decl))
- process_scope_var (stmt, decl, NULL_TREE, context_die);
- for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
- process_scope_var (stmt, NULL, BLOCK_NONLOCALIZED_VAR (stmt, i),
- context_die);
+ if (debug_info_level > DINFO_LEVEL_TERSE)
+ {
+ for (decl = BLOCK_VARS (stmt); decl != NULL; decl = DECL_CHAIN (decl))
+ process_scope_var (stmt, decl, NULL_TREE, context_die);
+ for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
+ process_scope_var (stmt, NULL, BLOCK_NONLOCALIZED_VAR (stmt, i),
+ context_die);
+ }
- /* If we're at -g1, we're not interested in subblocks. */
- if (debug_info_level <= DINFO_LEVEL_TERSE)
+ /* If we're at -g1 and not generating minimal line tables,
+ we're not interested in subblocks. */
+ if (!generate_debug_line_table && debug_info_level <= DINFO_LEVEL_TERSE)
return;
/* Output the DIEs to represent all sub-blocks (and the items declared
@@ -22189,7 +22200,7 @@ dwarf2out_source_line (unsigned int line, const char *filename,
unsigned int file_num;
dw_line_info_table *table;
- if (debug_info_level < DINFO_LEVEL_NORMAL || line == 0)
+ if (!generate_debug_line_table || line == 0)
return;
/* The discriminator column was added in dwarf4. Simplify the below
@@ -23719,7 +23730,7 @@ dwarf2out_finish (const char *filename)
}
}
- if (debug_info_level >= DINFO_LEVEL_NORMAL)
+ if (generate_debug_line_table)
add_AT_lineptr (comp_unit_die (), DW_AT_stmt_list,
debug_line_section_label);
@@ -23746,7 +23757,7 @@ dwarf2out_finish (const char *filename)
/* Add a pointer to the line table for the main compilation unit
so that the debugger can make sense of DW_AT_decl_file
attributes. */
- if (debug_info_level >= DINFO_LEVEL_NORMAL)
+ if (generate_debug_line_table)
add_AT_lineptr (ctnode->root_die, DW_AT_stmt_list,
debug_line_section_label);
@@ -609,6 +609,11 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
{
enum unwind_info_type ui_except;
+ /* If -gmlt was specified, make sure debug level is at least 1. */
+ if (opts->x_generate_debug_line_table
+ && opts->x_debug_info_level < DINFO_LEVEL_TERSE)
+ opts->x_debug_info_level = DINFO_LEVEL_TERSE;
+
if (opts->x_dump_base_name && ! IS_ABSOLUTE_PATH (opts->x_dump_base_name))
{
/* First try to make OPTS->X_DUMP_BASE_NAME relative to the
@@ -1649,6 +1654,16 @@ common_handle_option (struct gcc_options *opts,
loc);
break;
+ case OPT_gmlt:
+ set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, "", opts, opts_set,
+ loc);
+ /* Clear the debug level to NONE so that a subsequent bare -g will
+ set it to NORMAL (level 2). If no subsequent option sets the
+ level explicitly, we will set it to TERSE in finish_options(). */
+ opts->x_debug_info_level = DINFO_LEVEL_NONE;
+ opts->x_generate_debug_line_table = true;
+ break;
+
case OPT_gvms:
set_debug_level (VMS_DEBUG, false, arg, opts, opts_set, loc);
break;
@@ -1856,6 +1871,8 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg,
else
opts->x_debug_info_level = (enum debug_info_levels) argval;
}
+
+ generate_debug_line_table = debug_info_level >= DINFO_LEVEL_NORMAL;
}
/* Arrange to dump core on error for diagnostic context DC. (The
new file mode 100644
@@ -0,0 +1,32 @@
+/* Test that -gmlt includes line tables and inlined subroutine entries,
+ and excludes types and variables. */
+/* Origin: Cary Coutant <ccoutant@google.com> */
+/* { dg-do compile } */
+/* { dg-options "-O2 -gdwarf-2 -dA -gmlt" } */
+/* { dg-final { scan-assembler "DW_AT_stmt_list" } } */
+/* { dg-final { scan-assembler "DW_TAG_subprogram" } } */
+/* { dg-final { scan-assembler "DW_TAG_inlined_subroutine" } } */
+/* { dg-final { scan-assembler-not "DW_TAG_variable" } } */
+/* { dg-final { scan-assembler-not "DW_TAG_formal_parameter" } } */
+/* { dg-final { scan-assembler-not "DW_TAG_base_type" } } */
+
+static inline __attribute__((always_inline)) int
+a(int i, int j)
+{
+ return (i << 5) + j;
+}
+
+int
+b(int i, int j)
+{
+ return (i >> 5) + (j << 27);
+}
+
+int
+c(int i, int j)
+{
+ int r = a(i, j);
+ r = b(r, i);
+ r = b(r, j);
+ return r;
+}
new file mode 100644
@@ -0,0 +1,31 @@
+/* Test that -g overrides -gmlt. */
+/* Origin: Cary Coutant <ccoutant@google.com> */
+/* { dg-do compile } */
+/* { dg-options "-O2 -gdwarf-2 -dA -gmlt -g" } */
+/* { dg-final { scan-assembler "DW_AT_stmt_list" } } */
+/* { dg-final { scan-assembler "DW_TAG_subprogram" } } */
+/* { dg-final { scan-assembler "DW_TAG_inlined_subroutine" } } */
+/* { dg-final { scan-assembler "DW_TAG_variable" } } */
+/* { dg-final { scan-assembler "DW_TAG_formal_parameter" } } */
+/* { dg-final { scan-assembler "DW_TAG_base_type" } } */
+
+static inline __attribute__((always_inline)) int
+a(int i, int j)
+{
+ return (i << 5) + j;
+}
+
+int
+b(int i, int j)
+{
+ return (i >> 5) + (j << 27);
+}
+
+int
+c(int i, int j)
+{
+ int r = a(i, j);
+ r = b(r, i);
+ r = b(r, j);
+ return r;
+}
@@ -548,8 +548,9 @@ remove_unused_scope_block_p (tree scope)
else if (!nsubblocks)
;
/* For terse debug info we can eliminate info on unused variables. */
- else if (debug_info_level == DINFO_LEVEL_NONE
- || debug_info_level == DINFO_LEVEL_TERSE)
+ else if (!generate_debug_line_table
+ && (debug_info_level == DINFO_LEVEL_NONE
+ || debug_info_level == DINFO_LEVEL_TERSE))
{
/* Even for -g0/-g1 don't prune outer scopes from artificial
functions, otherwise diagnostics using tree_nonartificial_location