OSDN Git Service

Remove CYGNUS LOCAL tags.
[pf3gnuchains/gcc-fork.git] / gcc / varasm.c
index 3ef8644..5702646 100644 (file)
@@ -1,5 +1,5 @@
 /* Output variables, constants and external declarations, for GNU compiler.
-   Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 89, 92-5, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +15,8 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 /* This file handles generation of all the assembler code
@@ -42,6 +43,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "bytecode.h"
 
 #include "obstack.h"
+#include "c-pragma.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"
@@ -96,7 +98,22 @@ int size_directive_output;
 
 tree last_assemble_variable_decl;
 
+
+#ifdef HANDLE_PRAGMA_WEAK
+/* Any weak symbol declarations waiting to be emitted.  */
+
+struct weak_syms
+{
+  struct weak_syms *next;
+  char *name;
+  char *value;
+};
+
+static struct weak_syms *weak_decls;
+#endif
+
 /* Nonzero if at least one function definition has been seen.  */
+
 static int function_defined;
 
 struct addr_const;
@@ -129,13 +146,14 @@ static int output_addressed_constants     PROTO((tree));
 static void bc_assemble_integer                PROTO((tree, int));
 static void output_constructor         PROTO((tree, int));
 \f
+static enum in_section { no_section, in_text, in_data, in_named
+#ifdef BSS_SECTION_ASM_OP
+  , in_bss
+#endif
 #ifdef EXTRA_SECTIONS
-static enum in_section {no_section, in_text, in_data, in_named, EXTRA_SECTIONS} in_section
-  = no_section;
-#else
-static enum in_section {no_section, in_text, in_data, in_named} in_section
-  = no_section;
+  , EXTRA_SECTIONS
 #endif
+} in_section = no_section;
 
 /* Return a non-zero value if DECL has a section attribute.  */
 #define IN_NAMED_SECTION(DECL) \
@@ -214,6 +232,14 @@ in_text_section ()
   return in_section == in_text;
 }
 
+/* Determine if we're in the data section. */
+
+int
+in_data_section ()
+{
+  return in_section == in_data;
+}
+
 /* Tell assembler to change to section NAME for DECL.
    If DECL is NULL, just switch to section NAME.
    If NAME is NULL, get the name from DECL.  */
@@ -224,14 +250,15 @@ named_section (decl, name)
      char *name;
 {
   if (decl != NULL_TREE
-      && (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL))
+      && TREE_CODE_CLASS (TREE_CODE (decl)) != 'd')
     abort ();
   if (name == NULL)
     name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
 
   if (in_section != in_named || strcmp (name, in_named_name))
     {
-      in_named_name = name;
+      in_named_name = obstack_alloc (&permanent_obstack, strlen (name) + 1);
+      strcpy (in_named_name, name);
       in_section = in_named;
     
 #ifdef ASM_OUTPUT_SECTION_NAME
@@ -245,6 +272,90 @@ named_section (decl, name)
     }
 }
 
