OSDN Git Service

* ChangeLog.2, ChangeLog.3, ChangeLog.5, ChangeLog, alias.c,
[pf3gnuchains/gcc-fork.git] / gcc / varasm.c
index 0dea54d..123b57c 100644 (file)
@@ -43,6 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "hashtab.h"
 #include "c-pragma.h"
 #include "ggc.h"
+#include "langhooks.h"
 #include "tm_p.h"
 #include "debug.h"
 #include "target.h"
@@ -60,10 +61,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define ASM_STABS_OP "\t.stabs\t"
 #endif
 
-/* Define the prefix to use when check_memory_usage_flag is enable.  */
-#define CHKR_PREFIX "_CHKR_"
-#define CHKR_PREFIX_SIZE (sizeof (CHKR_PREFIX) - 1)
-
 /* The (assembler) name of the first globally-visible object output.  */
 const char *first_global_object_name;
 const char *weak_global_object_name;
@@ -96,13 +93,10 @@ struct varasm_status
 
   /* Current offset in constant pool (does not include any machine-specific
      header).  */
-  int x_pool_offset;
+  HOST_WIDE_INT x_pool_offset;
 
   /* Chain of all CONST_DOUBLE rtx's constructed for the current function.
-     They are chained through the CONST_DOUBLE_CHAIN.
-     A CONST_DOUBLE rtx has CONST_DOUBLE_MEM != cc0_rtx iff it is on this chain.
-     In that case, CONST_DOUBLE_MEM is either a MEM,
-     or const0_rtx if no MEM has been made for this CONST_DOUBLE yet.  */
+     They are chained through the CONST_DOUBLE_CHAIN.  */
   rtx x_const_double_chain;
 };
 
@@ -135,6 +129,15 @@ int size_directive_output;
 
 tree last_assemble_variable_decl;
 
+/* RTX_UNCHANGING_P in a MEM can mean it is stored into, for initialization.
+   So giving constant the alias set for the type will allow such
+   initializations to appear to conflict with the load of the constant.  We
+   avoid this by giving all constants an alias set for just constants.
+   Since there will be no stores to that a alias set, nothing will ever
+   conflict with them.  */
+
+static HOST_WIDE_INT const_alias_set;
+
 static const char *strip_reg_name      PARAMS ((const char *));
 static int contains_pointers_p         PARAMS ((tree));
 static void assemble_real_1            PARAMS ((PTR));
@@ -162,8 +165,11 @@ static int output_addressed_constants      PARAMS ((tree));
 static void output_after_function_constants PARAMS ((void));
 static unsigned HOST_WIDE_INT array_size_for_constructor PARAMS ((tree));
 static unsigned min_align              PARAMS ((unsigned, unsigned));
-static void output_constructor         PARAMS ((tree, int, unsigned));
+static void output_constructor         PARAMS ((tree, HOST_WIDE_INT,
+                                                unsigned int));
+#ifdef ASM_WEAKEN_LABEL
 static void remove_from_pending_weak_list      PARAMS ((const char *));
+#endif
 static int in_named_entry_eq           PARAMS ((const PTR, const PTR));
 static hashval_t in_named_entry_hash   PARAMS ((const PTR));
 #ifdef ASM_OUTPUT_BSS
@@ -522,7 +528,7 @@ asm_output_bss (file, decl, name, size, rounded)
 static void
 asm_output_aligned_bss (file, decl, name, size, align)
      FILE *file;
