OSDN Git Service

* dwarf2out.c (gen_compile_unit_die): Use DW_LANG_Go for Go.
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 7109c9d..850eb55 100644 (file)
@@ -98,6 +98,7 @@ along with GCC; see the file COPYING3.  If not see
 
 static void dwarf2out_source_line (unsigned int, const char *, int, bool);
 static rtx last_var_location_insn;
+static rtx cached_next_real_insn;
 
 #ifdef VMS_DEBUGGING_INFO
 int vms_file_stats_name (const char *, long long *, long *, char *, int *);
@@ -1090,6 +1091,7 @@ dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
   last_var_location_insn = NULL_RTX;
+  cached_next_real_insn = NULL_RTX;
 
   if (dwarf2out_do_cfi_asm ())
     fprintf (asm_out_file, "\t.cfi_endproc\n");
@@ -7652,7 +7654,15 @@ size_of_die (dw_die_ref die)
          size += size_of_sleb128 (AT_int (a));
          break;
        case dw_val_class_unsigned_const:
-         size += constant_size (AT_unsigned (a));
+         {
+           int csize = constant_size (AT_unsigned (a));
+           if (dwarf_version == 3
+               && a->dw_attr == DW_AT_data_member_location
+               && csize >= 4)
+             size += size_of_uleb128 (AT_unsigned (a));
+           else
+             size += csize;
+         }
          break;
        case dw_val_class_const_double:
          size += 2 * HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
@@ -7953,8 +7963,16 @@ value_format (dw_attr_ref a)
        case 2:
          return DW_FORM_data2;
        case 4:
+         /* In DWARF3 DW_AT_data_member_location with
+            DW_FORM_data4 or DW_FORM_data8 is a loclistptr, not
+            constant, so we need to use DW_FORM_udata if we need
+            a large constant.  */
+         if (dwarf_version == 3 && a->dw_attr == DW_AT_data_member_location)
+           return DW_FORM_udata;
          return DW_FORM_data4;
        case 8:
+         if (dwarf_version == 3 && a->dw_attr == DW_AT_data_member_location)
+           return DW_FORM_udata;
          return DW_FORM_data8;
        default:
          gcc_unreachable ();
@@ -8261,8 +8279,15 @@ output_die (dw_die_ref die)
          break;
 
        case dw_val_class_unsigned_const:
-         dw2_asm_output_data (constant_size (AT_unsigned (a)),
-                              AT_unsigned (a), "%s", name);
+         {
+           int csize = constant_size (AT_unsigned (a));
+           if (dwarf_version == 3
+               && a->dw_attr == DW_AT_data_member_location
+               && csize >= 4)
+             dw2_asm_output_data_uleb128 (AT_unsigned (a), "%s", name);
+           else
+             dw2_asm_output_data (csize, AT_unsigned (a), "%s", name);
+         }
          break;
 
        case dw_val_class_const_double:
@@ -9848,7 +9873,14 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
     }
   /* This probably indicates a bug.  */
   else if (mod_type_die && mod_type_die->die_tag == DW_TAG_base_type)
-    add_name_attribute (mod_type_die, "__unknown__");
+    {
+      name = TYPE_NAME (type);
+      if (name
+         && TREE_CODE (name) == TYPE_DECL)
+       name = DECL_NAME (name);
+      add_name_attribute (mod_type_die,
+                         name ? IDENTIFIER_POINTER (name) : "__unknown__");
+    }
 
   if (qualified_type)
     equate_type_number_to_die (qualified_type, mod_type_die);
@@ -11672,12 +11704,22 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
       break;
 
     case MEM:
+      {
+       rtx new_rtl = avoid_constant_pool_reference (rtl);
+       if (new_rtl != rtl)
+         {
+           mem_loc_result = mem_loc_descriptor (new_rtl, mode, mem_mode,
+                                                initialized);
+           if (mem_loc_result != NULL)
+             return mem_loc_result;
+         }
+      }
       mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0),
                                           get_address_mode (rtl), mode,
                                           VAR_INIT_STATUS_INITIALIZED);
       if (mem_loc_result == NULL)
        mem_loc_result = tls_mem_loc_descriptor (rtl);