+#ifdef BSS_SECTION_ASM_OP
+
+/* Tell the assembler to switch to the bss section.  */
+
+void
+bss_section (decl, name)
+{
+  if (in_section != in_bss)
+    {
+      if (output_bytecode)
+       bc_data ();
+      else
+       {
+#ifdef SHARED_BSS_SECTION_ASM_OP
+         if (flag_shared_data)
+           fprintf (asm_out_file, "%s\n", SHARED_BSS_SECTION_ASM_OP);
+         else
+#endif
+           fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP);
+       }
+
+      in_section = in_bss;
+    }
+}
+
+#ifdef ASM_OUTPUT_BSS
+
+/* Utility function for ASM_OUTPUT_BSS for targets to use if
+   they don't support alignments in .bss.
+   ??? It is believed that this function will work in most cases so such
+   support is localized here.  */
+
+static void
+asm_output_bss (file, decl, name, size, rounded)
+     FILE *file;
+     tree decl;
+     char *name;
+     int size, rounded;
+{
+  ASM_GLOBALIZE_LABEL (file, name);
+  bss_section ();
+#ifdef ASM_DECLARE_OBJECT_NAME
+  last_assemble_variable_decl = decl;
+  ASM_DECLARE_OBJECT_NAME (file, name, decl);
+#else
+  /* Standard thing is just output label for the object.  */
+  ASM_OUTPUT_LABEL (file, name);
+#endif /* ASM_DECLARE_OBJECT_NAME */
+  ASM_OUTPUT_SKIP (file, rounded);
+}
+
+#endif
+
+#ifdef ASM_OUTPUT_ALIGNED_BSS
+
+/* Utility function for targets to use in implementing
+   ASM_OUTPUT_ALIGNED_BSS.
+   ??? It is believed that this function will work in most cases so such
+   support is localized here.  */
+
+static void
+asm_output_aligned_bss (file, decl, name, size, align)
+     FILE *file;
+     tree decl;
+     char *name;
+     int size, align;
+{
+  ASM_GLOBALIZE_LABEL (file, name);
+  bss_section ();
+  ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
+#ifdef ASM_DECLARE_OBJECT_NAME
+  last_assemble_variable_decl = decl;
+  ASM_DECLARE_OBJECT_NAME (file, name, decl);
+#else
+  /* Standard thing is just output label for the object.  */
+  ASM_OUTPUT_LABEL (file, name);
+#endif /* ASM_DECLARE_OBJECT_NAME */
+  ASM_OUTPUT_SKIP (file, size);
+}
+
+#endif
+
+#endif /* BSS_SECTION_ASM_OP */
+
 /* Switch to the section for function DECL.
 
    If DECL is NULL_TREE, switch to the text section.
@@ -258,8 +369,50 @@ function_section (decl)
   if (decl != NULL_TREE
       && DECL_SECTION_NAME (decl) != NULL_TREE)
     named_section (decl, (char *) 0);
- else
-   text_section ();
+  else
+    text_section ();
+}
+
+/* Switch to section for variable DECL.
+
+   RELOC is the `reloc' argument to SELECT_SECTION.  */
+
+void
+variable_section (decl, reloc)
+     tree decl;
+     int reloc;
+{
+  if (IN_NAMED_SECTION (decl))
+    named_section (decl, NULL);
+  else
+    {
+      /* C++ can have const variables that get initialized from constructors,
+        and thus can not be in a readonly section.  We prevent this by
+        verifying that the initial value is constant for objects put in a
+        readonly section.
+
+        error_mark_node is used by the C front end to indicate that the
+        initializer has not been seen yet.  In this case, we assume that
+        the initializer must be constant.
+
+        C++ uses error_mark_node for variables that have complicated
+        initializers, but these variables go in BSS so we won't be called
+        for them.  */
+
+#ifdef SELECT_SECTION
+      SELECT_SECTION (decl, reloc);
+#else
+      if (TREE_READONLY (decl)
+         && ! TREE_THIS_VOLATILE (decl)
+         && DECL_INITIAL (decl)
+         && (DECL_INITIAL (decl) == error_mark_node
+             || TREE_CONSTANT (DECL_INITIAL (decl)))
+         && ! (flag_pic && reloc))
+       readonly_data_section ();
+      else
+       data_section ();
+#endif
+    }
 }
 \f
 /* Create the rtl to represent a function, for a function definition.
@@ -331,9 +484,7 @@ bc_make_decl_rtl (decl, asmspec, top_level)
   if (DECL_RTL (decl) == 0)
     {
       /* Print an error message for register variables.  */
-      if (DECL_REGISTER (decl) && TREE_CODE (decl) == FUNCTION_DECL)
-       error ("function declared `register'");
-      else if (DECL_REGISTER (decl))
+      if (DECL_REGISTER (decl))
        error ("global register variables not supported in the interpreter");
 
       /* Handle ordinary static variables and functions.  */
@@ -475,30 +626,34 @@ make_decl_rtl (decl, asmspec, top_level)
       DECL_RTL (decl) = 0;
 
       /* First detect errors in declaring global registers.  */
-      if (DECL_REGISTER (decl) && reg_number == -1)
+      if (TREE_CODE (decl) != FUNCTION_DECL
+         && DECL_REGISTER (decl) && reg_number == -1)
        error_with_decl (decl,
                         "register name not specified for `%s'");
-      else if (DECL_REGISTER (decl) && reg_number < 0)
+      else if (TREE_CODE (decl) != FUNCTION_DECL
+              && DECL_REGISTER (decl) && reg_number < 0)
        error_with_decl (decl,
                         "invalid register name for `%s'");
-      else if ((reg_number >= 0 || reg_number == -3) && ! DECL_REGISTER (decl))
+      else if ((reg_number >= 0 || reg_number == -3)
+              && (TREE_CODE (decl) == FUNCTION_DECL
+                  && ! DECL_REGISTER (decl)))
        error_with_decl (decl,
                         "register name given for non-register variable `%s'");
-      else if (DECL_REGISTER (decl) && TREE_CODE (decl) == FUNCTION_DECL)
-       error ("function declared `register'");
-      else if (DECL_REGISTER (decl) && TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
-       error_with_decl (decl, "data type of `%s' isn't suitable for a register");
-      else if (DECL_REGISTER (decl)
-              && ! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl))))
-       error_with_decl (decl, "register number for `%s' isn't suitable for the data type");
+      else if (TREE_CODE (decl) != FUNCTION_DECL
+              && DECL_REGISTER (decl)
+              && TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
+       error_with_decl (decl,
+                        "data type of `%s' isn't suitable for a register");
+      else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl)
+              && ! HARD_REGNO_MODE_OK (reg_number,
+                                       TYPE_MODE (TREE_TYPE (decl))))
+       error_with_decl (decl,
+                        "register number for `%s' isn't suitable for data type");
       /* Now handle properly declared static register variables.  */
