OSDN Git Service

* expr.c (expand_expr) [MULT_EXPR]: Do not apply distributive law
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 890b9b4..8d7d48b 100644 (file)
@@ -1,5 +1,5 @@
 /* Output Dwarf2 format symbol table information from the GNU C compiler.
-   Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
    Contributed by Gary Funck (gary@intrepid.com).
    Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
@@ -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 ";#"
@@ -478,8 +473,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 +778,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 +933,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);
@@ -966,7 +968,7 @@ stack_adjust_offset (pattern)
          /* We handle only adjustments by constant amount.  */
          if (GET_CODE (XEXP (src, 1)) != PLUS ||
              GET_CODE (val) != CONST_INT)
-           abort();
+           abort ();
 
          offset = -INTVAL (val);
        }
@@ -1484,7 +1486,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
@@ -1719,13 +1721,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 +1754,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;
        }
@@ -2111,7 +2128,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 +3063,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 *));
@@ -3177,6 +3200,7 @@ struct dw_ranges_struct
 typedef struct limbo_die_struct
 {
   dw_die_ref die;
+  tree created_for;
   struct limbo_die_struct *next;
 }
 limbo_die_node;
@@ -3241,16 +3265,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
@@ -3510,7 +3524,8 @@ static void remove_AT                     PARAMS ((dw_die_ref,
 static inline void free_die            PARAMS ((dw_die_ref));
 static void remove_children            PARAMS ((dw_die_ref));
 static void add_child_die              PARAMS ((dw_die_ref, dw_die_ref));
-static dw_die_ref new_die              PARAMS ((enum dwarf_tag, dw_die_ref));
+static dw_die_ref new_die              PARAMS ((enum dwarf_tag, dw_die_ref,
+                                                tree));
 static dw_die_ref lookup_type_die      PARAMS ((tree));
 static void equate_type_number_to_die  PARAMS ((tree, dw_die_ref));
 static dw_die_ref lookup_decl_die      PARAMS ((tree));
@@ -3657,6 +3672,7 @@ static void add_loc_descr_to_loc_list   PARAMS ((dw_loc_list_ref *,
                                                 const char *, const char *, const char *));
 static void output_loc_list            PARAMS ((dw_loc_list_ref));
 static char *gen_internal_sym          PARAMS ((const char *));
+static void mark_limbo_die_list                PARAMS ((void *));
 
 /* Section names used to hold DWARF debugging information.  */
 #ifndef DEBUG_INFO_SECTION
@@ -5047,9 +5063,10 @@ splice_child_die (parent, child)
 /* Return a pointer to a newly created DIE node.  */
 
 static inline dw_die_ref
-new_die (tag_value, parent_die)
+new_die (tag_value, parent_die, t)
      enum dwarf_tag tag_value;
      dw_die_ref parent_die;
+     tree t;
 {
   dw_die_ref die = (dw_die_ref) xcalloc (1, sizeof (die_node));
 
@@ -5063,6 +5080,7 @@ new_die (tag_value, parent_die)
 
       limbo_node = (limbo_die_node *) xmalloc (sizeof (limbo_die_node));
       limbo_node->die = die;
+      limbo_node->created_for = t;
       limbo_node->next = limbo_die_list;
       limbo_die_list = limbo_node;
     }
@@ -5110,8 +5128,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)
     {
@@ -5597,7 +5615,7 @@ is_symbol_die (c)
 
 static char *
 gen_internal_sym (prefix)
-       const char *prefix;
+     const char *prefix;
 {
   char buf[256];
   static int label_num;
@@ -6190,7 +6208,7 @@ 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");
@@ -6338,7 +6356,7 @@ output_die (die)
            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);
          }
@@ -6595,7 +6613,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");
        }
@@ -7003,8 +7021,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,
@@ -7351,7 +7378,7 @@ base_type_die (type)
       abort ();
     }
 
-  base_type_result = new_die (DW_TAG_base_type, comp_unit_die);
+  base_type_result = new_die (DW_TAG_base_type, comp_unit_die, type);
   if (demangle_name_func)
     type_name = (*demangle_name_func) (type_name);
 
