*** empty log message ***
authorJason Merrill <merrill@gnu.org>
Mon, 7 Oct 1996 22:02:43 +0000 (22:02 +0000)
committerJason Merrill <merrill@gnu.org>
Mon, 7 Oct 1996 22:02:43 +0000 (22:02 +0000)
From-SVN: r12911

gcc/dwarf2.h
gcc/dwarf2out.c

index 483607312c0adfbec9308c0d8c1231ba8f641941..98556cdc2a4ef0295fff18984b3c27ce09af9c59 100644 (file)
@@ -193,6 +193,10 @@ enum dwarf_attribute
     DW_AT_MIPS_loop_unroll_factor = 0x2005,
     DW_AT_MIPS_software_pipeline_depth = 0x2006,
     DW_AT_MIPS_linkage_name = 0x2007,
+    DW_AT_MIPS_stride = 0x2008,
+    DW_AT_MIPS_abstract_name = 0x2009,
+    DW_AT_MIPS_clone_origin = 0x200a,
+    DW_AT_MIPS_has_inlines = 0x200b,
     /* GNU extensions.  */
     DW_AT_sf_names = 0x2101,
     DW_AT_src_info = 0x2102,
index 1f83237c872957f92e4d56082cdadb9a07414d62..fe3db1e6d5023d2270fa268cb555c659c8abd343 100644 (file)
@@ -105,6 +105,7 @@ typedef struct die_struct *dw_die_ref;
 typedef struct dw_attr_struct *dw_attr_ref;
 typedef struct dw_val_struct *dw_val_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 dw_loc_descr_struct *dw_loc_descr_ref;
 typedef struct dw_cfi_struct *dw_cfi_ref;
 typedef struct dw_fde_struct *dw_fde_ref;
@@ -129,6 +130,16 @@ typedef struct dw_line_info_struct
   }
 dw_line_info_entry;
 
+/* Line information for functions in separate sections; each one gets its
+   own sequence.  */
+typedef struct dw_separate_line_info_struct
+  {
+    unsigned long dw_file_num;
+    unsigned long dw_line_num;
+    unsigned long function;
+  }
+dw_separate_line_info_entry;
+
 /* The dw_val_node describes an attibute's value, as it is
    represnted internally.  */
 typedef struct dw_val_struct
@@ -448,12 +459,22 @@ static unsigned abbrev_die_table_in_use;
 #define ABBREV_DIE_TABLE_INCREMENT 256
 
 /* A pointer to the base of a table that contains line information
-   for each source code line in the compilation unit.  */
+   for each source code line in .text in the compilation unit.  */
 static dw_line_info_ref line_info_table;
 
 /* Number of elements currently allocated for line_info_table.  */
 static unsigned line_info_table_allocated;
 
+/* Number of elements in separate_line_info_table currently in use.  */
+static unsigned separate_line_info_table_in_use;
+
+/* 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 dw_separate_line_info_ref separate_line_info_table;
+
+/* Number of elements currently allocated for separate_line_info_table.  */
+static unsigned separate_line_info_table_allocated;
+
 /* Number of elements in line_info_table currently in use.  */
 static unsigned line_info_table_in_use;
 
@@ -703,6 +724,9 @@ static unsigned lookup_filename ();
 #ifndef LINE_CODE_LABEL_FMT
 #define LINE_CODE_LABEL_FMT    ".L_LC%u"
 #endif
+#ifndef SEPARATE_LINE_CODE_LABEL_FMT
+#define SEPARATE_LINE_CODE_LABEL_FMT   ".L_SLC%u"
+#endif
 #ifndef SFNAMES_ENTRY_LABEL_FMT
 #define SFNAMES_ENTRY_LABEL_FMT        ".L_F%u"
 #endif
@@ -2212,7 +2236,7 @@ remove_AT (die, attr_kind)
            if (die->die_attr_last == a->dw_attr_next)
              die->die_attr_last = a;
            a->dw_attr_next = a->dw_attr_next->dw_attr_next;
-           return;
+           break;
          }
       if (removed)
        free (removed);