-      if (mem_loc_result != 0)
+      if (mem_loc_result != NULL)
        {
          if (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE
              || GET_MODE_CLASS (mode) != MODE_INT)
@@ -11705,12 +11747,6 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
                           new_loc_descr (DW_OP_deref_size,
                                          GET_MODE_SIZE (mode), 0));
        }
-      else
-       {
-         rtx new_rtl = avoid_constant_pool_reference (rtl);
-         if (new_rtl != rtl)
-           return mem_loc_descriptor (new_rtl, mode, mem_mode, initialized);
-       }
       break;
 
     case LO_SUM:
@@ -12475,7 +12511,8 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
         legitimate to make the Dwarf info refer to the whole register which
         contains the given subreg.  */
       if (REG_P (SUBREG_REG (rtl)) && subreg_lowpart_p (rtl))
-       loc_result = loc_descriptor (SUBREG_REG (rtl), mode, initialized);
+       loc_result = loc_descriptor (SUBREG_REG (rtl),
+                                    GET_MODE (SUBREG_REG (rtl)), initialized);
       else
        goto do_default;
       break;
@@ -15387,7 +15424,11 @@ add_gnat_descriptive_type_attribute (dw_die_ref die, tree type,
   dtype_die = lookup_type_die (dtype);
   if (!dtype_die)
     {
+      /* The descriptive type indirectly references TYPE if this is also the
+        case for TYPE itself.  Do not deal with the circularity here.  */
+      TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) = 1;
       gen_type_die (dtype, context_die);
+      TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) = 0;
       dtype_die = lookup_type_die (dtype);
       gcc_assert (dtype_die);
     }
@@ -17986,6 +18027,14 @@ gen_label_die (tree decl, dw_die_ref context_die)
          ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn));
          add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
        }
+      else if (insn
+              && NOTE_P (insn)
+              && NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL
+              && CODE_LABEL_NUMBER (insn) != -1)
+       {
+         ASM_GENERATE_INTERNAL_LABEL (label, "LDL", CODE_LABEL_NUMBER (insn));
+         add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
+       }
     }
 }
 
@@ -18384,6 +18433,11 @@ gen_compile_unit_die (const char *filename)
        language = DW_LANG_ObjC;
       else if (strcmp (language_string, "GNU Objective-C++") == 0)
        language = DW_LANG_ObjC_plus_plus;
+      else if (dwarf_version >= 5 || !dwarf_strict)
+       {
+         if (strcmp (language_string, "GNU Go") == 0)
+           language = DW_LANG_Go;
+       }
     }
 
   add_AT_unsigned (die, DW_AT_language, language);
@@ -18800,8 +18854,9 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
 
       /* Use the DIE of the containing namespace as the parent DIE of
          the type description DIE we want to generate.  */
-      if (DECL_CONTEXT (TYPE_NAME (type))
-         && TREE_CODE (DECL_CONTEXT (TYPE_NAME (type))) == NAMESPACE_DECL)
+      if (DECL_FILE_SCOPE_P (TYPE_NAME (type))
+         || (DECL_CONTEXT (TYPE_NAME (type))
+             && TREE_CODE (DECL_CONTEXT (TYPE_NAME (type))) == NAMESPACE_DECL))
        context_die = get_context_die (DECL_CONTEXT (TYPE_NAME (type)));
 
       TREE_ASM_WRITTEN (type) = 1;
