OSDN Git Service

2002-05-27 H.J. Lu (hjl@gnu.org)
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 298005a..f6ef2fa 100644 (file)
@@ -298,11 +298,6 @@ static struct dw_loc_descr_struct *build_cfa_loc
 static void def_cfa_1                  PARAMS ((const char *,
                                                 dw_cfa_location *));
 
-/* .debug_str support.  */
-static hashnode indirect_string_alloc  PARAMS ((hash_table *));
-static int output_indirect_string      PARAMS ((struct cpp_reader *,
-                                                hashnode, const PTR));
-
 /* How to start an assembler comment.  */
 #ifndef ASM_COMMENT_START
 #define ASM_COMMENT_START ";#"
@@ -349,15 +344,17 @@ static int output_indirect_string PARAMS ((struct cpp_reader *,
 
 #ifdef SET_ASM_OP
 #ifndef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
-#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO)            \
- do {                                                                  \
-  fprintf (FILE, "%s", SET_ASM_OP);                                    \
-  assemble_name (FILE, SY);                                            \
-  fputc (',', FILE);                                                   \
-  assemble_name (FILE, HI);                                            \
-  fputc ('-', FILE);                                                   \
-  assemble_name (FILE, LO);                                            \
- } while (0)
+#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO)    \
+  do                                                                   \
+    {                                                                  \
+      fprintf (FILE, "%s", SET_ASM_OP);                                        \
+      assemble_name (FILE, SY);                                                \
+      fputc (',', FILE);                                               \
+      assemble_name (FILE, HI);                                                \
+      fputc ('-', FILE);                                               \
+      assemble_name (FILE, LO);                                                \
+    }                                                                  \
+  while (0)
 #endif
 #endif
 
@@ -478,8 +475,18 @@ dwarf_cfi_name (cfi_opc)
       return "DW_CFA_def_cfa_register";
     case DW_CFA_def_cfa_offset:
       return "DW_CFA_def_cfa_offset";
+
+    /* DWARF 3 */
     case DW_CFA_def_cfa_expression:
       return "DW_CFA_def_cfa_expression";
+    case DW_CFA_expression:
+      return "DW_CFA_expression";
+    case DW_CFA_offset_extended_sf:
+      return "DW_CFA_offset_extended_sf";
+    case DW_CFA_def_cfa_sf:
+      return "DW_CFA_def_cfa_sf";
+    case DW_CFA_def_cfa_offset_sf:
+      return "DW_CFA_def_cfa_offset_sf";
 
     /* SGI/MIPS specific */
     case DW_CFA_MIPS_advance_loc8:
@@ -773,10 +780,7 @@ reg_save (label, reg, sreg, offset)
 #endif
       offset /= DWARF_CIE_DATA_ALIGNMENT;
       if (offset < 0)
-       {
-         cfi->dw_cfi_opc = DW_CFA_GNU_negative_offset_extended;
-         offset = -offset;
-       }
+       cfi->dw_cfi_opc = DW_CFA_offset_extended_sf;
 
       cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
     }
@@ -931,7 +935,7 @@ initial_return_save (rtl)
 
 static long
 stack_adjust_offset (pattern)
-  rtx pattern;
+     rtx pattern;
 {
   rtx src = SET_SRC (pattern);
   rtx dest = SET_DEST (pattern);
@@ -948,6 +952,8 @@ stack_adjust_offset (pattern)
        return 0;
 
       offset = INTVAL (XEXP (src, 1));
+      if (code == PLUS)
+       offset = -offset;
     }
   else if (GET_CODE (dest) == MEM)
     {
@@ -955,30 +961,47 @@ stack_adjust_offset (pattern)
       src = XEXP (dest, 0);
       code = GET_CODE (src);
 
-      if ((code != PRE_DEC && code != PRE_INC && code != PRE_MODIFY)
-         || XEXP (src, 0) != stack_pointer_rtx)
-       return 0;
-
-      if (code == PRE_MODIFY)
+      switch (code)
        {
-         rtx val = XEXP (XEXP (src, 1), 1);
+       case PRE_MODIFY:
+       case POST_MODIFY:
+         if (XEXP (src, 0) == stack_pointer_rtx)
+           {
+             rtx val = XEXP (XEXP (src, 1), 1);
+             /* We handle only adjustments by constant amount.  */
+             if (GET_CODE (XEXP (src, 1)) != PLUS ||
+                 GET_CODE (val) != CONST_INT)
+               abort ();
+             offset = -INTVAL (val);
+             break;
+           }
+         return 0;
 
-         /* We handle only adjustments by constant amount.  */
-         if (GET_CODE (XEXP (src, 1)) != PLUS ||
-             GET_CODE (val) != CONST_INT)
-           abort();
+       case PRE_DEC:
+       case POST_DEC:
+         if (XEXP (src, 0) == stack_pointer_rtx)
+           {
+             offset = GET_MODE_SIZE (GET_MODE (dest));
+             break;
+           }
+         return 0;
+
+       case PRE_INC:
+       case POST_INC:
+         if (XEXP (src, 0) == stack_pointer_rtx)
+           {
+             offset = -GET_MODE_SIZE (GET_MODE (dest));
+             break;
+           }
+         return 0;
 
-         offset = -INTVAL (val);
+       default:
+         return 0;
        }
-      else
-       offset = GET_MODE_SIZE (GET_MODE (dest));
     }
   else
     return 0;
 
-  if (code == PLUS || code == PRE_INC)
-    offset = -offset;
-
   return offset;
 }
 
