OSDN Git Service

Support procedures for testing profile-directed optimizations.
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index cbae8a9..b366ecf 100644 (file)
@@ -5,22 +5,22 @@
    Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
    Extensively modified by Jason Merrill (jason@cygnus.com).
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 /* TODO: Implement .debug_str handling, and share entries somehow.
         Emit .debug_line header even when there are no functions, since
@@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA.  */
 #include "function.h"
 #include "output.h"
 #include "expr.h"
+#include "libfuncs.h"
 #include "except.h"
 #include "dwarf2.h"
 #include "dwarf2out.h"
@@ -59,6 +60,10 @@ Boston, MA 02111-1307, USA.  */
 #include "diagnostic.h"
 #include "debug.h"
 
+#ifdef DWARF2_DEBUGGING_INFO
+static void dwarf2out_source_line      PARAMS ((unsigned int, const char *));
+#endif
+
 /* DWARF2 Abbreviation Glossary:
    CFA = Canonical Frame Address
           a fixed address on the stack which identifies a call frame.
@@ -232,8 +237,6 @@ static unsigned current_funcdef_fde;
 
 /* Forward declarations for functions defined in this file.  */
 
-static void dwarf2out_init             PARAMS ((FILE *, const char *));
-static void dwarf2out_finish           PARAMS ((FILE *, const char *));
 static char *stripattributes           PARAMS ((const char *));
 static const char *dwarf_cfi_name      PARAMS ((unsigned));
 static dw_cfi_ref new_cfi              PARAMS ((void));
@@ -275,18 +278,6 @@ static void def_cfa_1                      PARAMS ((const char *, dw_cfa_location *));
 #define SECTION_ASM_OP "\t.section\t"
 #endif
 
-/* The default format used by the ASM_OUTPUT_SECTION macro (see below) to
-   print the SECTION_ASM_OP and the section name.  The default here works for
-   almost all svr4 assemblers, except for the sparc, where the section name
-   must be enclosed in double quotes.  (See sparcv4.h).  */
-#ifndef SECTION_FORMAT
-#ifdef PUSHSECTION_FORMAT
-#define SECTION_FORMAT PUSHSECTION_FORMAT
-#else
-#define SECTION_FORMAT         "%s%s\n"
-#endif
-#endif
-
 #ifndef DEBUG_FRAME_SECTION
 #define DEBUG_FRAME_SECTION    ".debug_frame"
 #endif
@@ -314,11 +305,6 @@ static void def_cfa_1                      PARAMS ((const char *, dw_cfa_location *));
    output operations.  These may be overridden from within the tm.h file,
    but typically, that is unnecessary.  */
 
-#ifndef ASM_OUTPUT_SECTION
-#define ASM_OUTPUT_SECTION(FILE, SECTION) \
-  fprintf ((FILE), SECTION_FORMAT, SECTION_ASM_OP, SECTION)
-#endif
-
 #ifdef SET_ASM_OP
 #ifndef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
 #define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO)            \
@@ -364,14 +350,6 @@ expand_builtin_dwarf_fp_regnum ()
 #define INCOMING_FRAME_SP_OFFSET 0
 #endif
 \f
-/* The target debug structure.  */
-
-struct gcc_debug_hooks dwarf2_debug_hooks =
-{
-  dwarf2out_init,
-  dwarf2out_finish
-};
-\f
 /* Return a pointer to a copy of the section string name S with all
    attributes stripped off, and an asterisk prepended (for assemble_name).  */
 
@@ -900,7 +878,7 @@ initial_return_save (rtl)
 }
 
 /* Given a SET, calculate the amount of stack adjustment it
-   contains. */
+   contains.  */
 
 static long
 stack_adjust_offset (pattern)
@@ -1004,7 +982,7 @@ dwarf2out_stack_adjust (insn)
           || GET_CODE (PATTERN (insn)) == SEQUENCE)
     {
       /* There may be stack adjustments inside compound insns.  Search
-         for them. */
+         for them.  */
       int j;
 
       offset = 0;
@@ -1759,12 +1737,12 @@ output_call_frame_info (for_eh)
 
   if (for_eh)
     {
-#ifdef EH_FRAME_SECTION
-      EH_FRAME_SECTION ();
+#ifdef EH_FRAME_SECTION_NAME
+      named_section_flags (EH_FRAME_SECTION_NAME, SECTION_WRITE);
 #else
       tree label = get_file_function_name ('F');
 
-      force_data_section ();
+      data_section ();
       ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
       ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
       ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
@@ -1772,7 +1750,7 @@ output_call_frame_info (for_eh)
       assemble_label ("__FRAME_BEGIN__");
     }
   else
-    ASM_OUTPUT_SECTION (asm_out_file, DEBUG_FRAME_SECTION);
+    named_section_flags (DEBUG_FRAME_SECTION, SECTION_DEBUG);
 
   /* Output the CIE.  */
   ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh);
@@ -1990,7 +1968,7 @@ output_call_frame_info (for_eh)
       ASM_OUTPUT_LABEL (asm_out_file, l2);
     }
 
-#ifndef EH_FRAME_SECTION
+#ifndef EH_FRAME_SECTION_NAME
   if (for_eh)
     dw2_asm_output_data (4, 0, "End of Table");
 #endif
@@ -2009,7 +1987,9 @@ output_call_frame_info (for_eh)
    the prologue.  */
 
 void
-dwarf2out_begin_prologue ()
+dwarf2out_begin_prologue (line, file)
+     unsigned int line ATTRIBUTE_UNUSED;
+     const char *file ATTRIBUTE_UNUSED;
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
   register dw_fde_ref fde;
@@ -2066,6 +2046,13 @@ dwarf2out_begin_prologue ()
   fde->uses_eh_lsda = cfun->uses_eh_lsda;
 
   args_size = old_args_size = 0;