-     tree decl;
+     tree decl ATTRIBUTE_UNUSED;
      const char *name;
      int size, align;
 {
@@ -601,18 +607,14 @@ variable_section (decl, reloc)
    table.  */
 
 void
-exception_section ()
+default_exception_section ()
 {
-#if defined (EXCEPTION_SECTION)
-  EXCEPTION_SECTION ();
-#else
   if (targetm.have_named_sections)
     named_section (NULL_TREE, ".gcc_except_table", 0);
   else if (flag_pic)
     data_section ();
   else
     readonly_data_section ();
-#endif
 }
 
 /* Tell assembler to switch to the section for string merging.  */
@@ -756,7 +758,7 @@ decode_reg_name (asmspec)
 
       /* Allow a decimal number as a "register name".  */
       for (i = strlen (asmspec) - 1; i >= 0; i--)
-       if (! (asmspec[i] >= '0' && asmspec[i] <= '9'))
+       if (! ISDIGIT (asmspec[i]))
          break;
       if (asmspec[0] != 0 && i < 0)
        {
@@ -951,25 +953,12 @@ make_decl_rtl (decl, asmspec)
       && name == IDENTIFIER_POINTER (DECL_NAME (decl)))
     {
       char *label;
+
       ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
       var_labelno++;
       new_name = label;
     }
 
-  /* When -fprefix-function-name is used, the functions
-     names are prefixed.  Only nested function names are not
-     prefixed.  */
-  else if (flag_prefix_function_name && TREE_CODE (decl) == FUNCTION_DECL)
-    {
-      size_t name_len = IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
-      char *pname;
-
-      pname = alloca (name_len + CHKR_PREFIX_SIZE + 1);
-      memcpy (pname, CHKR_PREFIX, CHKR_PREFIX_SIZE);
-      memcpy (pname + CHKR_PREFIX_SIZE, name, name_len + 1);
-      new_name = pname;
-    }
-
   if (name != new_name)
     {
       SET_DECL_ASSEMBLER_NAME (decl, get_identifier (new_name));
@@ -977,7 +966,7 @@ make_decl_rtl (decl, asmspec)
     }
 
   /* If this variable is to be treated as volatile, show its
-     tree node has side effects.   */
+     tree node has side effects.  */
   if ((flag_volatile_global && TREE_CODE (decl) == VAR_DECL
        && TREE_PUBLIC (decl))
       || ((flag_volatile_static && TREE_CODE (decl) == VAR_DECL
@@ -1027,7 +1016,9 @@ assemble_constant_align (exp)
 #endif
 
   if (align > BITS_PER_UNIT)
-    ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
+    {
+      ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
+    }
 }
 
 /* Output a string of literal assembler code
@@ -1070,7 +1061,7 @@ default_named_section_asm_out_destructor (symbol, priority)
   const char *section = ".dtors";
   char buf[16];
 
-  /* ??? This only works reliably with the GNU linker.   */
+  /* ??? This only works reliably with the GNU linker.  */
   if (priority != DEFAULT_INIT_PRIORITY)
     {
       sprintf (buf, ".dtors.%.5u",
@@ -1132,7 +1123,7 @@ default_named_section_asm_out_constructor (symbol, priority)
   const char *section = ".ctors";
   char buf[16];
 
-  /* ??? This only works reliably with the GNU linker.   */
+  /* ??? This only works reliably with the GNU linker.  */
   if (priority != DEFAULT_INIT_PRIORITY)
     {
       sprintf (buf, ".ctors.%.5u",
@@ -1206,7 +1197,9 @@ assemble_start_function (decl, fnname)
   /* Tell assembler to move to target machine's alignment for functions.  */
   align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
   if (align > 0)
-    ASM_OUTPUT_ALIGN (asm_out_file, align);
+    {
+      ASM_OUTPUT_ALIGN (asm_out_file, align);
+    }
 
   /* Handle a user-specified function alignment.
      Note that we still need to align to FUNCTION_BOUNDARY, as above,
@@ -1322,7 +1315,9 @@ assemble_align (align)
      int align;
 {
   if (align > BITS_PER_UNIT)
-    ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
+    {
+      ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
+    }
 }
 
 /* Assemble a string constant with the specified C string as contents.  */
@@ -1477,7 +1472,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
      int at_end ATTRIBUTE_UNUSED;
      int dont_output_data;
 {
-  register const char *name;
+  const char *name;
   unsigned int align;
   int reloc = 0;
   rtx decl_rtl;
@@ -1585,7 +1580,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
   if (align > MAX_OFILE_ALIGNMENT)
     {
       warning_with_decl (decl,
-       "alignment of `%s' is greater than maximum object file alignment. Using %d.",
+       "alignment of `%s' is greater than maximum object file alignment. Using %d",
                     MAX_OFILE_ALIGNMENT/BITS_PER_UNIT);
       align = MAX_OFILE_ALIGNMENT;
     }
@@ -1605,6 +1600,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
   /* Reset the alignment in case we have made it tighter, so we can benefit
      from it in get_pointer_alignment.  */
   DECL_ALIGN (decl) = align;
+  set_mem_align (decl_rtl, align);
 
   /* Handle uninitialized definitions.  */
 
@@ -1635,7 +1631,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
 #if !defined(ASM_OUTPUT_ALIGNED_COMMON) && !defined(ASM_OUTPUT_ALIGNED_DECL_COMMON) && !defined(ASM_OUTPUT_ALIGNED_BSS)
       if ((unsigned HOST_WIDE_INT) DECL_ALIGN (decl) / BITS_PER_UNIT > rounded)
          warning_with_decl
-           (decl, "requested alignment for %s is greater than implemented alignment of %d.",rounded);
+           (decl, "requested alignment for %s is greater than implemented alignment of %d",rounded);
 #endif
 
       asm_emit_uninitialised (decl, name, size, rounded);
@@ -1666,7 +1662,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
 
   /* Output any data that we will need to use the address of.  */
   if (DECL_INITIAL (decl) == error_mark_node)
-    reloc = contains_pointers_p (TREE_TYPE (decl));
+    reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0;
   else if (DECL_INITIAL (decl))
     reloc = output_addressed_constants (DECL_INITIAL (decl));
 
@@ -1680,8 +1676,10 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
 
   /* Output the alignment of this data.  */
   if (align > BITS_PER_UNIT)
-    ASM_OUTPUT_ALIGN (asm_out_file,
-                     floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT));
+    {
+      ASM_OUTPUT_ALIGN (asm_out_file,
+                       floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT));
+    }
 
   /* Do any machine/system dependent processing of the object.  */
 #ifdef ASM_DECLARE_OBJECT_NAME
@@ -1793,7 +1791,7 @@ assemble_external_libcall (fun)
 
 void
 assemble_global (name)
-     const char *name;
+     const char *name ATTRIBUTE_UNUSED;
 {
   ASM_GLOBALIZE_LABEL (asm_out_file, name);
 }
@@ -1822,9 +1820,6 @@ assemble_name (file, name)
   tree id;
 
   STRIP_NAME_ENCODING (real_name, name);
-  if (flag_prefix_function_name
-      && ! memcmp (real_name, CHKR_PREFIX, CHKR_PREFIX_SIZE))
-    real_name = real_name + CHKR_PREFIX_SIZE;
 
   id = maybe_get_identifier (real_name);
   if (id)
@@ -1903,7 +1898,9 @@ assemble_trampoline_template ()
   /* Write the assembler code to define one.  */
   align = floor_log2 (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
   if (align > 0)
-    ASM_OUTPUT_ALIGN (asm_out_file, align);
+    {
+      ASM_OUTPUT_ALIGN (asm_out_file, align);
+    }
 
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LTRAMP", 0);
   TRAMPOLINE_TEMPLATE (asm_out_file);
@@ -2170,7 +2167,7 @@ immed_double_const (i0, i1, mode)
      HOST_WIDE_INT i0, i1;
      enum machine_mode mode;
 {
-  register rtx r;
+  rtx r;
 
   if (GET_MODE_CLASS (mode) == MODE_INT
       || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
@@ -2241,7 +2238,7 @@ immed_double_const (i0, i1, mode)
        return r;
 
   /* No; make a new one and add it to the chain.  */
-  r = gen_rtx_CONST_DOUBLE (mode, const0_rtx, i0, i1);
+  r = gen_rtx_CONST_DOUBLE (mode, i0, i1);
 
   /* Don't touch const_double_chain if not inside any function.  */
   if (current_function_decl != 0)
@@ -2262,23 +2259,23 @@ immed_real_const_1 (d, mode)
      enum machine_mode mode;
 {
   union real_extract u;
-  register rtx r;
+  rtx r;
 
   /* Get the desired `double' value as a sequence of ints
      since that is how they are stored in a CONST_DOUBLE.  */
 
   u.d = d;
 
-  /* Detect special cases.  */
-  if (REAL_VALUES_IDENTICAL (dconst0, d))
+  /* Detect special cases.  Check for NaN first, because some ports
+     (specifically the i386) do not emit correct ieee-fp code by default, and
+     thus will generate a core dump here if we pass a NaN to REAL_VALUES_EQUAL
+     and if REAL_VALUES_EQUAL does a floating point comparison.  */
+  if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_IDENTICAL (dconst0, d))
     return CONST0_RTX (mode);
-
-  /* Check for NaN first, because some ports (specifically the i386) do not
-     emit correct ieee-fp code by default, and thus will generate a core
-     dump here if we pass a NaN to REAL_VALUES_EQUAL and if REAL_VALUES_EQUAL
-     does a floating point comparison.  */
   else if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst1, d))
     return CONST1_RTX (mode);
+  else if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst2, d))
+    return CONST2_RTX (mode);
 
   if (sizeof u == sizeof (HOST_WIDE_INT))
     return immed_double_const (u.i[0], 0, mode);
@@ -2317,12 +2314,6 @@ immed_real_const_1 (d, mode)
   else
     CONST_DOUBLE_CHAIN (r) = NULL_RTX;
 
-  /* Store const0_rtx in CONST_DOUBLE_MEM since this CONST_DOUBLE is on the
-     chain, but has not been allocated memory.  Actual use of CONST_DOUBLE_MEM
-     is only through force_const_mem.  */
-
-  CONST_DOUBLE_MEM (r) = const0_rtx;
-
   return r;
 }
 
@@ -2343,26 +2334,14 @@ immed_real_const (exp)
 void
 clear_const_double_mem ()
 {
-  register rtx r, next;
-  enum machine_mode mode;
-  int i;
+  rtx r, next;
 
   for (r = const_double_chain; r; r = next)
     {
       next = CONST_DOUBLE_CHAIN (r);
       CONST_DOUBLE_CHAIN (r) = 0;
-      CONST_DOUBLE_MEM (r) = cc0_rtx;
     }
   const_double_chain = 0;
-
-  for (i = 0; i <= 2; i++)
-    for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
-         mode = GET_MODE_WIDER_MODE (mode))
-      {
-       r = const_tiny_rtx[i][(int) mode];
-       CONST_DOUBLE_CHAIN (r) = 0;
-       CONST_DOUBLE_MEM (r) = cc0_rtx;
-      }
 }
 \f
 /* Given an expression EXP with a constant value,
@@ -2381,9 +2360,9 @@ decode_addr_const (exp, value)
      tree exp;
      struct addr_const *value;
 {
-  register tree target = TREE_OPERAND (exp, 0);
-  register int offset = 0;
-  register rtx x;
+  tree target = TREE_OPERAND (exp, 0);
+  int offset = 0;
+  rtx x;
 
   while (1)
     {
@@ -2480,6 +2459,11 @@ struct constant_descriptor
 #define MAX_HASH_TABLE 1009
 static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE];
 
+/* We maintain a hash table of STRING_CST values.  Unless we are asked to force
+   out a string constant, we defer output of the constants until we know
+   they are actually used.  This will be if something takes its address or if
+   there is a usage of the string in the RTL of a function.  */
+
 #define STRHASH(x) ((hashval_t)((long)(x) >> 3))
 
 struct deferred_string
@@ -2564,9 +2548,9 @@ static int
 const_hash (exp)
      tree exp;
 {
-  register const char *p;
-  register int len, hi, i;
-  register enum tree_code code = TREE_CODE (exp);
+  const char *p;
+  int len, hi, i;
+  enum tree_code code = TREE_CODE (exp);
 
   /* Either set P and LEN to the address and len of something to hash and
      exit the switch or return a value.  */
@@ -2605,7 +2589,7 @@ const_hash (exp)
        }
       else
        {
-         register tree link;
+         tree link;
 
          /* For record type, include the type in the hashing.
             We do not do so for array types
@@ -2702,9 +2686,9 @@ compare_constant_1 (exp, p)
      tree exp;
      const unsigned char *p;
 {
-  register const unsigned char *strp;
-  register int len;
-  register enum tree_code code = TREE_CODE (exp);
+  const unsigned char *strp;
+  int len;
+  enum tree_code code = TREE_CODE (exp);
 
   if (code != (enum tree_code) *p++)
     return 0;
@@ -2742,7 +2726,7 @@ compare_constant_1 (exp, p)
       strp = (const unsigned char *)TREE_STRING_POINTER (exp);
       len = TREE_STRING_LENGTH (exp);
       if (memcmp ((char *) &TREE_STRING_LENGTH (exp), p,
-               sizeof TREE_STRING_LENGTH (exp)))
+                 sizeof TREE_STRING_LENGTH (exp)))
        return 0;
 
       p += sizeof TREE_STRING_LENGTH (exp);
@@ -2771,7 +2755,7 @@ compare_constant_1 (exp, p)
        }
       else
        {
-         register tree link;
+         tree link;
          int length = list_length (CONSTRUCTOR_ELTS (exp));
          tree type;
          enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
@@ -2902,12 +2886,14 @@ compare_constant_1 (exp, p)
       return compare_constant_1 (TREE_OPERAND (exp, 0), p);
 
     default:
-      if (lang_expand_constant)
-        {
-          exp = (*lang_expand_constant) (exp);
-          return compare_constant_1 (exp, p);
-        }
-      return 0;
+      {
+       tree new = (*lang_hooks.expand_constant) (exp);
+
+       if (new != exp)
+          return compare_constant_1 (new, p);
+       else
+         return 0;
+      }
     }
 
   /* Compare constant contents.  */
@@ -2957,9 +2943,9 @@ static void
 record_constant_1 (exp)
      tree exp;
 {
-  register const unsigned char *strp;
-  register int len;
-  register enum tree_code code = TREE_CODE (exp);
+  const unsigned char *strp;
+  int len;
+  enum tree_code code = TREE_CODE (exp);
 
   obstack_1grow (&permanent_obstack, (unsigned int) code);
 
@@ -3006,7 +2992,7 @@ record_constant_1 (exp)
        }
       else
        {
-         register tree link;
+         tree link;
          int length = list_length (CONSTRUCTOR_ELTS (exp));
          enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
          tree type;
@@ -3114,12 +3100,13 @@ record_constant_1 (exp)
       return;
 
     default:
-      if (lang_expand_constant)
-        {
-          exp = (*lang_expand_constant) (exp);
+      {
+       tree new = (*lang_hooks.expand_constant) (exp);
+
+       if (new != exp)
           record_constant_1 (exp);
-        }
-      return;
+       return;
+      }
     }
 
   /* Record constant contents.  */
@@ -3276,16 +3263,20 @@ output_constant_def (exp, defer)
      tree exp;
      int defer;
 {
-  register int hash;
-  register struct constant_descriptor *desc;
+  int hash;
+  struct constant_descriptor *desc;
   struct deferred_string **defstr;
   char label[256];
   int reloc;
   int found = 1;
   int after_function = 0;
   int labelno = -1;
+  rtx rtl;
 
-  if (TREE_CST_RTL (exp))
+  /* We can't just use the saved RTL if this is a defererred string constant
+     and we are not to defer anymode.  */
+  if (TREE_CODE (exp) != INTEGER_CST && TREE_CST_RTL (exp)
+      && (defer || !STRING_POOL_ADDRESS_P (XEXP (TREE_CST_RTL (exp), 0))))
     return TREE_CST_RTL (exp);
 
   /* Make sure any other constants whose addresses appear in EXP
@@ -3320,16 +3311,21 @@ output_constant_def (exp, defer)
       const_hash_table[hash] = desc;
 
       /* We have a symbol name; construct the SYMBOL_REF and the MEM.  */
-      desc->rtl
+      rtl = desc->rtl
        = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
                       gen_rtx_SYMBOL_REF (Pmode, desc->label));
 
-      set_mem_attributes (desc->rtl, exp, 1);
+      set_mem_attributes (rtl, exp, 1);
+      set_mem_alias_set (rtl, 0);
+      set_mem_alias_set (rtl, const_alias_set);
 
       found = 0;
     }
+  else
+    rtl = desc->rtl;
 
-  TREE_CST_RTL (exp) = desc->rtl;
+  if (TREE_CODE (exp) != INTEGER_CST)
+    TREE_CST_RTL (exp) = rtl;
 
   /* Optionally set flags or add text to the name to record information
      such as that it is a function name.  If the name is changed, the macro
@@ -3340,7 +3336,7 @@ output_constant_def (exp, defer)
   if (! found)
     {
       ENCODE_SECTION_INFO (exp);
-      desc->rtl = TREE_CST_RTL (exp);
+      desc->rtl = rtl;
       desc->label = XSTR (XEXP (desc->rtl, 0), 0);
     }
 #endif
@@ -3352,7 +3348,7 @@ output_constant_def (exp, defer)
 #endif
 
   if (found
-      && STRING_POOL_ADDRESS_P (XEXP (desc->rtl, 0))
+      && STRING_POOL_ADDRESS_P (XEXP (rtl, 0))
       && (!defer || defer_addressed_constants_flag || after_function))
     {
       defstr = (struct deferred_string **)
@@ -3364,7 +3360,7 @@ output_constant_def (exp, defer)
             remove it from deferred string hash table.  */
          found = 0;
          labelno = (*defstr)->labelno;
-         STRING_POOL_ADDRESS_P (XEXP (desc->rtl, 0)) = 0;
+         STRING_POOL_ADDRESS_P (XEXP (rtl, 0)) = 0;
          htab_clear_slot (const_str_htab, (void **) defstr);
        }
     }
@@ -3375,8 +3371,9 @@ output_constant_def (exp, defer)
     {
       if (defer_addressed_constants_flag || after_function)
        {
-         struct deferred_constant *p;
-         p = (struct deferred_constant *) xmalloc (sizeof (struct deferred_constant));
+         struct deferred_constant *p
+           = (struct deferred_constant *)
+             xmalloc (sizeof (struct deferred_constant));
 
          p->exp = copy_constant (exp);
          p->reloc = reloc;
@@ -3417,13 +3414,13 @@ output_constant_def (exp, defer)
                  p->label = desc->label;
                  p->labelno = labelno;
                  *defstr = p;
-                 STRING_POOL_ADDRESS_P (XEXP (desc->rtl, 0)) = 1;
+                 STRING_POOL_ADDRESS_P (XEXP (rtl, 0)) = 1;
                }
            }
        }
     }
 