-      else if (DECL_REGISTER (decl))
+      else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
        {
          int nregs;
-#if 0 /* yylex should print the warning for this */
-         if (pedantic)
-           pedwarn ("ANSI C forbids global register variables");
-#endif
+
          if (DECL_INITIAL (decl) != 0 && top_level)
            {
              DECL_INITIAL (decl) = 0;
@@ -538,7 +693,8 @@ make_decl_rtl (decl, asmspec, top_level)
         unit that behaved thusly).  So warn the user.  */
       else if (TREE_CODE (decl) == VAR_DECL
               && DECL_SECTION_NAME (decl) != NULL_TREE
-              && DECL_INITIAL (decl) == NULL_TREE)
+              && DECL_INITIAL (decl) == NULL_TREE
+              && DECL_COMMON (decl))
        {
          warning_with_decl (decl,
                             "section attribute ignored for uninitialized variable `%s'");
@@ -568,6 +724,7 @@ make_decl_rtl (decl, asmspec, top_level)
 
          DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl),
                                     gen_rtx (SYMBOL_REF, Pmode, name));
+         DECL_ASSEMBLER_NAME (decl) = get_identifier (name);
 
          /* If this variable is to be treated as volatile, show its
             tree node has side effects.  If it has side effects, either
@@ -750,6 +907,23 @@ assemble_start_function (decl, fnname)
 
   output_constant_pool (fnname, decl);
 
+#ifdef ASM_OUTPUT_SECTION_NAME
+  /* If the function is to be put in its own section and it's not in a section
+     already, indicate so.  */
+  if (flag_function_sections
+      && DECL_SECTION_NAME (decl) == NULL_TREE)
+    {
+#ifdef UNIQUE_SECTION
+      DECL_SECTION_NAME(decl) = UNIQUE_SECTION (decl);
+#else
+      char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+      /* Strip off any encoding in name.  */
+      STRIP_NAME_ENCODING (name, name);
+      DECL_SECTION_NAME (decl) = build_string (strlen (name), name);
+#endif
+    }
+#endif
+
   function_section (decl);
 
   /* Tell assembler to move to target machine's alignment for functions.  */
@@ -783,7 +957,19 @@ assemble_start_function (decl, fnname)
   if (TREE_PUBLIC (decl))
     {
       if (!first_global_object_name)
-       STRIP_NAME_ENCODING (first_global_object_name, fnname);
+       {
+         char *p;
+
+         STRIP_NAME_ENCODING (p, fnname);
+         first_global_object_name = permalloc (strlen (p) + 1);
+         strcpy (first_global_object_name, p);
+       }
+
+#ifdef ASM_WEAKEN_LABEL
+      if (DECL_WEAK (decl))
+       ASM_WEAKEN_LABEL (asm_out_file, fnname);
+      else
+#endif
       if (output_bytecode)
        BC_GLOBALIZE_LABEL (asm_out_file, fnname);
       else
@@ -791,15 +977,17 @@ assemble_start_function (decl, fnname)
     }
 
   /* Do any machine/system dependent processing of the function name */
-#ifdef ASM_DECLARE_FUNCTION_NAME
-  ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);
-#else
-  /* Standard thing is just output label for the function.  */
   if (output_bytecode)
     BC_OUTPUT_LABEL (asm_out_file, fnname);
   else
-    ASM_OUTPUT_LABEL (asm_out_file, fnname);
+    {
+#ifdef ASM_DECLARE_FUNCTION_NAME
+      ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);
+#else
+      /* Standard thing is just output label for the function.  */
+      ASM_OUTPUT_LABEL (asm_out_file, fnname);
 #endif /* ASM_DECLARE_FUNCTION_NAME */
+    }
 }
 
 /* Output assembler code associated with defining the size of the
@@ -990,7 +1178,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
     }
 
   /* Normally no need to say anything here for external references,
-     since assemble_external is called by the langauge-specific code
+     since assemble_external is called by the language-specific code
      when a declaration is first seen.  */
 
   if (DECL_EXTERNAL (decl))
@@ -1031,19 +1219,16 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
 
   TREE_ASM_WRITTEN (decl) = 1;
 
-  /* If storage size is erroneously variable, just continue.
-     Error message was already made.  */
+  app_disable ();
 
