OSDN Git Service

2007-09-26 Vincent Celier <celier@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2asm.c
index affa965..ac789f9 100644 (file)
@@ -1,11 +1,11 @@
 /* Dwarf2 assembler output helper routines.
 /* Dwarf2 assembler output helper routines.
-   Copyright (C) 2001 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 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
 
 This file is part of GCC.
 
 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
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -14,17 +14,19 @@ 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
 for more details.
 
 You should have received a copy of the GNU General Public License
-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.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 #include "config.h"
 #include "system.h"
 
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "flags.h"
 #include "tree.h"
 #include "rtl.h"
 #include "output.h"
 #include "flags.h"
 #include "tree.h"
 #include "rtl.h"
 #include "output.h"
+#include "target.h"
 #include "dwarf2asm.h"
 #include "dwarf2.h"
 #include "splay-tree.h"
 #include "dwarf2asm.h"
 #include "dwarf2.h"
 #include "splay-tree.h"
@@ -37,77 +39,46 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define ASM_COMMENT_START ";#"
 #endif
 
 #define ASM_COMMENT_START ";#"
 #endif
 
-/* We don't have unaligned support, let's hope the normal output works for
-   .debug_frame.  But we know it won't work for .debug_info.  */
-#if !defined(UNALIGNED_INT_ASM_OP) && defined(DWARF2_DEBUGGING_INFO)
- #error DWARF2_DEBUGGING_INFO requires UNALIGNED_INT_ASM_OP.
-#endif
-
 \f
 \f
-/* Despite the fact that assemble_integer handles unaligned data,
-   continue emitting things by hand when possible, since that makes
-   the assembler commentary come out prettier.  */
-#ifdef UNALIGNED_INT_ASM_OP
-static const char * unaligned_integer_asm_op  PARAMS ((int));
-
-static inline const char *
-unaligned_integer_asm_op (size)
-     int size;
+/* Output an unaligned integer with the given value and size.  Prefer not
+   to print a newline, since the caller may want to add a comment.  */
+
+void
+dw2_assemble_integer (int size, rtx x)
 {
 {
-  const char *op;
-  switch (size)
+  const char *op = integer_asm_op (size, FALSE);
+
+  if (op)
     {
     {
-    case 1:
-      op = ASM_BYTE_OP;
-      break;
-    case 2:
-      op = UNALIGNED_SHORT_ASM_OP;
-      break;
-    case 4:
-      op = UNALIGNED_INT_ASM_OP;
-      break;
-    case 8:
-#ifdef UNALIGNED_DOUBLE_INT_ASM_OP
-      op = UNALIGNED_DOUBLE_INT_ASM_OP;
-      break;
-#endif
-    default:
-      abort ();
+      fputs (op, asm_out_file);
+      if (GET_CODE (x) == CONST_INT)
+       fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
+      else
+       output_addr_const (asm_out_file, x);
     }
     }
-  return op;
+  else
+    assemble_integer (x, size, BITS_PER_UNIT, 1);
 }
 }
-#endif /* UNALIGNED_INT_ASM_OP */
+
 
 /* Output an immediate constant in a given size.  */
 
 void
 
 /* Output an immediate constant in a given size.  */
 
 void