@@ -2952,12 +2976,12 @@ static unsigned long
 size_of_line_info ()
 {
   register unsigned long size;
-  register dw_line_info_ref line_info;
   register unsigned long lt_index;
   register unsigned long current_line;
   register long line_offset;
   register long line_delta;
   register unsigned long current_file;
+  register unsigned long function;
   /* Version number.  */
   size = 2;
   /* Prolog length specifier.  */
@@ -2971,6 +2995,7 @@ size_of_line_info ()
   current_line = 1;
   for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
     {
+      register dw_line_info_ref line_info;
       /* Advance pc instruction.  */
       size += 1 + 2;
       line_info = &line_info_table[lt_index];
@@ -3005,6 +3030,65 @@ size_of_line_info ()
   size += 1 + 2;
   /* End of line number info. marker.  */
   size += 1 + size_of_uleb128 (1) + 1;
+  function = 0;
+  current_file = 1;
+  current_line = 1;
+  for (lt_index = 0; lt_index < separate_line_info_table_in_use; )
+    {
+      register dw_separate_line_info_ref line_info
+       = &separate_line_info_table[lt_index];
+      if (function != line_info->function)
+       {
+         function = line_info->function;
+         /* Set address register instruction.  */
+         size += 1 + size_of_uleb128 (1 + PTR_SIZE)
+           + 1 + PTR_SIZE;
+       }
+      else
+       {
+         /* Advance pc instruction.  */
+         size += 1 + 2;
+       }
+      if (line_info->dw_file_num != current_file)
+       {
+         /* Set file number instruction.  */
+         size += 1;
+         current_file = line_info->dw_file_num;
+         size += size_of_uleb128 (current_file);
+       }
+      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))
+           {
+             /* 1-byte special line number instruction.  */
+             size += 1;
+           }
+         else
+           {
+             /* Advance line instruction.  */
+             size += 1;
+             size += size_of_sleb128 (line_offset);
+             /* Generate line entry instruction.  */
+             size += 1;
+           }
+       }
+      ++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;
+         /* Advance pc instruction.  */
+         size += 1 + 2;
+         /* End of line number info. marker.  */
+         size += 1 + size_of_uleb128 (1) + 1;
+       }
+    }
   return size;
 }
 