-  return TREE_CST_RTL (exp);
+  return rtl;
 }
 
 /* Now output assembler code to define the label for EXP,
@@ -3460,7 +3457,9 @@ output_constant_def_contents (exp, reloc, labelno)
     }
 
   if (align > BITS_PER_UNIT)
-    ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
+    {
+      ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
+    }
 
   /* Output the label itself.  */
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", labelno);
@@ -3484,12 +3483,11 @@ struct pool_constant
 {
   struct constant_descriptor *desc;
   struct pool_constant *next, *next_sym;
-  const char *label;
   rtx constant;
   enum machine_mode mode;
   int labelno;
-  int align;
-  int offset;
+  unsigned int align;
+  HOST_WIDE_INT offset;
   int mark;
 };
 
@@ -3520,23 +3518,6 @@ init_varasm_status (f)
   p->x_const_double_chain = 0;
 }
 
-/* Nested functions diddle with our const_double_chain via
-   clear_const_double_mem and const_tiny_rtx.  Remove these
-   entries from our const_double_chain.  */
-
-void
-restore_varasm_status (f)
-     struct function *f;
-{
-  rtx *p = &f->varasm->x_const_double_chain;
-
-  while (*p)
-    if (CONST_DOUBLE_MEM (*p) == cc0_rtx)
-      *p = CONST_DOUBLE_CHAIN (*p);
-    else
-      p = &CONST_DOUBLE_CHAIN (*p);
-}
-
 /* Mark PC for GC.  */
 
 static void