+
+  /* We only want to output line number information for the genuine
+     dwarf2 prologue case, not the eh frame case.  */
+#ifdef DWARF2_DEBUGGING_INFO
+  if (file)
+    dwarf2out_source_line (line, file);
+#endif
 }
 
 /* Output a marker (i.e. a label) for the absolute end of the generated code
@@ -2111,12 +2098,13 @@ dwarf2out_frame_finish ()
 #ifdef MIPS_DEBUGGING_INFO
   if (write_symbols == DWARF2_DEBUG)
     output_call_frame_info (0);
-  if (flag_unwind_tables || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS))
+  if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions))
     output_call_frame_info (1);
 #else
-  if (write_symbols == DWARF2_DEBUG
-      || flag_unwind_tables || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS))
-    output_call_frame_info (1);
+  int for_eh = (! USING_SJLJ_EXCEPTIONS
+               && (flag_unwind_tables || flag_exceptions));
+  if (write_symbols == DWARF2_DEBUG || for_eh)
+    output_call_frame_info (for_eh);
 #endif
 }
 \f
@@ -2135,6 +2123,7 @@ typedef struct dw_loc_list_struct *dw_loc_list_ref;
 typedef enum
 {
   dw_val_class_addr,
+  dw_val_class_offset,
   dw_val_class_loc,
   dw_val_class_loc_list,
   dw_val_class_const,
@@ -2178,6 +2167,7 @@ typedef struct dw_val_struct
   union
     {
       rtx val_addr;
+      long unsigned val_offset;
       dw_loc_list_ref  val_loc_list;
       dw_loc_descr_ref val_loc;
       long int val_int;
@@ -2212,7 +2202,7 @@ dw_loc_descr_node;
 
 /* Location lists are ranges + location descriptions for that range,
    so you can track variables that are in different places over
-   their entire life. */
+   their entire life.  */
 typedef struct dw_loc_list_struct
 {
   dw_loc_list_ref dw_loc_next;
@@ -2865,7 +2855,7 @@ output_cfa_loc (cfi)
   output_loc_sequence (loc);
 }
 
-/* This function builds a dwarf location descriptor seqeunce from
+/* This function builds a dwarf location descriptor sequence from
    a dw_cfa_location.  */
 
 static struct dw_loc_descr_struct *
@@ -3011,6 +3001,47 @@ get_cfa_from_loc_descr (cfa, loc)
 /* And now, the support for symbolic debugging information.  */
 #ifdef DWARF2_DEBUGGING_INFO
 
+static void dwarf2out_init             PARAMS ((const char *));
+static void dwarf2out_finish           PARAMS ((const char *));
+static void dwarf2out_define           PARAMS ((unsigned int, const char *));
+static void dwarf2out_undef            PARAMS ((unsigned int, const char *));
+static void dwarf2out_start_source_file        PARAMS ((unsigned, const char *));
+static void dwarf2out_end_source_file  PARAMS ((unsigned));
+static void dwarf2out_begin_block      PARAMS ((unsigned, unsigned));
+static void dwarf2out_end_block                PARAMS ((unsigned, unsigned));
+static bool dwarf2out_ignore_block     PARAMS ((tree));
+static void dwarf2out_global_decl      PARAMS ((tree));
+static void dwarf2out_abstract_function PARAMS ((tree));
+
+/* The debug hooks structure.  */
+
+struct gcc_debug_hooks dwarf2_debug_hooks =
+{
+  dwarf2out_init,
+  dwarf2out_finish,
+  dwarf2out_define,
+  dwarf2out_undef,
+  dwarf2out_start_source_file,
+  dwarf2out_end_source_file,
+  dwarf2out_begin_block,
+  dwarf2out_end_block,
+  dwarf2out_ignore_block,
+  dwarf2out_source_line,
+  dwarf2out_begin_prologue,
+  debug_nothing_int,           /* end_prologue */
+  dwarf2out_end_epilogue,
+  debug_nothing_tree,          /* begin_function */
+  debug_nothing_int,           /* end_function */
+  dwarf2out_decl,              /* function_decl */
+  dwarf2out_global_decl,
+  debug_nothing_tree,          /* deferred_inline_function */
+  /* The DWARF 2 backend tries to reduce debugging bloat by not
+     emitting the abstract description of inline functions until
+     something tries to reference them.  */
+  dwarf2out_abstract_function, /* outlining_inline_function */
+  debug_nothing_rtx            /* label */
+};
+\f
 /* 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.  */