@@ -1093,7 +1116,7 @@ flush_queued_reg_saves ()
 {
   struct queued_reg_save *q, *next;
 
-  for (q = queued_reg_saves; q ; q = next)
+  for (q = queued_reg_saves; q; q = next)
     {
       dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset);
       next = q->next;
@@ -1110,13 +1133,13 @@ clobbers_queued_reg_save (insn)
 {
   struct queued_reg_save *q;
 
-  for (q = queued_reg_saves; q ; q = q->next)
+  for (q = queued_reg_saves; q; q = q->next)
     if (modified_in_p (q->reg, insn))
       return true;
 
   return false;
 }
-  
+
 
 /* A temporary register holding an integral value used in adjusting SP
    or setting up the store_reg.  The "offset" field holds the integer
@@ -1167,7 +1190,7 @@ static dw_cfa_location cfa_temp;
               stores the value, which will be used to adjust the
               stack pointer.  cfa_temp is also used like cfa_store,
               to track stores to the stack via fp or a temp reg.
+
   Rules  1- 4: Setting a register's value to cfa.reg or an expression
               with cfa.reg as the first operand changes the cfa.reg and its
               cfa.offset.  Rule 1 and 4 also set cfa_temp.reg and
@@ -1484,7 +1507,7 @@ dwarf2out_frame_debug_expr (expr, label)
        case PRE_MODIFY:
          /* We can't handle variable size modifications.  */
          if (GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1)) != CONST_INT)
-           abort();
+           abort ();
          offset = -INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1));
 
          if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM
@@ -1635,7 +1658,7 @@ dwarf2out_frame_debug (insn)
   if (! RTX_FRAME_RELATED_P (insn))
     {
       if (!ACCUMULATE_OUTGOING_ARGS)
-        dwarf2out_stack_adjust (insn);
+       dwarf2out_stack_adjust (insn);
 
       return;
     }
@@ -1719,13 +1742,19 @@ output_cfi (cfi, fde, for_eh)
          break;
 
        case DW_CFA_offset_extended:
-       case DW_CFA_GNU_negative_offset_extended:
        case DW_CFA_def_cfa:
          dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
                                       NULL);
          dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
          break;
 
+       case DW_CFA_offset_extended_sf:
+       case DW_CFA_def_cfa_sf:
+         dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
+                                      NULL);
+         dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
+         break;
+
        case DW_CFA_restore_extended:
        case DW_CFA_undefined:
        case DW_CFA_same_value:
@@ -1746,13 +1775,22 @@ output_cfi (cfi, fde, for_eh)
          dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
          break;
 
+       case DW_CFA_def_cfa_offset_sf:
+         dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
+         break;
+
        case DW_CFA_GNU_window_save:
          break;
 
        case DW_CFA_def_cfa_expression:
+       case DW_CFA_expression:
          output_cfa_loc (cfi);
          break;
 
+       case DW_CFA_GNU_negative_offset_extended:
+         /* Obsoleted by DW_CFA_offset_extended_sf.  */
+         abort ();
+
        default:
          break;
        }
@@ -1778,6 +1816,10 @@ output_call_frame_info (for_eh)
   int per_encoding = DW_EH_PE_absptr;
   int lsda_encoding = DW_EH_PE_absptr;
 
+  /* Don't emit a CIE if there won't be any FDEs.  */
+  if (fde_table_in_use == 0)
+    return;
+
   /* If we don't have any functions we'll want to unwind out of, don't emit any
      EH unwind information.  */
   if (for_eh)
@@ -1860,7 +1902,7 @@ output_call_frame_info (for_eh)
       if (p > augmentation + 1)
        {
          augmentation[0] = 'z';
-          *p = '\0';
+         *p = '\0';
        }
 
       /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
@@ -1916,7 +1958,7 @@ output_call_frame_info (for_eh)
     output_cfi (cfi, NULL, for_eh);
 
   /* Pad the CIE out to an address sized boundary.  */
-  ASM_OUTPUT_ALIGN (asm_out_file, 
+  ASM_OUTPUT_ALIGN (asm_out_file,
                    floor_log2 (for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE));
   ASM_OUTPUT_LABEL (asm_out_file, l2);
 
@@ -1926,7 +1968,8 @@ output_call_frame_info (for_eh)
       fde = &fde_table[i];
 
       /* Don't emit EH unwind info for leaf functions that don't need it.  */
-      if (for_eh && fde->nothrow && ! fde->uses_eh_lsda)
+      if (!flag_asynchronous_unwind_tables && for_eh && fde->nothrow
+         && !  fde->uses_eh_lsda)
        continue;
 
       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, FDE_LABEL, for_eh + i * 2);
@@ -1948,15 +1991,15 @@ output_call_frame_info (for_eh)
                   gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin),
                   "FDE initial location");
          dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
-                               fde->dw_fde_end, fde->dw_fde_begin, 
+                               fde->dw_fde_end, fde->dw_fde_begin,
                                "FDE address range");
        }
       else
        {
          dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin,
                               "FDE initial location");
