((((SIZE) + (BOUNDARY) - 1) / (BOUNDARY)) * (BOUNDARY))
/* Offsets recorded in opcodes are a multiple of this alignment factor. */
+#ifndef DWARF_CIE_DATA_ALIGNMENT
#ifdef STACK_GROWS_DOWNWARD
#define DWARF_CIE_DATA_ALIGNMENT (-((int) UNITS_PER_WORD))
#else
#define DWARF_CIE_DATA_ALIGNMENT ((int) UNITS_PER_WORD)
#endif
+#endif /* not DWARF_CIE_DATA_ALIGNMENT */
/* A pointer to the base of a table that contains frame description
information for each routine. */
/* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
newline is produced. When flag_debug_asm is asserted, we add commentary
at the end of the line, so we must avoid output of a newline here. */
-#ifndef ASM_OUTPUT_DWARF_STRING
-#define ASM_OUTPUT_DWARF_STRING(FILE,P) \
+#ifndef ASM_OUTPUT_DWARF_NSTRING
+#define ASM_OUTPUT_DWARF_NSTRING(FILE,P,SLEN) \
do { \
- register int slen = strlen(P); \
+ register int slen = (SLEN); \
register const char *p = (P); \
register int i; \
fprintf (FILE, "\t.ascii \""); \
} \
while (0)
#endif
+#define ASM_OUTPUT_DWARF_STRING(FILE,P) \
+ ASM_OUTPUT_DWARF_NSTRING (FILE, P, strlen (P))
/* The DWARF 2 CFA column which tracks the return address. Normally this
is the column for PC, or the first column after all of the hard
else
cfi->dw_cfi_opc = DW_CFA_offset;
+#ifdef ENABLE_CHECKING
+ {
+ /* If we get an offset that is not a multiple of
+ DWARF_CIE_DATA_ALIGNMENT, there is either a bug in the
+ definition of DWARF_CIE_DATA_ALIGNMENT, or a bug in the machine
+ description. */
+ long check_offset = offset / DWARF_CIE_DATA_ALIGNMENT;
+
+ if (check_offset * DWARF_CIE_DATA_ALIGNMENT != offset)
+ abort ();
+ }
+#endif
offset /= DWARF_CIE_DATA_ALIGNMENT;
if (offset < 0)
{
}
else
return;
-
+
if (offset == 0)
return;
enum dwarf_location_atom dw_loc_opc;
dw_val_node dw_loc_oprnd1;
dw_val_node dw_loc_oprnd2;
+ int dw_loc_addr;
}
dw_loc_descr_node;
register unsigned long size = 0;
for (; loc != NULL; loc = loc->dw_loc_next)
- size += size_of_loc_descr (loc);
+ {
+ loc->dw_loc_addr = size;
+ size += size_of_loc_descr (loc);
+ }
return size;
}
break;
case DW_OP_skip:
case DW_OP_bra:
- ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int);
- fputc ('\n', asm_out_file);
+ {
+ int offset;
+
+ if (val1->val_class == dw_val_class_loc)
+ offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3);
+ else
+ abort ();
+
+ ASM_OUTPUT_DWARF_DATA2 (asm_out_file, offset);
+ fputc ('\n', asm_out_file);
+ }
break;
#else
case DW_OP_addr:
abort ();
if (cfa->base_offset)
- head = new_loc_descr (DW_OP_breg0 + cfa->reg, cfa->base_offset, 0);
- else
+ {
+ if (cfa->reg <= 31)
+ head = new_loc_descr (DW_OP_breg0 + cfa->reg, cfa->base_offset, 0);
+ else
+ head = new_loc_descr (DW_OP_bregx, cfa->reg, cfa->base_offset);
+ }
+ else if (cfa->reg <= 31)
head = new_loc_descr (DW_OP_reg0 + cfa->reg, 0, 0);
+ else
+ head = new_loc_descr (DW_OP_regx, cfa->reg, 0);
head->dw_loc_oprnd1.val_class = dw_val_class_const;
tmp = new_loc_descr (DW_OP_deref, 0, 0);
add_loc_descr (&head, tmp);
(DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \
- (2 * DWARF_OFFSET_SIZE + 4))
-/* The default is to have gcc emit the line number tables. */
+/* Use assembler line directives if available. */
#ifndef DWARF2_ASM_LINE_DEBUG_INFO
+#ifdef HAVE_AS_DWARF2_DEBUG_LINE
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
+#else
#define DWARF2_ASM_LINE_DEBUG_INFO 0
#endif
+#endif
/* Define the architecture-dependent minimum instruction length (in bytes).
In this implementation of DWARF, this field is used for information
/* A list of DIEs with a NULL parent waiting to be relocated. */
static limbo_die_node *limbo_die_list = 0;
-/* Pointer to an array of filenames referenced by this compilation unit. */
-static char **file_table;
-
-/* Total number of entries in the table (i.e. array) pointed to by
- `file_table'. This is the *total* and includes both used and unused
- slots. */
-static unsigned file_table_allocated;
-
-/* Number of entries in the file_table which are actually in use. */
-static unsigned file_table_in_use;
+/* Structure used by lookup_filename to manage sets of filenames. */
+struct file_table
+{
+ char **table;
+ unsigned allocated;
+ unsigned in_use;
+ unsigned last_lookup_index;
+};
/* Size (in elements) of increments by which we may expand the filename
table. */
#define FILE_TABLE_INCREMENT 64
+/* Filenames referenced by declarations this compilation unit. */
+static struct file_table decl_file_table;
+
+/* Filenames referenced by line numbers in this compilation unit. */
+static struct file_table line_file_table;
+
/* Local pointer to the name of the main input file. Initialized in
dwarf2out_init. */
static const char *primary_filename;
static void add_arange PARAMS ((tree, dw_die_ref));
static void output_aranges PARAMS ((void));
static void output_line_info PARAMS ((void));
+static void output_file_names PARAMS ((void));
static dw_die_ref base_type_die PARAMS ((tree));
static tree root_type PARAMS ((tree));
static int is_base_type PARAMS ((tree));
static int type_is_enum PARAMS ((tree));
static unsigned int reg_number PARAMS ((rtx));
static dw_loc_descr_ref reg_loc_descriptor PARAMS ((rtx));
+static dw_loc_descr_ref int_loc_descriptor PARAMS ((HOST_WIDE_INT));
static dw_loc_descr_ref based_loc_descr PARAMS ((unsigned, long));
static int is_based_loc PARAMS ((rtx));
static dw_loc_descr_ref mem_loc_descriptor PARAMS ((rtx, enum machine_mode mode));
static dw_loc_descr_ref concat_loc_descriptor PARAMS ((rtx, rtx));
static dw_loc_descr_ref loc_descriptor PARAMS ((rtx));
+static dw_loc_descr_ref loc_descriptor_from_tree PARAMS ((tree, int));
static HOST_WIDE_INT ceiling PARAMS ((HOST_WIDE_INT, unsigned int));
static tree field_type PARAMS ((tree));
static unsigned int simple_type_align_in_bits PARAMS ((tree));
enum dwarf_attribute, rtx));
static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree));
static void add_const_value_attribute PARAMS ((dw_die_ref, rtx));
+static rtx rtl_for_decl_location PARAMS ((tree));
static void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree));
static void tree_add_const_value_attribute PARAMS ((dw_die_ref, tree));
static void add_name_attribute PARAMS ((dw_die_ref, const char *));
static void decls_for_scope PARAMS ((tree, dw_die_ref, int));
static int is_redundant_typedef PARAMS ((tree));
static void gen_decl_die PARAMS ((tree, dw_die_ref));
-static unsigned lookup_filename PARAMS ((const char *));
+static unsigned lookup_filename PARAMS ((struct file_table *,
+ const char *));
+static void init_file_table PARAMS ((struct file_table *));
static void add_incomplete_type PARAMS ((tree));
static void retry_incomplete_types PARAMS ((void));
static void gen_type_die_for_member PARAMS ((tree, tree, dw_die_ref));
#ifndef BSS_END_LABEL
#define BSS_END_LABEL "Lebss"
#endif
-#ifndef INSN_LABEL_FMT
-#define INSN_LABEL_FMT "LI%u_"
-#endif
#ifndef BLOCK_BEGIN_LABEL
#define BLOCK_BEGIN_LABEL "LBB"
#endif
save_rtx (orig)
register rtx orig;
{
- if (ggc_p)
- VARRAY_PUSH_RTX (used_rtx_varray, orig);
- else
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- orig = copy_rtx (orig);
- pop_obstacks ();
- }
+ VARRAY_PUSH_RTX (used_rtx_varray, orig);
return orig;
}
case dw_val_class_float:
free (a->dw_attr_val.v.val_float.array);
break;
-
+
default:
break;
}
= (dw_die_ref *) xrealloc (decl_die_table,
sizeof (dw_die_ref) * num_allocated);
- bzero ((char *) &decl_die_table[decl_die_table_allocated],
+ memset ((char *) &decl_die_table[decl_die_table_allocated], 0,
(num_allocated - decl_die_table_allocated) * sizeof (dw_die_ref));
decl_die_table_allocated = num_allocated;
}
{
line_info = &line_info_table[i];
fprintf (outfile, "%5d: ", i);
- fprintf (outfile, "%-20s", file_table[line_info->dw_file_num]);
+ fprintf (outfile, "%-20s", line_file_table.table[line_info->dw_file_num]);
fprintf (outfile, "%6ld", line_info->dw_line_num);
fprintf (outfile, "\n");
}
#if 0
/* We can only use this in debugging, since the frontend doesn't check
- to make sure that we leave every include file we enter. */
+ to make sure that we leave every include file we enter. */
if (unit != NULL)
abort ();
#endif
= (dw_die_ref *) xrealloc (abbrev_die_table,
sizeof (dw_die_ref) * n_alloc);
- bzero ((char *) &abbrev_die_table[abbrev_die_table_allocated],
+ memset ((char *) &abbrev_die_table[abbrev_die_table_allocated], 0,
(n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref));
abbrev_die_table_allocated = n_alloc;
}
null byte used to terminate the table. */
size += 1;
- for (ft_index = 1; ft_index < file_table_in_use; ++ft_index)
+ for (ft_index = 1; ft_index < decl_file_table.in_use; ++ft_index)
{
/* File name entry. */
- size += size_of_string (file_table[ft_index]);
+ size += size_of_string (decl_file_table.table[ft_index]);
/* Include directory index. */
size += size_of_uleb128 (0);
output_comp_unit (die)
dw_die_ref die;
{
- char *secname;
+ const char *secname;
if (die->die_child == 0)
return;
if (die->die_symbol)
{
- secname = (char *) alloca (strlen (die->die_symbol) + 24);
- sprintf (secname, ".gnu.linkonce.wi.%s", die->die_symbol);
+ char *tmp = (char *) alloca (strlen (die->die_symbol) + 24);
+ sprintf (tmp, ".gnu.linkonce.wi.%s", die->die_symbol);
+ secname = tmp;
die->die_symbol = NULL;
}
else
- secname = (char *) DEBUG_INFO_SECTION;
+ secname = (const char *) DEBUG_INFO_SECTION;
/* Output debugging information. */
fputc ('\n', asm_out_file);
fputc ('\n', asm_out_file);
}
+
+/* Data structure containing information about input files. */
+struct file_info
+{
+ char *path; /* Complete file name. */
+ char *fname; /* File name part. */
+ int length; /* Length of entire string. */
+ int file_idx; /* Index in input file table. */
+ int dir_idx; /* Index in directory table. */
+};
+
+/* Data structure containing information about directories with source
+ files. */
+struct dir_info
+{
+ char *path; /* Path including directory name. */
+ int length; /* Path length. */
+ int prefix; /* Index of directory entry which is a prefix. */
+ int nbytes; /* Total number of bytes in all file names excluding
+ paths. */
+ int count; /* Number of files in this directory. */
+ int dir_idx; /* Index of directory used as base. */
+ int used; /* Used in the end? */
+};
+
+/* Callback function for file_info comparison. We sort by looking at
+ the directories in the path. */
+static int
+file_info_cmp (p1, p2)
+ const void *p1;
+ const void *p2;
+{
+ const struct file_info *s1 = p1;
+ const struct file_info *s2 = p2;
+ unsigned char *cp1;
+ unsigned char *cp2;
+
+ /* Take care of file names without directories. */
+ if (s1->path == s1->fname)
+ return -1;
+ else if (s2->path == s2->fname)
+ return 1;
+
+ cp1 = (unsigned char *) s1->path;
+ cp2 = (unsigned char *) s2->path;
+
+ while (1)
+ {
+ ++cp1;
+ ++cp2;
+ /* Reached the end of the first path? */
+ if (cp1 == (unsigned char *) s1->fname)
+ /* It doesn't really matter in which order files from the
+ same directory are sorted in. Therefore don't test for
+ the second path reaching the end. */
+ return -1;
+ else if (cp2 == (unsigned char *) s2->fname)
+ return 1;
+
+ /* Character of current path component the same? */
+ if (*cp1 != *cp2)
+ return *cp1 - *cp2;
+ }
+}
+
+/* Output the directory table and the file name table. We try to minimize
+ the total amount of memory needed. A heuristic is used to avoid large
+ slowdowns with many input files. */
+static void
+output_file_names ()
+{
+ struct file_info *files;
+ struct dir_info *dirs;
+ int *saved;
+ int *savehere;
+ int *backmap;
+ int ndirs;
+ int idx_offset;
+ int i;
+ int idx;
+
+ /* Allocate the various arrays we need. */
+ files = (struct file_info *) alloca (line_file_table.in_use
+ * sizeof (struct file_info));
+ dirs = (struct dir_info *) alloca (line_file_table.in_use
+ * sizeof (struct dir_info));
+
+ /* Sort the file names. */
+ for (i = 1; i < (int) line_file_table.in_use; ++i)
+ {
+ char *f;
+
+ /* Skip all leading "./". */
+ f = line_file_table.table[i];
+ while (f[0] == '.' && f[1] == '/')
+ f += 2;
+
+ /* Create a new array entry. */
+ files[i].path = f;
+ files[i].length = strlen (f);
+ files[i].file_idx = i;
+
+ /* Search for the file name part. */
+ f = strrchr (f, '/');
+ files[i].fname = f == NULL ? files[i].path : f + 1;
+ }
+ qsort (files + 1, line_file_table.in_use - 1, sizeof (files[0]),
+ file_info_cmp);
+
+ /* Find all the different directories used. */
+ dirs[0].path = files[1].path;
+ dirs[0].length = files[1].fname - files[1].path;
+ dirs[0].prefix = -1;
+ dirs[0].nbytes = files[1].length - dirs[1].length + 1;
+ dirs[0].count = 1;
+ dirs[0].dir_idx = 0;
+ dirs[0].used = 0;
+ files[1].dir_idx = 0;
+ ndirs = 1;
+
+ for (i = 2; i < (int) line_file_table.in_use; ++i)
+ if (files[i].fname - files[i].path == dirs[ndirs - 1].length
+ && memcmp (dirs[ndirs - 1].path, files[i].path,
+ dirs[ndirs - 1].length) == 0)
+ {
+ /* Same directory as last entry. */
+ files[i].dir_idx = ndirs - 1;
+ dirs[ndirs - 1].nbytes += files[i].length - dirs[ndirs - 1].length + 1;
+ ++dirs[ndirs - 1].count;
+ }
+ else
+ {
+ int j;
+
+ /* This is a new directory. */
+ dirs[ndirs].path = files[i].path;
+ dirs[ndirs].length = files[i].fname - files[i].path;
+ dirs[ndirs].nbytes = files[i].length - dirs[i].length + 1;
+ dirs[ndirs].count = 1;
+ dirs[ndirs].dir_idx = ndirs;
+ dirs[ndirs].used = 0;
+ files[i].dir_idx = ndirs;
+
+ /* Search for a prefix. */
+ dirs[ndirs].prefix = -1;
+ for (j = 0; j < ndirs; ++j)
+ if (dirs[j].length < dirs[ndirs].length
+ && dirs[j].length != 0
+ && memcmp (dirs[j].path, dirs[ndirs].path, dirs[j].length) == 0)
+ dirs[ndirs].prefix = j;
+
+ ++ndirs;
+ }
+
+ /* Now to the actual work. We have to find a subset of the
+ directories which allow expressing the file name using references
+ to the directory table with the least amount of characters. We
+ do not do an exhaustive search where we would have to check out
+ every combination of every single possible prefix. Instead we
+ use a heuristic which provides nearly optimal results in most
+ cases and never is much off. */
+ saved = (int *) alloca (ndirs * sizeof (int));
+ savehere = (int *) alloca (ndirs * sizeof (int));
+
+ memset (saved, '\0', ndirs * sizeof (saved[0]));
+ for (i = 0; i < ndirs; ++i)
+ {
+ int j;
+ int total;
+
+ /* We can always safe some space for the current directory. But
+ this does not mean it will be enough to justify adding the
+ directory. */
+ savehere[i] = dirs[i].length;
+ total = (savehere[i] - saved[i]) * dirs[i].count;
+
+ for (j = i + 1; j < ndirs; ++j)
+ {
+ savehere[j] = 0;
+
+ if (saved[j] < dirs[i].length)
+ {
+ /* Determine whether the dirs[i] path is a prefix of the
+ dirs[j] path. */
+ int k;
+
+ k = dirs[j].prefix;
+ while (k != -1 && k != i)
+ k = dirs[k].prefix;
+
+ if (k == i)
+ {
+ /* Yes it is. We can possibly safe some memory but
+ writing the filenames in dirs[j] relative to
+ dirs[i]. */
+ savehere[j] = dirs[i].length;
+ total += (savehere[j] - saved[j]) * dirs[j].count;
+ }
+ }
+ }
+
+ /* Check whether we can safe enough to justify adding the dirs[i]
+ directory. */
+ if (total > dirs[i].length + 1)
+ {
+ /* It's worthwhile adding. */
+ for (j = i; j < ndirs; ++j)
+ if (savehere[j] > 0)
+ {
+ /* Remember how much we saved for this directory so far. */
+ saved[j] = savehere[j];
+
+ /* Remember the prefix directory. */
+ dirs[j].dir_idx = i;
+ }
+ }
+ }
+
+ /* We have to emit them in the order they appear in the line_file_table
+ array since the index is used in the debug info generation. To
+ do this efficiently we generate a back-mapping of the indices
+ first. */
+ backmap = (int *) alloca (line_file_table.in_use * sizeof (int));
+ for (i = 1; i < (int) line_file_table.in_use; ++i)
+ {
+ backmap[files[i].file_idx] = i;
+ /* Mark this directory as used. */
+ dirs[dirs[files[i].dir_idx].dir_idx].used = 1;
+ }
+
+ /* That was it. We are ready to emit the information. First the
+ directory name table. Here we have to make sure that the first
+ actually emitted directory name has the index one. Zero is
+ reserved for the current working directory. Make sure we do not
+ confuse these indices with the one for the constructed table
+ (even though most of the time they are identical). */
+ idx = 1;
+ idx_offset = dirs[0].path[0] == '/' ? 1 : 0;
+ for (i = 1 - idx_offset; i < ndirs; ++i)
+ if (dirs[i].used != 0)
+ {
+ dirs[i].used = idx++;
+
+ if (flag_debug_asm)
+ {
+ ASM_OUTPUT_DWARF_NSTRING (asm_out_file,
+ dirs[i].path, dirs[i].length - 1);
+ fprintf (asm_out_file, "%s Directory Entry: 0x%x\n",
+ ASM_COMMENT_START, dirs[i].used);
+ }
+ else
+ {
+ ASM_OUTPUT_ASCII (asm_out_file, dirs[i].path, dirs[i].length - 1);
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
+ fputc ('\n', asm_out_file);
+ }
+ }
+ /* Correct the index for the current working directory entry if it
+ exists. */
+ if (idx_offset == 0)
+ dirs[0].used = 0;
+ /* Terminate the directory name array. */
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s End directory table", ASM_COMMENT_START);
+ fputc ('\n', asm_out_file);
+
+ /* Now write all the file names. */
+ for (i = 1; i < (int) line_file_table.in_use; ++i)
+ {
+ int file_idx = backmap[i];
+ int dir_idx = dirs[files[file_idx].dir_idx].dir_idx;
+
+ if (flag_debug_asm)
+ {
+ ASM_OUTPUT_DWARF_STRING (asm_out_file,
+ files[file_idx].path
+ + dirs[dir_idx].length);
+ fprintf (asm_out_file, "%s File Entry: 0x%x\n",
+ ASM_COMMENT_START, i);
+ }
+ else
+ ASM_OUTPUT_ASCII (asm_out_file,
+ files[file_idx].path + dirs[dir_idx].length,
+ (files[file_idx].length
+ - dirs[dir_idx].length) + 1);
+
+ /* Include directory index. */
+ output_uleb128 (dirs[dir_idx].used);
+ fputc ('\n', asm_out_file);
+
+ /* Modification time. */
+ output_uleb128 (0);
+ fputc ('\n', asm_out_file);
+
+ /* File length in bytes. */
+ output_uleb128 (0);
+ fputc ('\n', asm_out_file);
+ }
+
+ /* Terminate the file name table */
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s End file name table", ASM_COMMENT_START);
+ fputc ('\n', asm_out_file);
+}
+
+
/* Output the source line number correspondence information. This
information goes into the .debug_line section. */
char prev_line_label[MAX_ARTIFICIAL_LABEL_BYTES];
register unsigned opc;
register unsigned n_op_args;
- register unsigned long ft_index;
register unsigned long lt_index;
register unsigned long current_line;
register long line_offset;
fputc ('\n', asm_out_file);
}
- if (flag_debug_asm)
- fprintf (asm_out_file, "%s Include Directory Table\n", ASM_COMMENT_START);
-
- /* Include directory table is empty, at present */
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
- fputc ('\n', asm_out_file);
- if (flag_debug_asm)
- fprintf (asm_out_file, "%s File Name Table\n", ASM_COMMENT_START);
-
- for (ft_index = 1; ft_index < file_table_in_use; ++ft_index)
- {
- if (flag_debug_asm)
- {
- ASM_OUTPUT_DWARF_STRING (asm_out_file, file_table[ft_index]);
- fprintf (asm_out_file, "%s File Entry: 0x%lx",
- ASM_COMMENT_START, ft_index);
- }
- else
- {
- ASM_OUTPUT_ASCII (asm_out_file,
- file_table[ft_index],
- (int) strlen (file_table[ft_index]) + 1);
- }
-
- fputc ('\n', asm_out_file);
-
- /* Include directory index */
- output_uleb128 (0);
- fputc ('\n', asm_out_file);
-
- /* Modification time */
- output_uleb128 (0);
- fputc ('\n', asm_out_file);
-
- /* File length in bytes */
- output_uleb128 (0);
- fputc ('\n', asm_out_file);
- }
-
- /* Terminate the file name table */
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
- fputc ('\n', asm_out_file);
+ /* Write out the information about the files we use. */
+ output_file_names ();
/* 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
fputc ('\n', asm_out_file);
output_uleb128 (current_file);
if (flag_debug_asm)
- fprintf (asm_out_file, " (\"%s\")", file_table[current_file]);
+ fprintf (asm_out_file, " (\"%s\")",
+ line_file_table.table[current_file]);
fputc ('\n', asm_out_file);
}
fputc ('\n', asm_out_file);
output_uleb128 (current_file);
if (flag_debug_asm)
- fprintf (asm_out_file, " (\"%s\")", file_table[current_file]);
+ fprintf (asm_out_file, " (\"%s\")",
+ line_file_table.table[current_file]);
fputc ('\n', asm_out_file);
}
return loc_result;
}
+/* Return a location descriptor that designates a constant. */
+
+static dw_loc_descr_ref
+int_loc_descriptor (i)
+ HOST_WIDE_INT i;
+{
+ enum dwarf_location_atom op;
+
+ /* Pick the smallest representation of a constant, rather than just
+ defaulting to the LEB encoding. */
+ if (i >= 0)
+ {
+ if (i <= 31)
+ op = DW_OP_lit0 + i;
+ else if (i <= 0xff)
+ op = DW_OP_const1u;
+ else if (i <= 0xffff)
+ op = DW_OP_const2u;
+ else if (HOST_BITS_PER_WIDE_INT == 32
+ || i <= 0xffffffff)
+ op = DW_OP_const4u;
+ else
+ op = DW_OP_constu;
+ }
+ else
+ {
+ if (i >= -0x80)
+ op = DW_OP_const1s;
+ else if (i >= -0x8000)
+ op = DW_OP_const2s;
+ else if (HOST_BITS_PER_WIDE_INT == 32
+ || i >= -0x80000000)
+ op = DW_OP_const4s;
+ else
+ op = DW_OP_consts;
+ }
+
+ return new_loc_descr (op, i, 0);
+}
+
/* Return a location descriptor that designates a base+offset location. */
static dw_loc_descr_ref
break;
case MEM:
- mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
- add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
+ {
+ dw_loc_descr_ref deref;
+
+ mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
+
+ if (GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE)
+ deref = new_loc_descr (DW_OP_deref, 0, 0);
+ else
+ deref = new_loc_descr (DW_OP_deref_size, GET_MODE_SIZE (mode), 0);
+
+ add_loc_descr (&mem_loc_result, deref);
+ }
break;
- case LABEL_REF:
- /* Some ports can transform a symbol ref into a label ref, because
+ case LABEL_REF:
+ /* Some ports can transform a symbol ref into a label ref, because
the symbol ref is too far away and has to be dumped into a constant
pool. */
case CONST:
INTVAL (XEXP (rtl, 1)));
else
{
- add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0),
- mode));
- add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1),
- mode));
- add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_plus, 0, 0));
+ mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
+
+ if (GET_CODE (XEXP (rtl, 1)) == CONST_INT
+ && INTVAL (XEXP (rtl, 1)) >= 0)
+ {
+ add_loc_descr (&mem_loc_result,
+ new_loc_descr (DW_OP_plus_uconst,
+ INTVAL (XEXP (rtl, 1)), 0));
+ }
+ else
+ {
+ add_loc_descr (&mem_loc_result,
+ mem_loc_descriptor (XEXP (rtl, 1), mode));
+ add_loc_descr (&mem_loc_result,
+ new_loc_descr (DW_OP_plus, 0, 0));
+ }
}
break;
case MULT:
/* If a pseudo-reg is optimized away, it is possible for it to
be replaced with a MEM containing a multiply. */
- add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0), mode));
- add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1), mode));
+ add_loc_descr (&mem_loc_result,
+ mem_loc_descriptor (XEXP (rtl, 0), mode));
+ add_loc_descr (&mem_loc_result,
+ mem_loc_descriptor (XEXP (rtl, 1), mode));
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0));
break;
case CONST_INT:
- mem_loc_result = new_loc_descr (DW_OP_constu, INTVAL (rtl), 0);
+ mem_loc_result = int_loc_descriptor (INTVAL (rtl));
break;
default:
return loc_result;
}
+/* Similar, but generate the descriptor from trees instead of rtl.
+ This comes up particularly with variable length arrays. */
+
+static dw_loc_descr_ref
+loc_descriptor_from_tree (loc, addressp)
+ tree loc;
+ int addressp;
+{
+ dw_loc_descr_ref ret = NULL;
+ int indirect_size = 0;
+ int unsignedp = TREE_UNSIGNED (TREE_TYPE (loc));
+ enum dwarf_location_atom op;
+
+ /* ??? Most of the time we do not take proper care for sign/zero
+ extending the values properly. Hopefully this won't be a real
+ problem... */
+
+ switch (TREE_CODE (loc))
+ {
+ case ERROR_MARK:
+ break;
+
+ case VAR_DECL:
+ case PARM_DECL:
+ {
+ rtx rtl = rtl_for_decl_location (loc);
+ enum machine_mode mode = DECL_MODE (loc);
+
+ if (rtl == NULL_RTX)
+ break;
+ else if (CONSTANT_P (rtl))
+ {
+ ret = new_loc_descr (DW_OP_addr, 0, 0);
+ ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
+ ret->dw_loc_oprnd1.v.val_addr = rtl;
+ indirect_size = GET_MODE_SIZE (mode);
+ }
+ else
+ {
+ if (GET_CODE (rtl) == MEM)
+ {
+ indirect_size = GET_MODE_SIZE (mode);
+ rtl = XEXP (rtl, 0);
+ }
+ ret = mem_loc_descriptor (rtl, mode);
+ }
+ }
+ break;
+
+ case INDIRECT_REF:
+ ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+ indirect_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (loc)));
+ break;
+
+ case COMPONENT_REF:
+ case BIT_FIELD_REF:
+ case ARRAY_REF:
+ {
+ tree obj, offset;
+ HOST_WIDE_INT bitsize, bitpos, bytepos;
+ enum machine_mode mode;
+ int volatilep;
+ unsigned int alignment;
+
+ obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &volatilep, &alignment);
+ ret = loc_descriptor_from_tree (obj, 1);
+
+ if (offset != NULL_TREE)
+ {
+ /* Variable offset. */
+ add_loc_descr (&ret, loc_descriptor_from_tree (offset, 0));
+ add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
+ }
+
+ if (addressp)
+ {
+ /* We cannot address anything not on a unit boundary. */
+ if (bitpos % BITS_PER_UNIT != 0)
+ abort ();
+ }
+ else
+ {
+ if (bitpos % BITS_PER_UNIT != 0
+ || bitsize % BITS_PER_UNIT != 0)
+ {
+ /* ??? We could handle this by loading and shifting etc.
+ Wait until someone needs it before expending the effort. */
+ abort ();
+ }
+
+ indirect_size = bitsize / BITS_PER_UNIT;
+ }
+
+ bytepos = bitpos / BITS_PER_UNIT;
+ if (bytepos > 0)
+ add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0));
+ else if (bytepos < 0)
+ {
+ add_loc_descr (&ret, int_loc_descriptor (bytepos));
+ add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
+ }
+ break;
+ }
+
+ case INTEGER_CST:
+ if (host_integerp (loc, 0))
+ ret = int_loc_descriptor (tree_low_cst (loc, 0));
+ break;
+ break;
+
+ case BIT_AND_EXPR:
+ op = DW_OP_and;
+ goto do_binop;
+ case BIT_XOR_EXPR:
+ op = DW_OP_xor;
+ goto do_binop;
+ case BIT_IOR_EXPR:
+ op = DW_OP_or;
+ goto do_binop;
+ case TRUNC_DIV_EXPR:
+ op = DW_OP_div;
+ goto do_binop;
+ case MINUS_EXPR:
+ op = DW_OP_minus;
+ goto do_binop;
+ case TRUNC_MOD_EXPR:
+ op = DW_OP_mod;
+ goto do_binop;
+ case MULT_EXPR:
+ op = DW_OP_mul;
+ goto do_binop;
+ case LSHIFT_EXPR:
+ op = DW_OP_shl;
+ goto do_binop;
+ case RSHIFT_EXPR:
+ op = (unsignedp ? DW_OP_shr : DW_OP_shra);
+ goto do_binop;
+ case PLUS_EXPR:
+ if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
+ && host_integerp (TREE_OPERAND (loc, 1), 0))
+ {
+ ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+ add_loc_descr (&ret,
+ new_loc_descr (DW_OP_plus_uconst,
+ tree_low_cst (TREE_OPERAND (loc, 1),
+ 0),
+ 0));
+ break;
+ }
+ op = DW_OP_plus;
+ goto do_binop;
+ case LE_EXPR:
+ if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+ break;
+ op = DW_OP_le;
+ goto do_binop;
+ case GE_EXPR:
+ if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+ break;
+ op = DW_OP_ge;
+ goto do_binop;
+ case LT_EXPR:
+ if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+ break;
+ op = DW_OP_lt;
+ goto do_binop;
+ case GT_EXPR:
+ if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+ break;
+ op = DW_OP_gt;
+ goto do_binop;
+ case EQ_EXPR:
+ op = DW_OP_eq;
+ goto do_binop;
+ case NE_EXPR:
+ op = DW_OP_ne;
+ goto do_binop;
+
+ do_binop:
+ ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+ add_loc_descr (&ret, loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0));
+ add_loc_descr (&ret, new_loc_descr (op, 0, 0));
+ break;
+
+ case BIT_NOT_EXPR:
+ op = DW_OP_not;
+ goto do_unop;
+ case ABS_EXPR:
+ op = DW_OP_abs;
+ goto do_unop;
+ case NEGATE_EXPR:
+ op = DW_OP_neg;
+ goto do_unop;
+
+ do_unop:
+ ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+ add_loc_descr (&ret, new_loc_descr (op, 0, 0));
+ break;
+
+ case MAX_EXPR:
+ loc = build (COND_EXPR, TREE_TYPE (loc),
+ build (LT_EXPR, integer_type_node,
+ TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
+ TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
+ /* FALLTHRU */
+
+ case COND_EXPR:
+ {
+ dw_loc_descr_ref bra_node, jump_node, tmp;
+
+ ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+ bra_node = new_loc_descr (DW_OP_bra, 0, 0);
+ add_loc_descr (&ret, bra_node);
+
+ tmp = loc_descriptor_from_tree (TREE_OPERAND (loc, 2), 0);
+ add_loc_descr (&ret, tmp);
+ jump_node = new_loc_descr (DW_OP_skip, 0, 0);
+ add_loc_descr (&ret, jump_node);
+
+ tmp = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
+ add_loc_descr (&ret, tmp);
+ bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
+ bra_node->dw_loc_oprnd1.v.val_loc = tmp;
+
+ /* ??? Need a node to point the skip at. Use a nop. */
+ tmp = new_loc_descr (DW_OP_nop, 0, 0);
+ add_loc_descr (&ret, tmp);
+ jump_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
+ jump_node->dw_loc_oprnd1.v.val_loc = tmp;
+ }
+ break;
+
+ default:
+ abort ();
+ }
+
+ /* If we can't fill the request for an address, die. */
+ if (addressp && indirect_size == 0)
+ abort ();
+
+ /* If we've got an address and don't want one, dereference. */
+ if (!addressp && indirect_size > 0)
+ {
+ if (indirect_size > DWARF2_ADDR_SIZE)
+ abort ();
+ if (indirect_size == DWARF2_ADDR_SIZE)
+ op = DW_OP_deref;
+ else
+ op = DW_OP_deref_size;
+ add_loc_descr (&ret, new_loc_descr (op, indirect_size, 0));
+ }
+
+ return ret;
+}
+
/* Given a value, round it up to the lowest multiple of `boundary'
which is not less than the value itself. */
simple_type_size_in_bits (type)
register tree type;
{
+ tree type_size_tree;
+
if (TREE_CODE (type) == ERROR_MARK)
return BITS_PER_WORD;
- else
- {
- register tree type_size_tree = TYPE_SIZE (type);
-
- if (! host_integerp (type_size_tree, 1))
- return TYPE_ALIGN (type);
+ type_size_tree = TYPE_SIZE (type);
- return tree_low_cst (type_size_tree, 1);
- }
+ if (type_size_tree == NULL_TREE)
+ return 0;
+ if (! host_integerp (type_size_tree, 1))
+ return TYPE_ALIGN (type);
+ return tree_low_cst (type_size_tree, 1);
}
/* Given a pointer to what is assumed to be a FIELD_DECL node, compute and
type = field_type (decl);
field_size_tree = DECL_SIZE (decl);
- /* If there was an error, the size could be zero. */
+ /* The size could be unspecified if there was an error, or for
+ a flexible array member. */
if (! field_size_tree)
- {
- if (errorcount)
- return 0;
-
- abort ();
- }
+ field_size_tree = bitsize_zero_node;
/* We cannot yet cope with fields whose positions are variable, so
for now, when we see such things, we simply return 0. Someday, we may
bitpos_int = int_bit_position (decl);
- /* If we don't know the size of the field, pretend it's a full word. */
+ /* If we don't know the size of the field, pretend it's a full word. */
if (host_integerp (field_size_tree, 1))
field_size_in_bits = tree_low_cst (field_size_tree, 1);
else
}
-/* Generate *either* an DW_AT_location attribute or else an DW_AT_const_value
- data attribute for a variable or a parameter. We generate the
- DW_AT_const_value attribute only in those cases where the given variable
- or parameter does not have a true "location" either in memory or in a
- register. This can happen (for example) when a constant is passed as an
- actual argument in a call to an inline function. (It's possible that
- these things can crop up in other ways also.) Note that one type of
- constant value which can be passed into an inlined function is a constant
- pointer. This can happen for example if an actual argument in an inlined
- function call evaluates to a compile-time constant address. */
-
-static void
-add_location_or_const_value_attribute (die, decl)
- register dw_die_ref die;
- register tree decl;
+static rtx
+rtl_for_decl_location (decl)
+ tree decl;
{
register rtx rtl;
- register tree declared_type;
- register tree passed_type;
-
- if (TREE_CODE (decl) == ERROR_MARK)
- return;
-
- if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL)
- abort ();
/* Here we have to decide where we are going to say the parameter "lives"
(as far as the debugger is concerned). We only have a couple of
{
if (rtl == NULL_RTX || is_pseudo_reg (rtl))
{
- declared_type = type_main_variant (TREE_TYPE (decl));
- passed_type = type_main_variant (DECL_ARG_TYPE (decl));
+ tree declared_type = type_main_variant (TREE_TYPE (decl));
+ tree passed_type = type_main_variant (DECL_ARG_TYPE (decl));
/* This decl represents a formal parameter which was optimized out.
Note that DECL_INCOMING_RTL may be NULL in here, but we handle
}
}
- if (rtl == NULL_RTX)
- return;
-
- rtl = eliminate_regs (rtl, 0, NULL_RTX);
+ if (rtl != NULL_RTX)
+ {
+ rtl = eliminate_regs (rtl, 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
- if (current_function_uses_only_leaf_regs)
- leaf_renumber_regs_insn (rtl);
+ if (current_function_uses_only_leaf_regs)
+ leaf_renumber_regs_insn (rtl);
#endif
+ }
+
+ return rtl;
+}
+
+/* Generate *either* an DW_AT_location attribute or else an DW_AT_const_value
+ data attribute for a variable or a parameter. We generate the
+ DW_AT_const_value attribute only in those cases where the given variable
+ or parameter does not have a true "location" either in memory or in a
+ register. This can happen (for example) when a constant is passed as an
+ actual argument in a call to an inline function. (It's possible that
+ these things can crop up in other ways also.) Note that one type of
+ constant value which can be passed into an inlined function is a constant
+ pointer. This can happen for example if an actual argument in an inlined
+ function call evaluates to a compile-time constant address. */
+
+static void
+add_location_or_const_value_attribute (die, decl)
+ register dw_die_ref die;
+ register tree decl;
+{
+ register rtx rtl;
+
+ if (TREE_CODE (decl) == ERROR_MARK)
+ return;
+
+ if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL)
+ abort ();
+
+ rtl = rtl_for_decl_location (decl);
+ if (rtl == NULL_RTX)
+ return;
switch (GET_CODE (rtl))
{
default:;
}
}
-
+
/* Generate an DW_AT_name attribute given some string value to be included as
the value of the attribute. */
/* Else leave out the attribute. */
break;
- case MAX_EXPR:
case VAR_DECL:
- case COMPONENT_REF:
- /* ??? These types of bounds can be created by the Ada front end,
- and it isn't clear how to emit debug info for them. */
- break;
+ case PARM_DECL:
+ {
+ dw_die_ref decl_die = lookup_decl_die (bound);
+
+ /* ??? Can this happen, or should the variable have been bound
+ first? Probably it can, since I imagine that we try to create
+ the types of parameters in the order in which they exist in
+ the list, and won't have created a forward reference to a
+ later parameter. */
+ if (decl_die != NULL)
+ add_AT_die_ref (subrange_die, bound_attr, decl_die);
+ break;
+ }
default:
- abort ();
+ {
+ /* Otherwise try to create a stack operation procedure to
+ evaluate the value of the array bound. */
+
+ dw_die_ref ctx, decl_die;
+ dw_loc_descr_ref loc;
+
+ loc = loc_descriptor_from_tree (bound, 0);
+ if (loc == NULL)
+ break;
+
+ ctx = lookup_decl_die (current_function_decl);
+
+ decl_die = new_die (DW_TAG_variable, ctx);
+ add_AT_flag (decl_die, DW_AT_artificial, 1);
+ add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
+ add_AT_loc (decl_die, DW_AT_location, loc);
+
+ add_AT_die_ref (subrange_die, bound_attr, decl_die);
+ break;
+ }
}
}
register dw_die_ref die;
register tree decl;
{
- register unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl));
+ register unsigned file_index = lookup_filename (&decl_file_table,
+ DECL_SOURCE_FILE (decl));
add_AT_unsigned (die, DW_AT_decl_file, file_index);
add_AT_unsigned (die, DW_AT_decl_line, DECL_SOURCE_LINE (decl));
else if (old_die)
{
register unsigned file_index
- = lookup_filename (DECL_SOURCE_FILE (decl));
+ = lookup_filename (&decl_file_table, DECL_SOURCE_FILE (decl));
if (get_AT_flag (old_die, DW_AT_declaration) != 1)
{
if (DECL_NAME (decl))
{
register unsigned file_index
- = lookup_filename (DECL_SOURCE_FILE (decl));
+ = lookup_filename (&decl_file_table, DECL_SOURCE_FILE (decl));
if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index)
add_AT_unsigned (var_die, DW_AT_decl_file, file_index);
register dw_die_ref lbl_die = new_die (DW_TAG_label, context_die);
register rtx insn;
char label[MAX_ARTIFICIAL_LABEL_BYTES];
- char label2[MAX_ARTIFICIAL_LABEL_BYTES];
if (origin != NULL)
add_abstract_origin_attribute (lbl_die, origin);
if (INSN_DELETED_P (insn))
abort ();
- sprintf (label2, INSN_LABEL_FMT, current_funcdef_number);
- ASM_GENERATE_INTERNAL_LABEL (label, label2,
- (unsigned) INSN_UID (insn));
+ ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn));
add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
}
}
TREE_PUBLIC (context_list_decl) = TRUE;
add_name_attribute (unit_die, context_list);
- file_index = lookup_filename (filename);
+ file_index = lookup_filename (&decl_file_table, filename);
add_AT_unsigned (unit_die, DW_AT_decl_file, file_index);
add_pubname (context_list_decl, unit_die);
}
register unsigned blocknum;
{
function_section (current_function_decl);
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
+ ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
}
/* Output a marker (i.e. a label) for the end of the generated code for a
register unsigned blocknum;
{
function_section (current_function_decl);
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
+ ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
}
/* Returns nonzero if it is appropriate not to emit any debugging
return 1;
}
-/* Output a marker (i.e. a label) at a point in the assembly code which
- corresponds to a given source level label. */
-
-void
-dwarf2out_label (insn)
- register rtx insn;
-{
- char label[MAX_ARTIFICIAL_LABEL_BYTES];
-
- if (debug_info_level >= DINFO_LEVEL_NORMAL)
- {
- function_section (current_function_decl);
- sprintf (label, INSN_LABEL_FMT, current_funcdef_number);
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, label,
- (unsigned) INSN_UID (insn));
- }
-}
-
/* Lookup a filename (in the list of filenames that we know about here in
dwarf2out.c) and return its "index". The index of each (known) filename is
just a unique number which is associated with only that one filename.
was looked up last. This handles the majority of all searches. */
static unsigned
-lookup_filename (file_name)
+lookup_filename (t, file_name)
+ struct file_table *t;
const char *file_name;
{
- static unsigned last_file_lookup_index = 0;
register unsigned i;
- /* Check to see if the file name that was searched on the previous call
- matches this file name. If so, return the index. */
- if (last_file_lookup_index != 0)
- if (strcmp (file_name, file_table[last_file_lookup_index]) == 0)
- return last_file_lookup_index;
+ /* Check to see if the file name that was searched on the previous
+ call matches this file name. If so, return the index. */
+ if (t->last_lookup_index != 0)
+ if (strcmp (file_name, t->table[t->last_lookup_index]) == 0)
+ return t->last_lookup_index;
/* Didn't match the previous lookup, search the table */
- for (i = 1; i < file_table_in_use; ++i)
- if (strcmp (file_name, file_table[i]) == 0)
+ for (i = 1; i < t->in_use; ++i)
+ if (strcmp (file_name, t->table[i]) == 0)
{
- last_file_lookup_index = i;
+ t->last_lookup_index = i;
return i;
}
/* Prepare to add a new table entry by making sure there is enough space in
the table to do so. If not, expand the current table. */
- if (file_table_in_use == file_table_allocated)
+ if (i == t->allocated)
{
- file_table_allocated += FILE_TABLE_INCREMENT;
- file_table
- = (char **) xrealloc (file_table,
- file_table_allocated * sizeof (char *));
+ t->allocated = i + FILE_TABLE_INCREMENT;
+ t->table = (char **)
+ xrealloc (t->table, t->allocated * sizeof (char *));
}
/* Add the new entry to the end of the filename table. */
- file_table[file_table_in_use] = xstrdup (file_name);
- last_file_lookup_index = file_table_in_use++;
+ t->table[i] = xstrdup (file_name);
+ t->in_use = i + 1;
+ t->last_lookup_index = i;
+
+ return i;
+}
+
+static void
+init_file_table (t)
+ struct file_table *t;
+{
+ /* Allocate the initial hunk of the file_table. */
+ t->table = (char **) xcalloc (FILE_TABLE_INCREMENT, sizeof (char *));
+ t->allocated = FILE_TABLE_INCREMENT;
- return last_file_lookup_index;
+ /* Skip the first entry - file numbers begin at 1. */
+ t->in_use = 1;
+ t->last_lookup_index = 0;
}
/* Output a label to mark the beginning of a source code line entry
if (DWARF2_ASM_LINE_DEBUG_INFO)
{
- static const char *lastfile;
+ unsigned old_in_use = line_file_table.in_use;
+ unsigned file_num = lookup_filename (&line_file_table, filename);
/* Emit the .file and .loc directives understood by GNU as. */
- if (lastfile == 0 || strcmp (filename, lastfile))
+#if 0
+ /* ??? As of 2000-11-25, gas has a bug in which it doesn't
+ actually use the file number argument. It merely remembers
+ the last .file directive emitted. */
+ if (file_num >= old_in_use)
+ fprintf (asm_out_file, "\t.file %d \"%s\"\n", file_num, filename);
+ fprintf (asm_out_file, "\t.loc %d %d 0\n", file_num, line);
+#else
+ static int last_file_num;
+ if (file_num != last_file_num)
{
- if (lastfile == 0)
- ggc_add_string_root ((char **) &lastfile, 1);
-
+ last_file_num = file_num;
fprintf (asm_out_file, "\t.file 0 \"%s\"\n", filename);
- lastfile = filename;
}
-
fprintf (asm_out_file, "\t.loc 0 %d 0\n", line);
+#endif
/* Indicate that line number info exists. */
++line_info_table_in_use;
/* 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 = lookup_filename (filename);
+ line_info->dw_file_num = lookup_filename (&line_file_table, filename);
line_info->dw_line_num = line;
line_info->function = current_funcdef_number;
}
/* 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 = lookup_filename (filename);
+ line_info->dw_file_num = lookup_filename (&line_file_table, filename);
line_info->dw_line_num = line;
}
}
{
/* Record the end of the file for break_out_includes. */
new_die (DW_TAG_GNU_EINCL, comp_unit_die);
- }
+ }
}
/* Called from check_newline in c-parse.y. The `buffer' parameter contains
/* Remember the name of the primary input file. */
primary_filename = main_input_filename;
- /* Allocate the initial hunk of the file_table. */
- file_table = (char **) xcalloc (FILE_TABLE_INCREMENT, sizeof (char *));
- file_table_allocated = FILE_TABLE_INCREMENT;
-
- /* Skip the first entry - file numbers begin at 1. */
- file_table_in_use = 1;
+ init_file_table (&decl_file_table);
+ init_file_table (&line_file_table);
/* Allocate the initial hunk of the decl_die_table. */
decl_die_table
invoked when the given (base) source file was compiled. */
comp_unit_die = gen_compile_unit_die (main_input_filename);
- if (ggc_p)
- {
- VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray");
- ggc_add_rtx_varray_root (&used_rtx_varray, 1);
- }
+ VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray");
+ ggc_add_rtx_varray_root (&used_rtx_varray, 1);
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, ABBREV_SECTION_LABEL, 0);