@@ -7500,17 +7527,17 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
        ;
       else if (is_const_type)
        {
-         mod_type_die = new_die (DW_TAG_const_type, comp_unit_die);
+         mod_type_die = new_die (DW_TAG_const_type, comp_unit_die, type);
          sub_die = modified_type_die (type, 0, is_volatile_type, context_die);
        }
       else if (is_volatile_type)
        {
-         mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die);
+         mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die, type);
          sub_die = modified_type_die (type, 0, 0, context_die);
        }
       else if (code == POINTER_TYPE)
        {
-         mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die);
+         mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die, type);
          add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
 #if 0
          add_AT_unsigned (mod_type_die, DW_AT_address_class, 0);
@@ -7519,7 +7546,7 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
        }
       else if (code == REFERENCE_TYPE)
        {
-         mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die);
+         mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type);
          add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
 #if 0
          add_AT_unsigned (mod_type_die, DW_AT_address_class, 0);
@@ -7682,10 +7709,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
@@ -7773,10 +7800,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);
@@ -7848,6 +7889,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 ();
     }
@@ -7959,11 +8008,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;
@@ -7976,6 +8042,8 @@ loc_descriptor_from_tree (loc, addressp)
          }
        else
          {
+           enum machine_mode mode = GET_MODE (rtl);
+
            if (GET_CODE (rtl) == MEM)
              {
                indirect_p = 1;
@@ -8051,14 +8119,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;
@@ -8152,6 +8225,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;
@@ -8178,7 +8252,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:
       {
@@ -8746,7 +8820,18 @@ 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)))))
+       return rtl;
+      rtl = NULL_RTX;
+    }
+  else if (TREE_CODE (decl) == PARM_DECL)
     {
       if (rtl == NULL_RTX || is_pseudo_reg (rtl))
        {
@@ -8811,7 +8896,7 @@ 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))
+  else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl))
     rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
                       EXPAND_INITIALIZER);
 