@@ -3031,7 +3062,7 @@ 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;
+typedef struct dw_ranges_struct *dw_ranges_ref;
 
 /* Each entry in the line_info_table maintains the file and
    line number associated with the label generated for that
@@ -3092,6 +3123,11 @@ typedef struct pubname_struct
 }
 pubname_entry;
 
+struct dw_ranges_struct
+{
+  int block_num;
+};
+
 /* The limbo die list structure.  */
 typedef struct limbo_die_struct
 {
@@ -3237,17 +3273,7 @@ static unsigned decl_die_table_in_use;
    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
+varray_type decl_scope_table;
 
 /* A pointer to the base of a list of references to DIE's that
    are uniquely identified by their tag, presence/absence of
@@ -3302,9 +3328,8 @@ static unsigned pubname_table_in_use;
    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;
+/* Array of dies for which we should generate .debug_arange info.  */
+static dw_die_ref *arange_table;
 
 /* Number of elements currently allocated for arange_table.  */
 static unsigned arange_table_allocated;
@@ -3316,24 +3341,28 @@ static unsigned arange_table_in_use;
    arange_table.  */
 #define ARANGE_TABLE_INCREMENT 64
 
-/* Whether we have location lists that need outputting */
-static unsigned have_location_lists;
+/* Array of dies for which we should generate .debug_ranges info.  */
+static dw_ranges_ref ranges_table;
 
-/* A pointer to the base of a list of incomplete types which might be
-   completed at some later time.  */
+/* Number of elements currently allocated for ranges_table.  */
+static unsigned ranges_table_allocated;
 
-static tree *incomplete_types_list;
+/* Number of elements in ranges_table currently in use.  */
+static unsigned ranges_table_in_use;
 
-/* Number of elements currently allocated for the incomplete_types_list.  */
-static unsigned incomplete_types_allocated;
+/* Size (in elements) of increments by which we may expand the
+   ranges_table.  */
+#define RANGES_TABLE_INCREMENT 64
 
-/* Number of elements of incomplete_types_list currently in use.  */
-static unsigned incomplete_types;
+/* Whether we have location lists that need outputting */
+static unsigned have_location_lists;
 
-/* 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
+/* A pointer to the base of a list of incomplete types which might be
+   completed at some later time.  incomplete_types_list needs to be a VARRAY
+   because we want to tell the garbage collector about it.  If we don't tell
+   the garbage collector about it, we can garbage collect live data.
+   Bug 4215.*/
+varray_type incomplete_types;
 
 /* Record whether the function being analyzed contains inlined functions.  */
 static int current_function_has_inlines;
@@ -3401,6 +3430,9 @@ static void add_AT_lbl_id         PARAMS ((dw_die_ref,
 static void add_AT_lbl_offset          PARAMS ((dw_die_ref,
                                                 enum dwarf_attribute,
                                                 const char *));
+static void add_AT_offset              PARAMS ((dw_die_ref,
+                                                enum dwarf_attribute,
+                                                unsigned long));
 static dw_attr_ref get_AT              PARAMS ((dw_die_ref,
                                                 enum dwarf_attribute));
 static const char *get_AT_low_pc       PARAMS ((dw_die_ref));
@@ -3464,6 +3496,8 @@ 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 unsigned int add_ranges         PARAMS ((tree));
+static void output_ranges              PARAMS ((void));
 static void output_line_info           PARAMS ((void));
 static void output_file_names           PARAMS ((void));
 static dw_die_ref base_type_die                PARAMS ((tree));
@@ -3589,16 +3623,13 @@ static char *gen_internal_sym           PARAMS ((const char *));
 #ifndef DEBUG_STR_SECTION
 #define DEBUG_STR_SECTION      ".debug_str"
 #endif
+#ifndef DEBUG_RANGES_SECTION
+#define DEBUG_RANGES_SECTION   ".debug_ranges"
+#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"
+#ifndef TEXT_SECTION_NAME
+#define TEXT_SECTION_NAME      ".text"
 #endif
 
 /* Labels we insert at beginning sections we can reference instead of
@@ -3622,6 +3653,7 @@ static char *gen_internal_sym             PARAMS ((const char *));
 #ifndef DEBUG_MACINFO_SECTION_LABEL
 #define DEBUG_MACINFO_SECTION_LABEL     "Ldebug_macinfo"
 #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.
@@ -3986,6 +4018,31 @@ dwarf_attr_name (attr)
     case DW_AT_vtable_elem_location:
       return "DW_AT_vtable_elem_location";
 
+    case DW_AT_allocated:
+      return "DW_AT_allocated";
+    case DW_AT_associated:
+      return "DW_AT_associated";
+    case DW_AT_data_location:
+      return "DW_AT_data_location";
+    case DW_AT_stride:
+      return "DW_AT_stride";
+    case DW_AT_entry_pc:
+      return "DW_AT_entry_pc";
+    case DW_AT_use_UTF8:
+      return "DW_AT_use_UTF8";
+    case DW_AT_extension:
+      return "DW_AT_extension";
+    case DW_AT_ranges:
+      return "DW_AT_ranges";
+    case DW_AT_trampoline:
+      return "DW_AT_trampoline";
+    case DW_AT_call_column:
+      return "DW_AT_call_column";
+    case DW_AT_call_file:
+      return "DW_AT_call_file";
+    case DW_AT_call_line:
+      return "DW_AT_call_line";
+
     case DW_AT_MIPS_fde:
       return "DW_AT_MIPS_fde";
     case DW_AT_MIPS_loop_begin:
@@ -4558,6 +4615,23 @@ add_AT_lbl_offset (die, attr_kind, label)
   add_dwarf_attr (die, attr);
 }
 
+/* Add an offset attribute value to a DIE.  */
+
+static void
+add_AT_offset (die, attr_kind, offset)
+     register dw_die_ref die;
+     register enum dwarf_attribute attr_kind;
+     register unsigned long offset;
+{
+  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+
+  attr->dw_attr_next = NULL;
+  attr->dw_attr = attr_kind;
+  attr->dw_attr_val.val_class = dw_val_class_offset;
+  attr->dw_attr_val.v.val_offset = offset;
+  add_dwarf_attr (die, attr);
+}
+
 static inline const char *AT_lbl PARAMS ((dw_attr_ref));
 static inline const char *
 AT_lbl (a)
@@ -4970,11 +5044,15 @@ print_die (die, outfile)
        case dw_val_class_addr:
          fprintf (outfile, "address");
          break;
+       case dw_val_class_offset:
+         fprintf (outfile, "offset");
+         break;
        case dw_val_class_loc:
          fprintf (outfile, "location descriptor");
          break;
        case dw_val_class_loc_list:
-         fprintf (outfile, "location list -> label:%s", AT_loc_list (a)->ll_symbol);
+         fprintf (outfile, "location list -> label:%s",
+                  AT_loc_list (a)->ll_symbol);
          break;
        case dw_val_class_const:
          fprintf (outfile, "%ld", AT_int (a));
@@ -5205,6 +5283,7 @@ attr_checksum (at, ctx)
     case dw_val_class_str:
       PROCESS_STRING (AT_string (at));
       break;
+
     case dw_val_class_addr:
       r = AT_addr (at);
       switch (GET_CODE (r))
@@ -5218,6 +5297,10 @@ attr_checksum (at, ctx)
        }
       break;
 
+    case dw_val_class_offset:
+      PROCESS (at->dw_attr_val.v.val_offset);
+      break;
+
     case dw_val_class_loc:
       for (loc = AT_loc (at); loc; loc = loc->dw_loc_next)
        loc_checksum (loc, ctx);
@@ -5231,6 +5314,7 @@ attr_checksum (at, ctx)
     case dw_val_class_fde_ref:
     case dw_val_class_lbl_id:
     case dw_val_class_lbl_offset:
+      break;
 
     default:
       break;
@@ -5273,7 +5357,7 @@ static void
 compute_section_prefix (unit_die)
      dw_die_ref unit_die;
 {
-  char *p, *name;
+  char *name;
   int i;
   unsigned char checksum[16];
   struct md5_ctx ctx;
@@ -5282,18 +5366,22 @@ compute_section_prefix (unit_die)
   die_checksum (unit_die, &ctx);
   md5_finish_ctx (&ctx, checksum);
 
-  p = lbasename (get_AT_string (unit_die, DW_AT_name));
-  name = (char *) alloca (strlen (p) + 64);
-  sprintf (name, "%s.", p);
+  {
+    const char *p = lbasename (get_AT_string (unit_die, DW_AT_name));
+    name = (char *) alloca (strlen (p) + 64);
+    sprintf (name, "%s.", p);
+  }
 
   clean_symbol_name (name);
 
-  p = name + strlen (name);
-  for (i = 0; i < 4; ++i)
-    {
-      sprintf (p, "%.2x", checksum[i]);
-      p += 2;
-    }
+  {
+    char *p = name + strlen (name);
+    for (i = 0; i < 4; ++i)
+      {
+       sprintf (p, "%.2x", checksum[i]);
+       p += 2;
+      }
+  }
 
   comdat_symbol_id = unit_die->die_symbol = xstrdup (name);
   comdat_symbol_number = 0;
@@ -5636,6 +5724,9 @@ size_of_die (die)
        case dw_val_class_addr:
          size += DWARF2_ADDR_SIZE;
          break;
+       case dw_val_class_offset:
+         size += DWARF_OFFSET_SIZE;
+         break;
        case dw_val_class_loc:
          {
            register unsigned long lsize = size_of_locs (AT_loc (a));
@@ -5783,6 +5874,12 @@ value_format (a)
     {
     case dw_val_class_addr:
       return DW_FORM_addr;
+    case dw_val_class_offset:
+      if (DWARF_OFFSET_SIZE == 4)
+       return DW_FORM_data4;
+      if (DWARF_OFFSET_SIZE == 8)
+       return DW_FORM_data8;
+      abort ();
     case dw_val_class_loc_list:
       /* FIXME: Could be DW_FORM_data8, with a > 32 bit size
         .debug_loc section */
@@ -5832,6 +5929,7 @@ value_format (a)
       return DW_FORM_data;
     case dw_val_class_str:
       return DW_FORM_string;
+
     default:
       abort ();
     }
@@ -5908,7 +6006,7 @@ output_die_symbol (die)
 /* Return a new location list, given the begin and end range, and the
    expression. gensym tells us whether to generate a new internal
    symbol for this location list node, which is done for the head of
-   the list only. */ 
+   the list only.  */ 
 static inline dw_loc_list_ref
 new_loc_list (expr, begin, end, section, gensym)
      register dw_loc_descr_ref expr;
@@ -5939,15 +6037,13 @@ add_loc_descr_to_loc_list (list_head, descr, begin, end, section)
 {
   register dw_loc_list_ref *d;
   
-  /* Find the end of the chain. */
+  /* Find the end of the chain.  */
   for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
     ;
   /* Add a new location list node to the list */
   *d = new_loc_list (descr, begin, end, section, 0);
 }
 
-
-
 /* Output the location list given to us */
 static void
 output_loc_list (list_head)
@@ -5955,6 +6051,10 @@ output_loc_list (list_head)
 {
   register dw_loc_list_ref curr=list_head;
   ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol);
+
+  /* ??? This shouldn't be needed now that we've forced the
+     compilation unit base address to zero when there is code
+     in more than one section.  */
   if (strcmp (curr->section, ".text") == 0)
     {
       /* dw2_asm_output_data will mask off any extra bits in the ~0.  */
@@ -6016,6 +6116,11 @@ output_die (die)
          dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name);
          break;
 
+       case dw_val_class_offset:
+         dw2_asm_output_data (DWARF_OFFSET_SIZE, a->dw_attr_val.v.val_offset,
+                              "%s", name);
+         break;
+
        case dw_val_class_loc:
          size = size_of_locs (AT_loc (a));
 
@@ -6077,14 +6182,17 @@ output_die (die)
        case dw_val_class_flag:
          dw2_asm_output_data (1, AT_flag (a), "%s", name);
          break;
+
         case dw_val_class_loc_list:
          {
            char *sym = AT_loc_list (a)->ll_symbol;
            if (sym == 0)
              abort();
-           dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label, name);
+           dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym,
+                                 loc_section_label, "%s", name);
          }
          break;
+
        case dw_val_class_die_ref:
          if (AT_ref_external (a))
            {
@@ -6188,7 +6296,7 @@ output_comp_unit (die)
     secname = (const char *) DEBUG_INFO_SECTION;
 
   /* Output debugging information.  */
-  ASM_OUTPUT_SECTION (asm_out_file, secname);
+  named_section_flags (secname, SECTION_DEBUG);
   output_compilation_unit_header ();
   output_die (die);
 
@@ -6286,9 +6394,8 @@ add_arange (decl, die)
   if (arange_table_in_use == arange_table_allocated)
     {
       arange_table_allocated += ARANGE_TABLE_INCREMENT;
-      arange_table
-       = (arange_ref) xrealloc (arange_table,
-                                arange_table_allocated * sizeof (dw_die_ref));
+      arange_table = (dw_die_ref *)
+       xrealloc (arange_table, arange_table_allocated * sizeof (dw_die_ref));
     }
 
   arange_table[arange_table_in_use++] = die;
@@ -6374,6 +6481,80 @@ output_aranges ()
   dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
 }
 
+/* Add a new entry to .debug_ranges.  Return the offset at which it
+   was placed.  */
+
+static unsigned int
+add_ranges (block)
+     tree block;
+{
+  unsigned int in_use = ranges_table_in_use;
+
+  if (in_use == ranges_table_allocated)
+    {
+      ranges_table_allocated += RANGES_TABLE_INCREMENT;
+      ranges_table = (dw_ranges_ref)
+       xrealloc (ranges_table, (ranges_table_allocated
+                                * sizeof (struct dw_ranges_struct)));
+    }
+
+  ranges_table[in_use].block_num = (block ? BLOCK_NUMBER (block) : 0);
+  ranges_table_in_use = in_use + 1;
+
+  return in_use * 2 * DWARF2_ADDR_SIZE;
+}
+
+static void
+output_ranges ()
+{
+  register unsigned i;
+  const char *start_fmt = "Offset 0x%x";
+  const char *fmt = start_fmt;
+
+  for (i = 0; i < ranges_table_in_use; ++i)
+    {
+      int block_num = ranges_table[i].block_num;
+
+      if (block_num)
+       {
+         char blabel[MAX_ARTIFICIAL_LABEL_BYTES];
+         char elabel[MAX_ARTIFICIAL_LABEL_BYTES];
+
+         ASM_GENERATE_INTERNAL_LABEL (blabel, BLOCK_BEGIN_LABEL, block_num);
+         ASM_GENERATE_INTERNAL_LABEL (elabel, BLOCK_END_LABEL, block_num);
+
+         /* If all code is in the text section, then the compilation
+            unit base address defaults to DW_AT_low_pc, which is the
+            base of the text section.  */
+         if (separate_line_info_table_in_use == 0)
+           {
+             dw2_asm_output_delta (DWARF2_ADDR_SIZE, blabel,
+                                   text_section_label,
+                                   fmt, i * 2 * DWARF2_ADDR_SIZE);
+             dw2_asm_output_delta (DWARF2_ADDR_SIZE, elabel,
+                                   text_section_label, NULL);
+           }
+         /* Otherwise, we add a DW_AT_entry_pc attribute to force the
+            compilation unit base address to zero, which allows us to
+            use absolute addresses, and not worry about whether the
+            target supports cross-section arithmetic.  */
+         else
+           {
+             dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
+                                  fmt, i * 2 * DWARF2_ADDR_SIZE);
+             dw2_asm_output_addr (DWARF2_ADDR_SIZE, elabel, NULL);
+           }
+
+         fmt = NULL;
+       }
+      else
+       {
+         dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
+         dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
+         fmt = start_fmt;
+       }
+    }
+}
 
 /* Data structure containing information about input files.  */
 struct file_info
@@ -7455,7 +7636,7 @@ mem_loc_descriptor (rtl, mode)
 
     case PRE_MODIFY:
       /* Extract the PLUS expression nested inside and fall into
-         PLUS code bellow.  */
+         PLUS code below.  */
       rtl = XEXP (rtl, 1);
       goto plus;
 
@@ -8171,7 +8352,7 @@ add_const_value_attribute (die, rtl)
          {
            if ((unsigned long) val != (unsigned HOST_WIDE_INT) val)
              abort ();
-           add_AT_int (die, DW_AT_const_value, (unsigned long) val);
+           add_AT_unsigned (die, DW_AT_const_value, (unsigned long) val);
          }
       }
       break;