@@ -3547,6 +3528,7 @@ mark_pool_constant (pc)
     {
       ggc_mark (pc);
       ggc_mark_rtx (pc->constant);
+      ggc_mark_rtx (pc->desc->rtl);
       pc = pc->next;
     }
 }
@@ -3580,19 +3562,22 @@ free_varasm_status (f)
   /* Clear out the hash tables.  */
   for (i = 0; i < MAX_RTX_HASH_TABLE; ++i)
     {
-      struct constant_descriptorcd;
+      struct constant_descriptor *cd;
 
       cd = p->x_const_rtx_hash_table[i];
-      while (cd) {
-       struct constant_descriptor* next = cd->next;
-       free (cd);
-       cd = next;
-      }
+      while (cd)
+       {
+         struct constant_descriptor *next = cd->next;
+
+         free (cd);
+         cd = next;
+       }
     }
 
   free (p->x_const_rtx_hash_table);
   free (p->x_const_rtx_sym_hash_table);
   free (p);
+
   f->varasm = NULL;
 }
 \f
@@ -3705,8 +3690,8 @@ const_hash_rtx (mode, x)
      enum machine_mode mode;
      rtx x;
 {
-  register int hi;
-  register size_t i;
+  int hi;
+  size_t i;
 
   struct rtx_const value;
   decode_rtx_const (mode, x, &value);
@@ -3730,9 +3715,9 @@ compare_constant_rtx (mode, x, desc)
      rtx x;
      struct constant_descriptor *desc;
 {
-  register int *p = (int *) desc->u.contents;
-  register int *strp;
-  register int len;
+  int *p = (int *) desc->u.contents;
+  int *strp;
+  int len;
   struct rtx_const value;
 
   decode_rtx_const (mode, x, &value);
@@ -3765,6 +3750,24 @@ record_constant_rtx (mode, x)
   return ptr;
 }
 \f
+/* Given a constant rtx X, return a MEM for the location in memory at which
+   this constant has been placed.  Return 0 if it not has been placed yet.  */
+
+rtx
+mem_for_const_double (x)
+     rtx x;
+{
+  enum machine_mode mode = GET_MODE (x);
+  struct constant_descriptor *desc;
+
+  for (desc = const_rtx_hash_table[const_hash_rtx (mode, x)]; desc;
+       desc = desc->next)
+    if (compare_constant_rtx (mode, x, desc))
+      return desc->rtl;
+
+  return 0;
+}
+  
 /* Given a constant rtx X, make (or find) a memory constant for its value
    and return a MEM rtx to refer to it in memory.  */
 
@@ -3773,119 +3776,80 @@ force_const_mem (mode, x)
      enum machine_mode mode;
      rtx x;
 {
-  register int hash;
-  register struct constant_descriptor *desc;
+  int hash;
+  struct constant_descriptor *desc;
   char label[256];
-  const char *found = 0;
   rtx def;
-
-  /* If we want this CONST_DOUBLE in the same mode as it is in memory
-     (this will always be true for floating CONST_DOUBLEs that have been
-     placed in memory, but not for VOIDmode (integer) CONST_DOUBLEs),
-     use the previous copy.  Otherwise, make a new one.  Note that in
-     the unlikely event that this same CONST_DOUBLE is used in two different
-     modes in an alternating fashion, we will allocate a lot of different
-     memory locations, but this should be extremely rare.  */
-
-  if (GET_CODE (x) == CONST_DOUBLE
-      && GET_CODE (CONST_DOUBLE_MEM (x)) == MEM
-      && GET_MODE (CONST_DOUBLE_MEM (x)) == mode)
-    return CONST_DOUBLE_MEM (x);
+  struct pool_constant *pool;
+  unsigned int align;
 
   /* Compute hash code of X.  Search the descriptors for that hash code
-     to see if any of them describes X.  If yes, the descriptor records
-     the label number already assigned.  */
-
+     to see if any of them describes X.  If yes, we have an rtx to use.  */
   hash = const_hash_rtx (mode, x);
-
   for (desc = const_rtx_hash_table[hash]; desc; desc = desc->next)
     if (compare_constant_rtx (mode, x, desc))
-      {
-       found = desc->label;
-       break;
-      }
-
-  if (found == 0)
-    {
-      register struct pool_constant *pool;
-      int align;
-
-      /* No constant equal to X is known to have been output.
-        Make a constant descriptor to enter X in the hash table.
-        Assign the label number and record it in the descriptor for
-        future calls to this function to find.  */
-
-      desc = record_constant_rtx (mode, x);
-      desc->next = const_rtx_hash_table[hash];
-      const_rtx_hash_table[hash] = desc;
-
-      /* Align the location counter as required by EXP's data type.  */
-      align = GET_MODE_ALIGNMENT (mode == VOIDmode ? word_mode : mode);
+      return desc->rtl;
+
+  /* No constant equal to X is known to have been output.
+     Make a constant descriptor to enter X in the hash table
+     and make a MEM for it.  */
+  desc = record_constant_rtx (mode, x);
+  desc->next = const_rtx_hash_table[hash];
+  const_rtx_hash_table[hash] = desc;
+  
+  /* Align the location counter as required by EXP's data type.  */
+  align = GET_MODE_ALIGNMENT (mode == VOIDmode ? word_mode : mode);
 #ifdef CONSTANT_ALIGNMENT
-      align = CONSTANT_ALIGNMENT (make_tree (type_for_mode (mode, 0), x),
-                                 align);
+  align = CONSTANT_ALIGNMENT (make_tree (type_for_mode (mode, 0), x), align);
 #endif
 
-      pool_offset += (align / BITS_PER_UNIT) - 1;
-      pool_offset &= ~ ((align / BITS_PER_UNIT) - 1);
-
-      if (GET_CODE (x) == LABEL_REF)
-       LABEL_PRESERVE_P (XEXP (x, 0)) = 1;
-
-      /* Allocate a pool constant descriptor, fill it in, and chain it in.  */
-
-      pool = (struct pool_constant *) ggc_alloc (sizeof (struct pool_constant));
-      pool->desc = desc;
-      pool->constant = x;
-      pool->mode = mode;
-      pool->labelno = const_labelno;
-      pool->align = align;
-      pool->offset = pool_offset;
-      pool->mark = 1;
-      pool->next = 0;
-
-      if (last_pool == 0)
-       first_pool = pool;
-      else
-       last_pool->next = pool;
-
-      last_pool = pool;
-      pool_offset += GET_MODE_SIZE (mode);
-
-      /* Create a string containing the label name, in LABEL.  */
-      ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
-
-      ++const_labelno;
+  pool_offset += (align / BITS_PER_UNIT) - 1;
+  pool_offset &= ~ ((align / BITS_PER_UNIT) - 1);
+
+  if (GET_CODE (x) == LABEL_REF)
+    LABEL_PRESERVE_P (XEXP (x, 0)) = 1;
+
+  /* Allocate a pool constant descriptor, fill it in, and chain it in.  */
+  pool = (struct pool_constant *) ggc_alloc (sizeof (struct pool_constant));
+  pool->desc = desc;
+  pool->constant = x;
+  pool->mode = mode;
+  pool->labelno = const_labelno;
+  pool->align = align;
+  pool->offset = pool_offset;
+  pool->mark = 1;
+  pool->next = 0;
+
+  if (last_pool == 0)
+    first_pool = pool;
+  else
+    last_pool->next = pool;
+  
+  last_pool = pool;
+  pool_offset += GET_MODE_SIZE (mode);
 
-      desc->label = found = ggc_strdup (label);
+  /* Create a string containing the label name, in LABEL.  */
+  ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
 
-      /* Add label to symbol hash table.  */
-      hash = SYMHASH (found);
-      pool->label = found;
-      pool->next_sym = const_rtx_sym_hash_table[hash];
-      const_rtx_sym_hash_table[hash] = pool;
-    }
+  ++const_labelno;
 
-  /* We have a symbol name; construct the SYMBOL_REF and the MEM.  */
+  /* Construct the SYMBOL_REF and the MEM.  */
 
-  def = gen_rtx_MEM (mode, gen_rtx_SYMBOL_REF (Pmode, found));
+  pool->desc->rtl = def
+    = gen_rtx_MEM (mode, gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label)));
+  set_mem_alias_set (def, const_alias_set);
   set_mem_attributes (def, type_for_mode (mode, 0), 1);
   RTX_UNCHANGING_P (def) = 1;
 