-  if (DECL_SIZE (decl))
+  if (! dont_output_data)
     {
       if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
        goto finish;
 
-      app_disable ();
-
       /* This is better than explicit arithmetic, since it avoids overflow.  */
       size_tree = size_binop (CEIL_DIV_EXPR,
-                             DECL_SIZE (decl), size_int (BITS_PER_UNIT));
+                         DECL_SIZE (decl), size_int (BITS_PER_UNIT));
 
       if (TREE_INT_CST_HIGH (size_tree) != 0)
        {
@@ -1056,21 +1241,17 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
 
   /* Handle uninitialized definitions.  */
 
-  /* ANSI specifies that a tentative definition which is not merged with
-     a non-tentative definition behaves exactly like a definition with an
-     initializer equal to zero.  (Section 3.7.2)
-     -fno-common gives strict ANSI behavior.  Usually you don't want it.
-     This matters only for variables with external linkage.  */
-  if ((! flag_no_common || ! TREE_PUBLIC (decl))
-      && DECL_COMMON (decl)
-      && ! dont_output_data
-      && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
+  if ((DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)
+      /* If the target can't output uninitialized but not common global data
+        in .bss, then we have to use .data.  */
+#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
+      && (DECL_COMMON (decl) || ! TREE_PUBLIC (decl))
+#endif
+      && ! dont_output_data)
     {
       int size = TREE_INT_CST_LOW (size_tree);
       int rounded = size;
 
-      if (TREE_INT_CST_HIGH (size_tree) != 0)
-       error_with_decl (decl, "size of variable `%s' is too large");
       /* Don't allocate zero bytes of common,
         since that means "undefined external" in the linker.  */
       if (size == 0) rounded = 1;
@@ -1101,11 +1282,17 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
         while we are doing our final traversal of the chain of file-scope
         declarations.  */
 
-#if 0
+#if 0 /* ??? We should either delete this or add a comment describing what
+        it was intended to do and why we shouldn't delete it.  */
       if (flag_shared_data)
        data_section ();
 #endif
-      if (TREE_PUBLIC (decl))
+
+      if (TREE_PUBLIC (decl)
+#if defined (ASM_OUTPUT_BSS) || defined (ASM_OUTPUT_ALIGNED_BSS)
+         && DECL_COMMON (decl)
+#endif
+         )
        {
 #ifdef ASM_OUTPUT_SHARED_COMMON
          if (flag_shared_data)
@@ -1126,6 +1313,29 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
 #endif
              }
        }
+#if defined (ASM_OUTPUT_BSS) || defined (ASM_OUTPUT_ALIGNED_BSS)
+      else if (TREE_PUBLIC (decl))
+       {
+#ifdef ASM_OUTPUT_SHARED_BSS
+         if (flag_shared_data)
+           ASM_OUTPUT_SHARED_BSS (asm_out_file, decl, name, size, rounded);
+         else
+#endif
+           if (output_bytecode)
+             {
+               BC_OUTPUT_BSS (asm_out_file, name, size, rounded);
+             }
+           else
+             {
+#ifdef ASM_OUTPUT_ALIGNED_BSS
+               ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size,
+                                       DECL_ALIGN (decl));
+#else
+               ASM_OUTPUT_BSS (asm_out_file, decl, name, size, rounded);
+#endif
+             }
+       }
+#endif /* ASM_OUTPUT_BSS || ASM_OUTPUT_ALIGNED_BSS */
       else
        {
 #ifdef ASM_OUTPUT_SHARED_LOCAL
@@ -1150,13 +1360,27 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
       goto finish;
     }
 
-  /* Handle initialized definitions.  */
+  /* Handle initialized definitions.
+     Also handle uninitialized global definitions if -fno-common and the
+     target doesn't support ASM_OUTPUT_BSS.  */
 
   /* First make the assembler name(s) global if appropriate.  */
   if (TREE_PUBLIC (decl) && DECL_NAME (decl))
     {
       if (!first_global_object_name)
-       STRIP_NAME_ENCODING(first_global_object_name, name);
+       {
+         char *p;
+
+         STRIP_NAME_ENCODING (p, name);
+         first_global_object_name = permalloc (strlen (p) + 1);
+         strcpy (first_global_object_name, p);
+       }
+
+#ifdef ASM_WEAKEN_LABEL
+      if (DECL_WEAK (decl))
+       ASM_WEAKEN_LABEL (asm_out_file, name);
+      else
+#endif
       ASM_GLOBALIZE_LABEL (asm_out_file, name);
     }
 #if 0
@@ -1175,33 +1399,8 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
   else if (DECL_INITIAL (decl))
     reloc = output_addressed_constants (DECL_INITIAL (decl));
 
-  /* Switch to the proper section for this data.  */
-  if (IN_NAMED_SECTION (decl))
-    named_section (decl, NULL);
-  else
-    {
-      /* C++ can have const variables that get initialized from constructors,
-        and thus can not be in a readonly section.  We prevent this by
-        verifying that the initial value is constant for objects put in a
-        readonly section.
-
-        error_mark_node is used by the C front end to indicate that the
-        initializer has not been seen yet.  In this case, we assume that
-        the initializer must be constant.  */
-#ifdef SELECT_SECTION
-      SELECT_SECTION (decl, reloc);
-#else
-      if (TREE_READONLY (decl)
-         && ! TREE_THIS_VOLATILE (decl)
-         && DECL_INITIAL (decl)
-         && (DECL_INITIAL (decl) == error_mark_node
-             || TREE_CONSTANT (DECL_INITIAL (decl)))
-         && ! (flag_pic && reloc))
-       readonly_data_section ();
-      else
-       data_section ();
-#endif
-    }
+  /* Switch to the appropriate section.  */
+  variable_section (decl, reloc);
 
   /* dbxout.c needs to know this.  */
   if (in_text_section ())
@@ -1236,22 +1435,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
   /* If the debugging output changed sections, reselect the section
      that's supposed to be selected.  */
   if (in_section != saved_in_section)
-    {
-      /* Switch to the proper section for this data.  */
-#ifdef SELECT_SECTION
-      SELECT_SECTION (decl, reloc);
-#else
-      if (TREE_READONLY (decl)
-         && ! TREE_THIS_VOLATILE (decl)
-         && DECL_INITIAL (decl)
-         && (DECL_INITIAL (decl) == error_mark_node
-             || TREE_CONSTANT (DECL_INITIAL (decl)))
-         && ! (flag_pic && reloc))
-       readonly_data_section ();
-      else
-       data_section ();
-#endif
-    }
+    variable_section (decl, reloc);
 
   /* Compute and output the alignment of this data.  */
 
@@ -1296,26 +1480,27 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
     }
 
   /* Do any machine/system dependent processing of the object.  */