@@ -8945,7 +9030,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
@@ -8991,7 +9076,7 @@ add_bound_info (subrange_die, bound_attr, bound)
          && (! optimize || GET_CODE (SAVE_EXPR_RTL (bound)) == MEM))
        {
          dw_die_ref ctx = lookup_decl_die (current_function_decl);
-         dw_die_ref decl_die = new_die (DW_TAG_variable, ctx);
+         dw_die_ref decl_die = new_die (DW_TAG_variable, ctx, bound);
          rtx loc = SAVE_EXPR_RTL (bound);
 
          /* If the RTL for the SAVE_EXPR is memory, handle the case where
@@ -9045,7 +9130,16 @@ add_bound_info (subrange_die, bound_attr, bound)
        else
          ctx = lookup_decl_die (current_function_decl);
 
-       decl_die = new_die (DW_TAG_variable, ctx);
+       /* 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);
        add_AT_loc (decl_die, DW_AT_location, loc);
@@ -9094,7 +9188,7 @@ add_subscript_info (type_die, type)
       /* Arrays come in three flavors: Unspecified bounds, fixed bounds,
         and (in GNU C only) variable bounds.  Handle all three forms
          here.  */
-      subrange_die = new_die (DW_TAG_subrange_type, type_die);
+      subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
       if (domain)
        {
          /* We have an array type with specified bounds.  */
@@ -9611,7 +9705,7 @@ gen_array_type_die (type, context_die)
   gen_type_die (TREE_TYPE (type), context_die);
 #endif
 
-  array_die = new_die (DW_TAG_array_type, scope_die);
+  array_die = new_die (DW_TAG_array_type, scope_die, type);
 
 #if 0
   /* We default the array ordering.  SDB will probably do
@@ -9659,7 +9753,7 @@ gen_set_type_die (type, context_die)
      dw_die_ref context_die;
 {
   dw_die_ref type_die
-    = new_die (DW_TAG_set_type, scope_die_for (type, context_die));
+    = new_die (DW_TAG_set_type, scope_die_for (type, context_die), type);
 
   equate_type_number_to_die (type, type_die);
   add_type_attribute (type_die, TREE_TYPE (type), 0, 0, context_die);
@@ -9672,7 +9766,7 @@ gen_entry_point_die (decl, context_die)
      dw_die_ref context_die;
 {
   tree origin = decl_ultimate_origin (decl);
-  dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die);
+  dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die, decl);
 
   if (origin != NULL)
     add_abstract_origin_attribute (decl_die, origin);
@@ -9709,7 +9803,7 @@ gen_inlined_enumeration_type_die (type, context_die)
      tree type;
      dw_die_ref context_die;
 {
-  dw_die_ref type_die = new_die (DW_TAG_enumeration_type, context_die);
+  dw_die_ref type_die = new_die (DW_TAG_enumeration_type, context_die, type);
 
   /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
      be incomplete and such types are not marked.  */
@@ -9723,7 +9817,7 @@ gen_inlined_structure_type_die (type, context_die)
      tree type;
      dw_die_ref context_die;
 {
-  dw_die_ref type_die = new_die (DW_TAG_structure_type, context_die);
+  dw_die_ref type_die = new_die (DW_TAG_structure_type, context_die, type);
 
   /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
      be incomplete and such types are not marked.  */
@@ -9737,7 +9831,7 @@ gen_inlined_union_type_die (type, context_die)
      tree type;
      dw_die_ref context_die;
 {
-  dw_die_ref type_die = new_die (DW_TAG_union_type, context_die);
+  dw_die_ref type_die = new_die (DW_TAG_union_type, context_die, type);
 
   /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
      be incomplete and such types are not marked.  */
@@ -9759,7 +9853,7 @@ gen_enumeration_type_die (type, context_die)
   if (type_die == NULL)
     {
       type_die = new_die (DW_TAG_enumeration_type,
-                         scope_die_for (type, context_die));
+                         scope_die_for (type, context_die), type);
       equate_type_number_to_die (type, type_die);
       add_name_attribute (type_die, type_tag (type));
     }
@@ -9788,7 +9882,7 @@ gen_enumeration_type_die (type, context_die)
       for (link = TYPE_FIELDS (type);
           link != NULL; link = TREE_CHAIN (link))
        {
-         dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die);
+         dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die, link);
 
          add_name_attribute (enum_die,
                              IDENTIFIER_POINTER (TREE_PURPOSE (link)));
@@ -9827,7 +9921,7 @@ gen_formal_parameter_die (node, context_die)
      dw_die_ref context_die;
 {
   dw_die_ref parm_die
-    = new_die (DW_TAG_formal_parameter, context_die);
+    = new_die (DW_TAG_formal_parameter, context_die, node);
   tree origin;
 
   switch (TREE_CODE_CLASS (TREE_CODE (node)))
@@ -9870,10 +9964,10 @@ gen_formal_parameter_die (node, context_die)
 
 static void
 gen_unspecified_parameters_die (decl_or_type, context_die)
-     tree decl_or_type ATTRIBUTE_UNUSED;
+     tree decl_or_type;
      dw_die_ref context_die;
 {
-  new_die (DW_TAG_unspecified_parameters, context_die);
+  new_die (DW_TAG_unspecified_parameters, context_die, decl_or_type);
 }
 
 /* Generate a list of nameless DW_TAG_formal_parameter DIEs (and perhaps a
@@ -10051,7 +10145,7 @@ gen_subprogram_die (decl, context_die)
       if (old_die && old_die->die_parent == NULL)
        add_child_die (context_die, old_die);
 
-      subr_die = new_die (DW_TAG_subprogram, context_die);
+      subr_die = new_die (DW_TAG_subprogram, context_die, decl);
       add_abstract_origin_attribute (subr_die, origin);
     }
   else if (old_die)
@@ -10095,7 +10189,7 @@ gen_subprogram_die (decl, context_die)
        }
       else
        {
-         subr_die = new_die (DW_TAG_subprogram, context_die);
+         subr_die = new_die (DW_TAG_subprogram, context_die, decl);
          add_AT_die_ref (subr_die, DW_AT_specification, old_die);
          if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index)
            add_AT_unsigned (subr_die, DW_AT_decl_file, file_index);
@@ -10107,7 +10201,7 @@ gen_subprogram_die (decl, context_die)
     }
   else
     {
-      subr_die = new_die (DW_TAG_subprogram, context_die);
+      subr_die = new_die (DW_TAG_subprogram, context_die, decl);
 
       if (TREE_PUBLIC (decl))
        add_AT_flag (subr_die, DW_AT_external, 1);
@@ -10297,7 +10391,7 @@ gen_variable_die (decl, context_die)
      dw_die_ref context_die;
 {
   tree origin = decl_ultimate_origin (decl);
-  dw_die_ref var_die = new_die (DW_TAG_variable, context_die);
+  dw_die_ref var_die = new_die (DW_TAG_variable, context_die, decl);
 
   dw_die_ref old_die = lookup_decl_die (decl);
   int declaration = (DECL_EXTERNAL (decl)
@@ -10374,7 +10468,7 @@ gen_label_die (decl, context_die)
      dw_die_ref context_die;
 {
   tree origin = decl_ultimate_origin (decl);
-  dw_die_ref lbl_die = new_die (DW_TAG_label, context_die);
+  dw_die_ref lbl_die = new_die (DW_TAG_label, context_die, decl);
   rtx insn;
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
@@ -10418,7 +10512,7 @@ gen_lexical_block_die (stmt, context_die, depth)
      dw_die_ref context_die;
      int depth;
 {
-  dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die);
+  dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
   if (! BLOCK_ABSTRACT (stmt))
@@ -10463,7 +10557,7 @@ gen_inlined_subroutine_die (stmt, context_die, depth)
   if (! BLOCK_ABSTRACT (stmt))
     {
       dw_die_ref subr_die
-       = new_die (DW_TAG_inlined_subroutine, context_die);
+       = new_die (DW_TAG_inlined_subroutine, context_die, stmt);
       tree decl = block_ultimate_origin (stmt);
       char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
@@ -10489,7 +10583,7 @@ gen_field_die (decl, context_die)
      tree decl;
      dw_die_ref context_die;
 {
-  dw_die_ref decl_die = new_die (DW_TAG_member, context_die);
+  dw_die_ref decl_die = new_die (DW_TAG_member, context_die, decl);
 
   add_name_and_src_coords_attributes (decl_die, decl);
   add_type_attribute (decl_die, member_declared_type (decl),
@@ -10527,7 +10621,7 @@ gen_pointer_type_die (type, context_die)
      dw_die_ref context_die;
 {
   dw_die_ref ptr_die
-    = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die));
+    = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die), type);
 
   equate_type_number_to_die (type, ptr_die);
   add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die);
@@ -10545,7 +10639,7 @@ gen_reference_type_die (type, context_die)
      dw_die_ref context_die;
 {
   dw_die_ref ref_die
-    = new_die (DW_TAG_reference_type, scope_die_for (type, context_die));
+    = new_die (DW_TAG_reference_type, scope_die_for (type, context_die), type);
 
   equate_type_number_to_die (type, ref_die);
   add_type_attribute (ref_die, TREE_TYPE (type), 0, 0, context_die);
@@ -10561,7 +10655,8 @@ gen_ptr_to_mbr_type_die (type, context_die)
      dw_die_ref context_die;
 {
   dw_die_ref ptr_die
-    = new_die (DW_TAG_ptr_to_member_type, scope_die_for (type, context_die));
+    = new_die (DW_TAG_ptr_to_member_type,
+              scope_die_for (type, context_die), type);
 
   equate_type_number_to_die (type, ptr_die);
   add_AT_die_ref (ptr_die, DW_AT_containing_type,
@@ -10581,7 +10676,7 @@ gen_compile_unit_die (filename)
   const char *language_string = lang_hooks.name;
   int language;
 
-  die = new_die (DW_TAG_compile_unit, NULL);
+  die = new_die (DW_TAG_compile_unit, NULL, NULL);
   add_name_attribute (die, filename);
 
   if (wd != NULL && filename[0] != DIR_SEPARATOR)
@@ -10629,7 +10724,7 @@ gen_string_type_die (type, context_die)
      dw_die_ref context_die;
 {
   dw_die_ref type_die
-    = new_die (DW_TAG_string_type, scope_die_for (type, context_die));
+    = new_die (DW_TAG_string_type, scope_die_for (type, context_die), type);
 
   equate_type_number_to_die (type, type_die);
 
@@ -10648,7 +10743,7 @@ gen_inheritance_die (binfo, context_die)
      tree binfo;
      dw_die_ref context_die;
 {
-  dw_die_ref die = new_die (DW_TAG_inheritance, context_die);
+  dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo);
 
   add_type_attribute (die, BINFO_TYPE (binfo), 0, 0, context_die);
   add_data_member_location_attribute (die, binfo);
@@ -10757,7 +10852,7 @@ gen_struct_or_union_type_die (type, context_die)
 
       type_die = new_die (TREE_CODE (type) == RECORD_TYPE
                          ? DW_TAG_structure_type : DW_TAG_union_type,
-                         scope_die);
+                         scope_die, type);
       equate_type_number_to_die (type, type_die);
       if (old_die)
        add_AT_die_ref (type_die, DW_AT_specification, old_die);
@@ -10802,7 +10897,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);
     }
 }
@@ -10816,7 +10912,8 @@ gen_subroutine_type_die (type, context_die)
 {
   tree return_type = TREE_TYPE (type);
   dw_die_ref subr_die
-    = new_die (DW_TAG_subroutine_type, scope_die_for (type, context_die));
+    = new_die (DW_TAG_subroutine_type,
+              scope_die_for (type, context_die), type);
 
   equate_type_number_to_die (type, subr_die);
   add_prototyped_attribute (subr_die, type);
@@ -10838,7 +10935,7 @@ gen_typedef_die (decl, context_die)
     return;
 
   TREE_ASM_WRITTEN (decl) = 1;
-  type_die = new_die (DW_TAG_typedef, context_die);
+  type_die = new_die (DW_TAG_typedef, context_die, decl);
   origin = decl_ultimate_origin (decl);
   if (origin != NULL)
     add_abstract_origin_attribute (type_die, origin);
@@ -11373,6 +11470,15 @@ gen_decl_die (decl, context_die)
       abort ();
     }
 }
+
+static void
+mark_limbo_die_list (ptr)
+     void *ptr ATTRIBUTE_UNUSED;
+{
+  limbo_die_node *node;
+  for (node = limbo_die_list; node ; node = node->next)
+    ggc_mark_tree (node->created_for);
+}
 \f
 /* Add Ada "use" clause information for SGI Workshop debugger.  */
 
@@ -11385,7 +11491,7 @@ dwarf2out_add_library_unit_info (filename, context_list)
 
   if (filename != NULL)
     {
-      dw_die_ref unit_die = new_die (DW_TAG_module, comp_unit_die);
+      dw_die_ref unit_die = new_die (DW_TAG_module, comp_unit_die, NULL);
       tree context_list_decl
        = build_decl (LABEL_DECL, get_identifier (context_list),
                      void_type_node);
@@ -11733,7 +11839,7 @@ dwarf2out_start_source_file (lineno, filename)
   if (flag_eliminate_dwarf2_dups)
     {
       /* Record the beginning of the file for break_out_includes.  */
-      dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die);
+      dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL);
       add_AT_string (bincl_die, DW_AT_name, filename);
     }
 
@@ -11756,7 +11862,7 @@ dwarf2out_end_source_file (lineno)
 {
   if (flag_eliminate_dwarf2_dups)
     /* Record the end of the file for break_out_includes.  */
-    new_die (DW_TAG_GNU_EINCL, comp_unit_die);
+    new_die (DW_TAG_GNU_EINCL, comp_unit_die, NULL);
 
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
@@ -11864,6 +11970,8 @@ dwarf2out_init (main_input_filename)
   VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray");
   ggc_add_rtx_varray_root (&used_rtx_varray, 1);
 
+  ggc_add_root (&limbo_die_list, 1, 1, mark_limbo_die_list);
+
   ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
                               DEBUG_ABBREV_SECTION_LABEL, 0);
@@ -11961,14 +12069,41 @@ dwarf2out_finish (input_filename)
       if (die->die_parent == NULL)
        {
          dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
+         tree context;
 
          if (origin)
            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)))
+                      || (TYPE_P (node->created_for)
+                          && (context = TYPE_CONTEXT (node->created_for))))
+                  && TREE_CODE (context) == FUNCTION_DECL)
+           {
+             /* In certain situations, the lexical block containing a
+                nested function can be optimized away, which results
+                in the nested function die being orphaned.  Likewise
+                with the return type of that nested function.  Force
+                this to be a child of the containing function.  */
+             origin = lookup_decl_die (context);
+             if (! origin)
+               abort ();
+             add_child_die (origin, die);
+           }
          else
            abort ();
        }