+  /* Add label to symbol hash table.  */
+  hash = SYMHASH (XSTR (XEXP (def, 0), 0));
+  pool->next_sym = const_rtx_sym_hash_table[hash];
+  const_rtx_sym_hash_table[hash] = pool;
+
   /* Mark the symbol_ref as belonging to this constants pool.  */
   CONSTANT_POOL_ADDRESS_P (XEXP (def, 0)) = 1;
   current_function_uses_const_pool = 1;
 
-  if (GET_CODE (x) == CONST_DOUBLE)
-    {
-      if (CONST_DOUBLE_MEM (x) == cc0_rtx)
-       {
-         CONST_DOUBLE_CHAIN (x) = const_double_chain;
-         const_double_chain = x;
-       }
-      CONST_DOUBLE_MEM (x) = def;
-    }
-
   return def;
 }
 \f
@@ -3902,7 +3866,7 @@ find_pool_constant (f, addr)
 
   for (pool = f->varasm->x_const_rtx_sym_hash_table[SYMHASH (label)]; pool;
        pool = pool->next_sym)
-    if (pool->label == label)
+    if (XSTR (XEXP (pool->desc->rtl, 0), 0) == label)
       return pool;
 
   abort ();
@@ -4081,7 +4045,7 @@ output_constant_pool (fnname, fndecl)
 static void
 mark_constant_pool ()
 {
-  register rtx insn;
+  rtx insn;
   struct pool_constant *pool;
 
   if (first_pool == 0 && htab_elements (const_str_htab) == 0)
@@ -4110,8 +4074,8 @@ static void
 mark_constants (x)
      rtx x;
 {
-  register int i;
-  register const char *format_ptr;
+  int i;
+  const char *format_ptr;
 
   if (x == 0)
     return;
@@ -4121,10 +4085,6 @@ mark_constants (x)
       mark_constant (&x, NULL);
       return;
     }
-  /* Never search inside a CONST_DOUBLE, because CONST_DOUBLE_MEM may be
-     a MEM, but does not constitute a use of that MEM.  */
-  else if (GET_CODE (x) == CONST_DOUBLE)
-    return;
 
   /* Insns may appear inside a SEQUENCE.  Only check the patterns of
      insns, not any notes that may be attached.  We don't want to mark
@@ -4148,7 +4108,7 @@ mark_constants (x)
        case 'E':
          if (XVEC (x, i) != 0)
            {
-             register int j;
+             int j;
 
              for (j = 0; j < XVECLEN (x, i); j++)
                mark_constants (XVECEXP (x, i, j));
@@ -4172,7 +4132,7 @@ mark_constants (x)
 
 /* Given a SYMBOL_REF CURRENT_RTX, mark it and all constants it refers
    to as used.  Emit referenced deferred strings.  This function can
-   be used with for_each_rtx () to mark all SYMBOL_REFs in an rtx.  */
+   be used with for_each_rtx to mark all SYMBOL_REFs in an rtx.  */
 
 static int
 mark_constant (current_rtx, data)
@@ -4183,10 +4143,7 @@ mark_constant (current_rtx, data)
 
   if (x == NULL_RTX)
     return 0;
-  else if (GET_CODE(x) == CONST_DOUBLE)
-    /* Never search inside a CONST_DOUBLE because CONST_DOUBLE_MEM may
-       be a MEM but does not constitute a use of that MEM.  */
-    return -1;
+
   else if (GET_CODE (x) == SYMBOL_REF)
     {
       if (CONSTANT_POOL_ADDRESS_P (x))
@@ -4228,30 +4185,30 @@ output_addressed_constants (exp)
      tree exp;
 {
   int reloc = 0;
+  tree tem;
 
   /* Give the front-end a chance to convert VALUE to something that
      looks more like a constant to the back-end.  */
-  if (lang_expand_constant)
-    exp = (*lang_expand_constant) (exp);
+  exp = (*lang_hooks.expand_constant) (exp);
 
   switch (TREE_CODE (exp))
     {
     case ADDR_EXPR:
-      {
-       register tree constant = TREE_OPERAND (exp, 0);
-
-       while (TREE_CODE (constant) == COMPONENT_REF)
-         {
-           constant = TREE_OPERAND (constant, 0);
-         }
-
-       if (TREE_CODE_CLASS (TREE_CODE (constant)) == 'c'
-           || TREE_CODE (constant) == CONSTRUCTOR)
-         /* No need to do anything here
-            for addresses of variables or functions.  */
-         output_constant_def (constant, 0);
-      }
-      reloc = 1;
+      /* Go inside any operations that get_inner_reference can handle and see
+        if what's inside is a constant: no need to do anything here for
+        addresses of variables or functions.  */
+      for (tem = TREE_OPERAND (exp, 0); handled_component_p (tem);
+          tem = TREE_OPERAND (tem, 0))
+       ;
+
+      if (TREE_CODE_CLASS (TREE_CODE (tem)) == 'c'
+           || TREE_CODE (tem) == CONSTRUCTOR)
+         output_constant_def (tem, 0);
+
+      if (TREE_PUBLIC (tem))
+       reloc |= 2;
+      else
+       reloc |= 1;
       break;
 
     case PLUS_EXPR:
@@ -4267,12 +4224,10 @@ output_addressed_constants (exp)
       break;
 
     case CONSTRUCTOR:
-      {
-       register tree link;
-       for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
-         if (TREE_VALUE (link) != 0)
-           reloc |= output_addressed_constants (TREE_VALUE (link));
-      }
+      for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem))
+       if (TREE_VALUE (tem) != 0)
+           reloc |= output_addressed_constants (TREE_VALUE (tem));
+
       break;
 
     default:
@@ -4298,8 +4253,7 @@ initializer_constant_valid_p (value, endtype)
 {
   /* Give the front-end a chance to convert VALUE to something that
      looks more like a constant to the back-end.  */
-  if (lang_expand_constant)
-    value = (*lang_expand_constant) (value);
+  value = (*lang_hooks.expand_constant) (value);
 
   switch (TREE_CODE (value))
     {
@@ -4324,6 +4278,7 @@ initializer_constant_valid_p (value, endtype)
     case FDESC_EXPR:
       return staticp (TREE_OPERAND (value, 0)) ? TREE_OPERAND (value, 0) : 0;
 
+    case VIEW_CONVERT_EXPR:
     case NON_LVALUE_EXPR:
       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
 
@@ -4473,38 +4428,29 @@ initializer_constant_valid_p (value, endtype)
 void
 output_constant (exp, size, align)
      tree exp;
-     int size;
+     HOST_WIDE_INT size;
      unsigned int align;
 {
-  register enum tree_code code = TREE_CODE (TREE_TYPE (exp));
+  enum tree_code code;
+  HOST_WIDE_INT thissize;
 
-  /* Some front-ends use constants other than the standard
-     language-indepdent varieties, but which may still be output
-     directly.  Give the front-end a chance to convert EXP to a
-     language-independent representation.  */
-  if (lang_expand_constant)
-    {
-      exp = (*lang_expand_constant) (exp);
-      code = TREE_CODE (TREE_TYPE (exp));
-    }
+  /* Some front-ends use constants other than the standard language-indepdent
+     varieties, but which may still be output directly.  Give the front-end a
+     chance to convert EXP to a language-independent representation.  */
+  exp = (*lang_hooks.expand_constant) (exp);
 
   if (size == 0 || flag_syntax_only)
     return;
 
-  /* Eliminate the NON_LVALUE_EXPR_EXPR that makes a cast not be an lvalue.
-     That way we get the constant (we hope) inside it.  Also, strip off any
-     NOP_EXPR that converts between two record, union, array, or set types
-     or a CONVERT_EXPR that converts to a union TYPE.  */
-  while ((TREE_CODE (exp) == NOP_EXPR
-         && (TREE_TYPE (exp) == TREE_TYPE (TREE_OPERAND (exp, 0))
-             || AGGREGATE_TYPE_P (TREE_TYPE (exp))))
-        || (TREE_CODE (exp) == CONVERT_EXPR
-            && code == UNION_TYPE)
-        || TREE_CODE (exp) == NON_LVALUE_EXPR)
-    {
-      exp = TREE_OPERAND (exp, 0);
-      code = TREE_CODE (TREE_TYPE (exp));
-    }
+  /* Eliminate any conversions since we'll be outputting the underlying
+     constant.  */
+  while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
+        || TREE_CODE (exp) == NON_LVALUE_EXPR
+        || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
+    exp = TREE_OPERAND (exp, 0);
+
+  code = TREE_CODE (TREE_TYPE (exp));
+  thissize = int_size_in_bytes (TREE_TYPE (exp));
 
   /* Allow a constructor with no elements for any data type.
      This means to fill the space with zeros.  */
@@ -4526,6 +4472,8 @@ output_constant (exp, size, align)
       return;
     }
 
+  /* Now output the underlying data.  If we've handling the padding, return.
+     Otherwise, break and ensure THISSIZE is the size written.  */
   switch (code)
     {
     case CHAR_TYPE:
@@ -4534,16 +4482,10 @@ output_constant (exp, size, align)
     case ENUMERAL_TYPE:
     case POINTER_TYPE:
     case REFERENCE_TYPE:
-      /* ??? What about       (int)((float)(int)&foo + 4)    */
-      while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
-            || TREE_CODE (exp) == NON_LVALUE_EXPR)
-       exp = TREE_OPERAND (exp, 0);
-
       if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
                                           EXPAND_INITIALIZER),
                              size, align, 0))
        error ("initializer for integer value is too complicated");
-      size = 0;
       break;
 
     case REAL_TYPE:
@@ -4553,14 +4495,12 @@ output_constant (exp, size, align)
       assemble_real (TREE_REAL_CST (exp),
                     mode_for_size (size * BITS_PER_UNIT, MODE_FLOAT, 0),
                     align);
-      size = 0;
       break;
 
     case COMPLEX_TYPE:
-      output_constant (TREE_REALPART (exp), size / 2, align);
-      output_constant (TREE_IMAGPART (exp), size / 2,
-                      min_align (align, BITS_PER_UNIT * (size / 2)));
-      size -= (size / 2) * 2;
+      output_constant (TREE_REALPART (exp), thissize / 2, align);
+      output_constant (TREE_IMAGPART (exp), thissize / 2,
+                      min_align (align, BITS_PER_UNIT * (thissize / 2)));
       break;
 
     case ARRAY_TYPE:
@@ -4571,16 +4511,8 @@ output_constant (exp, size, align)
        }
       else if (TREE_CODE (exp) == STRING_CST)
        {
-         int excess = 0;
-
-         if (size > TREE_STRING_LENGTH (exp))
-           {
-             excess = size - TREE_STRING_LENGTH (exp);
-             size = TREE_STRING_LENGTH (exp);
-           }
-
-         assemble_string (TREE_STRING_POINTER (exp), size);
-         size = excess;
+         thissize = MIN (TREE_STRING_LENGTH (exp), size);
+         assemble_string (TREE_STRING_POINTER (exp), thissize);
        }
       else
        abort ();