@@ -8430,6 +8611,11 @@ add_location_or_const_value_attribute (die, decl)
   if (rtl == NULL_RTX)
     return;
 
+  /* If we don't look past the constant pool, we risk emitting a
+     reference to a constant pool entry that isn't referenced from
+     code, and thus is not emitted.  */
+  rtl = avoid_constant_pool_reference (rtl);
+
   switch (GET_CODE (rtl))
     {
     case ADDRESSOF:
@@ -8961,26 +9147,16 @@ static void
 push_decl_scope (scope)
      tree scope;
 {
-  /* Make room in the decl_scope_table, if necessary.  */
-  if (decl_scope_table_allocated == decl_scope_depth)
-    {
-      decl_scope_table_allocated += DECL_SCOPE_TABLE_INCREMENT;
-      decl_scope_table
-       = (tree *) xrealloc (decl_scope_table,
-                            decl_scope_table_allocated * sizeof (tree));
-    }
-
-  decl_scope_table[decl_scope_depth] = scope;
-  decl_scope_depth++;
+  VARRAY_PUSH_TREE (decl_scope_table, scope);
 }
 
 /* Pop a declaration scope.  */
 static inline void
 pop_decl_scope ()
 {
-  if (decl_scope_depth <= 0)
+  if (VARRAY_ACTIVE_SIZE (decl_scope_table) <= 0)
     abort ();
-  --decl_scope_depth;
+  VARRAY_POP (decl_scope_table);
 }
 
 /* Return the DIE for the scope that immediately contains this type.
@@ -9022,8 +9198,8 @@ scope_die_for (t, context_die)
         first we check to see if we're in the middle of emitting it
         so we know where the new DIE should go.  */
 
-      for (i = decl_scope_depth - 1; i >= 0; --i)
-       if (decl_scope_table[i] == containing_scope)
+      for (i = VARRAY_ACTIVE_SIZE (decl_scope_table) - 1; i >= 0; --i)
+       if (VARRAY_TREE (decl_scope_table, i) == containing_scope)
          break;
 
       if (i < 0)
@@ -9277,20 +9453,11 @@ gen_entry_point_die (decl, context_die)
 #endif
 
 /* Remember a type in the incomplete_types_list.  */
-
 static void
 add_incomplete_type (type)
      tree type;
 {
-  if (incomplete_types == incomplete_types_allocated)
-    {
-      incomplete_types_allocated += INCOMPLETE_TYPES_INCREMENT;
-      incomplete_types_list
-       = (tree *) xrealloc (incomplete_types_list,
-                            sizeof (tree) * incomplete_types_allocated);
-    }
-
-  incomplete_types_list[incomplete_types++] = type;
+  VARRAY_PUSH_TREE (incomplete_types, type);
 }
 
 /* Walk through the list of incomplete types again, trying once more to
@@ -9299,13 +9466,10 @@ add_incomplete_type (type)
 static void
 retry_incomplete_types ()
 {
-  register tree type;
-
-  while (incomplete_types)
+  int i;
+  for (i = VARRAY_ACTIVE_SIZE (incomplete_types) - 1; i >= 0; i--)
     {
-      --incomplete_types;
-      type = incomplete_types_list[incomplete_types];
-      gen_type_die (type, comp_unit_die);
+      gen_type_die (VARRAY_TREE (incomplete_types, i), comp_unit_die);
     }
 }
 
@@ -9583,7 +9747,7 @@ gen_type_die_for_member (type, member, context_die)
    of a function which we may later generate inlined and/or
    out-of-line instances of.  */
 
-void
+static void
 dwarf2out_abstract_function (decl)
      tree decl;
 {
@@ -9602,10 +9766,13 @@ dwarf2out_abstract_function (decl)
 
   /* Be sure we've emitted the in-class declaration DIE (if any) first, so
      we don't get confused by DECL_ABSTRACT.  */
-  context = decl_class_context (decl);
-  if (context)
-    gen_type_die_for_member
-      (context, decl, decl_function_context (decl) ? NULL : comp_unit_die);
+  if (debug_info_level > DINFO_LEVEL_TERSE)
+    {
+      context = decl_class_context (decl);
+      if (context)
+       gen_type_die_for_member
+         (context, decl, decl_function_context (decl) ? NULL : comp_unit_die);
+    }
  
   /* Pretend we've just finished compiling this function.  */
   save_fn = current_function_decl;
@@ -9921,6 +10088,7 @@ gen_variable_die (decl, context_die)
   /* ??? Loop unrolling/reorder_blocks should perhaps be rewritten to
      copy decls and set the DECL_ABSTRACT flag on them instead of
      sharing them.  */
+  /* ??? Duplicated blocks have been rewritten to use .debug_ranges.  */
   else if (old_die && TREE_STATIC (decl)
           && get_AT_flag (old_die, DW_AT_declaration) == 1)
     {
@@ -10032,12 +10200,30 @@ gen_lexical_block_die (stmt, context_die, depth)
 
   if (! BLOCK_ABSTRACT (stmt))
     {
-      ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
-                                  BLOCK_NUMBER (stmt));
-      add_AT_lbl_id (stmt_die, DW_AT_low_pc, label);
-      ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL,
-                                  BLOCK_NUMBER (stmt));
-      add_AT_lbl_id (stmt_die, DW_AT_high_pc, label);
+      if (BLOCK_FRAGMENT_CHAIN (stmt))
+       {
+         tree chain;
+
+         add_AT_offset (stmt_die, DW_AT_ranges, add_ranges (stmt));
+
+         chain = BLOCK_FRAGMENT_CHAIN (stmt);
+         do
+           {
+             add_ranges (chain);
+             chain = BLOCK_FRAGMENT_CHAIN (chain);
+           }
+         while (chain);
+         add_ranges (NULL);
+       }
+      else
+       {
+         ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
+                                      BLOCK_NUMBER (stmt));
+         add_AT_lbl_id (stmt_die, DW_AT_low_pc, label);
+         ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL,
+                                      BLOCK_NUMBER (stmt));
+         add_AT_lbl_id (stmt_die, DW_AT_high_pc, label);
+       }
     }
 
   decls_for_scope (stmt, stmt_die, depth);