@@ -20095,10 +20150,11 @@ dwarf2out_var_location (rtx loc_note)
 {
   char loclabel[MAX_ARTIFICIAL_LABEL_BYTES + 2];
   struct var_loc_node *newloc;
-  rtx next_real;
+  rtx next_real, next_note;
   static const char *last_label;
   static const char *last_postcall_label;
   static bool last_in_cold_section_p;
+  static rtx expected_next_loc_note;
   tree decl;
   bool var_loc_p;
 
@@ -20117,7 +20173,35 @@ dwarf2out_var_location (rtx loc_note)
   if (var_loc_p && !DECL_P (NOTE_VAR_LOCATION_DECL (loc_note)))
     return;
 
-  next_real = next_real_insn (loc_note);
+  /* Optimize processing a large consecutive sequence of location
+     notes so we don't spend too much time in next_real_insn.  If the
+     next insn is another location note, remember the next_real_insn
+     calculation for next time.  */
+  next_real = cached_next_real_insn;
+  if (next_real)
+    {
+      if (expected_next_loc_note != loc_note)
+       next_real = NULL_RTX;
+    }
+
+  next_note = NEXT_INSN (loc_note);
+  if (! next_note
+      || INSN_DELETED_P (next_note)
+      || GET_CODE (next_note) != NOTE
+      || (NOTE_KIND (next_note) != NOTE_INSN_VAR_LOCATION
+         && NOTE_KIND (next_note) != NOTE_INSN_CALL_ARG_LOCATION))
+    next_note = NULL_RTX;
+
+  if (! next_real)
+    next_real = next_real_insn (loc_note);
+
+  if (next_note)
+    {
+      expected_next_loc_note = next_note;
+      cached_next_real_insn = next_real;
+    }
+  else
+    cached_next_real_insn = NULL_RTX;
 
   /* If there are no instructions which would be affected by this note,
      don't do anything.  */
@@ -20300,6 +20384,10 @@ set_cur_line_info_table (section *sec)
       VEC_safe_push (dw_line_info_table_p, gc, separate_line_info, table);
     }
 
+  if (DWARF2_ASM_LINE_DEBUG_INFO)
+    table->is_stmt = (cur_line_info_table
+                     ? cur_line_info_table->is_stmt
+                     : DWARF_LINE_DEFAULT_IS_STMT_START);
   cur_line_info_table = table;
 }
 
@@ -20397,12 +20485,27 @@ dwarf2out_source_line (unsigned int line, const char *filename,
   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);
+      /* "\t.loc %u %u 0 is_stmt %u discriminator %u",
+        file_num, line, is_stmt, discriminator */
+      fputs ("\t.loc ", asm_out_file);
+      fprint_ul (asm_out_file, file_num);
+      putc (' ', asm_out_file);
+      fprint_ul (asm_out_file, line);
+      putc (' ', asm_out_file);
+      putc ('0', asm_out_file);
+
       if (is_stmt != table->is_stmt)
-       fprintf (asm_out_file, " is_stmt %d", is_stmt ? 1 : 0);
+       {
+         fputs (" is_stmt ", asm_out_file);
+         putc (is_stmt ? '1' : '0', asm_out_file);
+       }
       if (SUPPORTS_DISCRIMINATOR && discriminator != 0)
-       fprintf (asm_out_file, " discriminator %d", discriminator);
-      fputc ('\n', asm_out_file);
+       {
+         gcc_assert (discriminator > 0);
+         fputs (" discriminator ", asm_out_file);
+         fprint_ul (asm_out_file, (unsigned long) discriminator);
+       }
+      putc ('\n', asm_out_file);
     }
   else
     {
@@ -21786,13 +21889,26 @@ resolve_addr (dw_die_ref die)
          }
        break;
       case dw_val_class_loc:
-       if (!resolve_addr_in_expr (AT_loc (a)))
-         {
-           remove_AT (die, a->dw_attr);
-           ix--;
-         }
-       else
-         mark_base_types (AT_loc (a));
+       {
+         dw_loc_descr_ref l = AT_loc (a);
+         /* For -gdwarf-2 don't attempt to optimize
+            DW_AT_data_member_location containing
+            DW_OP_plus_uconst - older consumers might
+            rely on it being that op instead of a more complex,
+            but shorter, location description.  */
+         if ((dwarf_version > 2
+              || a->dw_attr != DW_AT_data_member_location
+              || l == NULL
+              || l->dw_loc_opc != DW_OP_plus_uconst
+              || l->dw_loc_next != NULL)
+             && !resolve_addr_in_expr (l))
+           {
+             remove_AT (die, a->dw_attr);
+             ix--;
+           }
+         else
+           mark_base_types (l);
+       }
        break;
       case dw_val_class_addr:
        if (a->dw_attr == DW_AT_const_value