@@ -4598,22 +4530,26 @@ output_constant (exp, size, align)
       if (TREE_CODE (exp) == INTEGER_CST)
        assemble_integer (expand_expr (exp, NULL_RTX,
                                       VOIDmode, EXPAND_INITIALIZER),
-                         size, align, 1);
+                        thissize, align, 1);
       else if (TREE_CODE (exp) == CONSTRUCTOR)
        {
-         unsigned char *buffer = (unsigned char *) alloca (size);
-         if (get_set_constructor_bytes (exp, buffer, size))
+         unsigned char *buffer = (unsigned char *) alloca (thissize);
+         if (get_set_constructor_bytes (exp, buffer, thissize))
            abort ();
-         assemble_string ((char *) buffer, size);
+         assemble_string ((char *) buffer, thissize);
        }
       else
        error ("unknown set constructor type");
       return;
 
+    case ERROR_MARK:
+      return;
+
     default:
-      break; /* ??? */
+      abort ();
     }
 
+  size -= thissize;
   if (size > 0)
     assemble_zeros (size);
 }
@@ -4629,13 +4565,12 @@ array_size_for_constructor (val)
 {
   tree max_index, i;
 
+  /* This code used to attempt to handle string constants that are not
+     arrays of single-bytes, but nothing else does, so there's no point in
+     doing it here.  */
   if (TREE_CODE (val) == STRING_CST)
-    {
-      HOST_WIDE_INT len = TREE_STRING_LENGTH(val);
-      HOST_WIDE_INT esz = int_size_in_bytes (TREE_TYPE (TREE_TYPE (val)));
-      HOST_WIDE_INT tsz = len * esz;
-      return tsz;
-    }
+    return TREE_STRING_LENGTH (val);
+
   max_index = NULL_TREE;
   for (i = CONSTRUCTOR_ELTS (val); i ; i = TREE_CHAIN (i))
     {
@@ -4668,18 +4603,18 @@ array_size_for_constructor (val)
 static void
 output_constructor (exp, size, align)
      tree exp;
-     int size;
+     HOST_WIDE_INT size;
      unsigned int align;
 {
   tree type = TREE_TYPE (exp);
-  register tree link, field = 0;
+  tree link, field = 0;
   tree min_index = 0;
   /* Number of bytes output or skipped so far.
      In other words, current position within the constructor.  */
   HOST_WIDE_INT total_bytes = 0;
   /* Non-zero means BYTE contains part of a byte, to be output.  */
   int byte_buffer_in_use = 0;
-  register int byte = 0;
+  int byte = 0;
 
   if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT)
     abort ();
@@ -4760,7 +4695,7 @@ output_constructor (exp, size, align)
          /* Output any buffered-up bit-fields preceding this element.  */
          if (byte_buffer_in_use)
            {
-             ASM_OUTPUT_BYTE (asm_out_file, byte);
+             assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
              total_bytes++;
              byte_buffer_in_use = 0;
            }
@@ -4838,7 +4773,7 @@ output_constructor (exp, size, align)
              /* Output remnant of any bit field in previous bytes.  */
              if (byte_buffer_in_use)
                {
-                 ASM_OUTPUT_BYTE (asm_out_file, byte);
+                 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
                  total_bytes++;
                  byte_buffer_in_use = 0;
                }
@@ -4874,7 +4809,7 @@ output_constructor (exp, size, align)
                 within this element when necessary.  */
              while (next_byte != total_bytes)
                {
-                 ASM_OUTPUT_BYTE (asm_out_file, byte);
+                 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
                  total_bytes++;
                  byte = 0;
                }
@@ -4960,7 +4895,7 @@ output_constructor (exp, size, align)
 
   if (byte_buffer_in_use)
     {
-      ASM_OUTPUT_BYTE (asm_out_file, byte);
+      assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
       total_bytes++;
     }
 
@@ -5047,6 +4982,7 @@ weak_finish ()
 /* Remove NAME from the pending list of weak symbols.  This prevents
    the compiler from emitting multiple .weak directives which confuses
    some assemblers.  */
+#ifdef ASM_WEAKEN_LABEL
 static void
 remove_from_pending_weak_list (name)
      const char *name;
@@ -5066,6 +5002,7 @@ remove_from_pending_weak_list (name)
         p = &(t->next);
     }
 }
