OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index bf93491..237c4a4 100644 (file)
@@ -105,6 +105,7 @@ typedef union dw_cfi_oprnd_struct
   unsigned long dw_cfi_reg_num;
   long int dw_cfi_offset;
   const char *dw_cfi_addr;
+  struct dw_loc_descr_struct *dw_cfi_loc;
 }
 dw_cfi_oprnd;
 
@@ -117,6 +118,19 @@ typedef struct dw_cfi_struct
 }
 dw_cfi_node;
 
+/* This is how we define the location of the CFA. We use to handle it
+   as REG + OFFSET all the time,  but now it can be more complex.
+   It can now be either REG + CFA_OFFSET or *(REG + BASE_OFFSET) + CFA_OFFSET.
+   Instead of passing around REG and OFFSET, we pass a copy 
+   of this structure.  */
+typedef struct cfa_loc
+{
+  unsigned long reg;  
+  long offset;
+  long base_offset;
+  int indirect;            /* 1 if CFA is accessed via a dereference.  */
+} dw_cfa_location;
+
 /* All call frame descriptions (FDE's) in the GCC generated DWARF
    refer to a single Common Information Entry (CIE), defined at
    the beginning of the .debug_frame section.  This used of a single
@@ -222,18 +236,24 @@ static unsigned long size_of_sleb128      PARAMS ((long));
 static void output_uleb128             PARAMS ((unsigned long));
 static void output_sleb128             PARAMS ((long));
 static void add_fde_cfi                        PARAMS ((const char *, dw_cfi_ref));
-static void lookup_cfa_1               PARAMS ((dw_cfi_ref, unsigned long *,
-                                                long *));
-static void lookup_cfa                 PARAMS ((unsigned long *, long *));
+static void lookup_cfa_1               PARAMS ((dw_cfi_ref, dw_cfa_location *));
+static void lookup_cfa                 PARAMS ((dw_cfa_location *));
 static void reg_save                   PARAMS ((const char *, unsigned,
                                                 unsigned, long));
 static void initial_return_save                PARAMS ((rtx));
 static void output_cfi                 PARAMS ((dw_cfi_ref, dw_fde_ref));
 static void output_call_frame_info     PARAMS ((int));
-static unsigned int reg_number         PARAMS ((rtx));
 static void dwarf2out_stack_adjust     PARAMS ((rtx));
 static void dwarf2out_frame_debug_expr PARAMS ((rtx, const char *));
 
+/* Support for complex CFA locations.  */
+static void output_cfa_loc             PARAMS ((dw_cfi_ref));
+static void get_cfa_from_loc_descr     PARAMS ((dw_cfa_location *, 
+                                               struct dw_loc_descr_struct *));
+static struct dw_loc_descr_struct *build_cfa_loc
+                                       PARAMS ((dw_cfa_location *));
+static void def_cfa_1                  PARAMS ((const char *, dw_cfa_location *));
+
 /* Definitions of defaults for assembler-dependent names of various
    pseudo-ops and section names.
    Theses may be overridden in the tm.h file (if necessary) for a particular
@@ -405,6 +425,12 @@ static void dwarf2out_frame_debug_expr     PARAMS ((rtx, const char *));
   fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_INT_ASM_OP, (unsigned) (VALUE))
 #endif
 
+#ifndef ASM_OUTPUT_DWARF_DATA8
+#define ASM_OUTPUT_DWARF_DATA8(FILE,VALUE) \
+  fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_DOUBLE_INT_ASM_OP, \
+          (unsigned long) (VALUE))
+#endif
+
 #ifndef ASM_OUTPUT_DWARF_DATA
 #define ASM_OUTPUT_DWARF_DATA(FILE,VALUE) \
   fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP, \
@@ -417,8 +443,8 @@ static void dwarf2out_frame_debug_expr      PARAMS ((rtx, const char *));
           (unsigned long) (VALUE))
 #endif
 
-#ifndef ASM_OUTPUT_DWARF_DATA8
-#define ASM_OUTPUT_DWARF_DATA8(FILE,HIGH_VALUE,LOW_VALUE)              \
+#ifndef ASM_OUTPUT_DWARF_CONST_DOUBLE
+#define ASM_OUTPUT_DWARF_CONST_DOUBLE(FILE,HIGH_VALUE,LOW_VALUE)       \
   do {                                                                 \
     if (WORDS_BIG_ENDIAN)                                              \
       {                                                                        \
@@ -438,38 +464,63 @@ static void dwarf2out_frame_debug_expr    PARAMS ((rtx, const char *));
 /* We don't have unaligned support, let's hope the normal output works for
    .debug_frame.  */
 
+#ifndef ASM_OUTPUT_DWARF_ADDR
 #define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \
   assemble_integer (gen_rtx_SYMBOL_REF (Pmode, LABEL), DWARF2_ADDR_SIZE, 1)
+#endif
 
+#ifndef ASM_OUTPUT_DWARF_ADDR_CONST
+#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,RTX) ASM_OUTPUT_DWARF_ADDR (FILE,RTX)
+#endif
+
+#ifndef ASM_OUTPUT_DWARF_OFFSET4
 #define ASM_OUTPUT_DWARF_OFFSET4(FILE,LABEL) \
   assemble_integer (gen_rtx_SYMBOL_REF (SImode, LABEL), 4, 1)
+#endif
 
+#ifndef ASM_OUTPUT_DWARF_OFFSET
 #define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL) \
   assemble_integer (gen_rtx_SYMBOL_REF (SImode, LABEL), 4, 1)
+#endif
 
+#ifndef ASM_OUTPUT_DWARF_DELTA2
 #define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2)                    \
   assemble_integer (gen_rtx_MINUS (HImode,                             \
                                   gen_rtx_SYMBOL_REF (Pmode, LABEL1),  \
                                   gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
                    2, 1)
+#endif
   
+#ifndef ASM_OUTPUT_DWARF_DELTA4
 #define ASM_OUTPUT_DWARF_DELTA4(FILE,LABEL1,LABEL2)                    \
   assemble_integer (gen_rtx_MINUS (SImode,                             \
                                   gen_rtx_SYMBOL_REF (Pmode, LABEL1),  \
                                   gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
                    4, 1)
+#endif
 
+#ifndef ASM_OUTPUT_DWARF_ADDR_DELTA
 #define ASM_OUTPUT_DWARF_ADDR_DELTA(FILE,LABEL1,LABEL2)                        \
   assemble_integer (gen_rtx_MINUS (Pmode,                              \
                                   gen_rtx_SYMBOL_REF (Pmode, LABEL1),  \
                                   gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
                    DWARF2_ADDR_SIZE, 1)
+#endif
 
+#ifndef ASM_OUTPUT_DWARF_DELTA
 #define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \
   ASM_OUTPUT_DWARF_DELTA4 (FILE,LABEL1,LABEL2)
+#endif
+
+#ifndef ASM_OUTPUT_DWARF_DATA2
+#define ASM_OUTPUT_DWARF_DATA2(FILE,VALUE) \
+  assemble_integer (GEN_INT (VALUE), 2, 1)
+#endif
 
+#ifndef ASM_OUTPUT_DWARF_DATA4
 #define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \
   assemble_integer (GEN_INT (VALUE), 4, 1)
+#endif
 
 #endif /* UNALIGNED_INT_ASM_OP */
 
@@ -564,24 +615,6 @@ stripattributes (s)
   return stripped;
 }
 
-/* Return the register number described by a given RTL node.  */
-
-static unsigned int
-reg_number (rtl)
-     register rtx rtl;
-{
-  register unsigned regno = REGNO (rtl);
-
-  if (regno >= FIRST_PSEUDO_REGISTER)
-    {
-      warning ("internal regno botch: regno = %d\n", regno);
-      regno = 0;
-    }
-
-  regno = DBX_REGISTER_NUMBER (regno);
-  return regno;
-}
-
 /* Generate code to initialize the register size table.  */
 
 void
@@ -595,9 +628,12 @@ expand_builtin_init_dwarf_reg_sizes (address)
 
   for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
     {
-      int offset = i * GET_MODE_SIZE (mode);
+      int offset = DWARF_FRAME_REGNUM (i) * GET_MODE_SIZE (mode);
       int size = GET_MODE_SIZE (reg_raw_mode[i]);
 
+      if (offset < 0)
+       continue;
+
       emit_move_insn (change_address (mem, mode,
                                      plus_constant (addr, offset)),
                      GEN_INT (size));
@@ -648,6 +684,8 @@ dwarf_cfi_name (cfi_opc)
       return "DW_CFA_def_cfa_register";
     case DW_CFA_def_cfa_offset:
       return "DW_CFA_def_cfa_offset";
+    case DW_CFA_def_cfa_expression:
+      return "DW_CFA_def_cfa_expression";
 
     /* SGI/MIPS specific */
     case DW_CFA_MIPS_advance_loc8:
@@ -749,22 +787,24 @@ add_fde_cfi (label, cfi)
 /* Subroutine of lookup_cfa.  */
 
 static inline void
-lookup_cfa_1 (cfi, regp, offsetp)
+lookup_cfa_1 (cfi, loc)
      register dw_cfi_ref cfi;
-     register unsigned long *regp;
-     register long *offsetp;
+     register dw_cfa_location *loc;
 {
   switch (cfi->dw_cfi_opc)
     {
     case DW_CFA_def_cfa_offset:
-      *offsetp = cfi->dw_cfi_oprnd1.dw_cfi_offset;
+      loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset;
       break;
     case DW_CFA_def_cfa_register:
-      *regp = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
+      loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
       break;
     case DW_CFA_def_cfa:
-      *regp = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
-      *offsetp = cfi->dw_cfi_oprnd2.dw_cfi_offset;
+      loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
+      loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset;
+      break;
+    case DW_CFA_def_cfa_expression:
+      get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc);
       break;
     default:
       break;
@@ -774,34 +814,33 @@ lookup_cfa_1 (cfi, regp, offsetp)
 /* Find the previous value for the CFA.  */
 
 static void
-lookup_cfa (regp, offsetp)
-     register unsigned long *regp;
-     register long *offsetp;
+lookup_cfa (loc)
+     register dw_cfa_location *loc;
 {
   register dw_cfi_ref cfi;
 
-  *regp = (unsigned long) -1;
-  *offsetp = 0;
+  loc->reg = (unsigned long) -1;
+  loc->offset = 0;
+  loc->indirect = 0;
+  loc->base_offset = 0;
 
   for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next)
-    lookup_cfa_1 (cfi, regp, offsetp);
+    lookup_cfa_1 (cfi, loc);
 
   if (fde_table_in_use)
     {
       register dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
       for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next)
-       lookup_cfa_1 (cfi, regp, offsetp);
+       lookup_cfa_1 (cfi, loc);
     }
 }
 
 /* The current rule for calculating the DWARF2 canonical frame address.  */
-static unsigned long cfa_reg;
-static long cfa_offset;
+dw_cfa_location cfa;
 
 /* The register used for saving registers to the stack, and its offset
    from the CFA.  */
-static unsigned cfa_store_reg;
-static long cfa_store_offset;
+dw_cfa_location cfa_store;
 
 /* The running total of the size of arguments pushed onto the stack.  */
 static long args_size;
@@ -816,45 +855,75 @@ static long old_args_size;
 void
 dwarf2out_def_cfa (label, reg, offset)
      register const char *label;
-     register unsigned reg;
-     register long offset;
+     unsigned reg;
+     long offset;
+{
+  dw_cfa_location loc;
+  loc.indirect = 0;
+  loc.base_offset = 0;
+  loc.reg = reg;
+  loc.offset = offset;
+  def_cfa_1 (label, &loc);
+}
+
+/* This routine does the actual work. The CFA is now calculated from
+   the dw_cfa_location structure.  */
+static void
+def_cfa_1 (label, loc_p)
+     register const char *label;
+     dw_cfa_location *loc_p;
 {
   register dw_cfi_ref cfi;
-  unsigned long old_reg;
-  long old_offset;
+  dw_cfa_location old_cfa, loc;
 
-  cfa_reg = reg;
-  cfa_offset = offset;
-  if (cfa_store_reg == reg)
-    cfa_store_offset = offset;
+  cfa = *loc_p;
+  loc = *loc_p;
 
-  reg = DWARF_FRAME_REGNUM (reg);
-  lookup_cfa (&old_reg, &old_offset);
+  if (cfa_store.reg == loc.reg && loc.indirect == 0)
+    cfa_store.offset = loc.offset;
 
-  if (reg == old_reg && offset == old_offset)
-    return;
+  loc.reg = DWARF_FRAME_REGNUM (loc.reg);
+  lookup_cfa (&old_cfa);
+
+  if (loc.reg == old_cfa.reg && loc.offset == old_cfa.offset &&
+      loc.indirect == old_cfa.indirect)
+    {
+      if (loc.indirect == 0)
+       return;
+      else 
+        if (loc.base_offset == old_cfa.base_offset)
+         return;
+    }
 
   cfi = new_cfi ();
 
-  if (reg == old_reg)
+  if (loc.reg == old_cfa.reg && loc.indirect == old_cfa.indirect)
     {
       cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
-      cfi->dw_cfi_oprnd1.dw_cfi_offset = offset;
+      cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset;
     }
 
 #ifndef MIPS_DEBUGGING_INFO  /* SGI dbx thinks this means no offset.  */
-  else if (offset == old_offset && old_reg != (unsigned long) -1)
+  else if (loc.offset == old_cfa.offset && old_cfa.reg != (unsigned long) -1
+          && loc.indirect == old_cfa.indirect)
     {
       cfi->dw_cfi_opc = DW_CFA_def_cfa_register;
-      cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
+      cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
     }
 #endif
 
-  else
+  else if (loc.indirect == 0)
     {
       cfi->dw_cfi_opc = DW_CFA_def_cfa;
-      cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
-      cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
+      cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
+      cfi->dw_cfi_oprnd2.dw_cfi_offset = loc.offset;
+    }
+  else
+    {
+      struct dw_loc_descr_struct * loc_list;
+      cfi->dw_cfi_opc = DW_CFA_def_cfa_expression;
+      loc_list = build_cfa_loc (&loc);
+      cfi->dw_cfi_oprnd1.dw_cfi_loc = loc_list;
     }
 
   add_fde_cfi (label, cfi);
@@ -1029,7 +1098,7 @@ initial_return_save (rtl)
       abort ();
     }
 
-  reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa_offset);
+  reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset);
 }
 
 /* Check INSN to see if it looks like a push or a stack adjustment, and
@@ -1060,7 +1129,7 @@ dwarf2out_stack_adjust (insn)
   /* If only calls can throw, and we have a frame pointer,
      save up adjustments until we see the CALL_INSN.  */
   else if (! asynchronous_exceptions
-          && cfa_reg != STACK_POINTER_REGNUM)
+          && cfa.reg != STACK_POINTER_REGNUM)
     return;
 
   if (GET_CODE (insn) == BARRIER)
@@ -1118,8 +1187,8 @@ dwarf2out_stack_adjust (insn)
   if (offset == 0)
     return;
 
-  if (cfa_reg == STACK_POINTER_REGNUM)
-    cfa_offset += offset;
+  if (cfa.reg == STACK_POINTER_REGNUM)
+    cfa.offset += offset;
 
 #ifndef STACK_GROWS_DOWNWARD
   offset = -offset;
@@ -1129,7 +1198,7 @@ dwarf2out_stack_adjust (insn)
     args_size = 0;
 
   label = dwarf2out_cfi_label ();
-  dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+  def_cfa_1 (label, &cfa);
   dwarf2out_args_size (label, args_size);
 }
 
@@ -1139,6 +1208,11 @@ static unsigned cfa_temp_reg;
 /* A temporary value used in adjusting SP or setting up the store_reg.  */
 static long cfa_temp_value;
 
+/* If we see a store of the CFA register, remember it in case we later also
+   copy it into another register.  The ARM saves the old SP in the stack,
+   but it also has a usable FP.  */
+static unsigned cfa_old_reg;
+
 /* Record call frame debugging information for an expression, which either
    sets SP or FP (adjusting how we calculate the frame address) or saves a
    register to the stack. */
@@ -1188,14 +1262,18 @@ dwarf2out_frame_debug_expr (expr, label)
         {
           /* Setting FP from SP.  */
         case REG:
-          if (cfa_reg != (unsigned) REGNO (src))
+          if (cfa.reg == (unsigned) REGNO (src)
+             || (cfa.indirect && cfa_old_reg == (unsigned) REGNO (src)))
+           /* OK */;
+         else
             abort ();
 
          /* We used to require that dest be either SP or FP, but the
             ARM copies SP to a temporary register, and from there to
             FP.  So we just rely on the backends to only set
             RTX_FRAME_RELATED_P on appropriate insns.  */
-          cfa_reg = REGNO (dest);
+          cfa.reg = REGNO (dest);
+         cfa.indirect = 0;
           break;
 
         case PLUS:
@@ -1220,19 +1298,19 @@ dwarf2out_frame_debug_expr (expr, label)
              if (XEXP (src, 0) == hard_frame_pointer_rtx)
                {
                  /* Restoring SP from FP in the epilogue.  */
-                 if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
+                 if (cfa.reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
                    abort ();
-                 cfa_reg = STACK_POINTER_REGNUM;
+                 cfa.reg = STACK_POINTER_REGNUM;
                }
              else if (XEXP (src, 0) != stack_pointer_rtx)
                abort ();
 
              if (GET_CODE (src) == PLUS)
                offset = -offset;
-             if (cfa_reg == STACK_POINTER_REGNUM)
-               cfa_offset += offset;
-             if (cfa_store_reg == STACK_POINTER_REGNUM)
-               cfa_store_offset += offset;
+             if (cfa.reg == STACK_POINTER_REGNUM)
+               cfa.offset += offset;
+             if (cfa_store.reg == STACK_POINTER_REGNUM)
+               cfa_store.offset += offset;
             }
           else if (dest == hard_frame_pointer_rtx)
             {
@@ -1242,14 +1320,14 @@ dwarf2out_frame_debug_expr (expr, label)
                abort ();
 
              if (GET_CODE (XEXP (src, 0)) == REG
-                 && (unsigned) REGNO (XEXP (src, 0)) == cfa_reg
+                 && (unsigned) REGNO (XEXP (src, 0)) == cfa.reg
                  && GET_CODE (XEXP (src, 1)) == CONST_INT)
                {
                  offset = INTVAL (XEXP (src, 1));
                  if (GET_CODE (src) == PLUS)
                    offset = -offset;
-                 cfa_offset += offset;
-                 cfa_reg = HARD_FRAME_POINTER_REGNUM;
+                 cfa.offset += offset;
+                 cfa.reg = HARD_FRAME_POINTER_REGNUM;
                }
              else 
                abort();
@@ -1262,10 +1340,10 @@ dwarf2out_frame_debug_expr (expr, label)
              if (GET_CODE (XEXP (src, 0)) != REG
                  || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg)
                abort ();
-             if (cfa_reg != STACK_POINTER_REGNUM)
+             if (cfa.reg != STACK_POINTER_REGNUM)
                abort ();
-             cfa_store_reg = REGNO (dest);
-             cfa_store_offset = cfa_offset - cfa_temp_value;
+             cfa_store.reg = REGNO (dest);
+             cfa_store.offset = cfa.offset - cfa_temp_value;
             }
           break;
 
@@ -1286,14 +1364,53 @@ dwarf2out_frame_debug_expr (expr, label)
         default:
           abort ();
         }
