dwarf2out.c (dw_separate_line_info_ref): Remove.

* dwarf2out.c (dw_separate_line_info_ref): Remove.
        (dw_separate_line_info_entry): Remove.
        (enum dw_line_info_opcode): New.
        (dw_line_info_entry): Use it.
        (dw_line_info_table, dw_line_info_table_p): New.
        (DWARF_LINE_OPCODE_BASE): Include dwarf3 opcodes.
        (line_info_table, line_info_label_num): Remove.
        (line_info_table_in_use): Remove.
        (separate_line_info_table): Remove.
        (separate_line_info_table_allocated): Remove.
        (separate_line_info_table_in_use): Remove.
        (LINE_INFO_TABLE_INCREMENT): Remove.
        (line_info_label_num): New.
        (cur_line_info_table): New.
        (text_section_line_info, cold_text_section_line_info): New.
        (separate_line_info): New.
        (SEPARATE_LINE_CODE_LABEL): Remove.
        (print_dwarf_line_table): Remove.
        (debug_dwarf): Don't dump it.
        (output_one_line_info_table): New.
        (output_line_info): Use it.
        (new_line_info_table): New.
        (set_cur_line_info_table): New.
        (dwarf2out_switch_text_section): Use it.
        (dwarf2out_begin_function): Likewise.
        (push_dw_line_info_entry): New.
        (dwarf2out_source_line): Rewrite for new line info tables.
        (dwarf2out_init): Remove dead initailizations.

From-SVN: r171816
This commit is contained in:
Richard Henderson 2011-03-31 19:41:12 -07:00 committed by Richard Henderson
parent 6979fa58f8
commit 576f85f168
2 changed files with 375 additions and 405 deletions

View File

@ -1,3 +1,34 @@
2011-03-31 Richard Henderson <rth@redhat.com>
* dwarf2out.c (dw_separate_line_info_ref): Remove.
(dw_separate_line_info_entry): Remove.
(enum dw_line_info_opcode): New.
(dw_line_info_entry): Use it.
(dw_line_info_table, dw_line_info_table_p): New.
(DWARF_LINE_OPCODE_BASE): Include dwarf3 opcodes.
(line_info_table, line_info_label_num): Remove.
(line_info_table_in_use): Remove.
(separate_line_info_table): Remove.
(separate_line_info_table_allocated): Remove.
(separate_line_info_table_in_use): Remove.
(LINE_INFO_TABLE_INCREMENT): Remove.
(line_info_label_num): New.
(cur_line_info_table): New.
(text_section_line_info, cold_text_section_line_info): New.
(separate_line_info): New.
(SEPARATE_LINE_CODE_LABEL): Remove.
(print_dwarf_line_table): Remove.
(debug_dwarf): Don't dump it.
(output_one_line_info_table): New.
(output_line_info): Use it.
(new_line_info_table): New.
(set_cur_line_info_table): New.
(dwarf2out_switch_text_section): Use it.
(dwarf2out_begin_function): Likewise.
(push_dw_line_info_entry): New.
(dwarf2out_source_line): Rewrite for new line info tables.
(dwarf2out_init): Remove dead initailizations.
2011-03-31 Joseph Myers <joseph@codesourcery.com>
* opts.h (cl_option): Add comments to fields. Add bit-fields for

View File