@@ -10669,11 +10855,22 @@ gen_block_die (stmt, context_die, depth)
   register enum tree_code origin_code;
 
   /* Ignore blocks never really used to make RTL.  */
-
   if (stmt == NULL_TREE || !TREE_USED (stmt)
       || (!TREE_ASM_WRITTEN (stmt) && !BLOCK_ABSTRACT (stmt)))
     return;
 
+  /* If the block is one fragment of a non-contiguous block, do not
+     process the variables, since they will have been done by the
+     origin block.  Do process subblocks.  */
+  if (BLOCK_FRAGMENT_ORIGIN (stmt))
+    {
+      tree sub;
+
+      for (sub= BLOCK_SUBBLOCKS (stmt); sub; sub = BLOCK_CHAIN (sub))
+       gen_block_die (sub, context_die, depth + 1);
+      return;
+    }
+
   /* Determine the "ultimate origin" of this block.  This block may be an
      inlined instance of an inlined instance of inline function, so we have
      to trace all of the way back through the origin chain to find out what
@@ -10976,6 +11173,21 @@ dwarf2out_add_library_unit_info (filename, context_list)
     }
 }
 
+/* Debug information for a global DECL.  Called from toplev.c after
+   compilation proper has finished.  */
+static void
+dwarf2out_global_decl (decl)
+     tree decl;
+{
+  /* Output DWARF2 information for file-scope tentative data object
+     declarations, file-scope (extern) function declarations (which
+     had no corresponding body) and file-scope tagged type
+     declarations and definitions which have not yet been forced out.  */
+
+  if (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl))
+    dwarf2out_decl (decl);
+}
+
 /* Write the debugging output for DECL.  */
 
 void