-      dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+      def_cfa_1 (label, &cfa);
+      break;
+
+      /* Skip over HIGH, assuming it will be followed by a LO_SUM, which
+        will fill in all of the bits.  */
+    case HIGH:
+      break;
+
+    case LO_SUM:
+      cfa_temp_reg = REGNO (dest);
+      cfa_temp_value = INTVAL (XEXP (src, 1));
       break;
 
     case MEM:
-      /* Saving a register to the stack.  Make sure dest is relative to the
-        CFA register.  */
       if (GET_CODE (src) != REG)
        abort ();
+
+      /* If the src is our current CFA, and it isn't the SP or FP, then we're
+         going to have to use an indrect mechanism.  */
+      if (REGNO (src) != STACK_POINTER_REGNUM 
+         && REGNO (src) != HARD_FRAME_POINTER_REGNUM 
+         && (unsigned) REGNO (src) == cfa.reg
+         /* Temporary KLUDGE to make ARM work.  */
+         && GET_CODE (XEXP (dest, 0)) != PRE_DEC)
+       {
+         /* We currently allow this to be ONLY a MEM or MEM + offset.  */
+         rtx x = XEXP (dest, 0);
+         int offset = 0;
+         if (GET_CODE (x) == PLUS || GET_CODE (x) ==  MINUS)
+           {
+             offset = INTVAL (XEXP (x, 1));
+             if (GET_CODE (x) == MINUS)
+               offset = -offset;
+             x = XEXP (x, 0);
+           }
+         if (GET_CODE (x) != REG)
+           abort ();
+         cfa_old_reg = cfa.reg;
+         cfa.reg = (unsigned) REGNO (x);
+         cfa.base_offset = offset;
+         cfa.indirect = 1;
+         def_cfa_1 (label, &cfa);
+         break;
+       }
+
+      /* Saving a register to the stack.  Make sure dest is relative to the
+        CFA register.  */
       switch (GET_CODE (XEXP (dest, 0)))
        {
          /* With a push.  */
@@ -1304,13 +1421,13 @@ dwarf2out_frame_debug_expr (expr, label)
            offset = -offset;
 
          if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM
-             || cfa_store_reg != STACK_POINTER_REGNUM)
+             || cfa_store.reg != STACK_POINTER_REGNUM)
            abort ();
-         cfa_store_offset += offset;
-         if (cfa_reg == STACK_POINTER_REGNUM)
-           cfa_offset = cfa_store_offset;
+         cfa_store.offset += offset;
+         if (cfa.reg == STACK_POINTER_REGNUM)
+           cfa.offset = cfa_store.offset;
 
-         offset = -cfa_store_offset;
+         offset = -cfa_store.offset;
          break;
 
          /* With an offset.  */
@@ -1320,22 +1437,22 @@ dwarf2out_frame_debug_expr (expr, label)
          if (GET_CODE (XEXP (dest, 0)) == MINUS)
            offset = -offset;
 
-         if (cfa_store_reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
+         if (cfa_store.reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
            abort ();
-         offset -= cfa_store_offset;
+         offset -= cfa_store.offset;
          break;
 
          /* Without an offset.  */
        case REG:
-         if (cfa_store_reg != REGNO (XEXP (dest, 0)))
+         if (cfa_store.reg != (unsigned) REGNO (XEXP (dest, 0)))
            abort();
-         offset = -cfa_store_offset;
+         offset = -cfa_store.offset;
          break;
 
        default:
          abort ();
        }
-      dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+      def_cfa_1 (label, &cfa);
       dwarf2out_reg_save (label, REGNO (src), offset);
       break;
 
@@ -1359,12 +1476,11 @@ dwarf2out_frame_debug (insn)
   if (insn == NULL_RTX)
     {
       /* Set up state for generating call frame debug info.  */
-      lookup_cfa (&cfa_reg, &cfa_offset);
-      if (cfa_reg != (unsigned long) DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM))
+      lookup_cfa (&cfa);
+      if (cfa.reg != (unsigned long) DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM))
        abort ();
-      cfa_reg = STACK_POINTER_REGNUM;
-      cfa_store_reg = cfa_reg;
-      cfa_store_offset = cfa_offset;
+      cfa.reg = STACK_POINTER_REGNUM;
+      cfa_store = cfa;
       cfa_temp_reg = -1;
       cfa_temp_value = 0;
       return;
@@ -1603,6 +1719,9 @@ output_cfi (cfi, fde)
          output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
           fputc ('\n', asm_out_file);
          break;
+       case DW_CFA_def_cfa_expression:
+         output_cfa_loc (cfi);
+         break;
        default:
          break;
        }
@@ -1948,20 +2067,13 @@ dwarf2out_frame_finish ()
     output_call_frame_info (1);  
 #endif
 }  
+\f
+/* And now, the subset of the debugging information support code necessary
+   for emitting location expressions.  */
 
-#endif /* .debug_frame support */
-
-/* And now, the support for symbolic debugging information.  */
-#ifdef DWARF2_DEBUGGING_INFO
-
-/* NOTE: In the comments in this file, many references are made to
-   "Debugging Information Entries".  This term is abbreviated as `DIE'
-   throughout the remainder of this file.  */
-
-/* An internal representation of the DWARF output is built, and then
-   walked to generate the DWARF debugging info.  The walk of the internal
-   representation is done after the entire program has been compiled.
-   The types below are used to describe the internal representation.  */
+typedef struct dw_val_struct *dw_val_ref;
+typedef struct die_struct *dw_die_ref;
+typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
 
 /* Each DIE may have a series of attribute/value pairs.  Values
    can take on several forms.  The forms that are used in this
@@ -1984,23 +2096,8 @@ typedef enum
 }
 dw_val_class;
 
-/* Various DIE's use offsets relative to the beginning of the
-   .debug_info section to refer to each other.  */
-
-typedef long int dw_offset;
-
-/* Define typedefs here to avoid circular dependencies.  */
-
-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 pubname_struct *pubname_ref;
-typedef dw_die_ref *arange_ref;
-
 /* Describe a double word constant value.  */
+/* ??? Every instance of long_long in the code really means CONST_DOUBLE.  */
 
 typedef struct dw_long_long_struct
 {
@@ -2018,28 +2115,6 @@ typedef struct dw_fp_struct
 }
 dw_float_const;
 
-/* Each entry in the line_info_table maintains the file and
-   line number associated with the label generated for that
-   entry.  The label gives the PC value associated with
-   the line number entry.  */
-
-typedef struct dw_line_info_struct
-{
-  unsigned long dw_file_num;
-  unsigned long dw_line_num;
-}
-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 attribute's value, as it is
    represented internally.  */
 
@@ -2076,1297 +2151,1818 @@ typedef struct dw_loc_descr_struct
 }
 dw_loc_descr_node;
 
-/* Each DIE attribute has a field specifying the attribute kind,
-   a link to the next attribute in the chain, and an attribute value.
-   Attributes are typically linked below the DIE they modify.  */
-
-typedef struct dw_attr_struct
-{
-  enum dwarf_attribute dw_attr;
-  dw_attr_ref dw_attr_next;
-  dw_val_node dw_attr_val;
-}
-dw_attr_node;
-
-/* The Debugging Information Entry (DIE) structure */
-
-typedef struct die_struct
-{
-  enum dwarf_tag die_tag;
-  dw_attr_ref die_attr;
-  dw_die_ref die_parent;
-  dw_die_ref die_child;
-  dw_die_ref die_sib;
-  dw_offset die_offset;
-  unsigned long die_abbrev;
-}
-die_node;
-
-/* The pubname structure */
+static const char *dwarf_stack_op_name PARAMS ((unsigned));
+static dw_loc_descr_ref new_loc_descr  PARAMS ((enum dwarf_location_atom,
+                                                unsigned long,
+                                                unsigned long));
+static void add_loc_descr              PARAMS ((dw_loc_descr_ref *,
+                                                dw_loc_descr_ref));
+static unsigned long size_of_loc_descr PARAMS ((dw_loc_descr_ref));
+static unsigned long size_of_locs      PARAMS ((dw_loc_descr_ref));
+static void output_loc_operands                PARAMS ((dw_loc_descr_ref));
+static void output_loc_sequence                PARAMS ((dw_loc_descr_ref));
 
-typedef struct pubname_struct
-{
-  dw_die_ref die;
-  char * name;
-}
-pubname_entry;
+/* Convert a DWARF stack opcode into its string name.  */
 