-#ifdef ASM_DECLARE_OBJECT_NAME
-  last_assemble_variable_decl = decl;
-  ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl);
-#else
-  /* Standard thing is just output label for the object.  */
   if (output_bytecode)
     BC_OUTPUT_LABEL (asm_out_file, name);
   else
-    ASM_OUTPUT_LABEL (asm_out_file, name);
+    {
+#ifdef ASM_DECLARE_OBJECT_NAME
+      last_assemble_variable_decl = decl;
+      ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl);
+#else
+      /* Standard thing is just output label for the object.  */
+      ASM_OUTPUT_LABEL (asm_out_file, name);
 #endif /* ASM_DECLARE_OBJECT_NAME */
+    }
 
   if (!dont_output_data)
     {
       if (DECL_INITIAL (decl))
        /* Output the actual data.  */
-       output_constant (DECL_INITIAL (decl),
-                        int_size_in_bytes (TREE_TYPE (decl)));
+       output_constant (DECL_INITIAL (decl), TREE_INT_CST_LOW (size_tree));
       else
        /* Leave space for it.  */
-       assemble_zeros (int_size_in_bytes (TREE_TYPE (decl)));
+       assemble_zeros (TREE_INT_CST_LOW (size_tree));
     }
 
  finish:
@@ -1334,22 +1519,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
       dbxout_symbol (decl, 0);
 
       if (in_section != saved_in_section)
-       {
-         /* Switch to the proper section for this data.  */
-#ifdef SELECT_SECTION
-         SELECT_SECTION (decl, reloc);
-#else
-         if (TREE_READONLY (decl)
-             && ! TREE_THIS_VOLATILE (decl)
-             && DECL_INITIAL (decl)
-             && (DECL_INITIAL (decl) == error_mark_node
-                 || TREE_CONSTANT (DECL_INITIAL (decl)))
-             && ! (flag_pic && reloc))
-           readonly_data_section ();
-         else
-           data_section ();
-#endif
-       }
+       variable_section (decl, reloc);
     }
 #else
   /* There must be a statement after a label.  */
@@ -1523,14 +1693,20 @@ assemble_name (file, name)
      char *name;
 {
   char *real_name;
+  int save_warn_id_clash = warn_id_clash;
 
   STRIP_NAME_ENCODING (real_name, name);
+
+  /* Don't warn about an identifier name length clash on this name, since
+     it can be a user symbol suffixed by a number.  */
+  warn_id_clash = 0;
   TREE_SYMBOL_REFERENCED (get_identifier (real_name)) = 1;
+  warn_id_clash = save_warn_id_clash;
 
   if (name[0] == '*')
     {
       if (output_bytecode)
-       bc_emit_labelref (name);
+       bc_emit_labelref (name, 0);
       else
        fputs (&name[1], file);
     }
@@ -1595,6 +1771,7 @@ assemble_static_space (size)
    This is done at most once per compilation.
    Returns an RTX for the address of the template.  */
 
+#ifdef TRAMPOLINE_TEMPLATE
 rtx
 assemble_trampoline_template ()
 {
@@ -1628,6 +1805,7 @@ assemble_trampoline_template ()
     = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label));
   return gen_rtx (SYMBOL_REF, Pmode, name);
 }