@@ -11094,9 +11306,10 @@ dwarf2out_decl (decl)
 /* Output a marker (i.e. a label) for the beginning of the generated code for
    a lexical block.  */
 
-void
-dwarf2out_begin_block (blocknum)
-     register unsigned blocknum;
+static void
+dwarf2out_begin_block (line, blocknum)
+     unsigned int line ATTRIBUTE_UNUSED;
+     unsigned int blocknum;
 {
   function_section (current_function_decl);
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
@@ -11105,9 +11318,10 @@ dwarf2out_begin_block (blocknum)
 /* Output a marker (i.e. a label) for the end of the generated code for a
    lexical block.  */
 
-void
-dwarf2out_end_block (blocknum)
-     register unsigned blocknum;
+static void
+dwarf2out_end_block (line, blocknum)
+     unsigned int line ATTRIBUTE_UNUSED;
+     unsigned int blocknum;
 {
   function_section (current_function_decl);
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
@@ -11120,7 +11334,7 @@ dwarf2out_end_block (blocknum)
    as we would end up with orphans, and in the presence of scheduling
    we may end up calling them anyway.  */
 
-int
+static bool
 dwarf2out_ignore_block (block)
      tree block;
 {
@@ -11204,10 +11418,10 @@ init_file_table ()
    and record information relating to this source line, in
    'line_info_table' for later output of the .debug_line section.  */
 
-void
-dwarf2out_line (filename, line)
+static void
+dwarf2out_source_line (line, filename)
+     unsigned int line;
      register const char *filename;
-     register unsigned line;
 {
   if (debug_info_level >= DINFO_LEVEL_NORMAL)
     {
@@ -11283,12 +11497,12 @@ dwarf2out_line (filename, line)
     }
 }
 
-/* Record the beginning of a new source file. */
+/* Record the beginning of a new source file.  */
 
-void
+static void
 dwarf2out_start_source_file (lineno, filename)
-     register unsigned int lineno ATTRIBUTE_UNUSED;
-     register const char *filename ATTRIBUTE_UNUSED;
+     register unsigned int lineno;
+     register const char *filename;
 {
   if (flag_eliminate_dwarf2_dups)
     {
@@ -11298,17 +11512,20 @@ dwarf2out_start_source_file (lineno, filename)
     }
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
-      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+      named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
       dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file");
-      dw2_asm_output_data_uleb128 (lineno, "Included from line number %d", lineno);
-      dw2_asm_output_data_uleb128 (lookup_filename (filename), "Filename we just started");
+      dw2_asm_output_data_uleb128 (lineno, "Included from line number %d",
+                                  lineno);
+      dw2_asm_output_data_uleb128 (lookup_filename (filename),
+                                  "Filename we just started");
     }
 }
 
 /* Record the end of a source file.  */
 
-void
-dwarf2out_end_source_file ()
+static void
+dwarf2out_end_source_file (lineno)
+     unsigned int lineno ATTRIBUTE_UNUSED;
 {
   if (flag_eliminate_dwarf2_dups)
     {
@@ -11317,7 +11534,7 @@ dwarf2out_end_source_file ()
     }
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
-      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+      named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
       dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
     }
 }
@@ -11326,7 +11543,7 @@ dwarf2out_end_source_file ()
    the tail part of the directive line, i.e. the part which is past the
    initial whitespace, #, whitespace, directive-name, whitespace part.  */
 
-void
+static void
 dwarf2out_define (lineno, buffer)
      register unsigned lineno ATTRIBUTE_UNUSED;
      register const char *buffer ATTRIBUTE_UNUSED;
@@ -11339,7 +11556,7 @@ dwarf2out_define (lineno, buffer)
     }
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
-      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+      named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
       dw2_asm_output_data (1, DW_MACINFO_define, "Define macro");
       dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno);
       dw2_asm_output_nstring (buffer, -1, "The macro");