@@ -3999,21 +4083,18 @@ output_aranges ()
 static void
 output_line_info ()
 {
-  register unsigned long line_info_len;
-  register unsigned long line_info_prolog_len;
   char line_label[MAX_ARTIFICIAL_LABEL_BYTES];
   char prev_line_label[MAX_ARTIFICIAL_LABEL_BYTES];
   register unsigned opc;
   register unsigned n_op_args;
-  register dw_line_info_ref line_info;
   register unsigned long ft_index;
   register unsigned long lt_index;
   register unsigned long current_line;
   register long line_offset;
   register long line_delta;
   register unsigned long current_file;
-  line_info_len = size_of_line_info ();
-  ASM_OUTPUT_DWARF_DATA4 (asm_out_file, line_info_len);
+  register unsigned long function;
+  ASM_OUTPUT_DWARF_DATA4 (asm_out_file, size_of_line_info ());
   if (flag_verbose_asm)
     {
       fprintf (asm_out_file, "\t%s Length of Source Line Info.",
@@ -4027,8 +4108,7 @@ output_line_info ()
               ASM_COMMENT_START);
     }
   fputc ('\n', asm_out_file);
-  line_info_prolog_len = size_of_line_prolog ();
-  ASM_OUTPUT_DWARF_DATA4 (asm_out_file, line_info_prolog_len);
+  ASM_OUTPUT_DWARF_DATA4 (asm_out_file, size_of_line_prolog ());
   if (flag_verbose_asm)
     {
       fprintf (asm_out_file, "\t%s Prolog Length",
@@ -4149,6 +4229,7 @@ output_line_info ()
   strcpy (prev_line_label, TEXT_SECTION);
   for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
     {
+      register dw_line_info_ref line_info;
       ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_fixed_advance_pc);
       if (flag_verbose_asm)
        {
@@ -4234,6 +4315,121 @@ output_line_info ()
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_end_sequence);
   fputc ('\n', asm_out_file);
+
+  function = 0;
+  current_file = 1;
+  current_line = 1;
+  for (lt_index = 0; lt_index < separate_line_info_table_in_use; )
+    {
+      register dw_separate_line_info_ref line_info
+       = &separate_line_info_table[lt_index];
+      sprintf (line_label, SEPARATE_LINE_CODE_LABEL_FMT, lt_index);
+      if (function != line_info->function)
+       {
+         function = line_info->function;
+         /* Set the address register to the first line in the function */
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
+         if (flag_verbose_asm)
+           fprintf (asm_out_file, "\t%s DW_LNE_set_address",
+                    ASM_COMMENT_START);
+         fputc ('\n', asm_out_file);
+         output_uleb128 (1 + PTR_SIZE);
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_set_address);
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_DWARF_ADDR (asm_out_file, line_label);
+         fputc ('\n', asm_out_file);
+       }
+      else
+       {
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_fixed_advance_pc);
+         if (flag_verbose_asm)
+           fprintf (asm_out_file, "\t%s DW_LNS_fixed_advance_pc",
+                    ASM_COMMENT_START);
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, line_label, prev_line_label);
+         fputc ('\n', asm_out_file);
+       }
+      if (line_info->dw_file_num != current_file)
+       {
+         current_file = line_info->dw_file_num;
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_set_file);
+         if (flag_verbose_asm)
+           {
+             fprintf (asm_out_file,
+                      "\t%s DW_LNS_set_file", ASM_COMMENT_START);
+           }
+         fputc ('\n', asm_out_file);
+         output_uleb128 (current_file);
+         if (flag_verbose_asm)
+           {
+             fprintf (asm_out_file, "\t%s \"%s\"",
+                      ASM_COMMENT_START, file_table[current_file]);
+           }
+         fputc ('\n', asm_out_file);
+       }
+      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))
+           {
+             ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+                                     DWARF_LINE_OPCODE_BASE + line_delta);
+             if (flag_verbose_asm)
+               {
+                 fprintf (asm_out_file,
+                          "\t%s line %d", ASM_COMMENT_START, current_line);
+               }
+             fputc ('\n', asm_out_file);
+           }
+         else
+           {
+             ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
+             if (flag_verbose_asm)
+               {
+                 fprintf (asm_out_file,
+                          "\t%s advance to line %d",
+                          ASM_COMMENT_START, current_line);
+               }
+             fputc ('\n', asm_out_file);
+             output_sleb128 (line_offset);
+             fputc ('\n', asm_out_file);
+             ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+             fputc ('\n', asm_out_file);
+           }
+       }
+      ++lt_index;
+      strcpy (prev_line_label, line_label);
+
+      /* 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;
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_fixed_advance_pc);
+         if (flag_verbose_asm)
+           fprintf (asm_out_file, "\t%s DW_LNS_fixed_advance_pc",
+                    ASM_COMMENT_START);
+         fputc ('\n', asm_out_file);
+         sprintf (line_label, FUNC_END_LABEL_FMT, function);
+         ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, line_label, prev_line_label);
+         fputc ('\n', asm_out_file);
+
+         /* Output the marker for the end of this sequence.  */
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
+         if (flag_verbose_asm)
+           fprintf (asm_out_file, "\t%s DW_LNE_end_sequence",
+                    ASM_COMMENT_START);
+         fputc ('\n', asm_out_file);
+         output_uleb128 (1);
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_end_sequence);
+         fputc ('\n', asm_out_file);
+       }
+    }
 }
 \f
 /**************** attribute support utilities ********************************/
@@ -6562,15 +6758,9 @@ gen_compile_unit_die (main_input_filename)
     {
       add_AT_unsigned (comp_unit_die, DW_AT_language, DW_LANG_C89);
     }
-  add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, TEXT_SECTION);
-  add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, TEXT_END_LABEL);
-  if (debug_info_level >= DINFO_LEVEL_NORMAL)
+  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
-      add_AT_section_offset (comp_unit_die, DW_AT_stmt_list, LINE_SECTION);
-      if (debug_info_level >= DINFO_LEVEL_VERBOSE)
-       {
-         add_AT_unsigned (comp_unit_die, DW_AT_macro_info, 0);
-       }
+      add_AT_unsigned (comp_unit_die, DW_AT_macro_info, 0);
     }
 }
 