+#endif
 \f
 /* Assemble the integer constant X into an object of SIZE bytes.
    X must be either a CONST_INT or CONST_DOUBLE.
@@ -2282,9 +2460,12 @@ compare_constant_1 (exp, p)
     }
   else if (code == CONSTRUCTOR && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
     {
-      len = int_size_in_bytes (TREE_TYPE (exp));
+      int xlen = len = int_size_in_bytes (TREE_TYPE (exp));
       strp = (char*) alloca (len);
       get_set_constructor_bytes (exp, (unsigned char *) strp, len);
+      if (bcmp ((char *) &xlen, p, sizeof xlen))
+       return 0;
+      p += sizeof xlen;
     }
   else if (code == CONSTRUCTOR)
     {
@@ -2403,102 +2584,112 @@ record_constant_1 (exp)
 
   obstack_1grow (&permanent_obstack, (unsigned int) code);
 
-  if (code == INTEGER_CST)
+  switch (code)
     {
+    case INTEGER_CST:
       obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
       strp = (char *) &TREE_INT_CST_LOW (exp);
       len = 2 * sizeof TREE_INT_CST_LOW (exp);
-    }
-  else if (code == REAL_CST)
-    {
+      break;
+
+    case REAL_CST:
       obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
       strp = (char *) &TREE_REAL_CST (exp);
       len = sizeof TREE_REAL_CST (exp);
-    }
-  else if (code == STRING_CST)
-    {
+      break;
+
+    case STRING_CST:
       if (flag_writable_strings)
        return;
+
       strp = TREE_STRING_POINTER (exp);
       len = TREE_STRING_LENGTH (exp);
       obstack_grow (&permanent_obstack, (char *) &TREE_STRING_LENGTH (exp),
                    sizeof TREE_STRING_LENGTH (exp));
-    }
-  else if (code == COMPLEX_CST)
-    {
+      break;
+
+    case COMPLEX_CST:
       record_constant_1 (TREE_REALPART (exp));
       record_constant_1 (TREE_IMAGPART (exp));
       return;
-    }
-  else if (code == CONSTRUCTOR && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
-    {
-      int nbytes = int_size_in_bytes (TREE_TYPE (exp));
-      obstack_grow (&permanent_obstack, &nbytes, sizeof (nbytes));
-      obstack_blank (&permanent_obstack, nbytes);
-      get_set_constructor_bytes (exp,
-                                (unsigned char *) permanent_obstack.next_free,
-                                nbytes);
-      return;
-    }
-  else if (code == CONSTRUCTOR)
-    {
-      register tree link;
-      int length = list_length (CONSTRUCTOR_ELTS (exp));
-      tree type;
-
-      obstack_grow (&permanent_obstack, (char *) &length, sizeof length);
 
-      /* For record constructors, insist that the types match.
-        For arrays, just verify both constructors are for arrays.  */
-      if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
-       type = TREE_TYPE (exp);
-      else
-       type = 0;
-      obstack_grow (&permanent_obstack, (char *) &type, sizeof type);
-
-      /* For arrays, insist that the size in bytes match.  */
-      if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+    case CONSTRUCTOR:
+      if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
        {
-         int size = int_size_in_bytes (TREE_TYPE (exp));
-         obstack_grow (&permanent_obstack, (char *) &size, sizeof size);
+         int nbytes = int_size_in_bytes (TREE_TYPE (exp));
+         obstack_grow (&permanent_obstack, &nbytes, sizeof (nbytes));
+         obstack_blank (&permanent_obstack, nbytes);
+         get_set_constructor_bytes
+           (exp, (unsigned char *) permanent_obstack.next_free-nbytes,
+            nbytes);
+         return;
        }