-dw2_asm_output_data VPARAMS ((int size, unsigned HOST_WIDE_INT value,
-                             const char *comment, ...))
+dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value,
+                    const char *comment, ...)
 {
 {
-#ifndef ANSI_PROTOTYPES
-  int size;
-  unsigned HOST_WIDE_INT value;
-  const char *comment;
-#endif
   va_list ap;
   va_list ap;
+  const char *op = integer_asm_op (size, FALSE);
 
 
-  VA_START (ap, comment);
-
-#ifndef ANSI_PROTOTYPES
-  size = va_arg (ap, int);
-  value = va_arg (ap, unsigned HOST_WIDE_INT);
-  comment = va_arg (ap, const char *);
-#endif
+  va_start (ap, comment);
 
   if (size * 8 < HOST_BITS_PER_WIDE_INT)
 
   if (size * 8 < HOST_BITS_PER_WIDE_INT)
-    value &= ~(~(unsigned HOST_WIDE_INT)0 << (size * 8));
+    value &= ~(~(unsigned HOST_WIDE_INT) 0 << (size * 8));
 
 
-#ifdef UNALIGNED_INT_ASM_OP
-  fputs (unaligned_integer_asm_op (size), asm_out_file);
-  fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
-#else
-  assemble_integer (GEN_INT (value), size, BITS_PER_UNIT, 1);
-#endif
+  if (op)
+    fprintf (asm_out_file, "%s" HOST_WIDE_INT_PRINT_HEX, op, value);
+  else
+    assemble_integer (GEN_INT (value), size, BITS_PER_UNIT, 1);
 
   if (flag_debug_asm && comment)
     {
 
   if (flag_debug_asm && comment)
     {
@@ -126,36 +97,21 @@ dw2_asm_output_data VPARAMS ((int size, unsigned HOST_WIDE_INT value,
    symbol must appear after both symbols are defined.  */
 
 void
    symbol must appear after both symbols are defined.  */
 
 void
-dw2_asm_output_delta VPARAMS ((int size, const char *lab1, const char *lab2,
-                              const char *comment, ...))
+dw2_asm_output_delta (int size, const char *lab1, const char *lab2,
+                     const char *comment, ...)
 {
 {
-#ifndef ANSI_PROTOTYPES
-  int size;
-  const char *lab1, *lab2;
-  const char *comment;
-#endif
   va_list ap;
 
   va_list ap;
 
-  VA_START (ap, comment);
-
-#ifndef ANSI_PROTOTYPES
-  size = va_arg (ap, int);
-  lab1 = va_arg (ap, const char *);
-  lab2 = va_arg (ap, const char *);
-  comment = va_arg (ap, const char *);
-#endif
+  va_start (ap, comment);
 
 
-#ifdef UNALIGNED_INT_ASM_OP
-  fputs (unaligned_integer_asm_op (size), asm_out_file);
-  assemble_name (asm_out_file, lab1);
-  fputc ('-', asm_out_file);
-  assemble_name (asm_out_file, lab2);
+#ifdef ASM_OUTPUT_DWARF_DELTA
+  ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2);
 #else
 #else
-  assemble_integer (gen_rtx_MINUS (Pmode, gen_rtx_SYMBOL_REF (Pmode, lab1),
-                                  gen_rtx_SYMBOL_REF (Pmode, lab2)),
-                   size, BITS_PER_UNIT, 1);
+  dw2_assemble_integer (size,
+                       gen_rtx_MINUS (Pmode,
+                                      gen_rtx_SYMBOL_REF (Pmode, lab1),
+                                      gen_rtx_SYMBOL_REF (Pmode, lab2)));
 #endif
 #endif
-
   if (flag_debug_asm && comment)
     {
       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
   if (flag_debug_asm && comment)
     {
       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
@@ -166,40 +122,26 @@ dw2_asm_output_delta VPARAMS ((int size, const char *lab1, const char *lab2,
   va_end (ap);
 }
 
   va_end (ap);
 }
 
-/* Output a section-relative reference to a label.  In general this
-   can only be done for debugging symbols.  E.g. on most targets with
-   the GNU linker, this is accomplished with a direct reference and
-   the knowledge that the debugging section will be placed at VMA 0.
-   Some targets have special relocations for this that we must use.  */
+/* Output a section-relative reference to a LABEL, which was placed in
+   BASE.  In general this can only be done for debugging symbols.
+   E.g. on most targets with the GNU linker, this is accomplished with
+   a direct reference and the knowledge that the debugging section
+   will be placed at VMA 0.  Some targets have special relocations for
+   this that we must use.  */
 
 void
 
 void
-dw2_asm_output_offset VPARAMS ((int size, const char *label,
-                              const char *comment, ...))
+dw2_asm_output_offset (int size, const char *label,
+                      section *base ATTRIBUTE_UNUSED,
+                      const char *comment, ...)
 {
 {
-#ifndef ANSI_PROTOTYPES
-  int size;
-  const char *label;
-  const char *comment;
-#endif
   va_list ap;
 
   va_list ap;
 
-  VA_START (ap, comment);
-
-#ifndef ANSI_PROTOTYPES
-  size = va_arg (ap, int);
-  label = va_arg (ap, const char *);
-  comment = va_arg (ap, const char *);
-#endif
+  va_start (ap, comment);
 
 #ifdef ASM_OUTPUT_DWARF_OFFSET
 
 #ifdef ASM_OUTPUT_DWARF_OFFSET
-  ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label);
+  ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, base);
 #else
 #else
-#ifdef UNALIGNED_INT_ASM_OP
-  fputs (unaligned_integer_asm_op (size), asm_out_file);
-  assemble_name (asm_out_file, label);
-#else
-  assemble_integer (gen_rtx_SYMBOL_REF (Pmode, label), size, BITS_PER_UNIT, 1);
-#endif
+  dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
 #endif
 
   if (flag_debug_asm && comment)
 #endif
 
   if (flag_debug_asm && comment)
@@ -212,39 +154,27 @@ dw2_asm_output_offset VPARAMS ((int size, const char *label,
   va_end (ap);
 }
 
   va_end (ap);
 }
 
+#if 0
+
 /* Output a self-relative reference to a label, possibly in a
    different section or object file.  */
 
 void
 /* Output a self-relative reference to a label, possibly in a
    different section or object file.  */
 
 void
-dw2_asm_output_pcrel VPARAMS ((int size, const char *label,
-                              const char *comment, ...))
+dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED,
+                     const char *label ATTRIBUTE_UNUSED,
+                     const char *comment, ...)
 {
 {
-#ifndef ANSI_PROTOTYPES
-  int size;
-  const char *label;
-  const char *comment;
-#endif
   va_list ap;
 
   va_list ap;
 
-  VA_START (ap, comment);
-
-#ifndef ANSI_PROTOTYPES
-  size = va_arg (ap, int);
-  label = va_arg (ap, const char *);
-  comment = va_arg (ap, const char *);
-#endif
+  va_start (ap, comment);
 
 #ifdef ASM_OUTPUT_DWARF_PCREL
   ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
 #else
 
 #ifdef ASM_OUTPUT_DWARF_PCREL
   ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
 #else
-#ifdef UNALIGNED_INT_ASM_OP
-  fputs (unaligned_integer_asm_op (size), asm_out_file);
-  assemble_name (asm_out_file, label);
-  fputc ('-', asm_out_file);
-  fputc ('.', asm_out_file);
-#else
-  abort ();
-#endif
+  dw2_assemble_integer (size,
+                       gen_rtx_MINUS (Pmode,
+                                      gen_rtx_SYMBOL_REF (Pmode, label),
+                                      pc_rtx));
 #endif
 
   if (flag_debug_asm && comment)
 #endif
 
   if (flag_debug_asm && comment)
@@ -256,34 +186,19 @@ dw2_asm_output_pcrel VPARAMS ((int size, const char *label,
 
   va_end (ap);
 }
 
   va_end (ap);
 }
+#endif /* 0 */
 
 /* Output an absolute reference to a label.  */
 
 void
 
 /* Output an absolute reference to a label.  */
 
 void
-dw2_asm_output_addr VPARAMS ((int size, const char *label,
-                             const char *comment, ...))
+dw2_asm_output_addr (int size, const char *label,
+                    const char *comment, ...)
 {
 {
-#ifndef ANSI_PROTOTYPES
-  int size;
-  const char *label;
-  const char *comment;
-#endif
   va_list ap;
 
   va_list ap;
 
-  VA_START (ap, comment);
+  va_start (ap, comment);
 
 
-#ifndef ANSI_PROTOTYPES
-  size = va_arg (ap, int);
-  label = va_arg (ap, const char *);
-  comment = va_arg (ap, const char *);
-#endif
-
-#ifdef UNALIGNED_INT_ASM_OP
-  fputs (unaligned_integer_asm_op (size), asm_out_file);
-  assemble_name (asm_out_file, label);
-#else
-  assemble_integer (gen_rtx_SYMBOL_REF (Pmode, label), size, BITS_PER_UNIT, 1);
-#endif
+  dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
 
   if (flag_debug_asm && comment)
     {
 
   if (flag_debug_asm && comment)
     {
@@ -298,30 +213,14 @@ dw2_asm_output_addr VPARAMS ((int size, const char *label,
 /* Similar, but use an RTX expression instead of a text label.  */
 
 void
 /* Similar, but use an RTX expression instead of a text label.  */
 
 void
-dw2_asm_output_addr_rtx VPARAMS ((int size, rtx addr,
-                                 const char *comment, ...))
+dw2_asm_output_addr_rtx (int size, rtx addr,
+                        const char *comment, ...)
 {
 {
-#ifndef ANSI_PROTOTYPES
-  int size;
-  rtx addr;
-  const char *comment;
-#endif
   va_list ap;
 
   va_list ap;
 
-  VA_START (ap, comment);
+  va_start (ap, comment);
 
 
-#ifndef ANSI_PROTOTYPES
-  size = va_arg (ap, int);
-  addr = va_arg (ap, rtx);
-  comment = va_arg (ap, const char *);
-#endif
-
-#ifdef UNALIGNED_INT_ASM_OP
-  fputs (unaligned_integer_asm_op (size), asm_out_file);
-  output_addr_const (asm_out_file, addr);
-#else
-  assemble_integer (addr, size, BITS_PER_UNIT, 1);
-#endif
+  dw2_assemble_integer (size, addr);
 
   if (flag_debug_asm && comment)
     {
 
   if (flag_debug_asm && comment)
     {
@@ -333,25 +232,23 @@ dw2_asm_output_addr_rtx VPARAMS ((int size, rtx addr,
   va_end (ap);
 }
 
   va_end (ap);
 }
 
+/* Output the first ORIG_LEN characters of STR as a string.
+   If ORIG_LEN is equal to -1, ignore this parameter and output
+   the entire STR instead.
+   If COMMENT is not NULL and comments in the debug information
+   have been requested by the user, append the given COMMENT
+   to the generated output.  */
+   
 void
 void
-dw2_asm_output_nstring VPARAMS ((const char *str, size_t orig_len,
-                                const char *comment, ...))
+dw2_asm_output_nstring (const char *str, size_t orig_len,
+                       const char *comment, ...)
 {
 {
-#ifndef ANSI_PROTOTYPES
-  const char *str;
-  size_t orig_len;
-  const char *comment;
-#endif
+  size_t i, len;
   va_list ap;
   va_list ap;
-  size_t i, len = orig_len;
 
 
-  VA_START (ap, comment);
+  va_start (ap, comment);
 
 
-#ifndef ANSI_PROTOTYPES
-  str = va_arg (ap, const char *);
-  len = va_arg (ap, size_t);
-  comment = va_arg (ap, const char *);
-#endif
+  len = orig_len;
 
   if (len == (size_t) -1)
     len = strlen (str);
 
   if (len == (size_t) -1)
     len = strlen (str);
@@ -381,7 +278,7 @@ dw2_asm_output_nstring VPARAMS ((const char *str, size_t orig_len,
        len += 1;
       ASM_OUTPUT_ASCII (asm_out_file, str, len);
       if (orig_len != (size_t) -1)
        len += 1;
       ASM_OUTPUT_ASCII (asm_out_file, str, len);
       if (orig_len != (size_t) -1)
-       fprintf (asm_out_file, "%s0\n", ASM_BYTE_OP);
+       assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
     }
 
   va_end (ap);
     }
 
   va_end (ap);
@@ -391,14 +288,12 @@ dw2_asm_output_nstring VPARAMS ((const char *str, size_t orig_len,
 /* Return the size of an unsigned LEB128 quantity.  */
 
 int
 /* Return the size of an unsigned LEB128 quantity.  */
 
 int
-size_of_uleb128 (value)
-     unsigned HOST_WIDE_INT value;
+size_of_uleb128 (unsigned HOST_WIDE_INT value)
 {
 {
-  int size = 0, byte;
+  int size = 0;
 
   do
     {
 
   do
     {
-      byte = (value & 0x7f);
       value >>= 7;
       size += 1;
     }
       value >>= 7;
       size += 1;
     }
@@ -410,8 +305,7 @@ size_of_uleb128 (value)
 /* Return the size of a signed LEB128 quantity.  */
 
 int
 /* Return the size of a signed LEB128 quantity.  */
 
 int
-size_of_sleb128 (value)
-     HOST_WIDE_INT value;
+size_of_sleb128 (HOST_WIDE_INT value)
 {
   int size = 0, byte;
 
 {
   int size = 0, byte;
 
@@ -428,12 +322,11 @@ size_of_sleb128 (value)
 }
 
 /* Given an encoding, return the number of bytes the format occupies.
 }
 
 /* Given an encoding, return the number of bytes the format occupies.
-   This is only defined for fixed-size encodings, and so does not 
+   This is only defined for fixed-size encodings, and so does not
    include leb128.  */
 
 int
    include leb128.  */
 
 int
-size_of_encoded_value (encoding)
-     int encoding;
+size_of_encoded_value (int encoding)
 {
   if (encoding == DW_EH_PE_omit)
     return 0;
 {
   if (encoding == DW_EH_PE_omit)
     return 0;
@@ -448,15 +341,15 @@ size_of_encoded_value (encoding)
       return 4;
     case DW_EH_PE_udata8:
       return 8;
       return 4;
     case DW_EH_PE_udata8:
       return 8;
+    default:
+      gcc_unreachable ();
     }
     }
-  abort ();
 }
 
 /* Yield a name for a given pointer encoding.  */
 
 const char *
 }
 
 /* Yield a name for a given pointer encoding.  */
 
 const char *
-eh_data_format_name (format)
-     int format;
+eh_data_format_name (int format)
 {
 #if HAVE_DESIGNATED_INITIALIZERS
 #define S(p, v)                [p] = v,
 {
 #if HAVE_DESIGNATED_INITIALIZERS
 #define S(p, v)                [p] = v,
@@ -602,37 +495,27 @@ eh_data_format_name (format)
 #if HAVE_DESIGNATED_INITIALIZERS
   };
 
 #if HAVE_DESIGNATED_INITIALIZERS
   };
 
-  if (format < 0 || format > 0xff || format_names[format] == NULL)
-    abort ();
+  gcc_assert (format >= 0 && format < 0x100 && format_names[format]);
+  
   return format_names[format];
 #else
   }
   return format_names[format];
 #else
   }
-  abort ();
+  gcc_unreachable ();
 #endif
 }
 
 /* Output an unsigned LEB128 quantity.  */
 
 void
 #endif
 }
 
 /* Output an unsigned LEB128 quantity.  */
 
 void
-dw2_asm_output_data_uleb128 VPARAMS ((unsigned HOST_WIDE_INT value,
-                                     const char *comment, ...))
+dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
+                            const char *comment, ...)
 {
 {
-#ifndef ANSI_PROTOTYPES
-  unsigned HOST_WIDE_INT value;
-  const char *comment;
-#endif
   va_list ap;
 
   va_list ap;
 
-  VA_START (ap, comment);
-
-#ifndef ANSI_PROTOTYPES
-  value = va_arg (ap, unsigned HOST_WIDE_INT);
-  comment = va_arg (ap, const char *);
-#endif
+  va_start (ap, comment);
 
 #ifdef HAVE_AS_LEB128
 
 #ifdef HAVE_AS_LEB128
-  fputs ("\t.uleb128 ", asm_out_file);
-  fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
+  fprintf (asm_out_file, "\t.uleb128 " HOST_WIDE_INT_PRINT_HEX , value);
 
   if (flag_debug_asm && comment)
     {
 
   if (flag_debug_asm && comment)
     {
@@ -642,8 +525,10 @@ dw2_asm_output_data_uleb128 VPARAMS ((unsigned HOST_WIDE_INT value,
 #else
   {
     unsigned HOST_WIDE_INT work = value;
 #else
   {
     unsigned HOST_WIDE_INT work = value;
+    const char *byte_op = targetm.asm_out.byte_op;
 
 
-    fputs (ASM_BYTE_OP, asm_out_file);
+    if (byte_op)
+      fputs (byte_op, asm_out_file);
     do
       {
        int byte = (work & 0x7f);
     do
       {
        int byte = (work & 0x7f);
@@ -652,16 +537,21 @@ dw2_asm_output_data_uleb128 VPARAMS ((unsigned HOST_WIDE_INT value,
          /* More bytes to follow.  */
          byte |= 0x80;
 
          /* More bytes to follow.  */
          byte |= 0x80;
 
-       fprintf (asm_out_file, "0x%x", byte);
-       if (work != 0)
-         fputc (',', asm_out_file);
+       if (byte_op)
+         {
+           fprintf (asm_out_file, "0x%x", byte);
+           if (work != 0)
+             fputc (',', asm_out_file);
+         }
+       else
+         assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
       }
     while (work != 0);
 
   if (flag_debug_asm)
     {
       }
     while (work != 0);
 
   if (flag_debug_asm)
     {
-      fprintf (asm_out_file, "\t%s uleb128 ", ASM_COMMENT_START);
-      fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
+      fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
+              ASM_COMMENT_START, value);
       if (comment)
        {
          fputs ("; ", asm_out_file);
       if (comment)
        {
          fputs ("; ", asm_out_file);
@@ -675,28 +565,18 @@ dw2_asm_output_data_uleb128 VPARAMS ((unsigned HOST_WIDE_INT value,
   va_end (ap);
 }
 
   va_end (ap);
 }
 
-/* Output an signed LEB128 quantity.  */
+/* Output a signed LEB128 quantity.  */
 
 void
 
 void
-dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
-                                     const char *comment, ...))
+dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
+                            const char *comment, ...)
 {
 {
-#ifndef ANSI_PROTOTYPES
-  HOST_WIDE_INT value;
-  const char *comment;
-#endif
   va_list ap;
 
   va_list ap;
 
-  VA_START (ap, comment);
-
-#ifndef ANSI_PROTOTYPES
-  value = va_arg (ap, HOST_WIDE_INT);
-  comment = va_arg (ap, const char *);
-#endif
+  va_start (ap, comment);
 
 #ifdef HAVE_AS_LEB128
 
 #ifdef HAVE_AS_LEB128
-  fputs ("\t.sleb128 ", asm_out_file);
-  fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
+  fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value);
 
   if (flag_debug_asm && comment)
     {
 
   if (flag_debug_asm && comment)
     {
@@ -707,8 +587,10 @@ dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
   {
     HOST_WIDE_INT work = value;
     int more, byte;
   {
     HOST_WIDE_INT work = value;
     int more, byte;
+    const char *byte_op = targetm.asm_out.byte_op;
 
 
-    fputs (ASM_BYTE_OP, asm_out_file);
+    if (byte_op)
+      fputs (byte_op, asm_out_file);
     do
       {
        byte = (work & 0x7f);
     do
       {
        byte = (work & 0x7f);
@@ -719,16 +601,21 @@ dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
        if (more)
          byte |= 0x80;
 
        if (more)
          byte |= 0x80;
 
-       fprintf (asm_out_file, "0x%x", byte);
-       if (more)
-         fputc (',', asm_out_file);
+       if (byte_op)
+         {
+           fprintf (asm_out_file, "0x%x", byte);
+           if (more)
+             fputc (',', asm_out_file);
+         }
+       else
+         assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
       }
     while (more);
 
   if (flag_debug_asm)
     {
       }
     while (more);
 
   if (flag_debug_asm)
     {
-      fprintf (asm_out_file, "\t%s sleb128 ", ASM_COMMENT_START);
-      fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
+      fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
+              ASM_COMMENT_START, value);
       if (comment)
        {
          fputs ("; ", asm_out_file);
       if (comment)
        {
          fputs ("; ", asm_out_file);
@@ -743,23 +630,13 @@ dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
 }
 
 void
 }
 
 void
-dw2_asm_output_delta_uleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
-                                      const char *lab2 ATTRIBUTE_UNUSED,
-                                      const char *comment, ...))
+dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
+                             const char *lab2 ATTRIBUTE_UNUSED,
+                             const char *comment, ...)
 {
 {
-#ifndef ANSI_PROTOTYPES
-  const char *lab1, *lab2;
-  const char *comment;
-#endif
   va_list ap;
 
   va_list ap;
 
-  VA_START (ap, comment);
-
-#ifndef ANSI_PROTOTYPES
-  lab1 = va_arg (ap, const char *);
-  lab2 = va_arg (ap, const char *);
-  comment = va_arg (ap, const char *);
-#endif
+  va_start (ap, comment);
 
 #ifdef HAVE_AS_LEB128
   fputs ("\t.uleb128 ", asm_out_file);
 
 #ifdef HAVE_AS_LEB128
   fputs ("\t.uleb128 ", asm_out_file);
@@ -767,7 +644,7 @@ dw2_asm_output_delta_uleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
   fputc ('-', asm_out_file);
   assemble_name (asm_out_file, lab2);
 #else
   fputc ('-', asm_out_file);
   assemble_name (asm_out_file, lab2);
 #else
-  abort ();
+  gcc_unreachable ();
 #endif
 
   if (flag_debug_asm && comment)
 #endif
 
   if (flag_debug_asm && comment)
@@ -780,24 +657,16 @@ dw2_asm_output_delta_uleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
   va_end (ap);
 }
 
   va_end (ap);
 }
 
+#if 0
+
 void
 void
-dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
-                                      const char *lab2 ATTRIBUTE_UNUSED,
-                                      const char *comment, ...))
+dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
+                             const char *lab2 ATTRIBUTE_UNUSED,
+                             const char *comment, ...)
 {
 {
-#ifndef ANSI_PROTOTYPES
-  const char *lab1, *lab2;
-  const char *comment;
-#endif
   va_list ap;
 
   va_list ap;
 
-  VA_START (ap, comment);
-
-#ifndef ANSI_PROTOTYPES
-  lab1 = va_arg (ap, const char *);
-  lab2 = va_arg (ap, const char *);
-  comment = va_arg (ap, const char *);
-#endif
+  va_start (ap, comment);
 
 #ifdef HAVE_AS_LEB128
   fputs ("\t.sleb128 ", asm_out_file);
 
 #ifdef HAVE_AS_LEB128
   fputs ("\t.sleb128 ", asm_out_file);
@@ -805,7 +674,7 @@ dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
   fputc ('-', asm_out_file);
   assemble_name (asm_out_file, lab2);
 #else
   fputc ('-', asm_out_file);
   assemble_name (asm_out_file, lab2);
 #else
-  abort ();
+  gcc_unreachable ();
 #endif
 
   if (flag_debug_asm && comment)
 #endif
 
   if (flag_debug_asm && comment)
@@ -817,69 +686,102 @@ dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
 
   va_end (ap);
 }
 
   va_end (ap);
 }
+#endif /* 0 */
 \f
 \f
-static rtx dw2_force_const_mem PARAMS ((rtx));
-static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
+static rtx dw2_force_const_mem (rtx, bool);
+static int dw2_output_indirect_constant_1 (splay_tree_node, void *);
+
+static GTY((param1_is (char *), param2_is (tree))) splay_tree indirect_pool;
 
 
-static splay_tree indirect_pool;
+static GTY(()) int dw2_const_labelno;
+
+#if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
+# define USE_LINKONCE_INDIRECT 1
+#else
+# define USE_LINKONCE_INDIRECT 0
+#endif
 
 /* Put X, a SYMBOL_REF, in memory.  Return a SYMBOL_REF to the allocated
    memory.  Differs from force_const_mem in that a single pool is used for
    the entire unit of translation, and the memory is not guaranteed to be
 
 /* Put X, a SYMBOL_REF, in memory.  Return a SYMBOL_REF to the allocated
    memory.  Differs from force_const_mem in that a single pool is used for
    the entire unit of translation, and the memory is not guaranteed to be
-   "near" the function in any interesting sense.  */
+   "near" the function in any interesting sense.  PUBLIC controls whether
+   the symbol can be shared across the entire application (or DSO).  */
 
 static rtx
 
 static rtx
-dw2_force_const_mem (x)
-     rtx x;
+dw2_force_const_mem (rtx x, bool public)
 {
   splay_tree_node node;
 {
   splay_tree_node node;
-  const char *const_sym;
+  const char *str;
+  tree decl;
 
   if (! indirect_pool)
 
   if (! indirect_pool)
-    indirect_pool = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
+    indirect_pool = splay_tree_new_ggc (splay_tree_compare_pointers);
+
+  gcc_assert (GET_CODE (x) == SYMBOL_REF);
 
 
-  if (GET_CODE (x) != SYMBOL_REF)
-    abort ();
-  node = splay_tree_lookup (indirect_pool, (splay_tree_key) XSTR (x, 0));
+  str = targetm.strip_name_encoding (XSTR (x, 0));
+  node = splay_tree_lookup (indirect_pool, (splay_tree_key) str);
   if (node)
   if (node)
-    const_sym = (const char *) node->value;
+    decl = (tree) node->value;
   else
     {
   else
     {
-      extern int const_labelno;
-      char label[32];
       tree id;
 
       tree id;
 
-      ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
-      ++const_labelno;
-      const_sym = ggc_strdup (label);
+      if (public && USE_LINKONCE_INDIRECT)
+       {
+         char *ref_name = alloca (strlen (str) + sizeof "DW.ref.");
+
+         sprintf (ref_name, "DW.ref.%s", str);
+         id = get_identifier (ref_name);
+         decl = build_decl (VAR_DECL, id, ptr_type_node);
+         DECL_ARTIFICIAL (decl) = 1;
+         DECL_IGNORED_P (decl) = 1;
+         TREE_PUBLIC (decl) = 1;
+         DECL_INITIAL (decl) = decl;
+         make_decl_one_only (decl);
+       }
+      else
+       {
+         char label[32];
+
+         ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
+         ++dw2_const_labelno;
+         id = get_identifier (label);
+         decl = build_decl (VAR_DECL, id, ptr_type_node);
+         DECL_ARTIFICIAL (decl) = 1;
+         DECL_IGNORED_P (decl) = 1;
+         TREE_STATIC (decl) = 1;
+         DECL_INITIAL (decl) = decl;
+       }
 
 
-      id = maybe_get_identifier (XSTR (x, 0));
+      id = maybe_get_identifier (str);
       if (id)
        TREE_SYMBOL_REFERENCED (id) = 1;
 
       if (id)
        TREE_SYMBOL_REFERENCED (id) = 1;
 
-      splay_tree_insert (indirect_pool, (splay_tree_key) XSTR (x, 0),
-                        (splay_tree_value) const_sym);
+      splay_tree_insert (indirect_pool, (splay_tree_key) str,
+                        (splay_tree_value) decl);
     }
 
     }
 
-  return gen_rtx_SYMBOL_REF (Pmode, const_sym);
+  return XEXP (DECL_RTL (decl), 0);
 }
 
 /* A helper function for dw2_output_indirect_constants called through
    splay_tree_foreach.  Emit one queued constant to memory.  */
 
 static int
 }
 
 /* A helper function for dw2_output_indirect_constants called through
    splay_tree_foreach.  Emit one queued constant to memory.  */
 
 static int
-dw2_output_indirect_constant_1 (node, data)
-     splay_tree_node node;
-     void* data ATTRIBUTE_UNUSED;
+dw2_output_indirect_constant_1 (splay_tree_node node,
+                               void *data ATTRIBUTE_UNUSED)
 {
 {
-  const char *label, *sym;
+  const char *sym;
   rtx sym_ref;
   rtx sym_ref;
+  tree decl;
 
 
-  label = (const char *) node->value;
   sym = (const char *) node->key;
   sym = (const char *) node->key;
+  decl = (tree) node->value;
   sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
   sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
-
-  ASM_OUTPUT_LABEL (asm_out_file, label);
+  if (TREE_PUBLIC (decl) && USE_LINKONCE_INDIRECT)
+    fprintf (asm_out_file, "\t.hidden %sDW.ref.%s\n", user_label_prefix, sym);
+  assemble_variable (decl, 1, 1, 1);
   assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
 
   return 0;
   assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
 
   return 0;
@@ -888,62 +790,43 @@ dw2_output_indirect_constant_1 (node, data)
 /* Emit the constants queued through dw2_force_const_mem.  */
 
 void
 /* Emit the constants queued through dw2_force_const_mem.  */
 
 void
-dw2_output_indirect_constants ()
+dw2_output_indirect_constants (void)
 {
 {
-  if (! indirect_pool)
-    return;
-
-  /* Assume that the whole reason we're emitting these symbol references
-     indirectly is that they contain dynamic relocations, and are thus
-     read-write.  If there was no possibility of a dynamic relocation, we
-     might as well have used a direct relocation.  */
-  data_section ();
-
-  /* Everything we're emitting is a pointer.  Align appropriately.  */
-  assemble_align (POINTER_SIZE);
-
-  splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
+  if (indirect_pool)
+    splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
 }
 
 }
 
-/* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.  */
+/* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
+   If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
+   reference is shared across the entire application (or DSO).  */
 
 void
 
 void
-dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
-                                         rtx addr,
-                                         const char *comment, ...))
+dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool public,
+                                const char *comment, ...)
 {
 {
-#ifndef ANSI_PROTOTYPES
-  int encoding;
-  rtx addr;
-  const char *comment;
-#endif
-  va_list ap;
   int size;
   int size;
+  va_list ap;
 
 
-  VA_START (ap, comment);
-
-#ifndef ANSI_PROTOTYPES
-  encoding = va_arg (ap, int);
-  addr = va_arg (ap, rtx);
-  comment = va_arg (ap, const char *);
-#endif
+  va_start (ap, comment);
 
   size = size_of_encoded_value (encoding);
 
   if (encoding == DW_EH_PE_aligned)
     {
       assemble_align (POINTER_SIZE);
 
   size = size_of_encoded_value (encoding);
 
   if (encoding == DW_EH_PE_aligned)
     {
       assemble_align (POINTER_SIZE);
-      encoding = DW_EH_PE_absptr;
+      assemble_integer (addr, size, POINTER_SIZE, 1);
+      return;
     }
 
     }
 
-  /* NULL is _always_ represented as a plain zero.  */
-  if (addr == const0_rtx)
+  /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
+     "all others".  */
+  if (addr == const0_rtx || addr == const1_rtx)
     assemble_integer (addr, size, BITS_PER_UNIT, 1);
   else
     {
     restart:
       /* Allow the target first crack at emitting this.  Some of the
     assemble_integer (addr, size, BITS_PER_UNIT, 1);
   else
     {
     restart:
       /* Allow the target first crack at emitting this.  Some of the
-        special relocations require special directives instead of 
+        special relocations require special directives instead of
         just ".4byte" or whatever.  */
 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
       ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
         just ".4byte" or whatever.  */
 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
       ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
@@ -957,9 +840,9 @@ dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
          /* It is very tempting to use force_const_mem so that we share data
             with the normal constant pool.  However, we've already emitted
             the constant pool for this function.  Moreover, we'd like to
          /* It is very tempting to use force_const_mem so that we share data
             with the normal constant pool.  However, we've already emitted
             the constant pool for this function.  Moreover, we'd like to
-            share these constants across the entire unit of translation,
-            or better, across the entire application (or DSO).  */
-         addr = dw2_force_const_mem (addr);
+            share these constants across the entire unit of translation and
+            even, if possible, across the entire application (or DSO).  */
+         addr = dw2_force_const_mem (addr, public);
          encoding &= ~DW_EH_PE_indirect;
          goto restart;
        }
          encoding &= ~DW_EH_PE_indirect;
          goto restart;
        }
@@ -967,35 +850,22 @@ dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
       switch (encoding & 0xF0)
        {
        case DW_EH_PE_absptr:
       switch (encoding & 0xF0)
        {
        case DW_EH_PE_absptr:
-#ifdef UNALIGNED_INT_ASM_OP
-         fputs (unaligned_integer_asm_op (size), asm_out_file);
-         output_addr_const (asm_out_file, addr);
-#else
-         assemble_integer (addr, size, BITS_PER_UNIT, 1);
-#endif
+         dw2_assemble_integer (size, addr);
          break;
 
        case DW_EH_PE_pcrel:
          break;
 
        case DW_EH_PE_pcrel:
-         if (GET_CODE (addr) != SYMBOL_REF)
-           abort ();
+         gcc_assert (GET_CODE (addr) == SYMBOL_REF);
 #ifdef ASM_OUTPUT_DWARF_PCREL
          ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
 #else
 #ifdef ASM_OUTPUT_DWARF_PCREL
          ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
 #else
-#ifdef UNALIGNED_INT_ASM_OP
-         fputs (unaligned_integer_asm_op (size), asm_out_file);
-         assemble_name (asm_out_file, XSTR (addr, 0));
-         fputc ('-', asm_out_file);
-         fputc ('.', asm_out_file);
-#else
-         abort ();
-#endif
+         dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
 #endif
          break;
 
        default:
 #endif
          break;
 
        default:
-         /* Other encodings should have been handled by 
+         /* Other encodings should have been handled by
             ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX.  */
             ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX.  */
-         abort ();
+         gcc_unreachable ();
        }
 
 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
        }
 
 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
@@ -1012,3 +882,5 @@ dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
 
   va_end (ap);
 }
 
   va_end (ap);
 }
+
+#include "gt-dwarf2asm.h"