@@ -11350,14 +11567,14 @@ dwarf2out_define (lineno, buffer)
    the tail part of the directive line, i.e. the part which is past the
    initial whitespace, #, whitespace, directive-name, whitespace part.  */
 
-void
+static void
 dwarf2out_undef (lineno, buffer)
      register unsigned lineno ATTRIBUTE_UNUSED;
      register const char *buffer ATTRIBUTE_UNUSED;
 {
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
-      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+      named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
       dw2_asm_output_data (1, DW_MACINFO_undef, "Undefine macro");
       dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno);
       dw2_asm_output_nstring (buffer, -1, "The macro");
@@ -11367,8 +11584,7 @@ dwarf2out_undef (lineno, buffer)
 /* Set up for Dwarf output at the start of compilation.  */
 
 static void
-dwarf2out_init (asm_out_file, main_input_filename)
-     register FILE *asm_out_file;
+dwarf2out_init (main_input_filename)
      register const char *main_input_filename;
 {
   init_file_table ();
@@ -11388,10 +11604,8 @@ dwarf2out_init (asm_out_file, main_input_filename)
   decl_die_table_in_use = 0;
 
   /* Allocate the initial hunk of the decl_scope_table.  */
-  decl_scope_table
-    = (tree *) xcalloc (DECL_SCOPE_TABLE_INCREMENT, sizeof (tree));
-  decl_scope_table_allocated = DECL_SCOPE_TABLE_INCREMENT;
-  decl_scope_depth = 0;
+  VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table");
+  ggc_add_tree_varray_root (&decl_scope_table, 1);
 
   /* Allocate the initial hunk of the abbrev_die_table.  */
   abbrev_die_table
@@ -11416,6 +11630,9 @@ dwarf2out_init (asm_out_file, main_input_filename)
      invoked when the given (base) source file was compiled.  */
   comp_unit_die = gen_compile_unit_die (main_input_filename);
 
+  VARRAY_TREE_INIT (incomplete_types, 64, "incomplete_types");
+  ggc_add_tree_varray_root (&incomplete_types, 1);
+
   VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray");
   ggc_add_rtx_varray_root (&used_rtx_varray, 1);
 
@@ -11425,40 +11642,37 @@ dwarf2out_init (asm_out_file, main_input_filename)
   if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
     ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
   else
-    strcpy (text_section_label, stripattributes (TEXT_SECTION));
+    strcpy (text_section_label, stripattributes (TEXT_SECTION_NAME));
   ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
                               DEBUG_INFO_SECTION_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
                               DEBUG_LINE_SECTION_LABEL, 0);