-
-      for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
+      else
        {
-         if (TREE_VALUE (link))
-           record_constant_1 (TREE_VALUE (link));
+         register tree link;
+         int length = list_length (CONSTRUCTOR_ELTS (exp));
+         tree type;
+
+         obstack_grow (&permanent_obstack, (char *) &length, sizeof length);
+
+         /* For record constructors, insist that the types match.
+            For arrays, just verify both constructors are for arrays.  */
+         if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
+           type = TREE_TYPE (exp);
          else
+           type = 0;
+         obstack_grow (&permanent_obstack, (char *) &type, sizeof type);
+
+         /* For arrays, insist that the size in bytes match.  */
+         if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
            {
-             tree zero = 0;
+             int size = int_size_in_bytes (TREE_TYPE (exp));
+             obstack_grow (&permanent_obstack, (char *) &size, sizeof size);
+           }
+
+         for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
+           {
+             if (TREE_VALUE (link))
+               record_constant_1 (TREE_VALUE (link));
+             else
+               {
+                 tree zero = 0;
 
-             obstack_grow (&permanent_obstack, (char *) &zero, sizeof zero);
+                 obstack_grow (&permanent_obstack,
+                               (char *) &zero, sizeof zero);
+               }
            }
        }
-
       return;
-    }
-  else if (code == ADDR_EXPR)
-    {
-      struct addr_const value;
-      decode_addr_const (exp, &value);
-      /* Record the offset.  */
-      obstack_grow (&permanent_obstack,
-                   (char *) &value.offset, sizeof value.offset);
-      /* Record the symbol name.  */
-      obstack_grow (&permanent_obstack, XSTR (value.base, 0),
-                   strlen (XSTR (value.base, 0)) + 1);
+
+    case ADDR_EXPR:
+      {
+       struct addr_const value;
+
+       decode_addr_const (exp, &value);
+       /* Record the offset.  */
+       obstack_grow (&permanent_obstack,
+                     (char *) &value.offset, sizeof value.offset);
+       /* Record the symbol name.  */
+       obstack_grow (&permanent_obstack, XSTR (value.base, 0),
+                     strlen (XSTR (value.base, 0)) + 1);
+      }
       return;
-    }
-  else if (code == PLUS_EXPR || code == MINUS_EXPR)
-    {
+
+    case PLUS_EXPR:
+    case MINUS_EXPR:
       record_constant_1 (TREE_OPERAND (exp, 0));
       record_constant_1 (TREE_OPERAND (exp, 1));
       return;
-    }
-  else if (code == NOP_EXPR || code == CONVERT_EXPR)
-    {
+
+    case NOP_EXPR:
+    case CONVERT_EXPR:
+    case NON_LVALUE_EXPR:
       record_constant_1 (TREE_OPERAND (exp, 0));
       return;
+
+    default:
+      abort ();
     }
 
   /* Record constant contents.  */
@@ -2563,12 +2754,18 @@ copy_constant (exp)
 {
   switch (TREE_CODE (exp))
     {
+    case ADDR_EXPR:
+      /* For ADDR_EXPR, we do not want to copy the decl whose address
+        is requested.  We do want to copy constants though.  */
+      if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == 'c')
+       return build1 (TREE_CODE (exp), TREE_TYPE (exp),
+                      copy_constant (TREE_OPERAND (exp, 0)));
+      else
+       return copy_node (exp);
+
     case INTEGER_CST:
     case REAL_CST:
     case STRING_CST:
-    case ADDR_EXPR:
-      /* For ADDR_EXPR, we do not want to copy the decl
-        whose address is requested.  */
       return copy_node (exp);
 
     case COMPLEX_CST:
@@ -2894,6 +3091,7 @@ struct rtx_const
   union {
     union real_extract du;
     struct addr_const addr;
+    struct {HOST_WIDE_INT high, low;} di;
   } un;
 };
 
@@ -2924,9 +3122,16 @@ decode_rtx_const (mode, x, value)
     case CONST_DOUBLE:
       value->kind = RTX_DOUBLE;
       if (GET_MODE (x) != VOIDmode)
-       value->mode = GET_MODE (x);
-      bcopy ((char *) &CONST_DOUBLE_LOW (x),
-            (char *) &value->un.du, sizeof value->un.du);
+       {
+         value->mode = GET_MODE (x);
+         bcopy ((char *) &CONST_DOUBLE_LOW (x),
+                (char *) &value->un.du, sizeof value->un.du);
+       }
+      else
+       {
+         value->un.di.low = CONST_DOUBLE_LOW (x);
+         value->un.di.high = CONST_DOUBLE_HIGH (x);
+       }
       break;
 
     case CONST_INT:
@@ -3522,7 +3727,7 @@ output_constant (exp, size)
          unsigned char *buffer = (unsigned char *) alloca (size);
          if (get_set_constructor_bytes (exp, buffer, size))
            abort ();
-         assemble_string (buffer, size);
+         assemble_string ((char *) buffer, size);
        }
       else
        error ("unknown set constructor type");
@@ -3625,7 +3830,8 @@ bc_assemble_integer (exp, size)
   else
     if (size == 4
        && TREE_CODE (TREE_OPERAND (addr_part, 0)) == VAR_DECL)