-         dw2_asm_output_delta (DWARF2_ADDR_SIZE, 
-                               fde->dw_fde_end, fde->dw_fde_begin, 
+         dw2_asm_output_delta (DWARF2_ADDR_SIZE,
+                               fde->dw_fde_end, fde->dw_fde_begin,
                                "FDE address range");
        }
 
@@ -2009,7 +2052,7 @@ output_call_frame_info (for_eh)
        output_cfi (cfi, fde, for_eh);
 
       /* Pad the FDE out to an address sized boundary.  */
-      ASM_OUTPUT_ALIGN (asm_out_file, 
+      ASM_OUTPUT_ALIGN (asm_out_file,
                        floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)));
       ASM_OUTPUT_LABEL (asm_out_file, l2);
     }
@@ -2111,7 +2154,7 @@ dwarf2out_end_epilogue ()
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
   /* Output a label to mark the endpoint of the code generated for this
-     function.        */
+     function.  */
   ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, current_funcdef_number);
   ASM_OUTPUT_LABEL (asm_out_file, label);
   fde = &fde_table[fde_table_in_use - 1];
@@ -3046,6 +3089,12 @@ get_cfa_from_loc_descr (cfa, loc)
 /* And now, the support for symbolic debugging information.  */
 #ifdef DWARF2_DEBUGGING_INFO
 
+/* .debug_str support.  */
+static hashnode indirect_string_alloc  PARAMS ((hash_table *));
+static int output_indirect_string      PARAMS ((struct cpp_reader *,
+                                                 hashnode, const PTR));
+
+
 static void dwarf2out_init             PARAMS ((const char *));
 static void dwarf2out_finish           PARAMS ((const char *));
 static void dwarf2out_define           PARAMS ((unsigned int, const char *));
@@ -3060,7 +3109,7 @@ static void dwarf2out_abstract_function PARAMS ((tree));
 
 /* The debug hooks structure.  */
 