-  ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL, 0);
-  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LOC_SECTION);
-  ASM_OUTPUT_LABEL (asm_out_file, loc_section_label);
-  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_ABBREV_SECTION);
+  named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG);
   ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
-  if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
-    {
-      ASM_OUTPUT_SECTION (asm_out_file, TEXT_SECTION);
-      ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
-    }
-  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_INFO_SECTION);
+  named_section_flags (DEBUG_INFO_SECTION, SECTION_DEBUG);
   ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label);
-  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
+  named_section_flags (DEBUG_LINE_SECTION, SECTION_DEBUG);
   ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label);
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
-      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+      named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
       ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
                                   DEBUG_MACINFO_SECTION_LABEL, 0);
       ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
     }
+
+  if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
+    {
+      text_section ();
+      ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
+    }
 }
 
 /* Output stuff that dwarf requires at the end of every file,
    and generate the DWARF-2 debugging info.  */
 
 static void
-dwarf2out_finish (asm_out_file, input_filename)
-     register FILE *asm_out_file;
+dwarf2out_finish (input_filename)
      register const char *input_filename ATTRIBUTE_UNUSED;
 {
   limbo_die_node *node, *next_node;
@@ -11508,19 +11722,9 @@ dwarf2out_finish (asm_out_file, input_filename)
     add_sibling_attributes (node->die);
 
   /* Output a terminator label for the .text section.  */
-  ASM_OUTPUT_SECTION (asm_out_file, TEXT_SECTION);
+  text_section ();
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0);
 
-#if 0
-  /* Output a terminator label for the .data section.  */
-  ASM_OUTPUT_SECTION (asm_out_file, DATA_SECTION);
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, DATA_END_LABEL, 0);
-
-  /* Output a terminator label for the .bss section.  */
-  ASM_OUTPUT_SECTION (asm_out_file, BSS_SECTION);
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BSS_END_LABEL, 0);
-#endif
-
   /* Output the source line correspondence table.  We must do this
      even if there is no line information.  Otherwise, on an empty
      translation unit, we will generate a present, but empty,
@@ -11528,10 +11732,22 @@ dwarf2out_finish (asm_out_file, input_filename)
      examining the file.  */
   if (! DWARF2_ASM_LINE_DEBUG_INFO)
     {
-      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
+      named_section_flags (DEBUG_LINE_SECTION, SECTION_DEBUG);
       output_line_info ();
     }
 
+  /* Output location list section if necessary.  */
+  if (have_location_lists)
+    {
+      /* Output the location lists info.  */
+      named_section_flags (DEBUG_LOC_SECTION, SECTION_DEBUG);
+      ASM_GENERATE_INTERNAL_LABEL (loc_section_label,
+                                  DEBUG_LOC_SECTION_LABEL, 0);
+      ASM_OUTPUT_LABEL (asm_out_file, loc_section_label);
+      output_location_lists (die);
+      have_location_lists = 0;
+    }
+
   /* We can only use the low/high_pc attributes if all of the code was
      in .text.  */
   if (separate_line_info_table_in_use == 0)
@@ -11539,6 +11755,11 @@ dwarf2out_finish (asm_out_file, input_filename)
       add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label);
       add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);
     }
+  /* And if it wasn't, we need to give .debug_loc and .debug_ranges
+     an appropriate "base address".  Use zero so that these addresses
+     become absolute.  */
+  else if (have_location_lists || ranges_table_in_use)
+    add_AT_addr (comp_unit_die, DW_AT_entry_pc, const0_rtx);
 
   if (debug_info_level >= DINFO_LEVEL_NORMAL)
     add_AT_lbl_offset (comp_unit_die, DW_AT_stmt_list,
@@ -11554,13 +11775,13 @@ dwarf2out_finish (asm_out_file, input_filename)
   output_comp_unit (comp_unit_die);
 
   /* Output the abbreviation table.  */
-  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_ABBREV_SECTION);
+  named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG);
   output_abbrev_section ();
 
   if (pubname_table_in_use)
     {
       /* Output public names table.  */
-      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_PUBNAMES_SECTION);
+      named_section_flags (DEBUG_PUBNAMES_SECTION, SECTION_DEBUG);
       output_pubnames ();
     }
 
@@ -11569,24 +11790,22 @@ dwarf2out_finish (asm_out_file, input_filename)
   if (fde_table_in_use)
     {
       /* Output the address range information.  */
-      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_ARANGES_SECTION);
+      named_section_flags (DEBUG_ARANGES_SECTION, SECTION_DEBUG);
       output_aranges ();
     }
-  /* Output location list section if necessary */
-  if (have_location_lists)
+
+  /* Output ranges section if necessary.  */
+  if (ranges_table_in_use)
     {
-      /* Output the location lists info. */
-      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LOC_SECTION);
-      output_location_lists (die);
-      have_location_lists = 0;
+      named_section_flags (DEBUG_RANGES_SECTION, SECTION_DEBUG);
+      output_ranges ();
     }
 
-  /* Have to end the primary source file. */
+  /* Have to end the primary source file.  */
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     { 
-      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+      named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
       dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
     }
-  
 }
 #endif /* DWARF2_DEBUGGING_INFO */