@@ -6800,7 +6990,7 @@ gen_type_die (type, context_die)
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
-      /* For a non-file-scope tagged type, we can always go ahead and output
+      /* For a function-scope tagged type, we can always go ahead and output
          a Dwarf description of this type right now, even if the type in
          question is still incomplete, because if this local type *was* ever
          completed anywhere within its scope, that complete definition would
@@ -6827,7 +7017,8 @@ gen_type_die (type, context_die)
          ever going to know, so at that point in time, we can safely generate 
          correct Dwarf descriptions for these file-scope tagged types.  */
       is_complete = TYPE_SIZE (type) != 0
-       || TYPE_CONTEXT (type) != NULL
+       || (TYPE_CONTEXT (type) != NULL
+           && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) != 't')
        || finalizing;
       if (TREE_CODE (type) == ENUMERAL_TYPE)
        {
@@ -7569,27 +7760,57 @@ dwarfout_line (filename, line)
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
   register unsigned this_file_entry_num = lookup_filename (filename);
-  register dw_line_info_ref line_info;
   if (debug_info_level >= DINFO_LEVEL_NORMAL)
     {
       function_section (current_function_decl);
-      sprintf (label, LINE_CODE_LABEL_FMT, line_info_table_in_use);
-      ASM_OUTPUT_LABEL (asm_out_file, label);
-      fputc ('\n', asm_out_file);
 
-      /* expand the line info table if necessary */
-      if (line_info_table_in_use == line_info_table_allocated)
+      if (DECL_SECTION_NAME (current_function_decl))
        {
-         line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
-         line_info_table
-           = (dw_line_info_ref)
-           xrealloc (line_info_table,
-                  line_info_table_allocated * sizeof (dw_line_info_entry));
+         register dw_separate_line_info_ref line_info;
+         sprintf (label, SEPARATE_LINE_CODE_LABEL_FMT,
+                  separate_line_info_table_in_use);
+         ASM_OUTPUT_LABEL (asm_out_file, label);
+         fputc ('\n', asm_out_file);
+
+         /* 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
+               = (dw_separate_line_info_ref) xrealloc
+               (separate_line_info_table,
+                separate_line_info_table_allocated
+                * 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 = lookup_filename (filename);
+         line_info->dw_line_num = line;
+         line_info->function = current_funcdef_number;
+       }
+      else
+       {
+         register dw_line_info_ref line_info;
+         sprintf (label, LINE_CODE_LABEL_FMT, line_info_table_in_use);
+         ASM_OUTPUT_LABEL (asm_out_file, label);
+         fputc ('\n', asm_out_file);
+
+         /* 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
+               = (dw_line_info_ref) xrealloc
+               (line_info_table,
+                line_info_table_allocated * 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 = lookup_filename (filename);
+         line_info->dw_line_num = line;
        }
-      /* 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_line_num = line;
     }
 }
 
@@ -7762,17 +7983,29 @@ dwarfout_finish ()
   ASM_OUTPUT_LABEL (asm_out_file, BSS_END_LABEL);
 #endif
 
+  /* Output the source line correspondence table.  */
+  if (line_info_table_in_use > 1 || separate_line_info_table_in_use)
+    {
+      fputc ('\n', asm_out_file);
+      ASM_OUTPUT_SECTION (asm_out_file, LINE_SECTION);
+      output_line_info ();
+
+      /* We can only use the low/high_pc attributes if all of the code
+        was in .text.  */
+      if (separate_line_info_table_in_use == 0)
+       {
+         add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, TEXT_SECTION);
+         add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, TEXT_END_LABEL);
+       }
+      add_AT_section_offset (comp_unit_die, DW_AT_stmt_list, LINE_SECTION);
+    }
+
   /* Output the abbreviation table.  */
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION);
   build_abbrev_table (comp_unit_die);
   output_abbrev_section ();
 
-  /* Output the source line correspondence table.  */
-  fputc ('\n', asm_out_file);
-  ASM_OUTPUT_SECTION (asm_out_file, LINE_SECTION);
-  output_line_info ();
-
   /* Initialize the beginning DIE offset - and calculate sizes/offsets.   */
   next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
   calc_die_sizes (comp_unit_die);