+#endif /* ASM_WEAKEN_LABEL */
 
 /* Emit an assembler directive to make the symbol for DECL an alias to
    the symbol for TARGET.  */
@@ -5173,6 +5110,8 @@ init_varasm_once ()
                mark_const_hash_entry);
   ggc_add_root (&const_str_htab, 1, sizeof const_str_htab,
                mark_const_str_htab);
+
+  const_alias_set = new_alias_set ();
 }
 
 /* Select a set of attributes for section NAME based on the properties
@@ -5297,3 +5236,32 @@ default_pe_asm_named_section (name, flags)
               (flags & SECTION_CODE ? "discard" : "same_size"));
     }
 }
+\f
+/* Used for vtable gc in GNU binutils.  Record that the pointer at OFFSET
+   from SYMBOL is used in all classes derived from SYMBOL.  */
+
+void
+assemble_vtable_entry (symbol, offset)
+     rtx symbol;
+     HOST_WIDE_INT offset;
+{
+  fputs ("\t.vtable_entry ", asm_out_file);
+  output_addr_const (asm_out_file, symbol);
+  fputs (", ", asm_out_file);
+  fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, offset);
+  fputc ('\n', asm_out_file);
+}
+
+/* Used for vtable gc in GNU binutils.  Record the class hierarchy by noting
+   that the vtable symbol CHILD is derived from the vtable symbol PARENT.  */
+
+void
+assemble_vtable_inherit (child, parent)
+     rtx child, parent;
+{
+  fputs ("\t.vtable_inherit ", asm_out_file);
+  output_addr_const (asm_out_file, child);
+  fputs (", ", asm_out_file);
+  output_addr_const (asm_out_file, parent);
+  fputc ('\n', asm_out_file);
+}