@ -4242,6 +4242,7 @@ dwarf2out_note_section_used (void)
}
static void var_location_switch_text_section (void);
static void set_cur_line_info_table (section *);
void
dwarf2out_switch_text_section (void)
@ -4298,6 +4299,8 @@ dwarf2out_switch_text_section (void)
cfi = cfi->dw_cfi_next;
fde->dw_fde_switch_cfi = cfi;
var_location_switch_text_section ();
set_cur_line_info_table (sect);
}
/* And now, the subset of the debugging information support code necessary
@ -5819,31 +5822,70 @@ typedef long int dw_offset;
typedef struct dw_attr_struct *dw_attr_ref;
typedef struct dw_line_info_struct *dw_line_info_ref;
typedef struct dw_separate_line_info_struct *dw_separate_line_info_ref;
typedef struct pubname_struct *pubname_ref;
typedef struct dw_ranges_struct *dw_ranges_ref;
typedef struct dw_ranges_by_label_struct *dw_ranges_by_label_ref;
typedef struct comdat_type_struct *comdat_type_node_ref;
/* Each entry in the line_info_table maintains the file and
line number associated with the label generated for that
entry. The label gives the PC value associated with
the line number entry. */
/* The entries in the line_info table more-or-less mirror the opcodes
that are used in the real dwarf line table. Arrays of these entries
are collected per section when DWARF2_ASM_LINE_DEBUG_INFO is not
supported. */
enum dw_line_info_opcode {
/* Emit DW_LNE_set_address; the operand is the label index. */
LI_set_address,
/* Emit a row to the matrix with the given line. This may be done
via any combination of DW_LNS_copy, DW_LNS_advance_line, and
special opcodes. */
LI_set_line,
/* Emit a DW_LNS_set_file. */
LI_set_file,
/* Emit a DW_LNS_set_column. */
LI_set_column,
/* Emit a DW_LNS_negate_stmt; the operand is ignored. */
LI_negate_stmt,
/* Emit a DW_LNS_set_prologue_end/epilogue_begin; the operand is ignored. */
LI_set_prologue_end,
LI_set_epilogue_begin,
/* Emit a DW_LNE_set_discriminator. */
LI_set_discriminator
};
typedef struct GTY(()) dw_line_info_struct {
unsigned long dw_file_num;
unsigned long dw_line_num;
}
dw_line_info_entry;
enum dw_line_info_opcode opcode;
unsigned int val;
} dw_line_info_entry;
/* Line information for functions in separate sections; each one gets its
own sequence. */
typedef struct GTY(()) dw_separate_line_info_struct {
unsigned long dw_file_num;
unsigned long dw_line_num;
unsigned long function;
}
dw_separate_line_info_entry;
DEF_VEC_O(dw_line_info_entry);
DEF_VEC_ALLOC_O(dw_line_info_entry, gc);
typedef struct GTY(()) dw_line_info_table_struct {
/* The label that marks the end of this section. */
const char *end_label;
/* The values for the last row of the matrix, as collected in the table.
These are used to minimize the changes to the next row. */
unsigned int file_num;
unsigned int line_num;
unsigned int column_num;
int discrim_num;
bool is_stmt;
bool in_use;
VEC(dw_line_info_entry, gc) *entries;
} dw_line_info_table;
typedef dw_line_info_table *dw_line_info_table_p;
DEF_VEC_P(dw_line_info_table_p);
DEF_VEC_ALLOC_P(dw_line_info_table_p, gc);
/* Each DIE attribute has a field specifying the attribute kind,
a link to the next attribute in the chain, and an attribute value.
@ -6021,7 +6063,7 @@ skeleton_chain_node;
#define DWARF_LINE_BASE -10
/* First special line opcode - leave room for the standard opcodes. */
#define DWARF_LINE_OPCODE_BASE 10
#define DWARF_LINE_OPCODE_BASE ((int)DW_LNS_set_isa + 1)
/* Range of line offsets in a special line info. opcode. */
#define DWARF_LINE_RANGE (254-DWARF_LINE_OPCODE_BASE+1)
@ -6166,31 +6208,20 @@ static GTY(()) unsigned abbrev_die_table_in_use;
abbrev_die_table. */
#define ABBREV_DIE_TABLE_INCREMENT 256
/* A pointer to the base of a table that contains line information
for each source code line in .text in the compilation unit. */
static GTY((length ("line_info_table_allocated")))
dw_line_info_ref line_info_table;
/* A global counter for generating labels for line number data. */
static unsigned int line_info_label_num;
/* Number of elements currently allocated for line_info_table. */
static GTY(()) unsigned line_info_table_allocated;
/* The current table to which we should emit line number information
for the current function. This will be set up at the beginning of
assembly for the function. */
static dw_line_info_table *cur_line_info_table;
/* Number of elements in line_info_table currently in use. */
static GTY(()) unsigned line_info_table_in_use;
/* The two default tables of line number info. */
static GTY(()) dw_line_info_table *text_section_line_info;
static GTY(()) dw_line_info_table *cold_text_section_line_info;
/* A pointer to the base of a table that contains line information
for each source code line outside of .text in the compilation unit. */
static GTY ((length ("separate_line_info_table_allocated")))
dw_separate_line_info_ref separate_line_info_table;
/* Number of elements currently allocated for separate_line_info_table. */
static GTY(()) unsigned separate_line_info_table_allocated;
/* Number of elements in separate_line_info_table currently in use. */
static GTY(()) unsigned separate_line_info_table_in_use;
/* Size (in elements) of increments by which we may expand the
line_info_table. */
#define LINE_INFO_TABLE_INCREMENT 1024
/* The set of all non-default tables of line number info. */
static GTY(()) VEC (dw_line_info_table_p, gc) *separate_line_info;
/* A flag to tell pubnames/types export if there is an info section to
refer to. */
@ -6343,7 +6374,6 @@ 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 void print_spaces (FILE *);
static void print_die (dw_die_ref, FILE *);
static void print_dwarf_line_table (FILE *);
static dw_die_ref push_new_compile_unit (dw_die_ref, dw_die_ref);
static dw_die_ref pop_compile_unit (dw_die_ref);
static void loc_checksum (dw_loc_descr_ref, struct md5_ctx *);
@ -6421,6 +6451,7 @@ static unsigned int add_ranges (const_tree);
static void add_ranges_by_labels (dw_die_ref, const char *, const char *,
bool *);
static void output_ranges (void);
static dw_line_info_table *new_line_info_table (void);
static void output_line_info (void);
static void output_file_names (void);
static dw_die_ref base_type_die (tree);
@ -6662,9 +6693,6 @@ static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
#ifndef LINE_CODE_LABEL
#define LINE_CODE_LABEL "LM"
#endif
#ifndef SEPARATE_LINE_CODE_LABEL
#define SEPARATE_LINE_CODE_LABEL "LSM"
#endif
/* Return the root of the DIE's built for the current compilation unit. */
@ -8682,27 +8710,6 @@ print_die (dw_die_ref die, FILE *outfile)
fprintf (outfile, "\n");
}
/* Print the contents of the source code line number correspondence table.
This routine is a debugging aid only. */
static void
print_dwarf_line_table (FILE *outfile)
{
unsigned i;
dw_line_info_ref line_info;
fprintf (outfile, "\n\nDWARF source line information\n");
for (i = 1; i < line_info_table_in_use; i++)
{
line_info = &line_info_table[i];
fprintf (outfile, "%5d: %4ld %6ld\n", i,
line_info->dw_file_num,
line_info->dw_line_num);
}
fprintf (outfile, "\n\n");
}
/* Print the information collected for a given DIE. */
DEBUG_FUNCTION void
@ -8719,8 +8726,6 @@ debug_dwarf (void)
{
print_indent = 0;
print_die (comp_unit_die (), stderr);
if (! DWARF2_ASM_LINE_DEBUG_INFO)
print_dwarf_line_table (stderr);
}
/* Start a new compilation unit DIE for an include file. OLD_UNIT is the CU
@ -12289,6 +12294,117 @@ output_file_names (void)
}
/* Output one line number table into the .debug_line section. */
static void
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;
size_t i;
FOR_EACH_VEC_ELT (dw_line_info_entry, table->entries, i, ent)
{
switch (ent->opcode)
{
case LI_set_address:
/* ??? Unfortunately, we have little choice here currently, and
must always use the most general form. GCC does not know the
address delta itself, so we can't use DW_LNS_advance_pc. Many
ports do have length attributes which will give an upper bound
on the address range. We could perhaps use length attributes
to determine when it is safe to use DW_LNS_fixed_advance_pc. */
ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, ent->val);
/* 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_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);
break;
case LI_set_line:
if (ent->val == current_line)
{
/* We still need to start a new row, so output a copy insn. */
dw2_asm_output_data (1, DW_LNS_copy,
"copy line %u", current_line);
}
else
{
int line_offset = ent->val - current_line;
int line_delta = line_offset - DWARF_LINE_BASE;
current_line = ent->val;
if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
{
/* This can handle deltas from -10 to 234, using the current
definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE.
This takes 1 byte. */
dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta,
"line %u", current_line);
}
else
{
/* This can handle any delta. This takes at least 4 bytes,
depending on the value being encoded. */
dw2_asm_output_data (1, DW_LNS_advance_line,
"advance to line %u", current_line);
dw2_asm_output_data_sleb128 (line_offset, NULL);
dw2_asm_output_data (1, DW_LNS_copy, NULL);
}
}
break;
case LI_set_file:
dw2_asm_output_data (1, DW_LNS_set_file, "set file %u", ent->val);
dw2_asm_output_data_uleb128 (ent->val, "%u", ent->val);
break;
case LI_set_column:
dw2_asm_output_data (1, DW_LNS_set_column, "column %u", ent->val);
dw2_asm_output_data_uleb128 (ent->val, "%u", ent->val);
break;
case LI_negate_stmt:
current_is_stmt = !current_is_stmt;
dw2_asm_output_data (1, DW_LNS_negate_stmt,
"is_stmt %d", current_is_stmt);
break;
case LI_set_prologue_end:
dw2_asm_output_data (1, DW_LNS_set_prologue_end,
"set prologue end");
break;
case LI_set_epilogue_begin:
dw2_asm_output_data (1, DW_LNS_set_epilogue_begin,
"set epilogue begin");
break;
case LI_set_discriminator:
dw2_asm_output_data (1, 0, "discriminator %u", ent->val);
dw2_asm_output_data_uleb128 (1 + size_of_uleb128 (ent->val), NULL);
dw2_asm_output_data (1, DW_LNE_set_discriminator, NULL);
dw2_asm_output_data_uleb128 (ent->val, NULL);
break;
}
}
/* Emit debug info for the address of the end of the table. */
dw2_asm_output_data (1, 0, "set address %s", table->end_label);
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, table->end_label, NULL);
dw2_asm_output_data (1, 0, "end sequence");
dw2_asm_output_data_uleb128 (1, NULL);
dw2_asm_output_data (1, DW_LNE_end_sequence, NULL);
}
/* Output the source line number correspondence information. This
information goes into the .debug_line section. */
@ -12296,17 +12412,8 @@ static void
output_line_info (void)
{
char l1[20], l2[20], p1[20], p2[20];
char line_label[MAX_ARTIFICIAL_LABEL_BYTES];
char prev_line_label[MAX_ARTIFICIAL_LABEL_BYTES];
unsigned opc;
unsigned n_op_args;
unsigned long lt_index;
unsigned long current_line;
long line_offset;
long line_delta;
unsigned long current_file;
unsigned long function;
int ver = dwarf_version;
int opc;
ASM_GENERATE_INTERNAL_LABEL (l1, LINE_NUMBER_BEGIN_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (l2, LINE_NUMBER_END_LABEL, 0);
@ -12324,16 +12431,15 @@ output_line_info (void)
dw2_asm_output_delta (DWARF_OFFSET_SIZE, p2, p1, "Prolog Length");
ASM_OUTPUT_LABEL (asm_out_file, p1);
/* Define the architecture-dependent minimum instruction length (in
bytes). In this implementation of DWARF, this field is used for
information purposes only. Since GCC generates assembly language,
we have no a priori knowledge of how many instruction bytes are
generated for each source line, and therefore can use only the
DW_LNE_set_address and DW_LNS_fixed_advance_pc line information
commands. Accordingly, we fix this as `1', which is "correct
enough" for all architectures, and don't let the target override. */
dw2_asm_output_data (1, 1,
"Minimum Instruction Length");
/* Define the architecture-dependent minimum instruction length (in bytes).
In this implementation of DWARF, this field is used for information
purposes only. Since GCC generates assembly language, we have no
a priori knowledge of how many instruction bytes are generated for each
source line, and therefore can use only the DW_LNE_set_address and
DW_LNS_fixed_advance_pc line information commands. Accordingly, we fix
this as '1', which is "correct enough" for all architectures,
and don't let the target override. */
dw2_asm_output_data (1, 1, "Minimum Instruction Length");
if (ver >= 4)
dw2_asm_output_data (1, DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN,
@ -12349,6 +12455,7 @@ output_line_info (void)
for (opc = 1; opc < DWARF_LINE_OPCODE_BASE; opc++)
{
int n_op_args;
switch (opc)
{
case DW_LNS_advance_pc:
@ -12356,6 +12463,7 @@ output_line_info (void)
case DW_LNS_set_file:
case DW_LNS_set_column:
case DW_LNS_fixed_advance_pc:
case DW_LNS_set_isa:
n_op_args = 1;
break;
default:
@ -12371,236 +12479,19 @@ output_line_info (void)
output_file_names ();
ASM_OUTPUT_LABEL (asm_out_file, p2);
/* We used to set the address register to the first location in the text
section here, but that didn't accomplish anything since we already
have a line note for the opening brace of the first function. */
if (text_section_line_info && text_section_line_info->in_use)
output_one_line_info_table (text_section_line_info);
if (cold_text_section_line_info && cold_text_section_line_info->in_use)
output_one_line_info_table (cold_text_section_line_info);
/* Generate the line number to PC correspondence table, encoded as
a series of state machine operations. */
current_file = 1;
current_line = 1;
if (cfun && in_cold_section_p)
strcpy (prev_line_label, crtl->subsections.cold_section_label);
else
strcpy (prev_line_label, text_section_label);
for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
if (separate_line_info)
{
dw_line_info_ref line_info = &line_info_table[lt_index];
dw_line_info_table *table;
size_t i;
#if 0
/* Disable this optimization for now; GDB wants to see two line notes
at the beginning of a function so it can find the end of the
prologue. */
/* Don't emit anything for redundant notes. Just updating the
address doesn't accomplish anything, because we already assume
that anything after the last address is this line. */
if (line_info->dw_line_num == current_line
&& line_info->dw_file_num == current_file)
continue;
#endif
/* Emit debug info for the address of the current line.
Unfortunately, we have little choice here currently, and must always
use the most general form. GCC does not know the address delta
itself, so we can't use DW_LNS_advance_pc. Many ports do have length
attributes which will give an upper bound on the address range. We
could perhaps use length attributes to determine when it is safe to
use DW_LNS_fixed_advance_pc. */
ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, lt_index);
if (0)
{
/* This can handle deltas up to 0xffff. This takes 3 bytes. */
dw2_asm_output_data (1, DW_LNS_fixed_advance_pc,
"DW_LNS_fixed_advance_pc");
dw2_asm_output_delta (2, line_label, prev_line_label, NULL);
}
else
{
/* This can handle any delta. This takes
4+DWARF2_ADDR_SIZE bytes. */
dw2_asm_output_data (1, 0, "DW_LNE_set_address");
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);
}
strcpy (prev_line_label, line_label);
/* Emit debug info for the source file of the current line, if
different from the previous line. */
if (line_info->dw_file_num != current_file)
{
current_file = line_info->dw_file_num;
dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file");
dw2_asm_output_data_uleb128 (current_file, "%lu", current_file);
}
/* Emit debug info for the current line number, choosing the encoding
that uses the least amount of space. */
if (line_info->dw_line_num != current_line)
{
line_offset = line_info->dw_line_num - current_line;
line_delta = line_offset - DWARF_LINE_BASE;
current_line = line_info->dw_line_num;
if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
/* This can handle deltas from -10 to 234, using the current
definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE. This
takes 1 byte. */
dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta,
"line %lu", current_line);
else
{
/* This can handle any delta. This takes at least 4 bytes,
depending on the value being encoded. */
dw2_asm_output_data (1, DW_LNS_advance_line,
"advance to line %lu", current_line);
dw2_asm_output_data_sleb128 (line_offset, NULL);
dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy");
}
}
else
/* We still need to start a new row, so output a copy insn. */
dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy");
}
/* Emit debug info for the address of the end of the function. */
if (0)
{
dw2_asm_output_data (1, DW_LNS_fixed_advance_pc,
"DW_LNS_fixed_advance_pc");
dw2_asm_output_delta (2, text_end_label, prev_line_label, NULL);
}
else
{
dw2_asm_output_data (1, 0, "DW_LNE_set_address");
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, text_end_label, NULL);
}
dw2_asm_output_data (1, 0, "DW_LNE_end_sequence");
dw2_asm_output_data_uleb128 (1, NULL);
dw2_asm_output_data (1, DW_LNE_end_sequence, NULL);
function = 0;
current_file = 1;
current_line = 1;
for (lt_index = 0; lt_index < separate_line_info_table_in_use;)
{
dw_separate_line_info_ref line_info
= &separate_line_info_table[lt_index];
#if 0
/* Don't emit anything for redundant notes. */
if (line_info->dw_line_num == current_line
&& line_info->dw_file_num == current_file
&& line_info->function == function)
goto cont;
#endif
/* Emit debug info for the address of the current line. If this is
a new function, or the first line of a function, then we need
to handle it differently. */
ASM_GENERATE_INTERNAL_LABEL (line_label, SEPARATE_LINE_CODE_LABEL,
lt_index);
if (function != line_info->function)
{
function = line_info->function;
/* Set the address register to the first line in the function. */
dw2_asm_output_data (1, 0, "DW_LNE_set_address");
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);
}
else
{
/* ??? See the DW_LNS_advance_pc comment above. */
if (0)
{
dw2_asm_output_data (1, DW_LNS_fixed_advance_pc,
"DW_LNS_fixed_advance_pc");
dw2_asm_output_delta (2, line_label, prev_line_label, NULL);
}
else
{
dw2_asm_output_data (1, 0, "DW_LNE_set_address");
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);
}
}
strcpy (prev_line_label, line_label);
/* Emit debug info for the source file of the current line, if
different from the previous line. */
if (line_info->dw_file_num != current_file)
{
current_file = line_info->dw_file_num;
dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file");
dw2_asm_output_data_uleb128 (current_file, "%lu", current_file);
}
/* Emit debug info for the current line number, choosing the encoding
that uses the least amount of space. */
if (line_info->dw_line_num != current_line)
{
line_offset = line_info->dw_line_num - current_line;
line_delta = line_offset - DWARF_LINE_BASE;
current_line = line_info->dw_line_num;
if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta,
"line %lu", current_line);
else
{
dw2_asm_output_data (1, DW_LNS_advance_line,
"advance to line %lu", current_line);
dw2_asm_output_data_sleb128 (line_offset, NULL);
dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy");
}
}
else
dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy");
#if 0
cont:
#endif
lt_index++;
/* If we're done with a function, end its sequence. */
if (lt_index == separate_line_info_table_in_use
|| separate_line_info_table[lt_index].function != function)
{
current_file = 1;
current_line = 1;
/* Emit debug info for the address of the end of the function. */
ASM_GENERATE_INTERNAL_LABEL (line_label, FUNC_END_LABEL, function);
if (0)
{
dw2_asm_output_data (1, DW_LNS_fixed_advance_pc,
"DW_LNS_fixed_advance_pc");
dw2_asm_output_delta (2, line_label, prev_line_label, NULL);
}
else
{
dw2_asm_output_data (1, 0, "DW_LNE_set_address");
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);
}
/* Output the marker for the end of this sequence. */
dw2_asm_output_data (1, 0, "DW_LNE_end_sequence");
dw2_asm_output_data_uleb128 (1, NULL);
dw2_asm_output_data (1, DW_LNE_end_sequence, NULL);
}
FOR_EACH_VEC_ELT (dw_line_info_table_p, separate_line_info, i, table)
if (table->in_use)
output_one_line_info_table (table);
}
/* Output the marker for the end of the line number info. */
@ -22113,6 +22004,76 @@ var_location_switch_text_section (void)
htab_traverse (decl_loc_table, var_location_switch_text_section_1, NULL);
}
/* Create a new line number table. */
static dw_line_info_table *
new_line_info_table (void)
{
dw_line_info_table *table;
table = ggc_alloc_cleared_dw_line_info_table_struct ();
table->file_num = 1;
table->line_num = 1;
table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START;
return table;
}
/* Lookup the "current" table into which we emit line info, so
that we don't have to do it for every source line. */
static void
set_cur_line_info_table (section *sec)
{
dw_line_info_table *table;
if (sec == text_section)
{
table = text_section_line_info;
if (!table)
{
text_section_line_info = table = new_line_info_table ();
table->end_label = text_end_label;
}
}
else if (sec == cold_text_section)
{
table = cold_text_section_line_info;
if (!table)
{
cold_text_section_line_info = table = new_line_info_table ();
table->end_label = cold_end_label;
}
}
else
{
const char *end_label;
if (flag_reorder_blocks_and_partition)
{
if (in_cold_section_p)
end_label = crtl->subsections.cold_section_end_label;
else
end_label = crtl->subsections.hot_section_end_label;
}
else
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
current_function_funcdef_no);
end_label = ggc_strdup (label);
}
table = new_line_info_table ();
table->end_label = end_label;
VEC_safe_push (dw_line_info_table_p, gc, separate_line_info, table);
}
cur_line_info_table = table;
}
/* We need to reset the locations at the beginning of each
function. We can't do this in the end_function hook, because the
declarations that use the locations won't have been output when
@ -22121,114 +22082,100 @@ var_location_switch_text_section (void)
static void
dwarf2out_begin_function (tree fun)
{
if (function_section (fun) != text_section)
section *sec = function_section (fun);
if (sec != text_section)
have_multiple_function_sections = true;
if (flag_reorder_blocks_and_partition && !cold_text_section)
{
gcc_assert (current_function_decl == fun);
cold_text_section = unlikely_text_section ();
switch_to_section (cold_text_section);
ASM_OUTPUT_LABEL (asm_out_file, cold_text_section_label);
switch_to_section (current_function_section ());
switch_to_section (sec);
}
dwarf2out_note_section_used ();
call_site_count = 0;
tail_call_site_count = 0;
set_cur_line_info_table (sec);
}
/* Add OPCODE+VAL as an entry at the end of the opcode array in TABLE. */
static void
push_dw_line_info_entry (dw_line_info_table *table,
enum dw_line_info_opcode opcode, unsigned int val)
{
dw_line_info_entry e;
e.opcode = opcode;
e.val = val;
VEC_safe_push (dw_line_info_entry, gc, table->entries, &e);
}
/* Output a label to mark the beginning of a source code line entry
and record information relating to this source line, in
'line_info_table' for later output of the .debug_line section. */
/* ??? The discriminator parameter ought to be unsigned. */
static void
dwarf2out_source_line (unsigned int line, const char *filename,
int discriminator, bool is_stmt)
{
static bool last_is_stmt = true;
unsigned int file_num;
dw_line_info_table *table;
if (debug_info_level >= DINFO_LEVEL_NORMAL
&& line != 0)
if (debug_info_level < DINFO_LEVEL_NORMAL || line == 0)
return;
switch_to_section (current_function_section ());
/* If requested, emit something human-readable. */
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START, filename, line);
table = cur_line_info_table;
file_num = maybe_emit_file (lookup_filename (filename));
if (0 && file_num == table->file_num
&& line == table->line_num
&& discriminator == table->discrim_num
&& is_stmt == table->is_stmt)
return;
if (DWARF2_ASM_LINE_DEBUG_INFO)
{
int file_num = maybe_emit_file (lookup_filename (filename));
switch_to_section (current_function_section ());
/* If requested, emit something human-readable. */
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START,
filename, line);
if (DWARF2_ASM_LINE_DEBUG_INFO)
{
/* Emit the .loc directive understood by GNU as. */
fprintf (asm_out_file, "\t.loc %d %d 0", file_num, line);
if (is_stmt != last_is_stmt)
{
fprintf (asm_out_file, " is_stmt %d", is_stmt ? 1 : 0);
last_is_stmt = is_stmt;
}
if (SUPPORTS_DISCRIMINATOR && discriminator != 0)
fprintf (asm_out_file, " discriminator %d", discriminator);
fputc ('\n', asm_out_file);
/* Indicate that line number info exists. */
line_info_table_in_use++;
}
else if (function_section (current_function_decl) != text_section)
{
dw_separate_line_info_ref line_info;
targetm.asm_out.internal_label (asm_out_file,
SEPARATE_LINE_CODE_LABEL,
separate_line_info_table_in_use);
/* Expand the line info table if necessary. */
if (separate_line_info_table_in_use
== separate_line_info_table_allocated)
{
separate_line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
separate_line_info_table
= GGC_RESIZEVEC (dw_separate_line_info_entry,
separate_line_info_table,
separate_line_info_table_allocated);
memset (separate_line_info_table
+ separate_line_info_table_in_use,
0,
(LINE_INFO_TABLE_INCREMENT
* sizeof (dw_separate_line_info_entry)));
}
/* Add the new entry at the end of the line_info_table. */
line_info
= &separate_line_info_table[separate_line_info_table_in_use++];
line_info->dw_file_num = file_num;
line_info->dw_line_num = line;
line_info->function = current_function_funcdef_no;
}
else
{
dw_line_info_ref line_info;
targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL,
line_info_table_in_use);
/* Expand the line info table if necessary. */
if (line_info_table_in_use == line_info_table_allocated)
{
line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
line_info_table
= GGC_RESIZEVEC (dw_line_info_entry, line_info_table,
line_info_table_allocated);
memset (line_info_table + line_info_table_in_use, 0,
LINE_INFO_TABLE_INCREMENT * sizeof (dw_line_info_entry));
}
/* Add the new entry at the end of the line_info_table. */
line_info = &line_info_table[line_info_table_in_use++];
line_info->dw_file_num = file_num;
line_info->dw_line_num = line;
}
/* Emit the .loc directive understood by GNU as. */
fprintf (asm_out_file, "\t.loc %d %d 0", file_num, line);
if (is_stmt != table->is_stmt)
fprintf (asm_out_file, " is_stmt %d", is_stmt ? 1 : 0);
if (SUPPORTS_DISCRIMINATOR && discriminator != 0)
fprintf (asm_out_file, " discriminator %d", discriminator);
fputc ('\n', asm_out_file);
}
else
{
unsigned int label_num = ++line_info_label_num;
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 (file_num != table->file_num)
push_dw_line_info_entry (table, LI_set_file, file_num);
if (discriminator != table->discrim_num)
push_dw_line_info_entry (table, LI_set_discriminator, discriminator);
if (is_stmt != table->is_stmt)
push_dw_line_info_entry (table, LI_negate_stmt, 0);
push_dw_line_info_entry (table, LI_set_line, line);
}
table->file_num = file_num;
table->line_num = line;
table->discrim_num = discriminator;
table->is_stmt = is_stmt;
table->in_use = true;
}
/* Record the beginning of a new source file. */
@ -22389,14 +22336,6 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
/* Zero-th entry is allocated, but unused. */
abbrev_die_table_in_use = 1;
/* Allocate the initial hunk of the line_info_table. */
line_info_table = ggc_alloc_cleared_vec_dw_line_info_entry
(LINE_INFO_TABLE_INCREMENT);
line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
/* Zero-th entry is allocated, but unused. */
line_info_table_in_use = 1;
/* Allocate the pubtypes and pubnames vectors. */
pubname_table = VEC_alloc (pubname_entry, gc, 32);
pubtype_table = VEC_alloc (pubname_entry, gc, 32);