-/* The limbo die list structure.  */
-typedef struct limbo_die_struct
+static const char *
+dwarf_stack_op_name (op)
+     register unsigned op;
 {
-  dw_die_ref die;
-  struct limbo_die_struct *next;
-}
-limbo_die_node;
-
-/* How to start an assembler comment.  */
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START ";#"
-#endif
-
-/* Define a macro which returns non-zero for a TYPE_DECL which was
-   implicitly generated for a tagged type.
-
-   Note that unlike the gcc front end (which generates a NULL named
-   TYPE_DECL node for each complete tagged type, each array type, and
-   each function type node created) the g++ front end generates a
-   _named_ TYPE_DECL node for each tagged type node created.
-   These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to
-   generate a DW_TAG_typedef DIE for them.  */
-
-#define TYPE_DECL_IS_STUB(decl)                                \
-  (DECL_NAME (decl) == NULL_TREE                       \
-   || (DECL_ARTIFICIAL (decl)                          \
-       && is_tagged_type (TREE_TYPE (decl))            \
-       && ((decl == TYPE_STUB_DECL (TREE_TYPE (decl))) \
-          /* This is necessary for stub decls that     \
-             appear in nested inline functions.  */    \
-          || (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE \
-              && (decl_ultimate_origin (decl)          \
-                  == TYPE_STUB_DECL (TREE_TYPE (decl)))))))
-
-/* 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)
-
-/* Fixed size portion of debugging line information prolog.  */
-#define DWARF_LINE_PROLOG_HEADER_SIZE 5
-
-/* Fixed size portion of public names info.  */
-#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2)
-
-/* Fixed size portion of the address range info.  */
-#define DWARF_ARANGES_HEADER_SIZE                                      \
-  (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2)       \
-   - DWARF_OFFSET_SIZE)
-
-/* Size of padding portion in the address range info.  It must be
-   aligned to twice the pointer size.  */
-#define DWARF_ARANGES_PAD_SIZE \
-  (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \
-   - (2 * DWARF_OFFSET_SIZE + 4))
-
-/* The default is to have gcc emit the line number tables.  */
-#ifndef DWARF2_ASM_LINE_DEBUG_INFO
-#define DWARF2_ASM_LINE_DEBUG_INFO 0
-#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
-
-/* First special line opcde - leave room for the standard opcodes.  */
-#define DWARF_LINE_OPCODE_BASE  10
-
-/* Range of line offsets in a special line info. opcode.  */
-#define DWARF_LINE_RANGE  (254-DWARF_LINE_OPCODE_BASE+1)
-
-/* Flag that indicates the initial value of the is_stmt_start flag.
-   In the present implementation, we do not mark any lines as
-   the beginning of a source statement, because that information
-   is not made available by the GCC front-end.  */
-#define        DWARF_LINE_DEFAULT_IS_STMT_START 1
-
-/* This location is used by calc_die_sizes() to keep track
-   the offset of each DIE within the .debug_info section.  */
-static unsigned long next_die_offset;
-
-/* Record the root of the DIE's built for the current compilation unit.  */
-static dw_die_ref comp_unit_die;
-
-/* A list of DIEs with a NULL parent waiting to be relocated.  */
-static limbo_die_node *limbo_die_list = 0;
-
-/* Pointer to an array of filenames referenced by this compilation unit.  */
-static char **file_table;
-
-/* Total number of entries in the table (i.e. array) pointed to by
-   `file_table'.  This is the *total* and includes both used and unused
-   slots.  */
-static unsigned file_table_allocated;
-
-/* Number of entries in the file_table which are actually in use.  */
-static unsigned file_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the filename
-   table.  */
-#define FILE_TABLE_INCREMENT 64
-
-/* Local pointer to the name of the main input file.  Initialized in
-   dwarf2out_init.  */
-static const char *primary_filename;
-
-/* A pointer to the base of a table of references to DIE's that describe
-   declarations.  The table is indexed by DECL_UID() which is a unique
-   number identifying each decl.  */
-static dw_die_ref *decl_die_table;
-
-/* Number of elements currently allocated for the decl_die_table.  */
-static unsigned decl_die_table_allocated;
-
-/* Number of elements in decl_die_table currently in use.  */
-static unsigned decl_die_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the
-   decl_die_table.  */
-#define DECL_DIE_TABLE_INCREMENT 256
-
-/* A pointer to the base of a table of references to declaration
-   scopes.  This table is a display which tracks the nesting
-   of declaration scopes at the current scope and containing
-   scopes.  This table is used to find the proper place to
-   define type declaration DIE's.  */
-static tree *decl_scope_table;
-
-/* Number of elements currently allocated for the decl_scope_table.  */
-static int decl_scope_table_allocated;
-
-/* Current level of nesting of declaration scopes.  */
-static int decl_scope_depth;
-
-/* Size (in elements) of increments by which we may expand the
-   decl_scope_table.  */
-#define DECL_SCOPE_TABLE_INCREMENT 64
-
-/* A pointer to the base of a list of references to DIE's that
-   are uniquely identified by their tag, presence/absence of
-   children DIE's, and list of attribute/value pairs.  */
-static dw_die_ref *abbrev_die_table;
-
-/* Number of elements currently allocated for abbrev_die_table.  */
-static unsigned abbrev_die_table_allocated;
-
-/* Number of elements in type_die_table currently in use.  */
-static unsigned abbrev_die_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the
-   abbrev_die_table.  */
-#define ABBREV_DIE_TABLE_INCREMENT 256
-
-/* A pointer to the base of a table that contains line information
-   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;
-
-/* Size (in elements) of increments by which we may expand the
-   line_info_table.  */
-#define LINE_INFO_TABLE_INCREMENT 1024
-
-/* A pointer to the base of a table that contains a list of publicly
-   accessible names.  */
-static pubname_ref pubname_table;
-
-/* Number of elements currently allocated for pubname_table.  */
-static unsigned pubname_table_allocated;
-
-/* Number of elements in pubname_table currently in use.  */
-static unsigned pubname_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the
-   pubname_table.  */
-#define PUBNAME_TABLE_INCREMENT 64
-
-/* A pointer to the base of a table that contains a list of publicly
-   accessible names.  */
-static arange_ref arange_table;
-
-/* Number of elements currently allocated for arange_table.  */
-static unsigned arange_table_allocated;
-
-/* Number of elements in arange_table currently in use.  */
-static unsigned arange_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the
-   arange_table.  */
-#define ARANGE_TABLE_INCREMENT 64
-
-/* A pointer to the base of a list of incomplete types which might be
-   completed at some later time.  */
-
-static tree *incomplete_types_list;
-
-/* Number of elements currently allocated for the incomplete_types_list.  */
-static unsigned incomplete_types_allocated;
-
-/* Number of elements of incomplete_types_list currently in use.  */
-static unsigned incomplete_types;
-
-/* Size (in elements) of increments by which we may expand the incomplete
-   types list.  Actually, a single hunk of space of this size should
-   be enough for most typical programs.         */
-#define INCOMPLETE_TYPES_INCREMENT 64
-
-/* Record whether the function being analyzed contains inlined functions.  */
-static int current_function_has_inlines;
-#if 0 && defined (MIPS_DEBUGGING_INFO)
-static int comp_unit_has_inlines;
-#endif
-
-/* Array of RTXes referenced by the debugging information, which therefore
-   must be kept around forever.  We do this rather than perform GC on
-   the dwarf info because almost all of the dwarf info lives forever, and
-   it's easier to support non-GC frontends this way.  */
-static varray_type used_rtx_varray;
-
-/* Forward declarations for functions defined in this file.  */
-
-static int is_pseudo_reg               PARAMS ((rtx));
-static tree type_main_variant          PARAMS ((tree));
-static int is_tagged_type              PARAMS ((tree));
-static const char *dwarf_tag_name      PARAMS ((unsigned));
-static const char *dwarf_attr_name     PARAMS ((unsigned));
-static const char *dwarf_form_name     PARAMS ((unsigned));
-static const char *dwarf_stack_op_name PARAMS ((unsigned));
-#if 0
-static const char *dwarf_type_encoding_name PARAMS ((unsigned));
-#endif
-static tree decl_ultimate_origin       PARAMS ((tree));
-static tree block_ultimate_origin      PARAMS ((tree));
-static tree decl_class_context         PARAMS ((tree));
-static void add_dwarf_attr             PARAMS ((dw_die_ref, dw_attr_ref));
-static void add_AT_flag                        PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                unsigned));
-static void add_AT_int                 PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute, long));
-static void add_AT_unsigned            PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                unsigned long));
-static void add_AT_long_long           PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                unsigned long,
-                                                unsigned long));
-static void add_AT_float               PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                unsigned, long *));
-static void add_AT_string              PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                const char *));
-static void add_AT_die_ref             PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                dw_die_ref));
-static void add_AT_fde_ref             PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                unsigned));
-static void add_AT_loc                 PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                dw_loc_descr_ref));
-static void add_AT_addr                        PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                rtx));
-static void add_AT_lbl_id              PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                const char *));
-static void add_AT_lbl_offset          PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                const char *));
-static dw_attr_ref get_AT              PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute));
-static const char *get_AT_low_pc       PARAMS ((dw_die_ref));
-static const char *get_AT_hi_pc                PARAMS ((dw_die_ref));
-static const char *get_AT_string       PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute));
-static int get_AT_flag                 PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute));
-static unsigned get_AT_unsigned                PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute));
-static inline dw_die_ref get_AT_ref    PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute));
-static int is_c_family                 PARAMS ((void));
-static int is_fortran                  PARAMS ((void));
-static void remove_AT                  PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute));
-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 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));
-static void equate_decl_number_to_die  PARAMS ((tree, dw_die_ref));
-static dw_loc_descr_ref new_loc_descr  PARAMS ((enum dwarf_location_atom,
-                                                unsigned long,
-                                                unsigned long));
-static void add_loc_descr              PARAMS ((dw_loc_descr_ref *,
-                                                dw_loc_descr_ref));
-static void print_spaces               PARAMS ((FILE *));
-static void print_die                  PARAMS ((dw_die_ref, FILE *));
-static void print_dwarf_line_table     PARAMS ((FILE *));
-static void add_sibling_attributes     PARAMS ((dw_die_ref));
-static void build_abbrev_table         PARAMS ((dw_die_ref));
-static unsigned long size_of_string    PARAMS ((const char *));
-static unsigned long size_of_loc_descr PARAMS ((dw_loc_descr_ref));
-static unsigned long size_of_locs      PARAMS ((dw_loc_descr_ref));
-static int constant_size               PARAMS ((long unsigned));
-static unsigned long size_of_die       PARAMS ((dw_die_ref));
-static void calc_die_sizes             PARAMS ((dw_die_ref));
-static unsigned long size_of_line_prolog PARAMS ((void));
-static unsigned long size_of_pubnames  PARAMS ((void));
-static unsigned long size_of_aranges   PARAMS ((void));
-static enum dwarf_form value_format    PARAMS ((dw_attr_ref));
-static void output_value_format                PARAMS ((dw_attr_ref));
-static void output_abbrev_section      PARAMS ((void));
-static void output_loc_operands                PARAMS ((dw_loc_descr_ref));
-static void output_die                 PARAMS ((dw_die_ref));
-static void output_compilation_unit_header PARAMS ((void));
-static const char *dwarf2_name         PARAMS ((tree, int));
-static void add_pubname                        PARAMS ((tree, dw_die_ref));
-static void output_pubnames            PARAMS ((void));
-static void add_arange                 PARAMS ((tree, dw_die_ref));
-static void output_aranges             PARAMS ((void));
-static void output_line_info           PARAMS ((void));
-static dw_die_ref base_type_die                PARAMS ((tree));
-static tree root_type                  PARAMS ((tree));
-static int is_base_type                        PARAMS ((tree));
-static dw_die_ref modified_type_die    PARAMS ((tree, int, int, dw_die_ref));
-static int type_is_enum                        PARAMS ((tree));
-static dw_loc_descr_ref reg_loc_descriptor PARAMS ((rtx));
-static dw_loc_descr_ref based_loc_descr        PARAMS ((unsigned, long));
-static int is_based_loc                        PARAMS ((rtx));
-static dw_loc_descr_ref mem_loc_descriptor PARAMS ((rtx, enum machine_mode mode));
-static dw_loc_descr_ref concat_loc_descriptor PARAMS ((rtx, rtx));
-static dw_loc_descr_ref loc_descriptor PARAMS ((rtx));
-static HOST_WIDE_INT ceiling           PARAMS ((HOST_WIDE_INT, unsigned int));
-static tree field_type                 PARAMS ((tree));
-static unsigned int simple_type_align_in_bits PARAMS ((tree));
-static unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree));
-static HOST_WIDE_INT field_byte_offset PARAMS ((tree));
-static void add_AT_location_description        PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute, rtx));
-static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree));
-static void add_const_value_attribute  PARAMS ((dw_die_ref, rtx));
-static void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree));
-static void add_name_attribute         PARAMS ((dw_die_ref, const char *));
-static void add_bound_info             PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute, tree));
-static void add_subscript_info         PARAMS ((dw_die_ref, tree));
-static void add_byte_size_attribute    PARAMS ((dw_die_ref, tree));
-static void add_bit_offset_attribute   PARAMS ((dw_die_ref, tree));
-static void add_bit_size_attribute     PARAMS ((dw_die_ref, tree));
-static void add_prototyped_attribute   PARAMS ((dw_die_ref, tree));
-static void add_abstract_origin_attribute PARAMS ((dw_die_ref, tree));
-static void add_pure_or_virtual_attribute PARAMS ((dw_die_ref, tree));
-static void add_src_coords_attributes  PARAMS ((dw_die_ref, tree));
-static void add_name_and_src_coords_attributes PARAMS ((dw_die_ref, tree));
-static void push_decl_scope            PARAMS ((tree));
-static dw_die_ref scope_die_for                PARAMS ((tree, dw_die_ref));
-static void pop_decl_scope             PARAMS ((void));
-static void add_type_attribute         PARAMS ((dw_die_ref, tree, int, int,
-                                                dw_die_ref));
-static const char *type_tag            PARAMS ((tree));
-static tree member_declared_type       PARAMS ((tree));
-#if 0
-static const char *decl_start_label    PARAMS ((tree));
-#endif
-static void gen_array_type_die         PARAMS ((tree, dw_die_ref));
-static void gen_set_type_die           PARAMS ((tree, dw_die_ref));
-#if 0
-static void gen_entry_point_die                PARAMS ((tree, dw_die_ref));
-#endif
-static void gen_inlined_enumeration_type_die PARAMS ((tree, dw_die_ref));
-static void gen_inlined_structure_type_die PARAMS ((tree, dw_die_ref));
-static void gen_inlined_union_type_die PARAMS ((tree, dw_die_ref));
-static void gen_enumeration_type_die   PARAMS ((tree, dw_die_ref));
-static dw_die_ref gen_formal_parameter_die PARAMS ((tree, dw_die_ref));
-static void gen_unspecified_parameters_die PARAMS ((tree, dw_die_ref));
-static void gen_formal_types_die       PARAMS ((tree, dw_die_ref));
-static void gen_subprogram_die         PARAMS ((tree, dw_die_ref));
-static void gen_variable_die           PARAMS ((tree, dw_die_ref));
-static void gen_label_die              PARAMS ((tree, dw_die_ref));
-static void gen_lexical_block_die      PARAMS ((tree, dw_die_ref, int));
-static void gen_inlined_subroutine_die PARAMS ((tree, dw_die_ref, int));
-static void gen_field_die              PARAMS ((tree, dw_die_ref));
-static void gen_ptr_to_mbr_type_die    PARAMS ((tree, dw_die_ref));
-static dw_die_ref gen_compile_unit_die PARAMS ((const char *));
-static void gen_string_type_die                PARAMS ((tree, dw_die_ref));
-static void gen_inheritance_die                PARAMS ((tree, dw_die_ref));
-static void gen_member_die             PARAMS ((tree, dw_die_ref));
-static void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref));
-static void gen_subroutine_type_die    PARAMS ((tree, dw_die_ref));
-static void gen_typedef_die            PARAMS ((tree, dw_die_ref));
-static void gen_type_die               PARAMS ((tree, dw_die_ref));
-static void gen_tagged_type_instantiation_die PARAMS ((tree, dw_die_ref));
-static void gen_block_die              PARAMS ((tree, dw_die_ref, int));
-static void decls_for_scope            PARAMS ((tree, dw_die_ref, int));
-static int is_redundant_typedef                PARAMS ((tree));
-static void gen_decl_die               PARAMS ((tree, dw_die_ref));
-static unsigned lookup_filename                PARAMS ((const char *));
-static void add_incomplete_type                PARAMS ((tree));
-static void retry_incomplete_types     PARAMS ((void));
-static void gen_type_die_for_member    PARAMS ((tree, tree, dw_die_ref));
-static void gen_abstract_function      PARAMS ((tree));
-static rtx save_rtx                    PARAMS ((rtx));
-static void splice_child_die           PARAMS ((dw_die_ref, dw_die_ref));
-static void reverse_die_lists          PARAMS ((dw_die_ref));
-
-/* Section names used to hold DWARF debugging information.  */
-#ifndef DEBUG_INFO_SECTION
-#define DEBUG_INFO_SECTION     ".debug_info"
-#endif
-#ifndef ABBREV_SECTION
-#define ABBREV_SECTION         ".debug_abbrev"
-#endif
-#ifndef ARANGES_SECTION
-#define ARANGES_SECTION                ".debug_aranges"
-#endif
-#ifndef DW_MACINFO_SECTION
-#define DW_MACINFO_SECTION     ".debug_macinfo"
-#endif
-#ifndef DEBUG_LINE_SECTION
-#define DEBUG_LINE_SECTION     ".debug_line"
-#endif
-#ifndef LOC_SECTION
-#define LOC_SECTION            ".debug_loc"
-#endif
-#ifndef PUBNAMES_SECTION
-#define PUBNAMES_SECTION       ".debug_pubnames"
-#endif
-#ifndef STR_SECTION
-#define STR_SECTION            ".debug_str"
-#endif
-
-/* Standard ELF section names for compiled code and data.  */
-#ifndef TEXT_SECTION
-#define TEXT_SECTION           ".text"
-#endif
-#ifndef DATA_SECTION
-#define DATA_SECTION           ".data"
-#endif
-#ifndef BSS_SECTION
-#define BSS_SECTION            ".bss"
-#endif
-
-/* Labels we insert at beginning sections we can reference instead of
-   the section names themselves. */
-
-#ifndef TEXT_SECTION_LABEL
-#define TEXT_SECTION_LABEL      "Ltext"
-#endif
-#ifndef DEBUG_LINE_SECTION_LABEL
-#define DEBUG_LINE_SECTION_LABEL "Ldebug_line"
-#endif
-#ifndef DEBUG_INFO_SECTION_LABEL
-#define DEBUG_INFO_SECTION_LABEL "Ldebug_info"
-#endif
-#ifndef ABBREV_SECTION_LABEL
-#define ABBREV_SECTION_LABEL     "Ldebug_abbrev"
-#endif
-
-
-/* Definitions of defaults for formats and names of various special
-   (artificial) labels which may be generated within this file (when the -g
-   options is used and DWARF_DEBUGGING_INFO is in effect.
-   If necessary, these may be overridden from within the tm.h file, but
-   typically, overriding these defaults is unnecessary.  */
-
-static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
-static char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
-static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
-static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
-static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
-
-#ifndef TEXT_END_LABEL
-#define TEXT_END_LABEL         "Letext"
-#endif
-#ifndef DATA_END_LABEL
-#define DATA_END_LABEL         "Ledata"
-#endif
-#ifndef BSS_END_LABEL
-#define BSS_END_LABEL           "Lebss"
-#endif
-#ifndef INSN_LABEL_FMT
-#define INSN_LABEL_FMT         "LI%u_"
-#endif
-#ifndef BLOCK_BEGIN_LABEL
-#define BLOCK_BEGIN_LABEL      "LBB"
-#endif
-#ifndef BLOCK_END_LABEL
-#define BLOCK_END_LABEL                "LBE"
-#endif
-#ifndef BODY_BEGIN_LABEL
-#define BODY_BEGIN_LABEL       "Lbb"
-#endif
-#ifndef BODY_END_LABEL
-#define BODY_END_LABEL         "Lbe"
-#endif
-#ifndef LINE_CODE_LABEL
-#define LINE_CODE_LABEL                "LM"
-#endif
-#ifndef SEPARATE_LINE_CODE_LABEL
-#define SEPARATE_LINE_CODE_LABEL       "LSM"
-#endif
-\f
-/* We allow a language front-end to designate a function that is to be
-   called to "demangle" any name before it it put into a DIE.  */
-
-static const char *(*demangle_name_func) PARAMS ((const char *));
-
-void
-dwarf2out_set_demangle_name_func (func)
-     const char *(*func) PARAMS ((const char *));
-{
-  demangle_name_func = func;
-}
-\f
-/* Return an rtx like ORIG which lives forever.  If we're doing GC,
-   that means adding it to used_rtx_varray.  If not, that means making
-   a copy on the permanent_obstack.  */
-
-static rtx
-save_rtx (orig)
-     register rtx orig;
-{
-  if (ggc_p)
-    VARRAY_PUSH_RTX (used_rtx_varray, orig);
-  else
-    {
-      push_obstacks_nochange ();
-      end_temporary_allocation ();
-      orig = copy_rtx (orig);
-      pop_obstacks ();
-    }
-
-  return orig;
-}
-
-/* Test if rtl node points to a pseudo register.  */
-
-static inline int
-is_pseudo_reg (rtl)
-     register rtx rtl;
-{
-  return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
-         || (GET_CODE (rtl) == SUBREG
-             && REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER));
-}
-
-/* Return a reference to a type, with its const and volatile qualifiers
-   removed.  */
-
-static inline tree
-type_main_variant (type)
-     register tree type;
-{
-  type = TYPE_MAIN_VARIANT (type);
-
-  /* There really should be only one main variant among any group of variants 
-     of a given type (and all of the MAIN_VARIANT values for all members of
-     the group should point to that one type) but sometimes the C front-end
-     messes this up for array types, so we work around that bug here.  */
-
-  if (TREE_CODE (type) == ARRAY_TYPE)
-    while (type != TYPE_MAIN_VARIANT (type))
-      type = TYPE_MAIN_VARIANT (type);
-
-  return type;
-}
-
-/* Return non-zero if the given type node represents a tagged type.  */
-
-static inline int
-is_tagged_type (type)
-     register tree type;
-{
-  register enum tree_code code = TREE_CODE (type);
-
-  return (code == RECORD_TYPE || code == UNION_TYPE
-         || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
-}
-
-/* Convert a DIE tag into its string name.  */
-
-static const char *
-dwarf_tag_name (tag)
-     register unsigned tag;
-{
-  switch (tag)
-    {
-    case DW_TAG_padding:
-      return "DW_TAG_padding";
-    case DW_TAG_array_type:
-      return "DW_TAG_array_type";
-    case DW_TAG_class_type:
-      return "DW_TAG_class_type";
-    case DW_TAG_entry_point:
-      return "DW_TAG_entry_point";
-    case DW_TAG_enumeration_type:
-      return "DW_TAG_enumeration_type";
-    case DW_TAG_formal_parameter:
-      return "DW_TAG_formal_parameter";
-    case DW_TAG_imported_declaration:
-      return "DW_TAG_imported_declaration";
-    case DW_TAG_label:
-      return "DW_TAG_label";
-    case DW_TAG_lexical_block:
-      return "DW_TAG_lexical_block";
-    case DW_TAG_member:
-      return "DW_TAG_member";
-    case DW_TAG_pointer_type:
-      return "DW_TAG_pointer_type";
-    case DW_TAG_reference_type:
-      return "DW_TAG_reference_type";
-    case DW_TAG_compile_unit:
-      return "DW_TAG_compile_unit";
-    case DW_TAG_string_type:
-      return "DW_TAG_string_type";
-    case DW_TAG_structure_type:
-      return "DW_TAG_structure_type";
-    case DW_TAG_subroutine_type:
-      return "DW_TAG_subroutine_type";
-    case DW_TAG_typedef:
-      return "DW_TAG_typedef";
-    case DW_TAG_union_type:
-      return "DW_TAG_union_type";
-    case DW_TAG_unspecified_parameters:
-      return "DW_TAG_unspecified_parameters";
-    case DW_TAG_variant:
-      return "DW_TAG_variant";
-    case DW_TAG_common_block:
-      return "DW_TAG_common_block";
-    case DW_TAG_common_inclusion:
-      return "DW_TAG_common_inclusion";
-    case DW_TAG_inheritance:
-      return "DW_TAG_inheritance";
-    case DW_TAG_inlined_subroutine:
-      return "DW_TAG_inlined_subroutine";
-    case DW_TAG_module:
-      return "DW_TAG_module";
-    case DW_TAG_ptr_to_member_type:
-      return "DW_TAG_ptr_to_member_type";
-    case DW_TAG_set_type:
-      return "DW_TAG_set_type";
-    case DW_TAG_subrange_type:
-      return "DW_TAG_subrange_type";
-    case DW_TAG_with_stmt:
-      return "DW_TAG_with_stmt";
-    case DW_TAG_access_declaration:
-      return "DW_TAG_access_declaration";
-    case DW_TAG_base_type:
-      return "DW_TAG_base_type";
-    case DW_TAG_catch_block:
-      return "DW_TAG_catch_block";
-    case DW_TAG_const_type:
-      return "DW_TAG_const_type";
-    case DW_TAG_constant:
-      return "DW_TAG_constant";
-    case DW_TAG_enumerator:
-      return "DW_TAG_enumerator";
-    case DW_TAG_file_type:
-      return "DW_TAG_file_type";
-    case DW_TAG_friend:
-      return "DW_TAG_friend";
-    case DW_TAG_namelist:
-      return "DW_TAG_namelist";
-    case DW_TAG_namelist_item:
-      return "DW_TAG_namelist_item";
-    case DW_TAG_packed_type:
-      return "DW_TAG_packed_type";
-    case DW_TAG_subprogram:
-      return "DW_TAG_subprogram";
-    case DW_TAG_template_type_param:
-      return "DW_TAG_template_type_param";
-    case DW_TAG_template_value_param:
-      return "DW_TAG_template_value_param";
-    case DW_TAG_thrown_type:
-      return "DW_TAG_thrown_type";
-    case DW_TAG_try_block:
-      return "DW_TAG_try_block";
-    case DW_TAG_variant_part:
-      return "DW_TAG_variant_part";
-    case DW_TAG_variable:
-      return "DW_TAG_variable";
-    case DW_TAG_volatile_type:
-      return "DW_TAG_volatile_type";
-    case DW_TAG_MIPS_loop:
-      return "DW_TAG_MIPS_loop";
-    case DW_TAG_format_label:
-      return "DW_TAG_format_label";
-    case DW_TAG_function_template:
-      return "DW_TAG_function_template";
-    case DW_TAG_class_template:
-      return "DW_TAG_class_template";
-    default:
-      return "DW_TAG_<unknown>";
-    }
-}
-
-/* Convert a DWARF attribute code into its string name.  */
-
-static const char *
-dwarf_attr_name (attr)
-     register unsigned attr;
-{
-  switch (attr)
-    {
-    case DW_AT_sibling:
-      return "DW_AT_sibling";
-    case DW_AT_location:
-      return "DW_AT_location";
-    case DW_AT_name:
-      return "DW_AT_name";
-    case DW_AT_ordering:
-      return "DW_AT_ordering";
-    case DW_AT_subscr_data:
-      return "DW_AT_subscr_data";
-    case DW_AT_byte_size:
-      return "DW_AT_byte_size";
-    case DW_AT_bit_offset:
-      return "DW_AT_bit_offset";
-    case DW_AT_bit_size:
-      return "DW_AT_bit_size";
-    case DW_AT_element_list:
-      return "DW_AT_element_list";
-    case DW_AT_stmt_list:
-      return "DW_AT_stmt_list";
-    case DW_AT_low_pc:
-      return "DW_AT_low_pc";
-    case DW_AT_high_pc:
-      return "DW_AT_high_pc";
-    case DW_AT_language:
-      return "DW_AT_language";
-    case DW_AT_member:
-      return "DW_AT_member";
-    case DW_AT_discr:
-      return "DW_AT_discr";
-    case DW_AT_discr_value:
-      return "DW_AT_discr_value";
-    case DW_AT_visibility:
-      return "DW_AT_visibility";
-    case DW_AT_import:
-      return "DW_AT_import";
-    case DW_AT_string_length:
-      return "DW_AT_string_length";
-    case DW_AT_common_reference:
-      return "DW_AT_common_reference";
-    case DW_AT_comp_dir:
-      return "DW_AT_comp_dir";
-    case DW_AT_const_value:
-      return "DW_AT_const_value";
-    case DW_AT_containing_type:
-      return "DW_AT_containing_type";
-    case DW_AT_default_value:
-      return "DW_AT_default_value";
-    case DW_AT_inline:
-      return "DW_AT_inline";
-    case DW_AT_is_optional:
-      return "DW_AT_is_optional";
-    case DW_AT_lower_bound:
-      return "DW_AT_lower_bound";
-    case DW_AT_producer:
-      return "DW_AT_producer";
-    case DW_AT_prototyped:
-      return "DW_AT_prototyped";
-    case DW_AT_return_addr:
-      return "DW_AT_return_addr";
-    case DW_AT_start_scope:
-      return "DW_AT_start_scope";
-    case DW_AT_stride_size:
-      return "DW_AT_stride_size";
-    case DW_AT_upper_bound:
-      return "DW_AT_upper_bound";
-    case DW_AT_abstract_origin:
-      return "DW_AT_abstract_origin";
-    case DW_AT_accessibility:
-      return "DW_AT_accessibility";
-    case DW_AT_address_class:
-      return "DW_AT_address_class";
-    case DW_AT_artificial:
-      return "DW_AT_artificial";
-    case DW_AT_base_types:
-      return "DW_AT_base_types";
-    case DW_AT_calling_convention:
-      return "DW_AT_calling_convention";
-    case DW_AT_count:
-      return "DW_AT_count";
-    case DW_AT_data_member_location:
-      return "DW_AT_data_member_location";
-    case DW_AT_decl_column:
-      return "DW_AT_decl_column";
-    case DW_AT_decl_file:
-      return "DW_AT_decl_file";
-    case DW_AT_decl_line:
-      return "DW_AT_decl_line";
-    case DW_AT_declaration:
-      return "DW_AT_declaration";
-    case DW_AT_discr_list:
-      return "DW_AT_discr_list";
-    case DW_AT_encoding:
-      return "DW_AT_encoding";
-    case DW_AT_external:
-      return "DW_AT_external";
-    case DW_AT_frame_base:
-      return "DW_AT_frame_base";
-    case DW_AT_friend:
-      return "DW_AT_friend";
-    case DW_AT_identifier_case:
-      return "DW_AT_identifier_case";
-    case DW_AT_macro_info:
-      return "DW_AT_macro_info";
-    case DW_AT_namelist_items:
-      return "DW_AT_namelist_items";
-    case DW_AT_priority:
-      return "DW_AT_priority";
-    case DW_AT_segment:
-      return "DW_AT_segment";
-    case DW_AT_specification:
-      return "DW_AT_specification";
-    case DW_AT_static_link:
-      return "DW_AT_static_link";
-    case DW_AT_type:
-      return "DW_AT_type";
-    case DW_AT_use_location:
-      return "DW_AT_use_location";
-    case DW_AT_variable_parameter:
-      return "DW_AT_variable_parameter";
-    case DW_AT_virtuality:
-      return "DW_AT_virtuality";
-    case DW_AT_vtable_elem_location:
-      return "DW_AT_vtable_elem_location";
-
-    case DW_AT_MIPS_fde:
-      return "DW_AT_MIPS_fde";
-    case DW_AT_MIPS_loop_begin:
-      return "DW_AT_MIPS_loop_begin";
-    case DW_AT_MIPS_tail_loop_begin:
-      return "DW_AT_MIPS_tail_loop_begin";
-    case DW_AT_MIPS_epilog_begin:
-      return "DW_AT_MIPS_epilog_begin";
-    case DW_AT_MIPS_loop_unroll_factor:
-      return "DW_AT_MIPS_loop_unroll_factor";
-    case DW_AT_MIPS_software_pipeline_depth:
-      return "DW_AT_MIPS_software_pipeline_depth";
-    case DW_AT_MIPS_linkage_name:
-      return "DW_AT_MIPS_linkage_name";
-    case DW_AT_MIPS_stride:
-      return "DW_AT_MIPS_stride";
-    case DW_AT_MIPS_abstract_name:
-      return "DW_AT_MIPS_abstract_name";
-    case DW_AT_MIPS_clone_origin:
-      return "DW_AT_MIPS_clone_origin";
-    case DW_AT_MIPS_has_inlines:
-      return "DW_AT_MIPS_has_inlines";
-
-    case DW_AT_sf_names:
-      return "DW_AT_sf_names";
-    case DW_AT_src_info:
-      return "DW_AT_src_info";
-    case DW_AT_mac_info:
-      return "DW_AT_mac_info";
-    case DW_AT_src_coords:
-      return "DW_AT_src_coords";
-    case DW_AT_body_begin:
-      return "DW_AT_body_begin";
-    case DW_AT_body_end:
-      return "DW_AT_body_end";
-    default:
-      return "DW_AT_<unknown>";
-    }
-}
-
-/* Convert a DWARF value form code into its string name.  */
-
-static const char *
-dwarf_form_name (form)
-     register unsigned form;
-{
-  switch (form)
+  switch (op)
     {
-    case DW_FORM_addr:
-      return "DW_FORM_addr";
-    case DW_FORM_block2:
-      return "DW_FORM_block2";
-    case DW_FORM_block4:
-      return "DW_FORM_block4";
-    case DW_FORM_data2:
-      return "DW_FORM_data2";
-    case DW_FORM_data4:
-      return "DW_FORM_data4";
-    case DW_FORM_data8:
-      return "DW_FORM_data8";
-    case DW_FORM_string:
-      return "DW_FORM_string";
-    case DW_FORM_block:
-      return "DW_FORM_block";
-    case DW_FORM_block1:
-      return "DW_FORM_block1";
-    case DW_FORM_data1:
-      return "DW_FORM_data1";
-    case DW_FORM_flag:
-      return "DW_FORM_flag";
-    case DW_FORM_sdata:
-      return "DW_FORM_sdata";
-    case DW_FORM_strp:
-      return "DW_FORM_strp";
-    case DW_FORM_udata:
-      return "DW_FORM_udata";
-    case DW_FORM_ref_addr:
-      return "DW_FORM_ref_addr";
-    case DW_FORM_ref1:
-      return "DW_FORM_ref1";
-    case DW_FORM_ref2:
-      return "DW_FORM_ref2";
-    case DW_FORM_ref4:
-      return "DW_FORM_ref4";
-    case DW_FORM_ref8:
-      return "DW_FORM_ref8";
-    case DW_FORM_ref_udata:
-      return "DW_FORM_ref_udata";
-    case DW_FORM_indirect:
-      return "DW_FORM_indirect";
+    case DW_OP_addr:
+      return "DW_OP_addr";
+    case DW_OP_deref:
+      return "DW_OP_deref";
+    case DW_OP_const1u:
+      return "DW_OP_const1u";
+    case DW_OP_const1s:
+      return "DW_OP_const1s";
+    case DW_OP_const2u:
+      return "DW_OP_const2u";
+    case DW_OP_const2s:
+      return "DW_OP_const2s";
+    case DW_OP_const4u:
+      return "DW_OP_const4u";
+    case DW_OP_const4s:
+      return "DW_OP_const4s";
+    case DW_OP_const8u:
+      return "DW_OP_const8u";
+    case DW_OP_const8s:
+      return "DW_OP_const8s";
+    case DW_OP_constu:
+      return "DW_OP_constu";
+    case DW_OP_consts:
+      return "DW_OP_consts";
+    case DW_OP_dup:
+      return "DW_OP_dup";
+    case DW_OP_drop:
+      return "DW_OP_drop";
+    case DW_OP_over:
+      return "DW_OP_over";
+    case DW_OP_pick:
+      return "DW_OP_pick";
+    case DW_OP_swap:
+      return "DW_OP_swap";
+    case DW_OP_rot:
+      return "DW_OP_rot";
+    case DW_OP_xderef:
+      return "DW_OP_xderef";
+    case DW_OP_abs:
+      return "DW_OP_abs";
+    case DW_OP_and:
+      return "DW_OP_and";
+    case DW_OP_div:
+      return "DW_OP_div";
+    case DW_OP_minus:
+      return "DW_OP_minus";
+    case DW_OP_mod:
+      return "DW_OP_mod";
+    case DW_OP_mul:
+      return "DW_OP_mul";
+    case DW_OP_neg:
+      return "DW_OP_neg";
+    case DW_OP_not:
+      return "DW_OP_not";
+    case DW_OP_or:
+      return "DW_OP_or";
+    case DW_OP_plus:
+      return "DW_OP_plus";
+    case DW_OP_plus_uconst:
+      return "DW_OP_plus_uconst";
+    case DW_OP_shl:
+      return "DW_OP_shl";
+    case DW_OP_shr:
+      return "DW_OP_shr";
+    case DW_OP_shra:
+      return "DW_OP_shra";
+    case DW_OP_xor:
+      return "DW_OP_xor";
+    case DW_OP_bra:
+      return "DW_OP_bra";
+    case DW_OP_eq:
+      return "DW_OP_eq";
+    case DW_OP_ge:
+      return "DW_OP_ge";
+    case DW_OP_gt:
+      return "DW_OP_gt";
+    case DW_OP_le:
+      return "DW_OP_le";
+    case DW_OP_lt:
+      return "DW_OP_lt";
+    case DW_OP_ne:
+      return "DW_OP_ne";
+    case DW_OP_skip:
+      return "DW_OP_skip";
+    case DW_OP_lit0:
+      return "DW_OP_lit0";
+    case DW_OP_lit1:
+      return "DW_OP_lit1";
+    case DW_OP_lit2:
+      return "DW_OP_lit2";
+    case DW_OP_lit3:
+      return "DW_OP_lit3";
+    case DW_OP_lit4:
+      return "DW_OP_lit4";
+    case DW_OP_lit5:
+      return "DW_OP_lit5";
+    case DW_OP_lit6:
+      return "DW_OP_lit6";
+    case DW_OP_lit7:
+      return "DW_OP_lit7";
+    case DW_OP_lit8:
+      return "DW_OP_lit8";
+    case DW_OP_lit9:
+      return "DW_OP_lit9";
+    case DW_OP_lit10:
+      return "DW_OP_lit10";
+    case DW_OP_lit11:
+      return "DW_OP_lit11";
+    case DW_OP_lit12:
+      return "DW_OP_lit12";
+    case DW_OP_lit13:
+      return "DW_OP_lit13";
+    case DW_OP_lit14:
+      return "DW_OP_lit14";
+    case DW_OP_lit15:
+      return "DW_OP_lit15";
+    case DW_OP_lit16:
+      return "DW_OP_lit16";
+    case DW_OP_lit17:
+      return "DW_OP_lit17";
+    case DW_OP_lit18:
+      return "DW_OP_lit18";
+    case DW_OP_lit19:
+      return "DW_OP_lit19";
+    case DW_OP_lit20:
+      return "DW_OP_lit20";
+    case DW_OP_lit21:
+      return "DW_OP_lit21";
+    case DW_OP_lit22:
+      return "DW_OP_lit22";
+    case DW_OP_lit23:
+      return "DW_OP_lit23";
+    case DW_OP_lit24:
+      return "DW_OP_lit24";
+    case DW_OP_lit25:
+      return "DW_OP_lit25";
+    case DW_OP_lit26:
+      return "DW_OP_lit26";
+    case DW_OP_lit27:
+      return "DW_OP_lit27";
+    case DW_OP_lit28:
+      return "DW_OP_lit28";
+    case DW_OP_lit29:
+      return "DW_OP_lit29";
+    case DW_OP_lit30:
+      return "DW_OP_lit30";
+    case DW_OP_lit31:
+      return "DW_OP_lit31";
+    case DW_OP_reg0:
+      return "DW_OP_reg0";
+    case DW_OP_reg1:
+      return "DW_OP_reg1";
+    case DW_OP_reg2:
+      return "DW_OP_reg2";
+    case DW_OP_reg3:
+      return "DW_OP_reg3";
+    case DW_OP_reg4:
+      return "DW_OP_reg4";
+    case DW_OP_reg5:
+      return "DW_OP_reg5";
+    case DW_OP_reg6:
+      return "DW_OP_reg6";
+    case DW_OP_reg7:
+      return "DW_OP_reg7";
+    case DW_OP_reg8:
+      return "DW_OP_reg8";
+    case DW_OP_reg9:
+      return "DW_OP_reg9";
+    case DW_OP_reg10:
+      return "DW_OP_reg10";
+    case DW_OP_reg11:
+      return "DW_OP_reg11";
+    case DW_OP_reg12:
+      return "DW_OP_reg12";
+    case DW_OP_reg13:
+      return "DW_OP_reg13";
+    case DW_OP_reg14:
+      return "DW_OP_reg14";
+    case DW_OP_reg15:
+      return "DW_OP_reg15";
+    case DW_OP_reg16:
+      return "DW_OP_reg16";
+    case DW_OP_reg17:
+      return "DW_OP_reg17";
+    case DW_OP_reg18:
+      return "DW_OP_reg18";
+    case DW_OP_reg19:
+      return "DW_OP_reg19";
+    case DW_OP_reg20:
+      return "DW_OP_reg20";
+    case DW_OP_reg21:
+      return "DW_OP_reg21";
+    case DW_OP_reg22:
+      return "DW_OP_reg22";
+    case DW_OP_reg23:
+      return "DW_OP_reg23";
+    case DW_OP_reg24:
+      return "DW_OP_reg24";
+    case DW_OP_reg25:
+      return "DW_OP_reg25";
+    case DW_OP_reg26:
+      return "DW_OP_reg26";
+    case DW_OP_reg27:
+      return "DW_OP_reg27";
+    case DW_OP_reg28:
+      return "DW_OP_reg28";
+    case DW_OP_reg29:
+      return "DW_OP_reg29";
+    case DW_OP_reg30:
+      return "DW_OP_reg30";
+    case DW_OP_reg31:
+      return "DW_OP_reg31";
+    case DW_OP_breg0:
+      return "DW_OP_breg0";
+    case DW_OP_breg1:
+      return "DW_OP_breg1";
+    case DW_OP_breg2:
+      return "DW_OP_breg2";
+    case DW_OP_breg3:
+      return "DW_OP_breg3";
+    case DW_OP_breg4:
+      return "DW_OP_breg4";
+    case DW_OP_breg5:
+      return "DW_OP_breg5";
+    case DW_OP_breg6:
+      return "DW_OP_breg6";
+    case DW_OP_breg7:
+      return "DW_OP_breg7";
+    case DW_OP_breg8:
+      return "DW_OP_breg8";
+    case DW_OP_breg9:
+      return "DW_OP_breg9";
+    case DW_OP_breg10:
+      return "DW_OP_breg10";
+    case DW_OP_breg11:
+      return "DW_OP_breg11";
+    case DW_OP_breg12:
+      return "DW_OP_breg12";
+    case DW_OP_breg13:
+      return "DW_OP_breg13";
+    case DW_OP_breg14:
+      return "DW_OP_breg14";
+    case DW_OP_breg15:
+      return "DW_OP_breg15";
+    case DW_OP_breg16:
+      return "DW_OP_breg16";
+    case DW_OP_breg17:
+      return "DW_OP_breg17";
+    case DW_OP_breg18:
+      return "DW_OP_breg18";
+    case DW_OP_breg19:
+      return "DW_OP_breg19";
+    case DW_OP_breg20:
+      return "DW_OP_breg20";
+    case DW_OP_breg21:
+      return "DW_OP_breg21";
+    case DW_OP_breg22:
+      return "DW_OP_breg22";
+    case DW_OP_breg23:
+      return "DW_OP_breg23";
+    case DW_OP_breg24:
+      return "DW_OP_breg24";
+    case DW_OP_breg25:
+      return "DW_OP_breg25";
+    case DW_OP_breg26:
+      return "DW_OP_breg26";
+    case DW_OP_breg27:
+      return "DW_OP_breg27";
+    case DW_OP_breg28:
+      return "DW_OP_breg28";
+    case DW_OP_breg29:
+      return "DW_OP_breg29";
+    case DW_OP_breg30:
+      return "DW_OP_breg30";
+    case DW_OP_breg31:
+      return "DW_OP_breg31";
+    case DW_OP_regx:
+      return "DW_OP_regx";
+    case DW_OP_fbreg:
+      return "DW_OP_fbreg";
+    case DW_OP_bregx:
+      return "DW_OP_bregx";
+    case DW_OP_piece:
+      return "DW_OP_piece";
+    case DW_OP_deref_size:
+      return "DW_OP_deref_size";
+    case DW_OP_xderef_size:
+      return "DW_OP_xderef_size";
+    case DW_OP_nop:
+      return "DW_OP_nop";
     default:
-      return "DW_FORM_<unknown>";
+      return "OP_<unknown>";
     }
 }
 
-/* Convert a DWARF stack opcode into its string name.  */
 
-static const char *
-dwarf_stack_op_name (op)
-     register unsigned op;
+/* Return a pointer to a newly allocated location description.  Location
+   descriptions are simple expression terms that can be strung
+   together to form more complicated location (address) descriptions.  */
+
+static inline dw_loc_descr_ref
+new_loc_descr (op, oprnd1, oprnd2)
+     register enum dwarf_location_atom op;
+     register unsigned long oprnd1;
+     register unsigned long oprnd2;
 {
-  switch (op)
+  register dw_loc_descr_ref descr
+    = (dw_loc_descr_ref) xmalloc (sizeof (dw_loc_descr_node));
+
+  descr->dw_loc_next = NULL;
+  descr->dw_loc_opc = op;
+  descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
+  descr->dw_loc_oprnd1.v.val_unsigned = oprnd1;
+  descr->dw_loc_oprnd2.val_class = dw_val_class_unsigned_const;
+  descr->dw_loc_oprnd2.v.val_unsigned = oprnd2;
+
+  return descr;
+}
+
+/* Add a location description term to a location description expression.  */
+
+static inline void
+add_loc_descr (list_head, descr)
+     register dw_loc_descr_ref *list_head;
+     register dw_loc_descr_ref descr;
+{
+  register dw_loc_descr_ref *d;
+
+  /* Find the end of the chain.  */
+  for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
+    ;
+
+  *d = descr;
+}
+
+/* Return the size of a location descriptor.  */
+
+static unsigned long
+size_of_loc_descr (loc)
+     register dw_loc_descr_ref loc;
+{
+  register unsigned long size = 1;
+
+  switch (loc->dw_loc_opc)
     {
     case DW_OP_addr:
-      return "DW_OP_addr";
-    case DW_OP_deref:
-      return "DW_OP_deref";
+      size += DWARF2_ADDR_SIZE;
+      break;
     case DW_OP_const1u:
-      return "DW_OP_const1u";
     case DW_OP_const1s:
-      return "DW_OP_const1s";
+      size += 1;
+      break;
     case DW_OP_const2u:
-      return "DW_OP_const2u";
     case DW_OP_const2s:
-      return "DW_OP_const2s";
+      size += 2;
+      break;
     case DW_OP_const4u:
-      return "DW_OP_const4u";
     case DW_OP_const4s:
-      return "DW_OP_const4s";
+      size += 4;
+      break;
     case DW_OP_const8u:
-      return "DW_OP_const8u";
     case DW_OP_const8s:
-      return "DW_OP_const8s";
+      size += 8;
+      break;
     case DW_OP_constu:
-      return "DW_OP_constu";
+      size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
+      break;
     case DW_OP_consts:
-      return "DW_OP_consts";
-    case DW_OP_dup:
-      return "DW_OP_dup";
-    case DW_OP_drop:
-      return "DW_OP_drop";
-    case DW_OP_over:
-      return "DW_OP_over";
+      size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
+      break;
     case DW_OP_pick:
-      return "DW_OP_pick";
-    case DW_OP_swap:
-      return "DW_OP_swap";
-    case DW_OP_rot:
-      return "DW_OP_rot";
-    case DW_OP_xderef:
-      return "DW_OP_xderef";
-    case DW_OP_abs:
-      return "DW_OP_abs";
-    case DW_OP_and:
-      return "DW_OP_and";
-    case DW_OP_div:
-      return "DW_OP_div";
-    case DW_OP_minus:
-      return "DW_OP_minus";
-    case DW_OP_mod:
-      return "DW_OP_mod";
-    case DW_OP_mul:
-      return "DW_OP_mul";
-    case DW_OP_neg:
-      return "DW_OP_neg";
-    case DW_OP_not:
-      return "DW_OP_not";
-    case DW_OP_or:
-      return "DW_OP_or";
-    case DW_OP_plus:
-      return "DW_OP_plus";
+      size += 1;
+      break;
     case DW_OP_plus_uconst:
-      return "DW_OP_plus_uconst";
-    case DW_OP_shl:
-      return "DW_OP_shl";
-    case DW_OP_shr:
-      return "DW_OP_shr";
-    case DW_OP_shra:
-      return "DW_OP_shra";
-    case DW_OP_xor:
-      return "DW_OP_xor";
+      size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
+      break;
+    case DW_OP_skip:
     case DW_OP_bra:
-      return "DW_OP_bra";
-    case DW_OP_eq:
-      return "DW_OP_eq";
-    case DW_OP_ge:
-      return "DW_OP_ge";
-    case DW_OP_gt:
-      return "DW_OP_gt";
-    case DW_OP_le:
-      return "DW_OP_le";
-    case DW_OP_lt:
-      return "DW_OP_lt";
-    case DW_OP_ne:
-      return "DW_OP_ne";
+      size += 2;
+      break;
+    case DW_OP_breg0:
+    case DW_OP_breg1:
+    case DW_OP_breg2:
+    case DW_OP_breg3:
+    case DW_OP_breg4:
+    case DW_OP_breg5:
+    case DW_OP_breg6:
+    case DW_OP_breg7:
+    case DW_OP_breg8:
+    case DW_OP_breg9:
+    case DW_OP_breg10:
+    case DW_OP_breg11:
+    case DW_OP_breg12:
+    case DW_OP_breg13:
+    case DW_OP_breg14:
+    case DW_OP_breg15:
+    case DW_OP_breg16:
+    case DW_OP_breg17:
+    case DW_OP_breg18:
+    case DW_OP_breg19:
+    case DW_OP_breg20:
+    case DW_OP_breg21:
+    case DW_OP_breg22:
+    case DW_OP_breg23:
+    case DW_OP_breg24:
+    case DW_OP_breg25:
+    case DW_OP_breg26:
+    case DW_OP_breg27:
+    case DW_OP_breg28:
+    case DW_OP_breg29:
+    case DW_OP_breg30:
+    case DW_OP_breg31:
+      size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
+      break;
+    case DW_OP_regx:
+      size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
+      break;
+    case DW_OP_fbreg:
+      size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
+      break;
+    case DW_OP_bregx:
+      size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
+      size += size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int);
+      break;
+    case DW_OP_piece:
+      size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
+      break;
+    case DW_OP_deref_size:
+    case DW_OP_xderef_size:
+      size += 1;
+      break;
+    default:
+      break;
+    }
+
+  return size;
+}
+
+/* Return the size of a series of location descriptors.  */
+
+static unsigned long
+size_of_locs (loc)
+     register dw_loc_descr_ref loc;
+{
+  register unsigned long size = 0;
+
+  for (; loc != NULL; loc = loc->dw_loc_next)
+    size += size_of_loc_descr (loc);
+
+  return size;
+}
+
+/* Output location description stack opcode's operands (if any).  */
+
+static void
+output_loc_operands (loc)
+     register dw_loc_descr_ref loc;
+{
+  register dw_val_ref val1 = &loc->dw_loc_oprnd1;
+  register dw_val_ref val2 = &loc->dw_loc_oprnd2;
+
+  switch (loc->dw_loc_opc)
+    {
+#ifdef DWARF2_DEBUGGING_INFO
+    case DW_OP_addr:
+      ASM_OUTPUT_DWARF_ADDR_CONST (asm_out_file, val1->v.val_addr);
+      fputc ('\n', asm_out_file);
+      break;
+    case DW_OP_const2u:
+    case DW_OP_const2s:
+      ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int);
+      fputc ('\n', asm_out_file);
+      break;
+    case DW_OP_const4u:
+    case DW_OP_const4s:
+      ASM_OUTPUT_DWARF_DATA4 (asm_out_file, val1->v.val_int);
+      fputc ('\n', asm_out_file);
+      break;
+    case DW_OP_const8u:
+    case DW_OP_const8s:
+      abort ();
+      fputc ('\n', asm_out_file);
+      break;
+    case DW_OP_skip:
+    case DW_OP_bra:
+      ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int);
+      fputc ('\n', asm_out_file);
+      break;
+#else
+    case DW_OP_addr:
+    case DW_OP_const2u:
+    case DW_OP_const2s:
+    case DW_OP_const4u:
+    case DW_OP_const4s:
+    case DW_OP_const8u:
+    case DW_OP_const8s:
     case DW_OP_skip:
-      return "DW_OP_skip";
-    case DW_OP_lit0:
-      return "DW_OP_lit0";
-    case DW_OP_lit1:
-      return "DW_OP_lit1";
-    case DW_OP_lit2:
-      return "DW_OP_lit2";
-    case DW_OP_lit3:
-      return "DW_OP_lit3";
-    case DW_OP_lit4:
-      return "DW_OP_lit4";
-    case DW_OP_lit5:
-      return "DW_OP_lit5";
-    case DW_OP_lit6:
-      return "DW_OP_lit6";
-    case DW_OP_lit7:
-      return "DW_OP_lit7";
-    case DW_OP_lit8:
-      return "DW_OP_lit8";
-    case DW_OP_lit9:
-      return "DW_OP_lit9";
-    case DW_OP_lit10:
-      return "DW_OP_lit10";
-    case DW_OP_lit11:
-      return "DW_OP_lit11";
-    case DW_OP_lit12:
-      return "DW_OP_lit12";
-    case DW_OP_lit13:
-      return "DW_OP_lit13";
-    case DW_OP_lit14:
-      return "DW_OP_lit14";
-    case DW_OP_lit15:
-      return "DW_OP_lit15";
-    case DW_OP_lit16:
-      return "DW_OP_lit16";
-    case DW_OP_lit17:
-      return "DW_OP_lit17";
-    case DW_OP_lit18:
-      return "DW_OP_lit18";
-    case DW_OP_lit19:
-      return "DW_OP_lit19";
-    case DW_OP_lit20:
-      return "DW_OP_lit20";
-    case DW_OP_lit21:
-      return "DW_OP_lit21";
-    case DW_OP_lit22:
-      return "DW_OP_lit22";
-    case DW_OP_lit23:
-      return "DW_OP_lit23";
-    case DW_OP_lit24:
-      return "DW_OP_lit24";
-    case DW_OP_lit25:
-      return "DW_OP_lit25";
-    case DW_OP_lit26:
-      return "DW_OP_lit26";
-    case DW_OP_lit27:
-      return "DW_OP_lit27";
-    case DW_OP_lit28:
-      return "DW_OP_lit28";
-    case DW_OP_lit29:
-      return "DW_OP_lit29";
-    case DW_OP_lit30:
-      return "DW_OP_lit30";
-    case DW_OP_lit31:
-      return "DW_OP_lit31";
-    case DW_OP_reg0:
-      return "DW_OP_reg0";
-    case DW_OP_reg1:
-      return "DW_OP_reg1";
-    case DW_OP_reg2:
-      return "DW_OP_reg2";
-    case DW_OP_reg3:
-      return "DW_OP_reg3";
-    case DW_OP_reg4:
-      return "DW_OP_reg4";
-    case DW_OP_reg5:
-      return "DW_OP_reg5";
-    case DW_OP_reg6:
-      return "DW_OP_reg6";
-    case DW_OP_reg7:
-      return "DW_OP_reg7";
-    case DW_OP_reg8:
-      return "DW_OP_reg8";
-    case DW_OP_reg9:
-      return "DW_OP_reg9";
-    case DW_OP_reg10:
-      return "DW_OP_reg10";
-    case DW_OP_reg11:
-      return "DW_OP_reg11";
-    case DW_OP_reg12:
-      return "DW_OP_reg12";
-    case DW_OP_reg13:
-      return "DW_OP_reg13";
-    case DW_OP_reg14:
-      return "DW_OP_reg14";
-    case DW_OP_reg15:
-      return "DW_OP_reg15";
-    case DW_OP_reg16:
-      return "DW_OP_reg16";
-    case DW_OP_reg17:
-      return "DW_OP_reg17";
-    case DW_OP_reg18:
-      return "DW_OP_reg18";
-    case DW_OP_reg19:
-      return "DW_OP_reg19";
-    case DW_OP_reg20:
-      return "DW_OP_reg20";
-    case DW_OP_reg21:
-      return "DW_OP_reg21";
-    case DW_OP_reg22:
-      return "DW_OP_reg22";
-    case DW_OP_reg23:
-      return "DW_OP_reg23";
-    case DW_OP_reg24:
-      return "DW_OP_reg24";
-    case DW_OP_reg25:
-      return "DW_OP_reg25";
-    case DW_OP_reg26:
-      return "DW_OP_reg26";
-    case DW_OP_reg27:
-      return "DW_OP_reg27";
-    case DW_OP_reg28:
-      return "DW_OP_reg28";
-    case DW_OP_reg29:
-      return "DW_OP_reg29";
-    case DW_OP_reg30:
-      return "DW_OP_reg30";
-    case DW_OP_reg31:
-      return "DW_OP_reg31";
+    case DW_OP_bra:
+      /* We currently don't make any attempt to make sure these are
+         aligned properly like we do for the main unwind info, so
+         don't support emitting things larger than a byte if we're
+         only doing unwinding.  */
+      abort ();
+#endif
+    case DW_OP_const1u:
+    case DW_OP_const1s:
+      ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_flag);
+      fputc ('\n', asm_out_file);
+      break;
+    case DW_OP_constu:
+      output_uleb128 (val1->v.val_unsigned);
+      fputc ('\n', asm_out_file);
+      break;
+    case DW_OP_consts:
+      output_sleb128 (val1->v.val_int);
+      fputc ('\n', asm_out_file);
+      break;
+    case DW_OP_pick:
+      ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_int);
+      fputc ('\n', asm_out_file);
+      break;
+    case DW_OP_plus_uconst:
+      output_uleb128 (val1->v.val_unsigned);
+      fputc ('\n', asm_out_file);
+      break;
     case DW_OP_breg0:
-      return "DW_OP_breg0";
     case DW_OP_breg1:
-      return "DW_OP_breg1";
     case DW_OP_breg2:
-      return "DW_OP_breg2";
     case DW_OP_breg3:
-      return "DW_OP_breg3";
     case DW_OP_breg4:
-      return "DW_OP_breg4";
     case DW_OP_breg5:
-      return "DW_OP_breg5";
     case DW_OP_breg6:
-      return "DW_OP_breg6";
     case DW_OP_breg7:
-      return "DW_OP_breg7";
     case DW_OP_breg8:
-      return "DW_OP_breg8";
     case DW_OP_breg9:
-      return "DW_OP_breg9";
     case DW_OP_breg10:
-      return "DW_OP_breg10";
     case DW_OP_breg11:
-      return "DW_OP_breg11";
     case DW_OP_breg12:
-      return "DW_OP_breg12";
     case DW_OP_breg13:
-      return "DW_OP_breg13";
     case DW_OP_breg14:
-      return "DW_OP_breg14";
     case DW_OP_breg15:
-      return "DW_OP_breg15";
     case DW_OP_breg16:
-      return "DW_OP_breg16";
     case DW_OP_breg17:
-      return "DW_OP_breg17";
     case DW_OP_breg18:
-      return "DW_OP_breg18";
     case DW_OP_breg19:
-      return "DW_OP_breg19";
     case DW_OP_breg20:
-      return "DW_OP_breg20";
     case DW_OP_breg21:
-      return "DW_OP_breg21";
     case DW_OP_breg22:
-      return "DW_OP_breg22";
     case DW_OP_breg23:
-      return "DW_OP_breg23";
     case DW_OP_breg24:
-      return "DW_OP_breg24";
     case DW_OP_breg25:
-      return "DW_OP_breg25";
     case DW_OP_breg26:
-      return "DW_OP_breg26";
     case DW_OP_breg27:
-      return "DW_OP_breg27";
     case DW_OP_breg28:
-      return "DW_OP_breg28";
     case DW_OP_breg29:
-      return "DW_OP_breg29";
     case DW_OP_breg30:
-      return "DW_OP_breg30";
     case DW_OP_breg31:
-      return "DW_OP_breg31";
+      output_sleb128 (val1->v.val_int);
+      fputc ('\n', asm_out_file);
+      break;
     case DW_OP_regx:
-      return "DW_OP_regx";
+      output_uleb128 (val1->v.val_unsigned);
+      fputc ('\n', asm_out_file);
+      break;
     case DW_OP_fbreg:
-      return "DW_OP_fbreg";
+      output_sleb128 (val1->v.val_int);
+      fputc ('\n', asm_out_file);
+      break;
     case DW_OP_bregx:
-      return "DW_OP_bregx";
+      output_uleb128 (val1->v.val_unsigned);
+      fputc ('\n', asm_out_file);
+      output_sleb128 (val2->v.val_int);
+      fputc ('\n', asm_out_file);
+      break;
     case DW_OP_piece:
-      return "DW_OP_piece";
+      output_uleb128 (val1->v.val_unsigned);
+      fputc ('\n', asm_out_file);
+      break;
     case DW_OP_deref_size:
-      return "DW_OP_deref_size";
     case DW_OP_xderef_size:
-      return "DW_OP_xderef_size";
-    case DW_OP_nop:
-      return "DW_OP_nop";
+      ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_flag);
+      fputc ('\n', asm_out_file);
+      break;
+    default:
+      /* Other codes have no operands.  */
+      break;
+    }
+}
+
+/* Output a sequence of location operations.  */
+
+static void
+output_loc_sequence (loc)
+     dw_loc_descr_ref loc;
+{
+  for (; loc != NULL; loc = loc->dw_loc_next)
+    {
+      /* Output the opcode.  */
+      ASM_OUTPUT_DWARF_DATA1 (asm_out_file, loc->dw_loc_opc);
+      if (flag_debug_asm)
+       fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START,
+                dwarf_stack_op_name (loc->dw_loc_opc));
+
+      fputc ('\n', asm_out_file);
+
+      /* Output the operand(s) (if any).  */
+      output_loc_operands (loc);
+    }
+}
+
+/* This routine will generate the correct assembly data for a location
+   description based on a cfi entry with a complex address.  */
+
+static void
+output_cfa_loc (cfi)
+     dw_cfi_ref cfi;
+{
+  dw_loc_descr_ref loc;
+  unsigned long size;
+
+  /* Output the size of the block.  */
+  loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
+  size = size_of_locs (loc);
+  output_uleb128 (size);
+  fputc ('\n', asm_out_file);
+
+  /* Now output the operations themselves.  */
+  output_loc_sequence (loc);
+}
+
+/* This function builds a dwarf location descriptor seqeunce from 
+   a dw_cfa_location. */
+
+static struct dw_loc_descr_struct *
+build_cfa_loc (cfa)
+     dw_cfa_location *cfa;
+{
+  struct dw_loc_descr_struct *head, *tmp;
+
+  if (cfa->indirect == 0)
+    abort ();
+
+  if (cfa->base_offset)
+    head = new_loc_descr (DW_OP_breg0 + cfa->reg, cfa->base_offset, 0);
+  else
+    head = new_loc_descr (DW_OP_reg0 + cfa->reg, 0, 0);
+  head->dw_loc_oprnd1.val_class = dw_val_class_const;
+  tmp = new_loc_descr (DW_OP_deref, 0, 0);
+  add_loc_descr (&head, tmp);
+  if (cfa->offset != 0)
+    {
+      tmp = new_loc_descr (DW_OP_plus_uconst, cfa->offset, 0);
+      add_loc_descr (&head, tmp);
+    }
+  return head;
+}
+
+/* This function fills in aa dw_cfa_location structure from a 
+   dwarf location descriptor sequence.  */
+
+static void
+get_cfa_from_loc_descr (cfa, loc)
+     dw_cfa_location *cfa;
+     struct dw_loc_descr_struct * loc;
+{
+  struct dw_loc_descr_struct * ptr;
+  cfa->offset = 0;
+  cfa->base_offset = 0;
+  cfa->indirect = 0;
+  cfa->reg = -1;
+
+  for (ptr = loc; ptr != NULL; ptr = ptr->dw_loc_next)
+    {
+      enum dwarf_location_atom op = ptr->dw_loc_opc;
+      switch (op)
+        {
+       case DW_OP_reg0:
+       case DW_OP_reg1:
+       case DW_OP_reg2:
+       case DW_OP_reg3:
+       case DW_OP_reg4:
+       case DW_OP_reg5:
+       case DW_OP_reg6:
+       case DW_OP_reg7:
+       case DW_OP_reg8:
+       case DW_OP_reg9:
+       case DW_OP_reg10:
+       case DW_OP_reg11:
+       case DW_OP_reg12:
+       case DW_OP_reg13:
+       case DW_OP_reg14:
+       case DW_OP_reg15:
+       case DW_OP_reg16:
+       case DW_OP_reg17:
+       case DW_OP_reg18:
+       case DW_OP_reg19:
+       case DW_OP_reg20:
+       case DW_OP_reg21:
+       case DW_OP_reg22:
+       case DW_OP_reg23:
+       case DW_OP_reg24:
+       case DW_OP_reg25:
+       case DW_OP_reg26:
+       case DW_OP_reg27:
+       case DW_OP_reg28:
+       case DW_OP_reg29:
+       case DW_OP_reg30:
+       case DW_OP_reg31:
+         cfa->reg = op - DW_OP_reg0;
+         break;
+       case DW_OP_regx:
+         cfa->reg = ptr->dw_loc_oprnd1.v.val_int;
+         break;
+       case DW_OP_breg0:
+       case DW_OP_breg1:
+       case DW_OP_breg2:
+       case DW_OP_breg3:
+       case DW_OP_breg4:
+       case DW_OP_breg5:
+       case DW_OP_breg6:
+       case DW_OP_breg7:
+       case DW_OP_breg8:
+       case DW_OP_breg9:
+       case DW_OP_breg10:
+       case DW_OP_breg11:
+       case DW_OP_breg12:
+       case DW_OP_breg13:
+       case DW_OP_breg14:
+       case DW_OP_breg15:
+       case DW_OP_breg16:
+       case DW_OP_breg17:
+       case DW_OP_breg18:
+       case DW_OP_breg19:
+       case DW_OP_breg20:
+       case DW_OP_breg21:
+       case DW_OP_breg22:
+       case DW_OP_breg23:
+       case DW_OP_breg24:
+       case DW_OP_breg25:
+       case DW_OP_breg26:
+       case DW_OP_breg27:
+       case DW_OP_breg28:
+       case DW_OP_breg29:
+       case DW_OP_breg30:
+       case DW_OP_breg31:
+         cfa->reg = op - DW_OP_breg0;
+         cfa->base_offset = ptr->dw_loc_oprnd1.v.val_int;
+         break;
+       case DW_OP_bregx:
+         cfa->reg = ptr->dw_loc_oprnd1.v.val_int;
+         cfa->base_offset = ptr->dw_loc_oprnd2.v.val_int;
+         break;
+       case DW_OP_deref:
+         cfa->indirect = 1;
+         break;
+       case DW_OP_plus_uconst:
+         cfa->offset =  ptr->dw_loc_oprnd1.v.val_unsigned;
+         break;
+       default:
+         fatal ("DW_LOC_OP %s not implememnted yet.\n",
+                dwarf_stack_op_name (ptr->dw_loc_opc));
+       }
+    }
+}
+#endif /* .debug_frame support */
+\f
+/* And now, the support for symbolic debugging information.  */
+#ifdef DWARF2_DEBUGGING_INFO
+
+/* NOTE: In the comments in this file, many references are made to
+   "Debugging Information Entries".  This term is abbreviated as `DIE'
+   throughout the remainder of this file.  */
+
+/* An internal representation of the DWARF output is built, and then
+   walked to generate the DWARF debugging info.  The walk of the internal
+   representation is done after the entire program has been compiled.
+   The types below are used to describe the internal representation.  */
+
+/* Various DIE's use offsets relative to the beginning of the
+   .debug_info section to refer to each other.  */
+
+typedef long int dw_offset;
+
+/* Define typedefs here to avoid circular dependencies.  */
+
+typedef struct dw_attr_struct *dw_attr_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 pubname_struct *pubname_ref;
+typedef dw_die_ref *arange_ref;
+
+/* Each entry in the line_info_table maintains the file and
+   line number associated with the label generated for that
+   entry.  The label gives the PC value associated with
+   the line number entry.  */
+
+typedef struct dw_line_info_struct
+{
+  unsigned long dw_file_num;
+  unsigned long dw_line_num;
+}
+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;
+
+/* Each DIE attribute has a field specifying the attribute kind,
+   a link to the next attribute in the chain, and an attribute value.
+   Attributes are typically linked below the DIE they modify.  */
+
+typedef struct dw_attr_struct
+{
+  enum dwarf_attribute dw_attr;
+  dw_attr_ref dw_attr_next;
+  dw_val_node dw_attr_val;
+}
+dw_attr_node;
+
+/* The Debugging Information Entry (DIE) structure */
+
+typedef struct die_struct
+{
+  enum dwarf_tag die_tag;
+  dw_attr_ref die_attr;
+  dw_die_ref die_parent;
+  dw_die_ref die_child;
+  dw_die_ref die_sib;
+  dw_offset die_offset;
+  unsigned long die_abbrev;
+}
+die_node;
+
+/* The pubname structure */
+
+typedef struct pubname_struct
+{
+  dw_die_ref die;
+  char * name;
+}
+pubname_entry;
+
+/* The limbo die list structure.  */
+typedef struct limbo_die_struct
+{
+  dw_die_ref die;
+  struct limbo_die_struct *next;
+}
+limbo_die_node;
+
+/* How to start an assembler comment.  */
+#ifndef ASM_COMMENT_START
+#define ASM_COMMENT_START ";#"
+#endif
+
+/* Define a macro which returns non-zero for a TYPE_DECL which was
+   implicitly generated for a tagged type.
+
+   Note that unlike the gcc front end (which generates a NULL named
+   TYPE_DECL node for each complete tagged type, each array type, and
+   each function type node created) the g++ front end generates a
+   _named_ TYPE_DECL node for each tagged type node created.
+   These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to
+   generate a DW_TAG_typedef DIE for them.  */
+
+#define TYPE_DECL_IS_STUB(decl)                                \
+  (DECL_NAME (decl) == NULL_TREE                       \
+   || (DECL_ARTIFICIAL (decl)                          \
+       && is_tagged_type (TREE_TYPE (decl))            \
+       && ((decl == TYPE_STUB_DECL (TREE_TYPE (decl))) \
+          /* This is necessary for stub decls that     \
+             appear in nested inline functions.  */    \
+          || (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE \
+              && (decl_ultimate_origin (decl)          \
+                  == TYPE_STUB_DECL (TREE_TYPE (decl)))))))
+
+/* 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)
+
+/* Fixed size portion of debugging line information prolog.  */
+#define DWARF_LINE_PROLOG_HEADER_SIZE 5
+
+/* Fixed size portion of public names info.  */
+#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2)
+
+/* Fixed size portion of the address range info.  */
+#define DWARF_ARANGES_HEADER_SIZE                                      \
+  (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2)       \
+   - DWARF_OFFSET_SIZE)
+
+/* Size of padding portion in the address range info.  It must be
+   aligned to twice the pointer size.  */
+#define DWARF_ARANGES_PAD_SIZE \
+  (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \
+   - (2 * DWARF_OFFSET_SIZE + 4))
+
+/* The default is to have gcc emit the line number tables.  */
+#ifndef DWARF2_ASM_LINE_DEBUG_INFO
+#define DWARF2_ASM_LINE_DEBUG_INFO 0
+#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
+
+/* First special line opcde - leave room for the standard opcodes.  */
+#define DWARF_LINE_OPCODE_BASE  10
+
+/* Range of line offsets in a special line info. opcode.  */
+#define DWARF_LINE_RANGE  (254-DWARF_LINE_OPCODE_BASE+1)
+
+/* Flag that indicates the initial value of the is_stmt_start flag.
+   In the present implementation, we do not mark any lines as
+   the beginning of a source statement, because that information
+   is not made available by the GCC front-end.  */
+#define        DWARF_LINE_DEFAULT_IS_STMT_START 1
+
+/* This location is used by calc_die_sizes() to keep track
+   the offset of each DIE within the .debug_info section.  */
+static unsigned long next_die_offset;
+
+/* Record the root of the DIE's built for the current compilation unit.  */
+static dw_die_ref comp_unit_die;
+
+/* A list of DIEs with a NULL parent waiting to be relocated.  */
+static limbo_die_node *limbo_die_list = 0;
+
+/* Pointer to an array of filenames referenced by this compilation unit.  */
+static char **file_table;
+
+/* Total number of entries in the table (i.e. array) pointed to by
+   `file_table'.  This is the *total* and includes both used and unused
+   slots.  */
+static unsigned file_table_allocated;
+
+/* Number of entries in the file_table which are actually in use.  */
+static unsigned file_table_in_use;
+
+/* Size (in elements) of increments by which we may expand the filename
+   table.  */
+#define FILE_TABLE_INCREMENT 64
+
+/* Local pointer to the name of the main input file.  Initialized in
+   dwarf2out_init.  */
+static const char *primary_filename;
+
+/* A pointer to the base of a table of references to DIE's that describe
+   declarations.  The table is indexed by DECL_UID() which is a unique
+   number identifying each decl.  */
+static dw_die_ref *decl_die_table;
+
+/* Number of elements currently allocated for the decl_die_table.  */
+static unsigned decl_die_table_allocated;
+
+/* Number of elements in decl_die_table currently in use.  */
+static unsigned decl_die_table_in_use;
+
+/* Size (in elements) of increments by which we may expand the
+   decl_die_table.  */
+#define DECL_DIE_TABLE_INCREMENT 256
+
+/* A pointer to the base of a table of references to declaration
+   scopes.  This table is a display which tracks the nesting
+   of declaration scopes at the current scope and containing
+   scopes.  This table is used to find the proper place to
+   define type declaration DIE's.  */
+static tree *decl_scope_table;
+
+/* Number of elements currently allocated for the decl_scope_table.  */
+static int decl_scope_table_allocated;
+
+/* Current level of nesting of declaration scopes.  */
+static int decl_scope_depth;
+
+/* Size (in elements) of increments by which we may expand the
+   decl_scope_table.  */
+#define DECL_SCOPE_TABLE_INCREMENT 64
+
+/* A pointer to the base of a list of references to DIE's that
+   are uniquely identified by their tag, presence/absence of
+   children DIE's, and list of attribute/value pairs.  */
+static dw_die_ref *abbrev_die_table;
+
+/* Number of elements currently allocated for abbrev_die_table.  */
+static unsigned abbrev_die_table_allocated;
+
+/* Number of elements in type_die_table currently in use.  */
+static unsigned abbrev_die_table_in_use;
+
+/* Size (in elements) of increments by which we may expand the
+   abbrev_die_table.  */
+#define ABBREV_DIE_TABLE_INCREMENT 256
+
+/* A pointer to the base of a table that contains line information
+   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;
+
+/* Size (in elements) of increments by which we may expand the
+   line_info_table.  */
+#define LINE_INFO_TABLE_INCREMENT 1024
+
+/* A pointer to the base of a table that contains a list of publicly
+   accessible names.  */
+static pubname_ref pubname_table;
+
+/* Number of elements currently allocated for pubname_table.  */
+static unsigned pubname_table_allocated;
+
+/* Number of elements in pubname_table currently in use.  */
+static unsigned pubname_table_in_use;
+
+/* Size (in elements) of increments by which we may expand the
+   pubname_table.  */
+#define PUBNAME_TABLE_INCREMENT 64
+
+/* A pointer to the base of a table that contains a list of publicly
+   accessible names.  */
+static arange_ref arange_table;
+
+/* Number of elements currently allocated for arange_table.  */
+static unsigned arange_table_allocated;
+
+/* Number of elements in arange_table currently in use.  */
+static unsigned arange_table_in_use;
+
+/* Size (in elements) of increments by which we may expand the
+   arange_table.  */
+#define ARANGE_TABLE_INCREMENT 64
+
+/* A pointer to the base of a list of incomplete types which might be
+   completed at some later time.  */
+
+static tree *incomplete_types_list;
+
+/* Number of elements currently allocated for the incomplete_types_list.  */
+static unsigned incomplete_types_allocated;
+
+/* Number of elements of incomplete_types_list currently in use.  */
+static unsigned incomplete_types;
+
+/* Size (in elements) of increments by which we may expand the incomplete
+   types list.  Actually, a single hunk of space of this size should
+   be enough for most typical programs.         */
+#define INCOMPLETE_TYPES_INCREMENT 64
+
+/* Record whether the function being analyzed contains inlined functions.  */
+static int current_function_has_inlines;
+#if 0 && defined (MIPS_DEBUGGING_INFO)
+static int comp_unit_has_inlines;
+#endif
+
+/* Array of RTXes referenced by the debugging information, which therefore
+   must be kept around forever.  We do this rather than perform GC on
+   the dwarf info because almost all of the dwarf info lives forever, and
+   it's easier to support non-GC frontends this way.  */
+static varray_type used_rtx_varray;
+
+/* Forward declarations for functions defined in this file.  */
+
+static int is_pseudo_reg               PARAMS ((rtx));
+static tree type_main_variant          PARAMS ((tree));
+static int is_tagged_type              PARAMS ((tree));
+static const char *dwarf_tag_name      PARAMS ((unsigned));
+static const char *dwarf_attr_name     PARAMS ((unsigned));
+static const char *dwarf_form_name     PARAMS ((unsigned));
+#if 0
+static const char *dwarf_type_encoding_name PARAMS ((unsigned));
+#endif
+static tree decl_ultimate_origin       PARAMS ((tree));
+static tree block_ultimate_origin      PARAMS ((tree));
+static tree decl_class_context         PARAMS ((tree));
+static void add_dwarf_attr             PARAMS ((dw_die_ref, dw_attr_ref));
+static void add_AT_flag                        PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                unsigned));
+static void add_AT_int                 PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute, long));
+static void add_AT_unsigned            PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                unsigned long));
+static void add_AT_long_long           PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                unsigned long,
+                                                unsigned long));
+static void add_AT_float               PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                unsigned, long *));
+static void add_AT_string              PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                const char *));
+static void add_AT_die_ref             PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                dw_die_ref));
+static void add_AT_fde_ref             PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                unsigned));
+static void add_AT_loc                 PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                dw_loc_descr_ref));
+static void add_AT_addr                        PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                rtx));
+static void add_AT_lbl_id              PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                const char *));
+static void add_AT_lbl_offset          PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                const char *));
+static dw_attr_ref get_AT              PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute));
+static const char *get_AT_low_pc       PARAMS ((dw_die_ref));
+static const char *get_AT_hi_pc                PARAMS ((dw_die_ref));
+static const char *get_AT_string       PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute));
+static int get_AT_flag                 PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute));
+static unsigned get_AT_unsigned                PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute));
+static inline dw_die_ref get_AT_ref    PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute));
+static int is_c_family                 PARAMS ((void));
+static int is_fortran                  PARAMS ((void));
+static void remove_AT                  PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute));
+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 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));
+static void equate_decl_number_to_die  PARAMS ((tree, dw_die_ref));
+static void print_spaces               PARAMS ((FILE *));
+static void print_die                  PARAMS ((dw_die_ref, FILE *));
+static void print_dwarf_line_table     PARAMS ((FILE *));
+static void add_sibling_attributes     PARAMS ((dw_die_ref));
+static void build_abbrev_table         PARAMS ((dw_die_ref));
+static unsigned long size_of_string    PARAMS ((const char *));
+static int constant_size               PARAMS ((long unsigned));
+static unsigned long size_of_die       PARAMS ((dw_die_ref));
+static void calc_die_sizes             PARAMS ((dw_die_ref));
+static unsigned long size_of_line_prolog PARAMS ((void));
+static unsigned long size_of_pubnames  PARAMS ((void));
+static unsigned long size_of_aranges   PARAMS ((void));
+static enum dwarf_form value_format    PARAMS ((dw_attr_ref));
+static void output_value_format                PARAMS ((dw_attr_ref));
+static void output_abbrev_section      PARAMS ((void));
+static void output_die                 PARAMS ((dw_die_ref));
+static void output_compilation_unit_header PARAMS ((void));
+static const char *dwarf2_name         PARAMS ((tree, int));
+static void add_pubname                        PARAMS ((tree, dw_die_ref));
+static void output_pubnames            PARAMS ((void));
+static void add_arange                 PARAMS ((tree, dw_die_ref));
+static void output_aranges             PARAMS ((void));
+static void output_line_info           PARAMS ((void));
+static dw_die_ref base_type_die                PARAMS ((tree));
+static tree root_type                  PARAMS ((tree));
+static int is_base_type                        PARAMS ((tree));
+static dw_die_ref modified_type_die    PARAMS ((tree, int, int, dw_die_ref));
+static int type_is_enum                        PARAMS ((tree));
+static unsigned int reg_number         PARAMS ((rtx));
+static dw_loc_descr_ref reg_loc_descriptor PARAMS ((rtx));
+static dw_loc_descr_ref based_loc_descr        PARAMS ((unsigned, long));
+static int is_based_loc                        PARAMS ((rtx));
+static dw_loc_descr_ref mem_loc_descriptor PARAMS ((rtx, enum machine_mode mode));
+static dw_loc_descr_ref concat_loc_descriptor PARAMS ((rtx, rtx));
+static dw_loc_descr_ref loc_descriptor PARAMS ((rtx));
+static HOST_WIDE_INT ceiling           PARAMS ((HOST_WIDE_INT, unsigned int));
+static tree field_type                 PARAMS ((tree));
+static unsigned int simple_type_align_in_bits PARAMS ((tree));
+static unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree));
+static HOST_WIDE_INT field_byte_offset PARAMS ((tree));
+static void add_AT_location_description        PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute, rtx));
+static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree));
+static void add_const_value_attribute  PARAMS ((dw_die_ref, rtx));
+static void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree));
+static void add_name_attribute         PARAMS ((dw_die_ref, const char *));
+static void add_bound_info             PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute, tree));
+static void add_subscript_info         PARAMS ((dw_die_ref, tree));
+static void add_byte_size_attribute    PARAMS ((dw_die_ref, tree));
+static void add_bit_offset_attribute   PARAMS ((dw_die_ref, tree));
+static void add_bit_size_attribute     PARAMS ((dw_die_ref, tree));
+static void add_prototyped_attribute   PARAMS ((dw_die_ref, tree));
+static void add_abstract_origin_attribute PARAMS ((dw_die_ref, tree));
+static void add_pure_or_virtual_attribute PARAMS ((dw_die_ref, tree));
+static void add_src_coords_attributes  PARAMS ((dw_die_ref, tree));
+static void add_name_and_src_coords_attributes PARAMS ((dw_die_ref, tree));
+static void push_decl_scope            PARAMS ((tree));
+static dw_die_ref scope_die_for                PARAMS ((tree, dw_die_ref));
+static void pop_decl_scope             PARAMS ((void));
+static void add_type_attribute         PARAMS ((dw_die_ref, tree, int, int,
+                                                dw_die_ref));
+static const char *type_tag            PARAMS ((tree));
+static tree member_declared_type       PARAMS ((tree));
+#if 0
+static const char *decl_start_label    PARAMS ((tree));
+#endif
+static void gen_array_type_die         PARAMS ((tree, dw_die_ref));
+static void gen_set_type_die           PARAMS ((tree, dw_die_ref));
+#if 0
+static void gen_entry_point_die                PARAMS ((tree, dw_die_ref));
+#endif
+static void gen_inlined_enumeration_type_die PARAMS ((tree, dw_die_ref));
+static void gen_inlined_structure_type_die PARAMS ((tree, dw_die_ref));
+static void gen_inlined_union_type_die PARAMS ((tree, dw_die_ref));
+static void gen_enumeration_type_die   PARAMS ((tree, dw_die_ref));
+static dw_die_ref gen_formal_parameter_die PARAMS ((tree, dw_die_ref));
+static void gen_unspecified_parameters_die PARAMS ((tree, dw_die_ref));
+static void gen_formal_types_die       PARAMS ((tree, dw_die_ref));
+static void gen_subprogram_die         PARAMS ((tree, dw_die_ref));
+static void gen_variable_die           PARAMS ((tree, dw_die_ref));
+static void gen_label_die              PARAMS ((tree, dw_die_ref));
+static void gen_lexical_block_die      PARAMS ((tree, dw_die_ref, int));
+static void gen_inlined_subroutine_die PARAMS ((tree, dw_die_ref, int));
+static void gen_field_die              PARAMS ((tree, dw_die_ref));
+static void gen_ptr_to_mbr_type_die    PARAMS ((tree, dw_die_ref));
+static dw_die_ref gen_compile_unit_die PARAMS ((const char *));
+static void gen_string_type_die                PARAMS ((tree, dw_die_ref));
+static void gen_inheritance_die                PARAMS ((tree, dw_die_ref));
+static void gen_member_die             PARAMS ((tree, dw_die_ref));
+static void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref));
+static void gen_subroutine_type_die    PARAMS ((tree, dw_die_ref));
+static void gen_typedef_die            PARAMS ((tree, dw_die_ref));
+static void gen_type_die               PARAMS ((tree, dw_die_ref));
+static void gen_tagged_type_instantiation_die PARAMS ((tree, dw_die_ref));
+static void gen_block_die              PARAMS ((tree, dw_die_ref, int));
+static void decls_for_scope            PARAMS ((tree, dw_die_ref, int));
+static int is_redundant_typedef                PARAMS ((tree));
+static void gen_decl_die               PARAMS ((tree, dw_die_ref));
+static unsigned lookup_filename                PARAMS ((const char *));
+static void add_incomplete_type                PARAMS ((tree));
+static void retry_incomplete_types     PARAMS ((void));
+static void gen_type_die_for_member    PARAMS ((tree, tree, dw_die_ref));
+static void gen_abstract_function      PARAMS ((tree));
+static rtx save_rtx                    PARAMS ((rtx));
+static void splice_child_die           PARAMS ((dw_die_ref, dw_die_ref));
+static void reverse_die_lists          PARAMS ((dw_die_ref));
+
+/* Section names used to hold DWARF debugging information.  */
+#ifndef DEBUG_INFO_SECTION
+#define DEBUG_INFO_SECTION     ".debug_info"
+#endif
+#ifndef ABBREV_SECTION
+#define ABBREV_SECTION         ".debug_abbrev"
+#endif
+#ifndef ARANGES_SECTION
+#define ARANGES_SECTION                ".debug_aranges"
+#endif
+#ifndef DW_MACINFO_SECTION
+#define DW_MACINFO_SECTION     ".debug_macinfo"
+#endif
+#ifndef DEBUG_LINE_SECTION
+#define DEBUG_LINE_SECTION     ".debug_line"
+#endif
+#ifndef LOC_SECTION
+#define LOC_SECTION            ".debug_loc"
+#endif
+#ifndef PUBNAMES_SECTION
+#define PUBNAMES_SECTION       ".debug_pubnames"
+#endif
+#ifndef STR_SECTION
+#define STR_SECTION            ".debug_str"
+#endif
+
+/* Standard ELF section names for compiled code and data.  */
+#ifndef TEXT_SECTION
+#define TEXT_SECTION           ".text"
+#endif
+#ifndef DATA_SECTION
+#define DATA_SECTION           ".data"
+#endif
+#ifndef BSS_SECTION
+#define BSS_SECTION            ".bss"
+#endif
+
+/* Labels we insert at beginning sections we can reference instead of
+   the section names themselves. */
+
+#ifndef TEXT_SECTION_LABEL
+#define TEXT_SECTION_LABEL      "Ltext"
+#endif
+#ifndef DEBUG_LINE_SECTION_LABEL
+#define DEBUG_LINE_SECTION_LABEL "Ldebug_line"
+#endif
+#ifndef DEBUG_INFO_SECTION_LABEL
+#define DEBUG_INFO_SECTION_LABEL "Ldebug_info"
+#endif
+#ifndef ABBREV_SECTION_LABEL
+#define ABBREV_SECTION_LABEL     "Ldebug_abbrev"
+#endif
+
+
+/* Definitions of defaults for formats and names of various special
+   (artificial) labels which may be generated within this file (when the -g
+   options is used and DWARF_DEBUGGING_INFO is in effect.
+   If necessary, these may be overridden from within the tm.h file, but
+   typically, overriding these defaults is unnecessary.  */
+
+static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+#ifndef TEXT_END_LABEL
+#define TEXT_END_LABEL         "Letext"
+#endif
+#ifndef DATA_END_LABEL
+#define DATA_END_LABEL         "Ledata"
+#endif
+#ifndef BSS_END_LABEL
+#define BSS_END_LABEL           "Lebss"
+#endif
+#ifndef INSN_LABEL_FMT
+#define INSN_LABEL_FMT         "LI%u_"
+#endif
+#ifndef BLOCK_BEGIN_LABEL
+#define BLOCK_BEGIN_LABEL      "LBB"
+#endif
+#ifndef BLOCK_END_LABEL
+#define BLOCK_END_LABEL                "LBE"
+#endif
+#ifndef BODY_BEGIN_LABEL
+#define BODY_BEGIN_LABEL       "Lbb"
+#endif
+#ifndef BODY_END_LABEL
+#define BODY_END_LABEL         "Lbe"
+#endif
+#ifndef LINE_CODE_LABEL
+#define LINE_CODE_LABEL                "LM"
+#endif
+#ifndef SEPARATE_LINE_CODE_LABEL
+#define SEPARATE_LINE_CODE_LABEL       "LSM"
+#endif
+\f
+/* We allow a language front-end to designate a function that is to be
+   called to "demangle" any name before it it put into a DIE.  */
+
+static const char *(*demangle_name_func) PARAMS ((const char *));
+
+void
+dwarf2out_set_demangle_name_func (func)
+     const char *(*func) PARAMS ((const char *));
+{
+  demangle_name_func = func;
+}
+\f
+/* Return an rtx like ORIG which lives forever.  If we're doing GC,
+   that means adding it to used_rtx_varray.  If not, that means making
+   a copy on the permanent_obstack.  */
+
+static rtx
+save_rtx (orig)
+     register rtx orig;
+{
+  if (ggc_p)
+    VARRAY_PUSH_RTX (used_rtx_varray, orig);
+  else
+    {
+      push_obstacks_nochange ();
+      end_temporary_allocation ();
+      orig = copy_rtx (orig);
+      pop_obstacks ();
+    }
+
+  return orig;
+}
+
+/* Test if rtl node points to a pseudo register.  */
+
+static inline int
+is_pseudo_reg (rtl)
+     register rtx rtl;
+{
+  return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
+         || (GET_CODE (rtl) == SUBREG
+             && REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER));
+}
+
+/* Return a reference to a type, with its const and volatile qualifiers
+   removed.  */
+
+static inline tree
+type_main_variant (type)
+     register tree type;
+{
+  type = TYPE_MAIN_VARIANT (type);
+
+  /* There really should be only one main variant among any group of variants 
+     of a given type (and all of the MAIN_VARIANT values for all members of
+     the group should point to that one type) but sometimes the C front-end
+     messes this up for array types, so we work around that bug here.  */
+
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    while (type != TYPE_MAIN_VARIANT (type))
+      type = TYPE_MAIN_VARIANT (type);
+
+  return type;
+}
+
+/* Return non-zero if the given type node represents a tagged type.  */
+
+static inline int
+is_tagged_type (type)
+     register tree type;
+{
+  register enum tree_code code = TREE_CODE (type);
+
+  return (code == RECORD_TYPE || code == UNION_TYPE
+         || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
+}
+
+/* Convert a DIE tag into its string name.  */
+
+static const char *
+dwarf_tag_name (tag)
+     register unsigned tag;
+{
+  switch (tag)
+    {
+    case DW_TAG_padding:
+      return "DW_TAG_padding";
+    case DW_TAG_array_type:
+      return "DW_TAG_array_type";
+    case DW_TAG_class_type:
+      return "DW_TAG_class_type";
+    case DW_TAG_entry_point:
+      return "DW_TAG_entry_point";
+    case DW_TAG_enumeration_type:
+      return "DW_TAG_enumeration_type";
+    case DW_TAG_formal_parameter:
+      return "DW_TAG_formal_parameter";
+    case DW_TAG_imported_declaration:
+      return "DW_TAG_imported_declaration";
+    case DW_TAG_label:
+      return "DW_TAG_label";
+    case DW_TAG_lexical_block:
+      return "DW_TAG_lexical_block";
+    case DW_TAG_member:
+      return "DW_TAG_member";
+    case DW_TAG_pointer_type:
+      return "DW_TAG_pointer_type";
+    case DW_TAG_reference_type:
+      return "DW_TAG_reference_type";
+    case DW_TAG_compile_unit:
+      return "DW_TAG_compile_unit";
+    case DW_TAG_string_type:
+      return "DW_TAG_string_type";
+    case DW_TAG_structure_type:
+      return "DW_TAG_structure_type";
+    case DW_TAG_subroutine_type:
+      return "DW_TAG_subroutine_type";
+    case DW_TAG_typedef:
+      return "DW_TAG_typedef";
+    case DW_TAG_union_type:
+      return "DW_TAG_union_type";
+    case DW_TAG_unspecified_parameters:
+      return "DW_TAG_unspecified_parameters";
+    case DW_TAG_variant:
+      return "DW_TAG_variant";
+    case DW_TAG_common_block:
+      return "DW_TAG_common_block";
+    case DW_TAG_common_inclusion:
+      return "DW_TAG_common_inclusion";
+    case DW_TAG_inheritance:
+      return "DW_TAG_inheritance";
+    case DW_TAG_inlined_subroutine:
+      return "DW_TAG_inlined_subroutine";
+    case DW_TAG_module:
+      return "DW_TAG_module";
+    case DW_TAG_ptr_to_member_type:
+      return "DW_TAG_ptr_to_member_type";
+    case DW_TAG_set_type:
+      return "DW_TAG_set_type";
+    case DW_TAG_subrange_type:
+      return "DW_TAG_subrange_type";
+    case DW_TAG_with_stmt:
+      return "DW_TAG_with_stmt";
+    case DW_TAG_access_declaration:
+      return "DW_TAG_access_declaration";
+    case DW_TAG_base_type:
+      return "DW_TAG_base_type";
+    case DW_TAG_catch_block:
+      return "DW_TAG_catch_block";
+    case DW_TAG_const_type:
+      return "DW_TAG_const_type";
+    case DW_TAG_constant:
+      return "DW_TAG_constant";
+    case DW_TAG_enumerator:
+      return "DW_TAG_enumerator";
+    case DW_TAG_file_type:
+      return "DW_TAG_file_type";
+    case DW_TAG_friend:
+      return "DW_TAG_friend";
+    case DW_TAG_namelist:
+      return "DW_TAG_namelist";
+    case DW_TAG_namelist_item:
+      return "DW_TAG_namelist_item";
+    case DW_TAG_packed_type:
+      return "DW_TAG_packed_type";
+    case DW_TAG_subprogram:
+      return "DW_TAG_subprogram";
+    case DW_TAG_template_type_param:
+      return "DW_TAG_template_type_param";
+    case DW_TAG_template_value_param:
+      return "DW_TAG_template_value_param";
+    case DW_TAG_thrown_type:
+      return "DW_TAG_thrown_type";
+    case DW_TAG_try_block:
+      return "DW_TAG_try_block";
+    case DW_TAG_variant_part:
+      return "DW_TAG_variant_part";
+    case DW_TAG_variable:
+      return "DW_TAG_variable";
+    case DW_TAG_volatile_type:
+      return "DW_TAG_volatile_type";
+    case DW_TAG_MIPS_loop:
+      return "DW_TAG_MIPS_loop";
+    case DW_TAG_format_label:
+      return "DW_TAG_format_label";
+    case DW_TAG_function_template:
+      return "DW_TAG_function_template";
+    case DW_TAG_class_template:
+      return "DW_TAG_class_template";
+    default:
+      return "DW_TAG_<unknown>";
+    }
+}
+
+/* Convert a DWARF attribute code into its string name.  */
+
+static const char *
+dwarf_attr_name (attr)
+     register unsigned attr;
+{
+  switch (attr)
+    {
+    case DW_AT_sibling:
+      return "DW_AT_sibling";
+    case DW_AT_location:
+      return "DW_AT_location";
+    case DW_AT_name:
+      return "DW_AT_name";
+    case DW_AT_ordering:
+      return "DW_AT_ordering";
+    case DW_AT_subscr_data:
+      return "DW_AT_subscr_data";
+    case DW_AT_byte_size:
+      return "DW_AT_byte_size";
+    case DW_AT_bit_offset:
+      return "DW_AT_bit_offset";
+    case DW_AT_bit_size:
+      return "DW_AT_bit_size";
+    case DW_AT_element_list:
+      return "DW_AT_element_list";
+    case DW_AT_stmt_list:
+      return "DW_AT_stmt_list";
+    case DW_AT_low_pc:
+      return "DW_AT_low_pc";
+    case DW_AT_high_pc:
+      return "DW_AT_high_pc";
+    case DW_AT_language:
+      return "DW_AT_language";
+    case DW_AT_member:
+      return "DW_AT_member";
+    case DW_AT_discr:
+      return "DW_AT_discr";
+    case DW_AT_discr_value:
+      return "DW_AT_discr_value";
+    case DW_AT_visibility:
+      return "DW_AT_visibility";
+    case DW_AT_import:
+      return "DW_AT_import";
+    case DW_AT_string_length:
+      return "DW_AT_string_length";
+    case DW_AT_common_reference:
+      return "DW_AT_common_reference";
+    case DW_AT_comp_dir:
+      return "DW_AT_comp_dir";
+    case DW_AT_const_value:
+      return "DW_AT_const_value";
+    case DW_AT_containing_type:
+      return "DW_AT_containing_type";
+    case DW_AT_default_value:
+      return "DW_AT_default_value";
+    case DW_AT_inline:
+      return "DW_AT_inline";
+    case DW_AT_is_optional:
+      return "DW_AT_is_optional";
+    case DW_AT_lower_bound:
+      return "DW_AT_lower_bound";
+    case DW_AT_producer:
+      return "DW_AT_producer";
+    case DW_AT_prototyped:
+      return "DW_AT_prototyped";
+    case DW_AT_return_addr:
+      return "DW_AT_return_addr";
+    case DW_AT_start_scope:
+      return "DW_AT_start_scope";
+    case DW_AT_stride_size:
+      return "DW_AT_stride_size";
+    case DW_AT_upper_bound:
+      return "DW_AT_upper_bound";
+    case DW_AT_abstract_origin:
+      return "DW_AT_abstract_origin";
+    case DW_AT_accessibility:
+      return "DW_AT_accessibility";
+    case DW_AT_address_class:
+      return "DW_AT_address_class";
+    case DW_AT_artificial:
+      return "DW_AT_artificial";
+    case DW_AT_base_types:
+      return "DW_AT_base_types";
+    case DW_AT_calling_convention:
+      return "DW_AT_calling_convention";
+    case DW_AT_count:
+      return "DW_AT_count";
+    case DW_AT_data_member_location:
+      return "DW_AT_data_member_location";
+    case DW_AT_decl_column:
+      return "DW_AT_decl_column";
+    case DW_AT_decl_file:
+      return "DW_AT_decl_file";
+    case DW_AT_decl_line:
+      return "DW_AT_decl_line";
+    case DW_AT_declaration:
+      return "DW_AT_declaration";
+    case DW_AT_discr_list:
+      return "DW_AT_discr_list";
+    case DW_AT_encoding:
+      return "DW_AT_encoding";
+    case DW_AT_external:
+      return "DW_AT_external";
+    case DW_AT_frame_base:
+      return "DW_AT_frame_base";
+    case DW_AT_friend:
+      return "DW_AT_friend";
+    case DW_AT_identifier_case:
+      return "DW_AT_identifier_case";
+    case DW_AT_macro_info:
+      return "DW_AT_macro_info";
+    case DW_AT_namelist_items:
+      return "DW_AT_namelist_items";
+    case DW_AT_priority:
+      return "DW_AT_priority";
+    case DW_AT_segment:
+      return "DW_AT_segment";
+    case DW_AT_specification:
+      return "DW_AT_specification";
+    case DW_AT_static_link:
+      return "DW_AT_static_link";
+    case DW_AT_type:
+      return "DW_AT_type";
+    case DW_AT_use_location:
+      return "DW_AT_use_location";
+    case DW_AT_variable_parameter:
+      return "DW_AT_variable_parameter";
+    case DW_AT_virtuality:
+      return "DW_AT_virtuality";
+    case DW_AT_vtable_elem_location:
+      return "DW_AT_vtable_elem_location";
+
+    case DW_AT_MIPS_fde:
+      return "DW_AT_MIPS_fde";
+    case DW_AT_MIPS_loop_begin:
+      return "DW_AT_MIPS_loop_begin";
+    case DW_AT_MIPS_tail_loop_begin:
+      return "DW_AT_MIPS_tail_loop_begin";
+    case DW_AT_MIPS_epilog_begin:
+      return "DW_AT_MIPS_epilog_begin";
+    case DW_AT_MIPS_loop_unroll_factor:
+      return "DW_AT_MIPS_loop_unroll_factor";
+    case DW_AT_MIPS_software_pipeline_depth:
+      return "DW_AT_MIPS_software_pipeline_depth";
+    case DW_AT_MIPS_linkage_name:
+      return "DW_AT_MIPS_linkage_name";
+    case DW_AT_MIPS_stride:
+      return "DW_AT_MIPS_stride";
+    case DW_AT_MIPS_abstract_name:
+      return "DW_AT_MIPS_abstract_name";
+    case DW_AT_MIPS_clone_origin:
+      return "DW_AT_MIPS_clone_origin";
+    case DW_AT_MIPS_has_inlines:
+      return "DW_AT_MIPS_has_inlines";
+
+    case DW_AT_sf_names:
+      return "DW_AT_sf_names";
+    case DW_AT_src_info:
+      return "DW_AT_src_info";
+    case DW_AT_mac_info:
+      return "DW_AT_mac_info";
+    case DW_AT_src_coords:
+      return "DW_AT_src_coords";
+    case DW_AT_body_begin:
+      return "DW_AT_body_begin";
+    case DW_AT_body_end:
+      return "DW_AT_body_end";
+    default:
+      return "DW_AT_<unknown>";
+    }
+}
+
+/* Convert a DWARF value form code into its string name.  */
+
+static const char *
+dwarf_form_name (form)
+     register unsigned form;
+{
+  switch (form)
+    {
+    case DW_FORM_addr:
+      return "DW_FORM_addr";
+    case DW_FORM_block2:
+      return "DW_FORM_block2";
+    case DW_FORM_block4:
+      return "DW_FORM_block4";
+    case DW_FORM_data2:
+      return "DW_FORM_data2";
+    case DW_FORM_data4:
+      return "DW_FORM_data4";
+    case DW_FORM_data8:
+      return "DW_FORM_data8";
+    case DW_FORM_string:
+      return "DW_FORM_string";
+    case DW_FORM_block:
+      return "DW_FORM_block";
+    case DW_FORM_block1:
+      return "DW_FORM_block1";
+    case DW_FORM_data1:
+      return "DW_FORM_data1";
+    case DW_FORM_flag:
+      return "DW_FORM_flag";
+    case DW_FORM_sdata:
+      return "DW_FORM_sdata";
+    case DW_FORM_strp:
+      return "DW_FORM_strp";
+    case DW_FORM_udata:
+      return "DW_FORM_udata";
+    case DW_FORM_ref_addr:
+      return "DW_FORM_ref_addr";
+    case DW_FORM_ref1:
+      return "DW_FORM_ref1";
+    case DW_FORM_ref2:
+      return "DW_FORM_ref2";
+    case DW_FORM_ref4:
+      return "DW_FORM_ref4";
+    case DW_FORM_ref8:
+      return "DW_FORM_ref8";
+    case DW_FORM_ref_udata:
+      return "DW_FORM_ref_udata";
+    case DW_FORM_indirect:
+      return "DW_FORM_indirect";
     default:
-      return "OP_<unknown>";
+      return "DW_FORM_<unknown>";
     }
 }
 
@@ -4101,6 +4697,8 @@ static inline dw_die_ref
 lookup_type_die (type)
      register tree type;
 {
+  if (TREE_CODE (type) == VECTOR_TYPE)
+    type = TYPE_DEBUG_REPRESENTATION_TYPE (type);
   return (dw_die_ref) TYPE_SYMTAB_POINTER (type);
 }
 
@@ -4157,45 +4755,6 @@ equate_decl_number_to_die (decl, decl_die)
 
   decl_die_table[decl_id] = decl_die;
 }