-      bc_emit_labelref (DECL_ASSEMBLER_NAME (TREE_OPERAND (addr_part, 0)),
+      bc_emit_labelref (IDENTIFIER_POINTER
+                       (DECL_ASSEMBLER_NAME (TREE_OPERAND (addr_part, 0))),
                        TREE_INT_CST_LOW (const_part));
     else
       abort ();                /* FIXME: there may be more cases.  */
@@ -3898,53 +4104,98 @@ output_constructor (exp, size)
     assemble_zeros (size - total_bytes);
 }
 
-
-#ifdef HANDLE_SYSV_PRAGMA
-
-/* Support #pragma weak by default if WEAK_ASM_OP and ASM_OUTPUT_DEF
-   are defined.  */
-#if defined (WEAK_ASM_OP) && defined (ASM_OUTPUT_DEF)
-
-/* See c-pragma.c for an identical definition.  */
-enum pragma_state
-{
-  ps_start,
-  ps_done,
-  ps_bad,
-  ps_weak,
-  ps_name,
-  ps_equals,
-  ps_value,
-  ps_pack,
-  ps_left,
-  ps_align,
-  ps_right
-};
-
 /* Output asm to handle ``#pragma weak'' */
 void
-handle_pragma_weak (what, asm_out_file, name, value)
+handle_pragma_weak (what, name, value)
      enum pragma_state what;
-     FILE *asm_out_file;
      char *name, *value;
 {
+#ifdef HANDLE_PRAGMA_WEAK
   if (what == ps_name || what == ps_value)
     {
-      fprintf (asm_out_file, "\t%s\t", WEAK_ASM_OP);
+      struct weak_syms *weak =
+       (struct weak_syms *)permalloc (sizeof (struct weak_syms));
+      weak->next = weak_decls;
+      weak->name = permalloc (strlen (name) + 1);
+      strcpy (weak->name, name);
+
+      if (what != ps_value)
+       weak->value = NULL_PTR;
 
-      if (output_bytecode)
-       BC_OUTPUT_LABELREF (asm_out_file, name);
       else
-       ASM_OUTPUT_LABELREF (asm_out_file, name);
+       {
+         weak->value = permalloc (strlen (value) + 1);
+         strcpy (weak->value, value);
+       }
 
-      fputc ('\n', asm_out_file);
-      if (what == ps_value)
-       ASM_OUTPUT_DEF (asm_out_file, name, value);
+      weak_decls = weak;
     }
   else if (! (what == ps_done || what == ps_start))
     warning ("malformed `#pragma weak'");
+#endif /* HANDLE_PRAGMA_WEAK */
+}
+
+/* Declare DECL to be a weak symbol.  */
+
+void
+declare_weak (decl)
+     tree decl;
+{
+  if (! TREE_PUBLIC (decl))
+    error_with_decl (decl, "weak declaration of `%s' must be public");
+  else if (TREE_ASM_WRITTEN (decl))
+    error_with_decl (decl, "weak declaration of `%s' must precede definition");
+  else if (SUPPORTS_WEAK)
+    DECL_WEAK (decl) = 1;
 }
 
-#endif /* HANDLE_PRAGMA_WEAK or (WEAK_ASM_OP and SET_ASM_OP) */
+/* Emit any pending weak declarations.  */
 
-#endif /* WEAK_ASM_OP && ASM_OUTPUT_DEF */
+void
+weak_finish ()
+{
+#ifdef HANDLE_PRAGMA_WEAK
+  if (HANDLE_PRAGMA_WEAK)
+    {
+      struct weak_syms *t;
+      for (t = weak_decls; t; t = t->next)
+       {
+         ASM_WEAKEN_LABEL (asm_out_file, t->name);
+         if (t->value)
+           ASM_OUTPUT_DEF (asm_out_file, t->name, t->value);
+       }
+    }
+#endif
+}
+
+void
+assemble_alias (decl, target)
+     tree decl, target;
+{
+#ifdef ASM_OUTPUT_DEF
+  char *name;
+
+  make_decl_rtl (decl, (char*)0, 1);
+  name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+
+  /* Make name accessible from other files, if appropriate.  */
+
+  if (TREE_PUBLIC (decl))
+    {
+#ifdef ASM_WEAKEN_LABEL
+      if (DECL_WEAK (decl))
+       ASM_WEAKEN_LABEL (asm_out_file, name);
+      else
+#endif
+      if (output_bytecode)
+       BC_GLOBALIZE_LABEL (asm_out_file, name);
+      else
+       ASM_GLOBALIZE_LABEL (asm_out_file, name);
+    }
+
+  ASM_OUTPUT_DEF (asm_out_file, name, IDENTIFIER_POINTER (target));
+  TREE_ASM_WRITTEN (decl) = 1;
+#else
+  warning ("alias definitions not supported in this configuration");
+#endif
+}