-struct gcc_debug_hooks dwarf2_debug_hooks =
+const struct gcc_debug_hooks dwarf2_debug_hooks =
 {
   dwarf2out_init,
   dwarf2out_finish,
@@ -3211,8 +3260,6 @@ limbo_die_node;
 /* Information concerning the compilation unit's programming
    language, and compiler version.  */
 
-extern int flag_traditional;
-
 /* Fixed size portion of the DWARF compilation unit header.  */
 #define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3)
 
@@ -3242,16 +3289,6 @@ extern int flag_traditional;
 #endif
 #endif
 
-/* 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.  */
-#ifndef DWARF_LINE_MIN_INSTR_LENGTH
-#define DWARF_LINE_MIN_INSTR_LENGTH 4
-#endif
-
 /* Minimum line offset in a special line info. opcode.
    This value was chosen to give a reasonable range of values.  */
 #define DWARF_LINE_BASE  -10
@@ -3651,7 +3688,7 @@ static void retry_incomplete_types        PARAMS ((void));
 static void gen_type_die_for_member    PARAMS ((tree, tree, dw_die_ref));
 static void splice_child_die           PARAMS ((dw_die_ref, dw_die_ref));
 static int file_info_cmp               PARAMS ((const void *, const void *));
-static dw_loc_list_ref new_loc_list     PARAMS ((dw_loc_descr_ref, 
+static dw_loc_list_ref new_loc_list     PARAMS ((dw_loc_descr_ref,
                                                 const char *, const char *,
                                                 const char *, unsigned));
 static void add_loc_descr_to_loc_list   PARAMS ((dw_loc_list_ref *,
@@ -4141,6 +4178,9 @@ dwarf_attr_name (attr)
       return "DW_AT_body_begin";
     case DW_AT_body_end:
       return "DW_AT_body_end";
+    case DW_AT_GNU_vector:
+      return "DW_AT_GNU_vector";
+
     case DW_AT_VMS_rtnbeg_pd_address:
       return "DW_AT_VMS_rtnbeg_pd_address";
 
@@ -4471,7 +4511,7 @@ add_AT_string (die, attr_kind, str)
 {
   dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
   struct indirect_string_node *node;
-  
+
   if (! debug_str_hash)
     {
       debug_str_hash = ht_create (10);
@@ -4882,7 +4922,7 @@ is_cxx ()
 {
   return (get_AT_unsigned (comp_unit_die, DW_AT_language)
          == DW_LANG_C_plus_plus);
-}  
+}
 
 static inline int
 is_fortran ()
@@ -5081,9 +5121,6 @@ static inline dw_die_ref
 lookup_type_die (type)
      tree type;
 {
-  if (TREE_CODE (type) == VECTOR_TYPE)
-    type = TYPE_DEBUG_REPRESENTATION_TYPE (type);
-
   return (dw_die_ref) TYPE_SYMTAB_POINTER (type);
 }
 
@@ -5115,8 +5152,8 @@ equate_decl_number_to_die (decl, decl_die)
      tree decl;
      dw_die_ref decl_die;
 {
-  unsigned decl_id = DECL_UID (decl);
-  unsigned num_allocated;
+  unsigned int decl_id = DECL_UID (decl);
+  unsigned int num_allocated;
 
   if (decl_id >= decl_die_table_allocated)
     {
@@ -5596,13 +5633,13 @@ is_symbol_die (c)
      dw_die_ref c;
 {
   return (is_type_die (c)
-         || (get_AT (c, DW_AT_declaration) 
+         || (get_AT (c, DW_AT_declaration)
              && !get_AT (c, DW_AT_specification)));
 }
 
 static char *
 gen_internal_sym (prefix)
-       const char *prefix;
+     const char *prefix;
 {
   char buf[256];
   static int label_num;
@@ -5649,7 +5686,7 @@ break_out_includes (die)
   dw_die_ref unit = NULL;
   limbo_die_node *node;
 
-  for (ptr = &(die->die_child); *ptr; )
+  for (ptr = &(die->die_child); *ptr;)
     {
       dw_die_ref c = *ptr;
 
@@ -5731,6 +5768,7 @@ output_location_lists (die)
     output_location_lists (c);
 
 }
+
 /* The format of each DIE (and its attribute value pairs) is encoded in an
    abbreviation table.  This routine builds the abbreviation table and assigns
    a unique abbreviation id for each abbreviation entry.  The children of each
@@ -6153,7 +6191,7 @@ new_loc_list (expr, begin, end, section, gensym)
   retlist->end = end;
   retlist->expr = expr;
   retlist->section = section;
-  if (gensym) 
+  if (gensym)
     retlist->ll_symbol = gen_internal_sym ("LLST");
 
   return retlist;
@@ -6170,7 +6208,7 @@ add_loc_descr_to_loc_list (list_head, descr, begin, end, section)
      const char *section;
 {
   dw_loc_list_ref *d;
-  
+
   /* Find the end of the chain.  */
   for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
     ;
@@ -6195,13 +6233,13 @@ output_loc_list (list_head)
   if (strcmp (curr->section, ".text") == 0)
     {
       /* dw2_asm_output_data will mask off any extra bits in the ~0.  */
-      dw2_asm_output_data (DWARF2_ADDR_SIZE, ~(unsigned HOST_WIDE_INT)0,
+      dw2_asm_output_data (DWARF2_ADDR_SIZE, ~(unsigned HOST_WIDE_INT) 0,
                           "Location list base address specifier fake entry");
       dw2_asm_output_offset (DWARF2_ADDR_SIZE, curr->section,
                             "Location list base address specifier base");
     }
 
-  for (curr = list_head; curr != NULL; curr=curr->dw_loc_next)
+  for (curr = list_head; curr != NULL; curr = curr->dw_loc_next)
     {
       unsigned long size;
 
@@ -6212,7 +6250,7 @@ output_loc_list (list_head)
                            "Location list end address (%s)",
                            list_head->ll_symbol);
       size = size_of_locs (curr->expr);
-      
+
       /* Output the block length for this list of location operations.  */
       if (size > 0xffff)
        abort ();
@@ -6301,7 +6339,7 @@ output_die (die)
 
            dw2_asm_output_data (1,
                                 2 * HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR,
-                                "%s", name);
+                                "%s", name);
 
            if (WORDS_BIG_ENDIAN)
              {
@@ -6326,7 +6364,7 @@ output_die (die)
            unsigned int i;
 
            dw2_asm_output_data (1, a->dw_attr_val.v.val_float.length * 4,
-                                "%s", name);
+                                "%s", name);
 
            for (i = 0; i < a->dw_attr_val.v.val_float.length; i++)
              dw2_asm_output_data (4, a->dw_attr_val.v.val_float.array[i],
@@ -6338,12 +6376,12 @@ output_die (die)
          dw2_asm_output_data (1, AT_flag (a), "%s", name);
          break;
 
-        case dw_val_class_loc_list:
+       case dw_val_class_loc_list:
          {
            char *sym = AT_loc_list (a)->ll_symbol;
 
            if (sym == 0)
-             abort();
+             abort ();
            dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym,
                                  loc_section_label, "%s", name);
          }
@@ -6463,16 +6501,16 @@ output_comp_unit (die)
     unmark_dies (die);
 }
 
-/* The DWARF2 pubname for a nested thingy looks like "A::f".  The output
-   of decl_printable_name for C++ looks like "A::f(int)".  Let's drop the
-   argument list, and maybe the scope.  */
+/* The DWARF2 pubname for a nested thingy looks like "A::f".  The
+   output of lang_hooks.decl_printable_name for C++ looks like
+   "A::f(int)".  Let's drop the argument list, and maybe the scope.  */
 
 static const char *
 dwarf2_name (decl, scope)
      tree decl;
      int scope;
 {
-  return (*decl_printable_name) (decl, scope ? 1 : 0);
+  return (*lang_hooks.decl_printable_name) (decl, scope ? 1 : 0);
 }
 
 /* Add a new entry to .debug_pubnames if appropriate.  */
@@ -6600,7 +6638,7 @@ output_aranges ()
       if (die->die_tag == DW_TAG_subprogram)
        {
          dw2_asm_output_addr (DWARF2_ADDR_SIZE, get_AT_low_pc (die),
-                                "Address");
+                              "Address");
          dw2_asm_output_delta (DWARF2_ADDR_SIZE, get_AT_hi_pc (die),
                                get_AT_low_pc (die), "Length");
        }
@@ -6908,7 +6946,7 @@ output_file_names ()
       if (total > dirs[i].length + 1)
        {
          /* It's worthwhile adding.  */
-          for (j = i; j < ndirs; j++)
+         for (j = i; j < ndirs; j++)
            if (savehere[j] > 0)
              {
                /* Remember how much we saved for this directory so far.  */
@@ -7008,8 +7046,17 @@ output_line_info ()
   dw2_asm_output_delta (DWARF_OFFSET_SIZE, p2, p1, "Prolog Length");
   ASM_OUTPUT_LABEL (asm_out_file, p1);
 
-  dw2_asm_output_data (1, DWARF_LINE_MIN_INSTR_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");
+
   dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START,
                       "Default is_stmt_start flag");
   dw2_asm_output_data (1, DWARF_LINE_BASE,
@@ -7460,10 +7507,10 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
 
       /* See if we already have the appropriately qualified variant of
         this type.  */
-      qualified_type 
+      qualified_type
        = get_qualified_type (type,
                              ((is_const_type ? TYPE_QUAL_CONST : 0)
-                              | (is_volatile_type 
+                              | (is_volatile_type
                                  ? TYPE_QUAL_VOLATILE : 0)));
 
       /* If we do, then we can just use its DIE, if it exists.  */
@@ -7475,7 +7522,7 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
        }
 
       /* Handle C typedef types.  */
-      if (qualified_type && TYPE_NAME (qualified_type) 
+      if (qualified_type && TYPE_NAME (qualified_type)
          && TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL
          && DECL_ORIGINAL_TYPE (TYPE_NAME (qualified_type)))
        {
@@ -7543,7 +7590,12 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
             copy was created to help us keep track of typedef names) and
             that copy might have a different TYPE_UID from the original
             ..._TYPE node.  */
-         mod_type_die = lookup_type_die (type_main_variant (type));
+         if (TREE_CODE (type) != VECTOR_TYPE)
+           mod_type_die = lookup_type_die (type_main_variant (type));
+         else
+           /* Vectors have the debugging information in the type,
+              not the main variant.  */
+           mod_type_die = lookup_type_die (type);
          if (mod_type_die == NULL)
            abort ();
        }
@@ -7687,10 +7739,10 @@ static inline int
 is_based_loc (rtl)
      rtx rtl;
 {
-    return (GET_CODE (rtl) == PLUS
-           && ((GET_CODE (XEXP (rtl, 0)) == REG
-                && REGNO (XEXP (rtl, 0)) < FIRST_PSEUDO_REGISTER
-                && GET_CODE (XEXP (rtl, 1)) == CONST_INT)));
+  return (GET_CODE (rtl) == PLUS
+         && ((GET_CODE (XEXP (rtl, 0)) == REG
+              && REGNO (XEXP (rtl, 0)) < FIRST_PSEUDO_REGISTER
+              && GET_CODE (XEXP (rtl, 1)) == CONST_INT)));
 }
 
 /* The following routine converts the RTL for a variable or parameter
@@ -7778,10 +7830,24 @@ mem_loc_descriptor (rtl, mode)
         by a different symbol.  */
       if (GET_CODE (rtl) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (rtl))
        {
-         rtx tmp = get_pool_constant (rtl);
+         bool marked;
+         rtx tmp = get_pool_constant_mark (rtl, &marked);
 
          if (GET_CODE (tmp) == SYMBOL_REF)
-           rtl = tmp;
+           {
+             rtl = tmp;
+             if (CONSTANT_POOL_ADDRESS_P (tmp))
+               get_pool_constant_mark (tmp, &marked);
+             else
+               marked = true;
+           }
+
+         /* If all references to this pool constant were optimized away,
+            it was not output and thus we can't represent it.
+            FIXME: might try to use DW_OP_const_value here, though
+            DW_OP_piece complicates it.  */
+         if (!marked)
+           return 0;
        }
 
       mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
@@ -7853,6 +7919,14 @@ mem_loc_descriptor (rtl, mode)
       mem_loc_result = int_loc_descriptor (INTVAL (rtl));
       break;
 
+    case ADDRESSOF:
+      /* If this is a MEM, return its address.  Otherwise, we can't
+        represent this.  */
+      if (GET_CODE (XEXP (rtl, 0)) == MEM)
+       return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode);
+      else
+       return 0;
+
     default:
       abort ();
     }
@@ -7964,11 +8038,28 @@ loc_descriptor_from_tree (loc, addressp)
         the names of types.  */
       return 0;
 
+    case CALL_EXPR:
+      return 0;
+
+    case ADDR_EXPR:
+      /* We can support this only if we can look through conversions and
+        find an INDIRECT_EXPR.  */
+      for (loc = TREE_OPERAND (loc, 0);
+          TREE_CODE (loc) == CONVERT_EXPR || TREE_CODE (loc) == NOP_EXPR
+          || TREE_CODE (loc) == NON_LVALUE_EXPR
+          || TREE_CODE (loc) == VIEW_CONVERT_EXPR
+          || TREE_CODE (loc) == SAVE_EXPR;
+          loc = TREE_OPERAND (loc, 0))
+       ;
+
+       return (TREE_CODE (loc) == INDIRECT_REF
+              ? loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp)
+              : 0);
+
     case VAR_DECL:
     case PARM_DECL:
       {
        rtx rtl = rtl_for_decl_location (loc);
-       enum machine_mode mode = GET_MODE (rtl);
 
        if (rtl == NULL_RTX)
          return 0;
@@ -7981,6 +8072,8 @@ loc_descriptor_from_tree (loc, addressp)
          }
        else
          {
+           enum machine_mode mode = GET_MODE (rtl);
+
            if (GET_CODE (rtl) == MEM)
              {
                indirect_p = 1;
@@ -8056,14 +8149,19 @@ loc_descriptor_from_tree (loc, addressp)
        return 0;
       break;
 
+    case TRUTH_AND_EXPR:
+    case TRUTH_ANDIF_EXPR:
     case BIT_AND_EXPR:
       op = DW_OP_and;
       goto do_binop;
 
+    case TRUTH_XOR_EXPR:
     case BIT_XOR_EXPR:
       op = DW_OP_xor;
       goto do_binop;
 
+    case TRUTH_OR_EXPR:
+    case TRUTH_ORIF_EXPR:
     case BIT_IOR_EXPR:
       op = DW_OP_or;
       goto do_binop;
@@ -8157,6 +8255,7 @@ loc_descriptor_from_tree (loc, addressp)
       add_loc_descr (&ret, new_loc_descr (op, 0, 0));
       break;
 
+    case TRUTH_NOT_EXPR:
     case BIT_NOT_EXPR:
       op = DW_OP_not;
       goto do_unop;
@@ -8183,7 +8282,7 @@ loc_descriptor_from_tree (loc, addressp)
                          TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
                   TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
 
-      /* ... fall through ... */
+      /* ... fall through ...  */
 
     case COND_EXPR:
       {
@@ -8571,7 +8670,7 @@ add_const_value_attribute (die, rtl)
         out, and the CONST_INT rtx is assigned VOIDmode.  */
       {
        HOST_WIDE_INT val = INTVAL (rtl);
-       
+
        /* ??? We really should be using HOST_WIDE_INT throughout.  */
        if (val < 0 && (long) val == val)
          add_AT_int (die, DW_AT_const_value, (long) val);
@@ -8600,7 +8699,7 @@ add_const_value_attribute (die, rtl)
        if (GET_MODE_CLASS (mode) == MODE_FLOAT)
          {
            unsigned length = GET_MODE_SIZE (mode) / 4;
-           long *array = (long *) xmalloc (sizeof (long) * length);
+           long *array = (long *) xmalloc (sizeof (long) * length);
            REAL_VALUE_TYPE rv;
 
            REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
@@ -8751,7 +8850,23 @@ rtl_for_decl_location (decl)
   /* Use DECL_RTL as the "location" unless we find something better.  */
   rtl = DECL_RTL_IF_SET (decl);
 
-  if (TREE_CODE (decl) == PARM_DECL)
+  /* When generating abstract instances, ignore everything except
+     constants and symbols living in memory.  */
+  if (! reload_completed)
+    {
+      if (rtl
+         && (CONSTANT_P (rtl)
+             || (GET_CODE (rtl) == MEM
+                 && CONSTANT_P (XEXP (rtl, 0)))))
+       {
+#ifdef ASM_SIMPLIFY_DWARF_ADDR
+         rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
+#endif
+         return rtl;
+       }
+      rtl = NULL_RTX;
+    }
+  else if (TREE_CODE (decl) == PARM_DECL)
     {
       if (rtl == NULL_RTX || is_pseudo_reg (rtl))
        {
@@ -8816,10 +8931,46 @@ rtl_for_decl_location (decl)
   /* A variable with no DECL_RTL but a DECL_INITIAL is a compile-time constant,
      and will have been substituted directly into all expressions that use it.
      C does not have such a concept, but C++ and other languages do.  */
-  else if (DECL_INITIAL (decl))
-    rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
-                      EXPAND_INITIALIZER);
+  else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl))
+    {
+      /* If a variable is initialized with a string constant without embedded
+        zeros, build CONST_STRING.  */
+      if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
+         && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+       {
+         tree arrtype = TREE_TYPE (decl);
+         tree enttype = TREE_TYPE (arrtype);
+         tree domain = TYPE_DOMAIN (arrtype);
+         tree init = DECL_INITIAL (decl);
+         enum machine_mode mode = TYPE_MODE (enttype);
+
+         if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == 1
+             && domain
+             && integer_zerop (TYPE_MIN_VALUE (domain))
+             && compare_tree_int (TYPE_MAX_VALUE (domain),
+                                  TREE_STRING_LENGTH (init) - 1) == 0
+             && ((size_t) TREE_STRING_LENGTH (init)
+                 == strlen (TREE_STRING_POINTER (init)) + 1))
+           rtl = gen_rtx_CONST_STRING (VOIDmode, TREE_STRING_POINTER (init));
+       }
+      /* If the initializer is something that we know will expand into an
+        immediate RTL constant, expand it now.  Expanding anything else
+        tends to produce unresolved symbols; see debug/5770 and c++/6381.  */
+      else if (TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST
+              || TREE_CODE (DECL_INITIAL (decl)) == REAL_CST)
+       {
+         rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
+                            EXPAND_INITIALIZER);
+         /* If expand_expr returns a MEM, it wasn't immediate.  */
+         if (rtl && GET_CODE (rtl) == MEM)
+           abort ();
+       }
+    }
 
+#ifdef ASM_SIMPLIFY_DWARF_ADDR
+  if (rtl)
+    rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
+#endif
   return rtl;
 }
 
@@ -8950,7 +9101,7 @@ add_bound_info (subrange_die, bound_attr, bound)
     case ERROR_MARK:
       return;
 
-    /* All fixed-bounds are represented by INTEGER_CST nodes.        */
+    /* All fixed-bounds are represented by INTEGER_CST nodes.  */
     case INTEGER_CST:
       if (! host_integerp (bound, 0)
          || (bound_attr == DW_AT_lower_bound
@@ -9050,6 +9201,15 @@ add_bound_info (subrange_die, bound_attr, bound)
        else
          ctx = lookup_decl_die (current_function_decl);
 
+       /* If we weren't able to find a context, it's most likely the case
+          that we are processing the return type of the function.  So
+          make a SAVE_EXPR to point to it and have the limbo DIE code
+          find the proper die.  The save_expr function doesn't always
+          make a SAVE_EXPR, so do it ourselves.  */
+       if (ctx == 0)
+         bound = build (SAVE_EXPR, TREE_TYPE (bound), bound,
+                        current_function_decl, NULL_TREE);
+
        decl_die = new_die (DW_TAG_variable, ctx, bound);
        add_AT_flag (decl_die, DW_AT_artificial, 1);
        add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
@@ -9617,6 +9777,16 @@ gen_array_type_die (type, context_die)
 #endif
 
   array_die = new_die (DW_TAG_array_type, scope_die, type);
+  add_name_attribute (array_die, type_tag (type));
+  equate_type_number_to_die (type, array_die);
+
+  if (TREE_CODE (type) == VECTOR_TYPE)
+    {
+      /* The frontend feeds us a representation for the vector as a struct
+        containing an array.  Pull out the array type.  */
+      type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
+      add_AT_flag (array_die, DW_AT_GNU_vector, 1);
+    }
 
 #if 0
   /* We default the array ordering.  SDB will probably do
@@ -9638,9 +9808,6 @@ gen_array_type_die (type, context_die)
 #endif
     add_subscript_info (array_die, type);
 
-  add_name_attribute (array_die, type_tag (type));
-  equate_type_number_to_die (type, array_die);
-
   /* Add representation of the type of the elements of this array type.  */
   element_type = TREE_TYPE (type);
 
@@ -9903,7 +10070,7 @@ gen_formal_types_die (function_or_method_type, context_die)
     }
   else
     arg = NULL_TREE;
-  
+
   first_parm_type = TYPE_ARG_TYPES (function_or_method_type);
 
   /* Make our first pass over the list of formal parameter types and output a
@@ -9987,7 +10154,7 @@ dwarf2out_abstract_function (decl)
   /* Make sure we have the actual abstract inline, not a clone.  */
   decl = DECL_ORIGIN (decl);
 
-  old_die = lookup_decl_die (decl);  
+  old_die = lookup_decl_die (decl);
   if (old_die && get_AT_unsigned (old_die, DW_AT_inline))
     /* We've already generated the abstract instance.  */
     return;
@@ -10001,7 +10168,7 @@ dwarf2out_abstract_function (decl)
        gen_type_die_for_member
          (context, decl, decl_function_context (decl) ? NULL : comp_unit_die);
     }
+
   /* Pretend we've just finished compiling this function.  */
   save_fn = current_function_decl;
   current_function_decl = decl;
@@ -10320,7 +10487,7 @@ gen_variable_die (decl, context_die)
 
      ??? Duplicated blocks have been rewritten to use .debug_ranges.  */
   else if (old_die && TREE_STATIC (decl)
-          && get_AT_flag (old_die, DW_AT_declaration) == 1)
+          && get_AT_flag (old_die, DW_AT_declaration) == 1)
     {
       /* This is a definition of a C++ class level static.  */
       add_AT_die_ref (var_die, DW_AT_specification, old_die);
@@ -10485,6 +10652,20 @@ gen_inlined_subroutine_die (stmt, context_die, depth)
       decls_for_scope (stmt, subr_die, depth);
       current_function_has_inlines = 1;
     }
+  else
+    /* We may get here if we're the outer block of function A that was
+       inlined into function B that was inlined into function C.  When
+       generating debugging info for C, dwarf2out_abstract_function(B)
+       would mark all inlined blocks as abstract, including this one.
+       So, we wouldn't (and shouldn't) expect labels to be generated
+       for this one.  Instead, just emit debugging info for
+       declarations within the block.  This is particularly important
+       in the case of initializers of arguments passed from B to us:
+       if they're statement expressions containing declarations, we
+       wouldn't generate dies for their abstract variables, and then,
+       when generating dies for the real variables, we'd die (pun
+       intended :-)  */
+    gen_lexical_block_die (stmt, context_die, depth);
 }
 
 /* Generate a DIE for a field in a record, or structure.  */
@@ -10618,8 +10799,6 @@ gen_compile_unit_die (filename)
     language = DW_LANG_Pascal83;
   else if (strcmp (language_string, "GNU Java") == 0)
     language = DW_LANG_Java;
-  else if (flag_traditional)
-    language = DW_LANG_C;
   else
     language = DW_LANG_C89;
 
@@ -10808,7 +10987,8 @@ gen_struct_or_union_type_die (type, context_die)
       add_AT_flag (type_die, DW_AT_declaration, 1);
 
       /* We don't need to do this for function-local types.  */
-      if (! decl_function_context (TYPE_STUB_DECL (type)))
+      if (TYPE_STUB_DECL (type)
+         && ! decl_function_context (TYPE_STUB_DECL (type)))
        VARRAY_PUSH_TREE (incomplete_types, type);
     }
 }
@@ -10886,10 +11066,13 @@ gen_type_die (type, context_die)
   if (type == NULL_TREE || type == error_mark_node)
     return;
 
-  /* We are going to output a DIE to represent the unqualified version of
-     this type (i.e. without any const or volatile qualifiers) so get the
-     main variant (i.e. the unqualified version) of this type now.  */
-  type = type_main_variant (type);
+  /* We are going to output a DIE to represent the unqualified version
+     of this type (i.e. without any const or volatile qualifiers) so
+     get the main variant (i.e. the unqualified version) of this type
+     now.  (Vectors are special because the debugging info is in the
+     cloned type itself).  */
+  if (TREE_CODE (type) != VECTOR_TYPE)
+    type = type_main_variant (type);
 
   if (TREE_ASM_WRITTEN (type))
     return;
@@ -10897,6 +11080,10 @@ gen_type_die (type, context_die)
   if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
       && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
     {
+      /* Prevent broken recursion; we can't hand off to the same type.  */
+      if (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) == type)
+       abort ();
+
       TREE_ASM_WRITTEN (type) = 1;
       gen_decl_die (TYPE_NAME (type), context_die);
       return;
@@ -10967,7 +11154,7 @@ gen_type_die (type, context_die)
       break;
 
     case VECTOR_TYPE:
-      gen_type_die (TYPE_DEBUG_REPRESENTATION_TYPE (type), context_die);
+      gen_array_type_die (type, context_die);
       break;
 
     case ENUMERAL_TYPE:
@@ -11386,7 +11573,7 @@ mark_limbo_die_list (ptr)
      void *ptr ATTRIBUTE_UNUSED;
 {
   limbo_die_node *node;
-  for (node = limbo_die_list; node ; node = node->next)
+  for (node = limbo_die_list; node; node = node->next)
     ggc_mark_tree (node->created_for);
 }
 \f
@@ -11639,7 +11826,11 @@ lookup_filename (file_name)
   file_table.last_lookup_index = i;
 
   if (DWARF2_ASM_LINE_DEBUG_INFO)
-    fprintf (asm_out_file, "\t.file %u \"%s\"\n", i, file_name);
+    {
+      fprintf (asm_out_file, "\t.file %u ", i);
+      output_quoted_string (asm_out_file, file_name);
+      fputc ('\n', asm_out_file);
+    }
 
   return i;
 }
@@ -11790,13 +11981,6 @@ dwarf2out_define (lineno, buffer)
      unsigned lineno ATTRIBUTE_UNUSED;
      const char *buffer ATTRIBUTE_UNUSED;
 {
-  static int initialized = 0;
-  if (!initialized)
-    {
-      dwarf2out_start_source_file (0, primary_filename);
-      initialized = 1;
-    }
-
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
       named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
@@ -11985,9 +12169,21 @@ dwarf2out_finish (input_filename)
            add_child_die (origin->die_parent, die);
          else if (die == comp_unit_die)
            ;
+         /* If this was an expression for a bound involved in a function
+            return type, it may be a SAVE_EXPR for which we weren't able
+            to find a DIE previously.  So try now.  */
+         else if (node->created_for
+                  && TREE_CODE (node->created_for) == SAVE_EXPR
+                  && 0 != (origin = (lookup_decl_die
+                                     (SAVE_EXPR_CONTEXT
+                                      (node->created_for)))))
+           add_child_die (origin, die);
+         else if (errorcount > 0 || sorrycount > 0)
+           /* It's OK to be confused by errors in the input.  */
+           add_child_die (comp_unit_die, die);
          else if (node->created_for
                   && ((DECL_P (node->created_for)
-                       && (context = DECL_CONTEXT (node->created_for)))
+                       && (context = DECL_CONTEXT (node->created_for)))
                       || (TYPE_P (node->created_for)
                           && (context = TYPE_CONTEXT (node->created_for))))
                   && TREE_CODE (context) == FUNCTION_DECL)
@@ -12002,9 +12198,6 @@ dwarf2out_finish (input_filename)
                abort ();
              add_child_die (origin, die);
            }
-         else if (errorcount > 0 || sorrycount > 0)
-           /* It's OK to be confused by errors in the input.  */
-           add_child_die (comp_unit_die, die);
          else
            abort ();
        }
@@ -12116,9 +12309,10 @@ dwarf2out_finish (input_filename)
 
   /* Have to end the primary source file.  */
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
-    { 
+    {
       named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
       dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
+      dw2_asm_output_data (1, 0, "End compilation unit");
     }
 
   /* If we emitted any DW_FORM_strp form attribute, output the string