-
-/* Return a pointer to a newly allocated location description.  Location
-   descriptions are simple expression terms that can be strung
-   together to form more complicated location (address) descriptions.  */
-
-static inline dw_loc_descr_ref
-new_loc_descr (op, oprnd1, oprnd2)
-     register enum dwarf_location_atom op;
-     register unsigned long oprnd1;
-     register unsigned long oprnd2;
-{
-  register dw_loc_descr_ref descr
-    = (dw_loc_descr_ref) xmalloc (sizeof (dw_loc_descr_node));
-
-  descr->dw_loc_next = NULL;
-  descr->dw_loc_opc = op;
-  descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
-  descr->dw_loc_oprnd1.v.val_unsigned = oprnd1;
-  descr->dw_loc_oprnd2.val_class = dw_val_class_unsigned_const;
-  descr->dw_loc_oprnd2.v.val_unsigned = oprnd2;
-
-  return descr;
-}
-
-/* Add a location description term to a location description expression.  */
-
-static inline void
-add_loc_descr (list_head, descr)
-     register dw_loc_descr_ref *list_head;
-     register dw_loc_descr_ref descr;
-{
-  register dw_loc_descr_ref *d;
-
-  /* Find the end of the chain.  */
-  for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
-    ;
-
-  *d = descr;
-}
 \f
 /* Keep track of the number of spaces used to indent the
    output of the debugging routines that print the structure of
@@ -4366,218 +4925,101 @@ reverse_die_lists (die)
 
 /* Traverse the DIE, reverse its lists of attributes and children, and
    add a sibling attribute if it may have the effect of speeding up
-   access to siblings.  To save some space, avoid generating sibling
-   attributes for DIE's without children.  */
-
-static void
-add_sibling_attributes (die)
-     register dw_die_ref die;
-{
-  register dw_die_ref c;
-
-  reverse_die_lists (die);
-
-  if (die != comp_unit_die && die->die_sib && die->die_child != NULL)
-    /* Add the sibling link to the front of the attribute list.  */
-    add_AT_die_ref (die, DW_AT_sibling, die->die_sib);
-
-  for (c = die->die_child; c != NULL; c = c->die_sib)
-    add_sibling_attributes (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 die are visited
-   recursively.  */
-
-static void
-build_abbrev_table (die)
-     register dw_die_ref die;
-{
-  register unsigned long abbrev_id;
-  register unsigned long n_alloc;
-  register dw_die_ref c;
-  register dw_attr_ref d_attr, a_attr;
-  for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
-    {
-      register dw_die_ref abbrev = abbrev_die_table[abbrev_id];
-
-      if (abbrev->die_tag == die->die_tag)
-       {
-         if ((abbrev->die_child != NULL) == (die->die_child != NULL))
-           {
-             a_attr = abbrev->die_attr;
-             d_attr = die->die_attr;
-
-             while (a_attr != NULL && d_attr != NULL)
-               {
-                 if ((a_attr->dw_attr != d_attr->dw_attr)
-                     || (value_format (a_attr) != value_format (d_attr)))
-                   break;
-
-                 a_attr = a_attr->dw_attr_next;
-                 d_attr = d_attr->dw_attr_next;
-               }
-
-             if (a_attr == NULL && d_attr == NULL)
-               break;
-           }
-       }
-    }
-
-  if (abbrev_id >= abbrev_die_table_in_use)
-    {
-      if (abbrev_die_table_in_use >= abbrev_die_table_allocated)
-       {
-         n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT;
-         abbrev_die_table 
-           = (dw_die_ref *) xrealloc (abbrev_die_table,
-                                      sizeof (dw_die_ref) * n_alloc);
-
-         bzero ((char *) &abbrev_die_table[abbrev_die_table_allocated],
-                (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref));
-         abbrev_die_table_allocated = n_alloc;
-       }
-
-      ++abbrev_die_table_in_use;
-      abbrev_die_table[abbrev_id] = die;
-    }
-
-  die->die_abbrev = abbrev_id;
-  for (c = die->die_child; c != NULL; c = c->die_sib)
-    build_abbrev_table (c);
-}
-\f
-/* Return the size of a string, including the null byte.
-
-   This used to treat backslashes as escapes, and hence they were not included
-   in the count.  However, that conflicts with what ASM_OUTPUT_ASCII does,
-   which treats a backslash as a backslash, escaping it if necessary, and hence
-   we must include them in the count.  */
-
-static unsigned long
-size_of_string (str)
-     register const char *str;
-{
-  return strlen (str) + 1;
-}
-
-/* Return the size of a location descriptor.  */
-
-static unsigned long
-size_of_loc_descr (loc)
-     register dw_loc_descr_ref loc;
-{
-  register unsigned long size = 1;
-
-  switch (loc->dw_loc_opc)
-    {
-    case DW_OP_addr:
-      size += DWARF2_ADDR_SIZE;
-      break;
-    case DW_OP_const1u:
-    case DW_OP_const1s:
-      size += 1;
-      break;
-    case DW_OP_const2u:
-    case DW_OP_const2s:
-      size += 2;
-      break;
-    case DW_OP_const4u:
-    case DW_OP_const4s:
-      size += 4;
-      break;
-    case DW_OP_const8u:
-    case DW_OP_const8s:
-      size += 8;
-      break;
-    case DW_OP_constu:
-      size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
-      break;
-    case DW_OP_consts:
-      size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
-      break;
-    case DW_OP_pick:
-      size += 1;
-      break;
-    case DW_OP_plus_uconst:
-      size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
-      break;
-    case DW_OP_skip:
-    case DW_OP_bra:
-      size += 2;
-      break;
-    case DW_OP_breg0:
-    case DW_OP_breg1:
-    case DW_OP_breg2:
-    case DW_OP_breg3:
-    case DW_OP_breg4:
-    case DW_OP_breg5:
-    case DW_OP_breg6:
-    case DW_OP_breg7:
-    case DW_OP_breg8:
-    case DW_OP_breg9:
-    case DW_OP_breg10:
-    case DW_OP_breg11:
-    case DW_OP_breg12:
-    case DW_OP_breg13:
-    case DW_OP_breg14:
-    case DW_OP_breg15:
-    case DW_OP_breg16:
-    case DW_OP_breg17:
-    case DW_OP_breg18:
-    case DW_OP_breg19:
-    case DW_OP_breg20:
-    case DW_OP_breg21:
-    case DW_OP_breg22:
-    case DW_OP_breg23:
-    case DW_OP_breg24:
-    case DW_OP_breg25:
-    case DW_OP_breg26:
-    case DW_OP_breg27:
-    case DW_OP_breg28:
-    case DW_OP_breg29:
-    case DW_OP_breg30:
-    case DW_OP_breg31:
-      size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
-      break;
-    case DW_OP_regx:
-      size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
-      break;
-    case DW_OP_fbreg:
-      size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
-      break;
-    case DW_OP_bregx:
-      size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
-      size += size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int);
-      break;
-    case DW_OP_piece:
-      size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
-      break;
-    case DW_OP_deref_size:
-    case DW_OP_xderef_size:
-      size += 1;
-      break;
-    default:
-      break;
-    }
+   access to siblings.  To save some space, avoid generating sibling
+   attributes for DIE's without children.  */
 
-  return size;
+static void
+add_sibling_attributes (die)
+     register dw_die_ref die;
+{
+  register dw_die_ref c;
+
+  reverse_die_lists (die);
+
+  if (die != comp_unit_die && die->die_sib && die->die_child != NULL)
+    /* Add the sibling link to the front of the attribute list.  */
+    add_AT_die_ref (die, DW_AT_sibling, die->die_sib);
+
+  for (c = die->die_child; c != NULL; c = c->die_sib)
+    add_sibling_attributes (c);
 }
 
-/* Return the size of a series of location descriptors.  */
+/* 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 die are visited
+   recursively.  */
 
-static unsigned long
-size_of_locs (loc)
-     register dw_loc_descr_ref loc;
+static void
+build_abbrev_table (die)
+     register dw_die_ref die;
 {
-  register unsigned long size = 0;
+  register unsigned long abbrev_id;
+  register unsigned long n_alloc;
+  register dw_die_ref c;
+  register dw_attr_ref d_attr, a_attr;
+  for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
+    {
+      register dw_die_ref abbrev = abbrev_die_table[abbrev_id];
 
-  for (; loc != NULL; loc = loc->dw_loc_next)
-    size += size_of_loc_descr (loc);
+      if (abbrev->die_tag == die->die_tag)
+       {
+         if ((abbrev->die_child != NULL) == (die->die_child != NULL))
+           {
+             a_attr = abbrev->die_attr;
+             d_attr = die->die_attr;
 
-  return size;
+             while (a_attr != NULL && d_attr != NULL)
+               {
+                 if ((a_attr->dw_attr != d_attr->dw_attr)
+                     || (value_format (a_attr) != value_format (d_attr)))
+                   break;
+
+                 a_attr = a_attr->dw_attr_next;
+                 d_attr = d_attr->dw_attr_next;
+               }
+
+             if (a_attr == NULL && d_attr == NULL)
+               break;
+           }
+       }
+    }
+
+  if (abbrev_id >= abbrev_die_table_in_use)
+    {
+      if (abbrev_die_table_in_use >= abbrev_die_table_allocated)
+       {
+         n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT;
+         abbrev_die_table 
+           = (dw_die_ref *) xrealloc (abbrev_die_table,
+                                      sizeof (dw_die_ref) * n_alloc);
+
+         bzero ((char *) &abbrev_die_table[abbrev_die_table_allocated],
+                (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref));
+         abbrev_die_table_allocated = n_alloc;
+       }
+
+      ++abbrev_die_table_in_use;
+      abbrev_die_table[abbrev_id] = die;
+    }
+
+  die->die_abbrev = abbrev_id;
+  for (c = die->die_child; c != NULL; c = c->die_sib)
+    build_abbrev_table (c);
+}
+\f
+/* Return the size of a string, including the null byte.
+
+   This used to treat backslashes as escapes, and hence they were not included
+   in the count.  However, that conflicts with what ASM_OUTPUT_ASCII does,
+   which treats a backslash as a backslash, escaping it if necessary, and hence
+   we must include them in the count.  */
+
+static unsigned long
+size_of_string (str)
+     register const char *str;
+{
+  return strlen (str) + 1;
 }
 
 /* Return the power-of-two number of bytes necessary to represent VALUE.  */
@@ -4627,7 +5069,7 @@ size_of_die (die)
          }
          break;
        case dw_val_class_const:
-         size += 4;
+         size += size_of_sleb128 (AT_int (a));
          break;
        case dw_val_class_unsigned_const:
          size += constant_size (AT_unsigned (a));
@@ -4784,7 +5226,7 @@ value_format (a)
          abort ();
        }
     case dw_val_class_const:
-      return DW_FORM_data4;
+      return DW_FORM_sdata;
     case dw_val_class_unsigned_const:
       switch (constant_size (AT_unsigned (a)))
        {
@@ -4889,125 +5331,6 @@ output_abbrev_section ()
   fprintf (asm_out_file, "\t%s\t0\n", ASM_BYTE_OP);
 }
 
-/* Output location description stack opcode's operands (if any).  */
-
-static void
-output_loc_operands (loc)
-     register dw_loc_descr_ref loc;
-{
-  register dw_val_ref val1 = &loc->dw_loc_oprnd1;
-  register dw_val_ref val2 = &loc->dw_loc_oprnd2;
-
-  switch (loc->dw_loc_opc)
-    {
-    case DW_OP_addr:
-      ASM_OUTPUT_DWARF_ADDR_CONST (asm_out_file, val1->v.val_addr);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_const1u:
-    case DW_OP_const1s:
-      ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_flag);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_const2u:
-    case DW_OP_const2s:
-      ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_const4u:
-    case DW_OP_const4s:
-      ASM_OUTPUT_DWARF_DATA4 (asm_out_file, val1->v.val_int);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_const8u:
-    case DW_OP_const8s:
-      abort ();
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_constu:
-      output_uleb128 (val1->v.val_unsigned);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_consts:
-      output_sleb128 (val1->v.val_int);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_pick:
-      ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_int);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_plus_uconst:
-      output_uleb128 (val1->v.val_unsigned);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_skip:
-    case DW_OP_bra:
-      ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_breg0:
-    case DW_OP_breg1:
-    case DW_OP_breg2:
-    case DW_OP_breg3:
-    case DW_OP_breg4:
-    case DW_OP_breg5:
-    case DW_OP_breg6:
-    case DW_OP_breg7:
-    case DW_OP_breg8:
-    case DW_OP_breg9:
-    case DW_OP_breg10:
-    case DW_OP_breg11:
-    case DW_OP_breg12:
-    case DW_OP_breg13:
-    case DW_OP_breg14:
-    case DW_OP_breg15:
-    case DW_OP_breg16:
-    case DW_OP_breg17:
-    case DW_OP_breg18:
-    case DW_OP_breg19:
-    case DW_OP_breg20:
-    case DW_OP_breg21:
-    case DW_OP_breg22:
-    case DW_OP_breg23:
-    case DW_OP_breg24:
-    case DW_OP_breg25:
-    case DW_OP_breg26:
-    case DW_OP_breg27:
-    case DW_OP_breg28:
-    case DW_OP_breg29:
-    case DW_OP_breg30:
-    case DW_OP_breg31:
-      output_sleb128 (val1->v.val_int);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_regx:
-      output_uleb128 (val1->v.val_unsigned);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_fbreg:
-      output_sleb128 (val1->v.val_int);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_bregx:
-      output_uleb128 (val1->v.val_unsigned);
-      fputc ('\n', asm_out_file);
-      output_sleb128 (val2->v.val_int);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_piece:
-      output_uleb128 (val1->v.val_unsigned);
-      fputc ('\n', asm_out_file);
-      break;
-    case DW_OP_deref_size:
-    case DW_OP_xderef_size:
-      ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_flag);
-      fputc ('\n', asm_out_file);
-      break;
-    default:
-      break;
-    }
-}
-
 /* Output the DIE and its attributes.  Called recursively to generate
    the definitions of each child DIE.  */
 
@@ -5018,7 +5341,6 @@ output_die (die)
   register dw_attr_ref a;
   register dw_die_ref c;
   register unsigned long size;
-  register dw_loc_descr_ref loc;
 
   output_uleb128 (die->die_abbrev);
   if (flag_debug_asm)
@@ -5056,23 +5378,15 @@ output_die (die)
                     ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
 
          fputc ('\n', asm_out_file);
-         for (loc = AT_loc (a); loc != NULL; loc = loc->dw_loc_next)
-           {
-             /* Output the opcode.  */
-             ASM_OUTPUT_DWARF_DATA1 (asm_out_file, loc->dw_loc_opc);
-             if (flag_debug_asm)
-               fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START,
-                        dwarf_stack_op_name (loc->dw_loc_opc));
-
-             fputc ('\n', asm_out_file);
 
-             /* Output the operand(s) (if any).  */
-             output_loc_operands (loc);
-           }
+         output_loc_sequence (AT_loc (a));
          break;
 
        case dw_val_class_const:
-         ASM_OUTPUT_DWARF_DATA4 (asm_out_file, AT_int (a));
+         /* ??? It would be slightly more efficient to use a scheme like is
+            used for unsigned constants below, but gdb 4.x does not sign
+            extend.  Gdb 5.x does sign extend.  */
+         output_sleb128 (AT_int (a));
          break;
 
        case dw_val_class_unsigned_const:
@@ -5088,9 +5402,7 @@ output_die (die)
              ASM_OUTPUT_DWARF_DATA4 (asm_out_file, AT_unsigned (a));
              break;
            case 8:
-             ASM_OUTPUT_DWARF_DATA8 (asm_out_file,
-                                     a->dw_attr_val.v.val_long_long.hi,
-                                     a->dw_attr_val.v.val_long_long.low);
+             ASM_OUTPUT_DWARF_DATA8 (asm_out_file, AT_unsigned (a));
              break;
            default:
              abort ();
@@ -5104,9 +5416,9 @@ output_die (die)
                   ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
 
          fputc ('\n', asm_out_file);
-         ASM_OUTPUT_DWARF_DATA8 (asm_out_file,
-                                 a->dw_attr_val.v.val_long_long.hi,
-                                 a->dw_attr_val.v.val_long_long.low);
+         ASM_OUTPUT_DWARF_CONST_DOUBLE (asm_out_file,
+                                        a->dw_attr_val.v.val_long_long.hi,
+                                        a->dw_attr_val.v.val_long_long.low);
 
          if (flag_debug_asm)
            fprintf (asm_out_file,
@@ -6234,6 +6546,24 @@ type_is_enum (type)
   return TREE_CODE (type) == ENUMERAL_TYPE;
 }
 
+/* Return the register number described by a given RTL node.  */
+
+static unsigned int
+reg_number (rtl)
+     register rtx rtl;
+{
+  register unsigned regno = REGNO (rtl);
+
+  if (regno >= FIRST_PSEUDO_REGISTER)
+    {
+      warning ("internal regno botch: regno = %d\n", regno);
+      regno = 0;
+    }
+
+  regno = DBX_REGISTER_NUMBER (regno);
+  return regno;
+}
+
 /* Return a location descriptor that designates a machine register.  */
 
 static dw_loc_descr_ref
@@ -8160,6 +8490,11 @@ gen_subprogram_die (decl, context_die)
       if (declaration && ! local_scope_p (context_die))
        abort ();
 
+      /* Fixup die_parent for the abstract instance of a nested
+        inline function.  */
+      if (old_die && old_die->die_parent == NULL)
+       add_child_die (context_die, old_die);
+
       subr_die = new_die (DW_TAG_subprogram, context_die);
       add_abstract_origin_attribute (subr_die, origin);
     }
@@ -9042,6 +9377,10 @@ gen_type_die (type, context_die)
        gen_array_type_die (type, context_die);
       break;
 
+    case VECTOR_TYPE:
+      gen_type_die (TYPE_DEBUG_REPRESENTATION_TYPE (type), context_die);
+      break;
+
     case ENUMERAL_TYPE:
     case RECORD_TYPE:
     case UNION_TYPE:
@@ -9598,31 +9937,23 @@ dwarf2out_end_block (blocknum)
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
 }
 
-/* We've decided not to emit any debugging information for BLOCK; make
-   sure that we don't end up with orphans as a result.  */
+/* Returns nonzero if it is appropriate not to emit any debugging
+   information for BLOCK, because it doesn't contain any instructions.
 
-void
+   Don't allow this for blocks with nested functions or local classes
+   as we would end up with orphans, and in the presence of scheduling
+   we may end up calling them anyway.  */
+
+int
 dwarf2out_ignore_block (block)
      tree block;
 {
   tree decl;
   for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
-    {
-      dw_die_ref die;
-
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-       die = lookup_decl_die (decl);
-      else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))
-       die = lookup_type_die (TREE_TYPE (decl));
-      else
-       die = NULL;
-
-      /* Just give them a dummy value for parent so dwarf2out_finish
-        doesn't blow up; we would use add_child_die if we really
-        wanted to add them to comp_unit_die's children.  */
-      if (die && die->die_parent == 0)
-       die->die_parent = comp_unit_die;
-    }
+    if (TREE_CODE (decl) == FUNCTION_DECL
+       || (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl)))
+      return 0;
+  return 1;
 }
 
 /* Output a marker (i.e. a label) at a point in the assembly code which