]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/varasm.c
c-pragma.h: Define HANDLE_GENERIC_PRAGMAS if REGISTER_TARGET_PRAGMAS is defined.
[gcc.git] / gcc / varasm.c
index d4da6983876b2a96bda10de3cbf4a833424772d1..5a10d65687fdd0b3a2b7788e57a9151a7b621db0 100644 (file)
@@ -1,5 +1,6 @@
 /* Output variables, constants and external declarations, for GNU compiler.
-   Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998, 1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -34,10 +35,10 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "function.h"
 #include "expr.h"
-#include "output.h"
 #include "hard-reg-set.h"
 #include "regs.h"
 #include "defaults.h"
+#include "output.h"
 #include "real.h"
 #include "toplev.h"
 #include "dbxout.h"
@@ -76,8 +77,8 @@ Boston, MA 02111-1307, USA.  */
 extern FILE *asm_out_file;
 
 /* The (assembler) name of the first globally-visible object output.  */
-char *first_global_object_name;
-char *weak_global_object_name;
+const char *first_global_object_name;
+const char *weak_global_object_name;
 
 extern struct obstack *current_obstack;
 extern struct obstack *saveable_obstack;
@@ -120,12 +121,12 @@ struct varasm_status
   rtx x_const_double_chain;
 };
 
-#define const_rtx_hash_table (current_function->varasm->x_const_rtx_hash_table)
-#define const_rtx_sym_hash_table (current_function->varasm->x_const_rtx_sym_hash_table)
-#define first_pool (current_function->varasm->x_first_pool)
-#define last_pool (current_function->varasm->x_last_pool)
-#define pool_offset (current_function->varasm->x_pool_offset)
-#define const_double_chain (current_function->varasm->x_const_double_chain)
+#define const_rtx_hash_table (cfun->varasm->x_const_rtx_hash_table)
+#define const_rtx_sym_hash_table (cfun->varasm->x_const_rtx_sym_hash_table)
+#define first_pool (cfun->varasm->x_first_pool)
+#define last_pool (cfun->varasm->x_last_pool)
+#define pool_offset (cfun->varasm->x_pool_offset)
+#define const_double_chain (cfun->varasm->x_const_double_chain)
 
 /* Number for making the label on the next
    constant that is stored in memory.  */
@@ -149,49 +150,46 @@ int size_directive_output;
 
 tree last_assemble_variable_decl;
 
-/* Nonzero if at least one function definition has been seen.  */
-
-static int function_defined;
-
-static const char *strip_reg_name      PROTO((const char *));
-static int contains_pointers_p         PROTO((tree));
-static void decode_addr_const          PROTO((tree, struct addr_const *));
-static int const_hash                  PROTO((tree));
-static int compare_constant            PROTO((tree,
+static const char *strip_reg_name      PARAMS ((const char *));
+static int contains_pointers_p         PARAMS ((tree));
+static void decode_addr_const          PARAMS ((tree, struct addr_const *));
+static int const_hash                  PARAMS ((tree));
+static int compare_constant            PARAMS ((tree,
                                               struct constant_descriptor *));
-static char *compare_constant_1                PROTO((tree, char *));
-static struct constant_descriptor *record_constant PROTO((tree));
-static void record_constant_1          PROTO((tree));
-static tree copy_constant              PROTO((tree));
-static void output_constant_def_contents  PROTO((tree, int, int));
-static void decode_rtx_const           PROTO((enum machine_mode, rtx,
+static const unsigned char *compare_constant_1  PARAMS ((tree, const unsigned char *));
+static struct constant_descriptor *record_constant PARAMS ((tree));
+static void record_constant_1          PARAMS ((tree));
+static tree copy_constant              PARAMS ((tree));
+static void output_constant_def_contents  PARAMS ((tree, int, int));
+static void decode_rtx_const           PARAMS ((enum machine_mode, rtx,
                                               struct rtx_const *));
-static int const_hash_rtx              PROTO((enum machine_mode, rtx));
-static int compare_constant_rtx                PROTO((enum machine_mode, rtx,
+static int const_hash_rtx              PARAMS ((enum machine_mode, rtx));
+static int compare_constant_rtx                PARAMS ((enum machine_mode, rtx,
                                               struct constant_descriptor *));
-static struct constant_descriptor *record_constant_rtx PROTO((enum machine_mode,
+static struct constant_descriptor *record_constant_rtx PARAMS ((enum machine_mode,
                                                              rtx));
-static struct pool_constant *find_pool_constant PROTO((struct function *, rtx));
-static void mark_constant_pool         PROTO((void));
-static void mark_constants             PROTO((rtx));
-static int output_addressed_constants  PROTO((tree));
-static void output_after_function_constants PROTO((void));
-static void output_constructor         PROTO((tree, int));
+static struct pool_constant *find_pool_constant PARAMS ((struct function *, rtx));
+static void mark_constant_pool         PARAMS ((void));
+static void mark_constants             PARAMS ((rtx));
+static int output_addressed_constants  PARAMS ((tree));
+static void output_after_function_constants PARAMS ((void));
+static void output_constructor         PARAMS ((tree, int));
 #ifdef ASM_WEAKEN_LABEL
-static void remove_from_pending_weak_list      PROTO ((char *));
+static void remove_from_pending_weak_list      PARAMS ((const char *));
 #endif
 #ifdef ASM_OUTPUT_BSS
-static void asm_output_bss             PROTO((FILE *, tree, char *, int, int));
+static void asm_output_bss             PARAMS ((FILE *, tree, const char *, int, int));
 #endif
 #ifdef BSS_SECTION_ASM_OP
 #ifdef ASM_OUTPUT_ALIGNED_BSS
-static void asm_output_aligned_bss     PROTO((FILE *, tree, char *, int, int));
+static void asm_output_aligned_bss     PARAMS ((FILE *, tree, const char *,
+                                                int, int));
 #endif
 #endif /* BSS_SECTION_ASM_OP */
-static void mark_pool_constant          PROTO((struct pool_constant *));
-static void mark_pool_sym_hash_table   PROTO((struct pool_sym **));
-static void mark_const_hash_entry      PROTO((void *));
-static void asm_emit_uninitialised     PROTO((tree, char *, int, int));
+static void mark_pool_constant          PARAMS ((struct pool_constant *));
+static void mark_pool_sym_hash_table   PARAMS ((struct pool_sym **));
+static void mark_const_hash_entry      PARAMS ((void *));
+static void asm_emit_uninitialised     PARAMS ((tree, const char*, int, int));
 \f
 static enum in_section { no_section, in_text, in_data, in_named
 #ifdef BSS_SECTION_ASM_OP
@@ -206,10 +204,12 @@ static enum in_section { no_section, in_text, in_data, in_named
 } in_section = no_section;
 
 /* Return a non-zero value if DECL has a section attribute.  */
+#ifndef IN_NAMED_SECTION
 #define IN_NAMED_SECTION(DECL) \
   ((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \
    && DECL_SECTION_NAME (DECL) != NULL_TREE)
-
+#endif
+     
 /* Text of section name when in_section == in_named.  */
 static char *in_named_name;
 
@@ -301,8 +301,7 @@ named_section (decl, name, reloc)
      const char *name;
      int reloc ATTRIBUTE_UNUSED;
 {
-  if (decl != NULL_TREE
-      && TREE_CODE_CLASS (TREE_CODE (decl)) != 'd')
+  if (decl != NULL_TREE && !DECL_P (decl))
     abort ();
   if (name == NULL)
     name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
@@ -377,9 +376,9 @@ bss_section ()
 static void
 asm_output_bss (file, decl, name, size, rounded)
      FILE *file;
-     tree decl;
-     char *name;
-     int size, rounded;
+     tree decl ATTRIBUTE_UNUSED;
+     const char *name;
+     int size ATTRIBUTE_UNUSED, rounded;
 {
   ASM_GLOBALIZE_LABEL (file, name);
   bss_section ();
@@ -406,7 +405,7 @@ static void
 asm_output_aligned_bss (file, decl, name, size, align)
      FILE *file;
      tree decl;
-     char *name;
+     const char *name;
      int size, align;
 {
   ASM_GLOBALIZE_LABEL (file, name);
@@ -520,70 +519,75 @@ void
 make_function_rtl (decl)
      tree decl;
 {
-  char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-  char *new_name = name;
+  const char *name;
+  const char *new_name;
+
+  if (DECL_RTL (decl) != 0)
+    {
+      /* ??? Another way to do this would be to do what halfpic.c does
+        and maintain a hashed table of such critters.  */
+      /* ??? Another way to do this would be to pass a flag bit to
+        ENCODE_SECTION_INFO saying whether this is a new decl or not.  */
+      /* Let the target reassign the RTL if it wants.
+        This is necessary, for example, when one machine specific
+        decl attribute overrides another.  */
+#ifdef REDO_SECTION_INFO_P
+      if (REDO_SECTION_INFO_P (decl))
+       ENCODE_SECTION_INFO (decl);
+#endif
+      return;
+    }
+
+  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  new_name = name;
 
-  /* Rename a nested function to avoid conflicts.  */
+  /* Rename a nested function to avoid conflicts, unless it's a member of
+     a local class, in which case the class name is already unique.  */
   if (decl_function_context (decl) != 0
+      && ! TYPE_P (DECL_CONTEXT (decl))
       && DECL_INITIAL (decl) != 0
       && DECL_RTL (decl) == 0)
     {
       char *label;
-
-      name = IDENTIFIER_POINTER (DECL_NAME (decl));
       ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
-      name = ggc_alloc_string (label, -1);
       var_labelno++;
+      new_name = label;
     }
-  else
+  /* When -fprefix-function-name is used, every function name is
+     prefixed.  Even static functions are prefixed because they
+     could be declared latter.  Note that a nested function name
+     is not prefixed.  */
+  else if (flag_prefix_function_name)
     {
-      /* When -fprefix-function-name is used, every function name is
-         prefixed.  Even static functions are prefixed because they
-         could be declared latter.  Note that a nested function name
-         is not prefixed.  */
-      if (flag_prefix_function_name)
-        {
-         size_t name_len = strlen (name);
+      size_t name_len = IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
+      char *pname;
 
-          new_name = ggc_alloc_string (NULL, name_len + CHKR_PREFIX_SIZE);
-         memcpy (new_name, CHKR_PREFIX, CHKR_PREFIX_SIZE);
-         memcpy (new_name + CHKR_PREFIX_SIZE, name, name_len + 1);
-          name = new_name;
-        }
+      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 (DECL_RTL (decl) == 0)
+  if (name != new_name)
     {
-      DECL_RTL (decl)
-       = gen_rtx_MEM (DECL_MODE (decl),
-                      gen_rtx_SYMBOL_REF (Pmode, name));
+      DECL_ASSEMBLER_NAME (decl) = get_identifier (new_name);
+      name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+    }
+
+  DECL_RTL (decl)
+    = gen_rtx_MEM (DECL_MODE (decl),
+                  gen_rtx_SYMBOL_REF (Pmode, name));
 
-      /* 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
-        ASM_OUTPUT_LABELREF will have to know how to strip this information.  */
+  /* 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 ASM_OUTPUT_LABELREF will have to know
+     how to strip this information.  */
 #ifdef ENCODE_SECTION_INFO
-      ENCODE_SECTION_INFO (decl);
+  ENCODE_SECTION_INFO (decl);
 #endif
-    }
-  else
-    {
-      /* ??? Another way to do this would be to do what halfpic.c does
-        and maintain a hashed table of such critters.  */
-      /* ??? Another way to do this would be to pass a flag bit to
-        ENCODE_SECTION_INFO saying whether this is a new decl or not.  */
-      /* Let the target reassign the RTL if it wants.
-        This is necessary, for example, when one machine specific
-        decl attribute overrides another.  */
-#ifdef REDO_SECTION_INFO_P
-      if (REDO_SECTION_INFO_P (decl))
-       ENCODE_SECTION_INFO (decl);
-#endif
-    }
-
-  /* Record at least one function has been defined.  */
-  function_defined = 1;
 }
 
+
 /* Given NAME, a putative register name, discard any customary prefixes.  */
 
 static const char *
@@ -641,7 +645,7 @@ decode_reg_name (asmspec)
        static struct { const char *name; int number; } table[]
          = ADDITIONAL_REGISTER_NAMES;
 
-       for (i = 0; i < (int)(sizeof (table) / sizeof (table[0])); i++)
+       for (i = 0; i < (int) ARRAY_SIZE (table); i++)
          if (! strcmp (asmspec, table[i].name))
            return table[i].number;
       }
@@ -673,54 +677,57 @@ make_decl_rtl (decl, asmspec, top_level)
      const char *asmspec;
      int top_level;
 {
-  register char *name = 0;
+  const char *name = 0;
+  const char *new_name = 0;
   int reg_number;
 
-  reg_number = decode_reg_name (asmspec);
-
-  if (DECL_ASSEMBLER_NAME (decl) != NULL_TREE)
-    name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-
-  if (reg_number == -2)
+  /* For a duplicate declaration, we can be called twice on the
+     same DECL node.  Don't discard the RTL already made.  */
+  if (DECL_RTL (decl) != 0)
     {
-      /* ASMSPEC is given, and not the name of a register.  */
-      size_t len = strlen (asmspec);
+      /* If the old RTL had the wrong mode, fix the mode.  */
+      if (GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl))
+       {
+         rtx rtl = DECL_RTL (decl);
+         PUT_MODE (rtl, DECL_MODE (decl));
+       }
 
-      name = ggc_alloc_string (NULL, len + 1);
-      name[0] = '*';
-      memcpy (&name[1], asmspec, len + 1);
+      /* ??? Another way to do this would be to do what halfpic.c does
+        and maintain a hashed table of such critters.  */
+      /* ??? Another way to do this would be to pass a flag bit to
+        ENCODE_SECTION_INFO saying whether this is a new decl or not.  */
+      /* Let the target reassign the RTL if it wants.
+        This is necessary, for example, when one machine specific
+        decl attribute overrides another.  */
+#ifdef REDO_SECTION_INFO_P
+      if (REDO_SECTION_INFO_P (decl))
+       ENCODE_SECTION_INFO (decl);
+#endif
+      return;
     }
 
-  /* For a duplicate declaration, we can be called twice on the
-     same DECL node.  Don't discard the RTL already made.  */
-  if (DECL_RTL (decl) == 0)
+  new_name = name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+
+  reg_number = decode_reg_name (asmspec);
+  if (reg_number == -2)
+    /* ASMSPEC is given, and not the name of a register.  */
+    new_name = asmspec;
+
+  if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
     {
       /* First detect errors in declaring global registers.  */
-      if (TREE_CODE (decl) != FUNCTION_DECL
-         && DECL_REGISTER (decl) && reg_number == -1)
-       error_with_decl (decl,
-                        "register name not specified for `%s'");
-      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)
-              && (TREE_CODE (decl) == FUNCTION_DECL
-                  && ! DECL_REGISTER (decl)))
-       error_with_decl (decl,
-                        "register name given for non-register variable `%s'");
-      else if (TREE_CODE (decl) != FUNCTION_DECL
-              && DECL_REGISTER (decl)
-              && TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
+      if (reg_number == -1)
+       error_with_decl (decl, "register name not specified for `%s'");
+      else if (reg_number < 0)
+       error_with_decl (decl, "invalid register name for `%s'");
+      else if (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))))
+      else if (! 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");
+                        "register specified for `%s' isn't suitable for data type");
       /* Now handle properly declared static register variables.  */
-      else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
+      else
        {
          int nregs;
 
@@ -729,9 +736,6 @@ make_decl_rtl (decl, asmspec, top_level)
              DECL_INITIAL (decl) = 0;
              error ("global register variable has initial value");
            }
-         if (fixed_regs[reg_number] == 0
-             && function_defined && top_level)
-           error ("global register variable follows a function definition");
          if (TREE_THIS_VOLATILE (decl))
            warning ("volatile register variables don't work as you might wish");
 
@@ -757,101 +761,81 @@ make_decl_rtl (decl, asmspec, top_level)
              while (nregs > 0)
                globalize_reg (reg_number + --nregs);
            }
+
+         /* As a register variable, it has no section.  */
+         return;
        }
-      /* Specifying a section attribute on a variable forces it into a
-         non-.bss section, and thus it cannot be common. */
-      else if (TREE_CODE (decl) == VAR_DECL
-              && DECL_SECTION_NAME (decl) != NULL_TREE
-              && DECL_INITIAL (decl) == NULL_TREE
-              && DECL_COMMON (decl))
-          DECL_COMMON (decl) = 0;
-
-      /* Now handle ordinary static variables and functions (in memory).
-        Also handle vars declared register invalidly.  */
-      if (DECL_RTL (decl) == 0)
-       {
-         /* Can't use just the variable's own name for a variable
-            whose scope is less than the whole file.
-            Concatenate a distinguishing number.  */
-         if (!top_level && !TREE_PUBLIC (decl) && asmspec == 0)
-           {
-             char *label;
+    }
 
-             ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
-             name = ggc_alloc_string (label, -1);
-             var_labelno++;
-           }
+  /* Now handle ordinary static variables and functions (in memory).
+     Also handle vars declared register invalidly.  */
 
-         if (name == 0)
-           abort ();
+  if (reg_number >= 0 || reg_number == -3)
+    error_with_decl (decl,
+                    "register name given for non-register variable `%s'");
 
-         /* When -fprefix-function-name is used, the functions
-            names are prefixed.  Only nested function names are not
-            prefixed.  */
-         if (flag_prefix_function_name && TREE_CODE (decl) == FUNCTION_DECL)
-           {
-             size_t name_len = strlen (name);
-             char *new_name;
+  /* Specifying a section attribute on a variable forces it into a
+     non-.bss section, and thus it cannot be common. */
+  if (TREE_CODE (decl) == VAR_DECL
+      && DECL_SECTION_NAME (decl) != NULL_TREE
+      && DECL_INITIAL (decl) == NULL_TREE
+      && DECL_COMMON (decl))
+    DECL_COMMON (decl) = 0;
+
+  /* Can't use just the variable's own name for a variable
+     whose scope is less than the whole file, unless it's a member
+     of a local class (which will already be unambiguous).
+     Concatenate a distinguishing number.  */
+  if (!top_level && !TREE_PUBLIC (decl)
+      && ! (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
+      && asmspec == 0)
+    {
+      char *label;
+      ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
+      var_labelno++;
+      new_name = label;
+    }
 
-             new_name = ggc_alloc_string (NULL, name_len + CHKR_PREFIX_SIZE);
-             memcpy (new_name, CHKR_PREFIX, CHKR_PREFIX_SIZE);
-             memcpy (new_name + CHKR_PREFIX_SIZE, name, name_len + 1);
-             name = new_name;
-           }
+  /* 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;
 
-         DECL_RTL (decl) = gen_rtx_MEM (DECL_MODE (decl),
-                                        gen_rtx_SYMBOL_REF (Pmode, name));
-         MEM_ALIAS_SET (DECL_RTL (decl)) = get_alias_set (decl);
-
-         /* If this variable is to be treated as volatile, show its
-            tree node has side effects.  If it has side effects, either
-            because of this test or from TREE_THIS_VOLATILE also
-            being set, show the MEM is volatile.  */
-         if (flag_volatile_global && TREE_CODE (decl) == VAR_DECL
-             && TREE_PUBLIC (decl))
-           TREE_SIDE_EFFECTS (decl) = 1;
-         else if (flag_volatile_static && TREE_CODE (decl) == VAR_DECL
-              && (TREE_PUBLIC (decl) || TREE_STATIC (decl)))
-           TREE_SIDE_EFFECTS (decl) = 1;
-
-         if (TREE_SIDE_EFFECTS (decl))
-           MEM_VOLATILE_P (DECL_RTL (decl)) = 1;
-
-         if (TREE_READONLY (decl))
-           RTX_UNCHANGING_P (DECL_RTL (decl)) = 1;
-         MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
-                              AGGREGATE_TYPE_P (TREE_TYPE (decl)));
-
-         /* 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 ASM_OUTPUT_LABELREF
-            will have to know how to strip this information.  */
-#ifdef ENCODE_SECTION_INFO
-         ENCODE_SECTION_INFO (decl);
-#endif
-       }
+      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;
     }
-  else
+
+  if (name != new_name)
     {
-      /* If the old RTL had the wrong mode, fix the mode.  */
-      if (GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl))
-       {
-         rtx rtl = DECL_RTL (decl);
-         PUT_MODE (rtl, DECL_MODE (decl));
-       }
+      DECL_ASSEMBLER_NAME (decl) = get_identifier (new_name);
+      name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+    }
 
-      /* ??? Another way to do this would be to do what halfpic.c does
-        and maintain a hashed table of such critters.  */
-      /* ??? Another way to do this would be to pass a flag bit to
-        ENCODE_SECTION_INFO saying whether this is a new decl or not.  */
-      /* Let the target reassign the RTL if it wants.
-        This is necessary, for example, when one machine specific
-        decl attribute overrides another.  */
-#ifdef REDO_SECTION_INFO_P
-      if (REDO_SECTION_INFO_P (decl))
-       ENCODE_SECTION_INFO (decl);
+  /* If this variable is to be treated as volatile, show its
+     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
+          && (TREE_PUBLIC (decl) || TREE_STATIC (decl)))))
+    TREE_SIDE_EFFECTS (decl) = 1;
+
+  DECL_RTL (decl) = gen_rtx_MEM (DECL_MODE (decl),
+                                gen_rtx_SYMBOL_REF (Pmode, name));
+  if (TREE_CODE (decl) != FUNCTION_DECL)
+    set_mem_attributes (DECL_RTL (decl), decl, 1);
+
+  /* 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 ASM_OUTPUT_LABELREF
+     will have to know how to strip this information.  */
+#ifdef ENCODE_SECTION_INFO
+  ENCODE_SECTION_INFO (decl);
 #endif
-    }
 }
 
 /* Make the rtl for variable VAR be volatile.
@@ -997,7 +981,7 @@ assemble_gc_entry (name)
 void
 assemble_start_function (decl, fnname)
      tree decl;
-     char *fnname;
+     const char *fnname;
 {
   int align;
 
@@ -1060,16 +1044,16 @@ assemble_start_function (decl, fnname)
       if (! first_global_object_name)
        {
          const char *p;
-         char **name;
+         char *name;
+
+         STRIP_NAME_ENCODING (p, fnname);
+         name = permalloc (strlen (p) + 1);
+         strcpy (name, p);
 
          if (! DECL_WEAK (decl) && ! DECL_ONE_ONLY (decl))
-           name = &first_global_object_name;
+           first_global_object_name = name;
          else
-           name = &weak_global_object_name;
-
-         STRIP_NAME_ENCODING (p, fnname);
-         *name = permalloc (strlen (p) + 1);
-         strcpy (*name, p);
+           weak_global_object_name = name;
        }
 
 #ifdef ASM_WEAKEN_LABEL
@@ -1239,11 +1223,12 @@ assemble_string (p, size)
 static void
 asm_emit_uninitialised (decl, name, size, rounded)
      tree decl;
-     char * name;
-     int size;
+     const char * name;
+     int size ATTRIBUTE_UNUSED;
      int rounded ATTRIBUTE_UNUSED;
 {
-  enum {
+  enum
+  {
     asm_dest_common,
     asm_dest_bss,
     asm_dest_local
@@ -1284,6 +1269,12 @@ asm_emit_uninitialised (decl, name, size, rounded)
        }
     }
 
+#ifdef ASM_OUTPUT_SECTION_NAME
+  /* We already know that DECL_SECTION_NAME() == NULL.  */
+  if (flag_data_sections != 0 || UNIQUE_SECTION_P (decl))
+    UNIQUE_SECTION (decl, 0);
+#endif
+  
   switch (destination)
     {
 #ifdef ASM_EMIT_BSS
@@ -1321,9 +1312,8 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
      int at_end ATTRIBUTE_UNUSED;
      int dont_output_data;
 {
-  register char *name;
+  register const char *name;
   unsigned int align;
-  tree size_tree = NULL_TREE;
   int reloc = 0;
   enum in_section saved_in_section;
 
@@ -1415,28 +1405,14 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
 
   app_disable ();
 
-  if (! dont_output_data)
+  if (! dont_output_data
+      && ! host_integerp (DECL_SIZE_UNIT (decl), 1))
     {
-      int size;
-
-      if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
-       goto finish;
-
-      /* 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));
-
-      size = TREE_INT_CST_LOW (size_tree);
-      if (TREE_INT_CST_HIGH (size_tree) != 0
-         || size != TREE_INT_CST_LOW (size_tree))
-       {
-         error_with_decl (decl, "size of variable `%s' is too large");
-         goto finish;
-       }
+      error_with_decl (decl, "size of variable `%s' is too large");
+      goto finish;
     }
 
   name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
-
   if (TREE_PUBLIC (decl) && DECL_NAME (decl)
       && ! first_global_object_name
       && ! (DECL_COMMON (decl) && (DECL_INITIAL (decl) == 0
@@ -1445,10 +1421,12 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
       && ! DECL_ONE_ONLY (decl))
     {
       const char *p;
+      char *xname;
 
       STRIP_NAME_ENCODING (p, name);
-      first_global_object_name = permalloc (strlen (p) + 1);
-      strcpy (first_global_object_name, p);
+      xname = permalloc (strlen (p) + 1);
+      strcpy (xname, p);
+      first_global_object_name = xname;
     }
 
   /* Compute the alignment of this data.  */
@@ -1496,23 +1474,26 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
 #if ! defined ASM_EMIT_BSS
       && DECL_COMMON (decl)
 #endif
-      && DECL_SECTION_NAME (decl) == 0
+      && DECL_SECTION_NAME (decl) == NULL_TREE
       && ! dont_output_data)
     {
-      int size = TREE_INT_CST_LOW (size_tree);
-      int rounded = size;
+      unsigned HOST_WIDE_INT size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
+      unsigned HOST_WIDE_INT rounded = size;
 
       /* Don't allocate zero bytes of common,
         since that means "undefined external" in the linker.  */
-      if (size == 0) rounded = 1;
+      if (size == 0)
+       rounded = 1;
+
       /* Round size up to multiple of BIGGEST_ALIGNMENT bits
         so that each uninitialized object starts on such a boundary.  */
       rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
       rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
                 * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
       
-#if !defined(ASM_OUTPUT_ALIGNED_COMMON) && !defined(ASM_OUTPUT_ALIGNED_BSS)
-      if ( (DECL_ALIGN (decl) / BITS_PER_UNIT) > rounded)
+/* Don't continue this line--convex cc version 4.1 would lose.  */
+#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);
 #endif
@@ -1585,8 +1566,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
     reloc = output_addressed_constants (DECL_INITIAL (decl));
 
 #ifdef ASM_OUTPUT_SECTION_NAME
-  if ((flag_data_sections != 0
-       && DECL_SECTION_NAME (decl) == NULL_TREE)
+  if ((flag_data_sections != 0 && DECL_SECTION_NAME (decl) == NULL_TREE)
       || UNIQUE_SECTION_P (decl))
     UNIQUE_SECTION (decl, reloc);
 #endif
@@ -1647,10 +1627,11 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
     {
       if (DECL_INITIAL (decl))
        /* Output the actual data.  */
-       output_constant (DECL_INITIAL (decl), TREE_INT_CST_LOW (size_tree));
+       output_constant (DECL_INITIAL (decl),
+                        tree_low_cst (DECL_SIZE_UNIT (decl), 1));
       else
        /* Leave space for it.  */
-       assemble_zeros (TREE_INT_CST_LOW (size_tree));
+       assemble_zeros (tree_low_cst (DECL_SIZE_UNIT (decl), 1));
     }
 
  finish:
@@ -1723,8 +1704,7 @@ assemble_external (decl)
      tree decl ATTRIBUTE_UNUSED;
 {
 #ifdef ASM_OUTPUT_EXTERNAL
-  if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd'
-      && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
+  if (DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
     {
       rtx rtl = DECL_RTL (decl);
 
@@ -2118,7 +2098,7 @@ immed_double_const (i0, i1, mode)
 
   /* Search the chain for an existing CONST_DOUBLE with the right value.
      If one is found, return it.  */
-  if (current_function != 0)
+  if (cfun != 0)
     for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))
       if (CONST_DOUBLE_LOW (r) == i0 && CONST_DOUBLE_HIGH (r) == i1
          && GET_MODE (r) == mode)
@@ -2134,7 +2114,7 @@ immed_double_const (i0, i1, mode)
 
   push_obstacks_nochange ();
   rtl_in_saveable_obstack ();
-  r = gen_rtx_CONST_DOUBLE (mode, NULL_RTX, i0, i1);
+  r = gen_rtx_CONST_DOUBLE (mode, const0_rtx, i0, i1);
   pop_obstacks ();
 
   /* Don't touch const_double_chain if not inside any function.  */
@@ -2144,11 +2124,6 @@ immed_double_const (i0, i1, mode)
       const_double_chain = r;
     }
 
-  /* Store const0_rtx in mem-slot since this CONST_DOUBLE is on the chain.
-     Actual use of mem-slot is only through force_const_mem.  */
-
-  CONST_DOUBLE_MEM (r) = const0_rtx;
-
   return r;
 }
 
@@ -2168,15 +2143,19 @@ immed_real_const_1 (d, mode)
 
   u.d = d;
 
-  /* Detect special cases.  */
-
-  if (REAL_VALUES_IDENTICAL (dconst0, d))
+  /* Detect special cases.  But be careful we don't use a CONST_DOUBLE
+     that's from a parent function since it may be in its constant pool.  */
+  if (REAL_VALUES_IDENTICAL (dconst0, d)
+      && (cfun == 0 || decl_function_context (current_function_decl) == 0))
     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))
+  else if ((! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst1, d))
+          && (cfun == 0
+              || decl_function_context (current_function_decl) == 0))
     return CONST1_RTX (mode);
 
   if (sizeof u == sizeof (HOST_WIDE_INT))
@@ -2190,7 +2169,7 @@ immed_real_const_1 (d, mode)
 
   /* Search the chain for an existing CONST_DOUBLE with the right value.
      If one is found, return it.  */
-  if (current_function != 0)
+  if (cfun != 0)
     for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))
       if (! bcmp ((char *) &CONST_DOUBLE_LOW (r), (char *) &u, sizeof u)
          && GET_MODE (r) == mode)
@@ -2210,12 +2189,15 @@ immed_real_const_1 (d, mode)
   PUT_MODE (r, mode);
   bcopy ((char *) &u, (char *) &CONST_DOUBLE_LOW (r), sizeof u);
 
-  /* Don't touch const_double_chain if not inside any function.  */
+  /* If we aren't inside a function, don't put r on the
+     const_double_chain.  */
   if (current_function_decl != 0)
     {
       CONST_DOUBLE_CHAIN (r) = const_double_chain;
       const_double_chain = r;
     }
+  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
@@ -2277,20 +2259,16 @@ decode_addr_const (exp, value)
   while (1)
     {
       if (TREE_CODE (target) == COMPONENT_REF
-         && (TREE_CODE (DECL_FIELD_BITPOS (TREE_OPERAND (target, 1)))
-             == INTEGER_CST))
+         && host_integerp (byte_position (TREE_OPERAND (target, 1)), 0))
+
        {
-         offset += TREE_INT_CST_LOW (DECL_FIELD_BITPOS (TREE_OPERAND (target, 1))) / BITS_PER_UNIT;
+         offset += int_byte_position (TREE_OPERAND (target, 1));
          target = TREE_OPERAND (target, 0);
        }
       else if (TREE_CODE (target) == ARRAY_REF)
        {
-         if (TREE_CODE (TREE_OPERAND (target, 1)) != INTEGER_CST
-             || TREE_CODE (TYPE_SIZE (TREE_TYPE (target))) != INTEGER_CST)
-           abort ();
-         offset += ((TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (target)))
-                     * TREE_INT_CST_LOW (TREE_OPERAND (target, 1)))
-                    / BITS_PER_UNIT);
+         offset += (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (target)), 1)
+                    * tree_low_cst (TREE_OPERAND (target, 1), 0));
          target = TREE_OPERAND (target, 0);
        }
       else
@@ -2344,7 +2322,7 @@ struct constant_descriptor
   struct constant_descriptor *next;
   char *label;
   rtx rtl;
-  char contents[1];
+  unsigned char contents[1];
 };
 
 #define HASHBITS 30
@@ -2361,7 +2339,7 @@ mark_const_hash_entry (ptr)
 
   while (desc)
     {
-      ggc_mark_string (desc->label);
+      ggc_mark_string ((const char *)desc->label);
       ggc_mark_rtx (desc->rtl);
       desc = desc->next;
     }
@@ -2373,7 +2351,7 @@ static int
 const_hash (exp)
      tree exp;
 {
-  register char *p;
+  register const char *p;
   register int len, hi, i;
   register enum tree_code code = TREE_CODE (exp);
 
@@ -2383,8 +2361,8 @@ const_hash (exp)
   switch (code)
     {
     case INTEGER_CST:
-      p = (char *) &TREE_INT_CST_LOW (exp);
-      len = 2 * sizeof TREE_INT_CST_LOW (exp);
+      p = (char *) &TREE_INT_CST (exp);
+      len = sizeof TREE_INT_CST (exp);
       break;
 
     case REAL_CST:
@@ -2404,9 +2382,12 @@ const_hash (exp)
     case CONSTRUCTOR:
       if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
        {
+         char *tmp;
+
          len = int_size_in_bytes (TREE_TYPE (exp));
-         p = (char *) alloca (len);
-         get_set_constructor_bytes (exp, (unsigned char *) p, len);
+         tmp = (char *) alloca (len);
+         get_set_constructor_bytes (exp, (unsigned char *) tmp, len);
+         p = tmp;
          break;
        }
       else
@@ -2469,7 +2450,8 @@ const_hash (exp)
       return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2;
       
     default:
-      abort ();
+      /* A language specific constant. Just hash the code. */
+      return code % MAX_HASH_TABLE;
     }
 
   /* Compute hashing function */
@@ -2502,12 +2484,12 @@ compare_constant (exp, desc)
    against a subdescriptor, and if it succeeds it returns the
    address of the subdescriptor for the next operand.  */
 
-static char *
+static const unsigned char *
 compare_constant_1 (exp, p)
      tree exp;
-     char *p;
+     const unsigned char *p;
 {
-  register char *strp;
+  register const unsigned char *strp;
   register int len;
   register enum tree_code code = TREE_CODE (exp);
 
@@ -2524,8 +2506,8 @@ compare_constant_1 (exp, p)
       if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
        return 0;
 
-      strp = (char *) &TREE_INT_CST_LOW (exp);
-      len = 2 * sizeof TREE_INT_CST_LOW (exp);
+      strp = (unsigned char *) &TREE_INT_CST (exp);
+      len = sizeof TREE_INT_CST (exp);
       break;
 
     case REAL_CST:
@@ -2533,7 +2515,7 @@ compare_constant_1 (exp, p)
       if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
        return 0;
 
-      strp = (char *) &TREE_REAL_CST (exp);
+      strp = (unsigned char *) &TREE_REAL_CST (exp);
       len = sizeof TREE_REAL_CST (exp);
       break;
 
@@ -2541,10 +2523,10 @@ compare_constant_1 (exp, p)
       if (flag_writable_strings)
        return 0;
 
-      if (*p++ != TYPE_MODE (TREE_TYPE (exp)))
+      if ((enum machine_mode) *p++ != TYPE_MODE (TREE_TYPE (exp)))
        return 0;
 
-      strp = TREE_STRING_POINTER (exp);
+      strp = (unsigned char *)TREE_STRING_POINTER (exp);
       len = TREE_STRING_LENGTH (exp);
       if (bcmp ((char *) &TREE_STRING_LENGTH (exp), p,
                sizeof TREE_STRING_LENGTH (exp)))
@@ -2564,9 +2546,10 @@ compare_constant_1 (exp, p)
       if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
        {
          int xlen = len = int_size_in_bytes (TREE_TYPE (exp));
+         unsigned char *tmp = (unsigned char *) alloca (len);
 
-         strp = (char *) alloca (len);
-         get_set_constructor_bytes (exp, (unsigned char *) strp, len);
+         get_set_constructor_bytes (exp, tmp, len);
+         strp = (unsigned char *) tmp;
          if (bcmp ((char *) &xlen, p, sizeof xlen))
            return 0;
 
@@ -2678,7 +2661,7 @@ compare_constant_1 (exp, p)
        struct addr_const value;
 
        decode_addr_const (exp, &value);
-       strp = (char *) &value.offset;
+       strp = (unsigned char *) &value.offset;
        len = sizeof value.offset;
        /* Compare the offset.  */
        while (--len >= 0)
@@ -2686,8 +2669,8 @@ compare_constant_1 (exp, p)
            return 0;
 
        /* Compare symbol name.  */
-       strp = XSTR (value.base, 0);
-       len = strlen (strp) + 1;
+       strp = (unsigned char *) XSTR (value.base, 0);
+       len = strlen ((char *) strp) + 1;
       }
       break;
 
@@ -2706,7 +2689,12 @@ compare_constant_1 (exp, p)
       return compare_constant_1 (TREE_OPERAND (exp, 0), p);
 
     default:
-      abort ();
+      if (lang_expand_constant)
+        {
+          exp = (*lang_expand_constant) (exp);
+          return compare_constant_1 (exp, p);
+        }
+      return 0;
     }
 
   /* Compare constant contents.  */
@@ -2747,7 +2735,7 @@ static void
 record_constant_1 (exp)
      tree exp;
 {
-  register char *strp;
+  register unsigned char *strp;
   register int len;
   register enum tree_code code = TREE_CODE (exp);
 
@@ -2757,13 +2745,13 @@ record_constant_1 (exp)
     {
     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);
+      strp = (unsigned char *) &TREE_INT_CST (exp);
+      len = sizeof TREE_INT_CST (exp);
       break;
 
     case REAL_CST:
       obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
-      strp = (char *) &TREE_REAL_CST (exp);
+      strp = (unsigned char *) &TREE_REAL_CST (exp);
       len = sizeof TREE_REAL_CST (exp);
       break;
 
@@ -2772,7 +2760,7 @@ record_constant_1 (exp)
        return;
 
       obstack_1grow (&permanent_obstack, TYPE_MODE (TREE_TYPE (exp)));
-      strp = TREE_STRING_POINTER (exp);
+      strp = (unsigned char *) TREE_STRING_POINTER (exp);
       len = TREE_STRING_LENGTH (exp);
       obstack_grow (&permanent_obstack, (char *) &TREE_STRING_LENGTH (exp),
                    sizeof TREE_STRING_LENGTH (exp));
@@ -2869,9 +2857,24 @@ record_constant_1 (exp)
        /* 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);
+
+       switch (GET_CODE (value.base))
+         {
+         case SYMBOL_REF:
+           /* Record the symbol name.  */
+           obstack_grow (&permanent_obstack, XSTR (value.base, 0),
+                         strlen (XSTR (value.base, 0)) + 1);
+           break;
+         case LABEL_REF:
+           /* Record the address of the CODE_LABEL.  It may not have
+              been emitted yet, so it's UID may be zero.  But pointer
+              identity is good enough.  */
+           obstack_grow (&permanent_obstack, &XEXP (value.base, 0),
+                         sizeof (rtx));
+           break;
+         default:
+           abort ();
+         }
       }
       return;
 
@@ -2889,7 +2892,12 @@ record_constant_1 (exp)
       return;
 
     default:
-      abort ();
+      if (lang_expand_constant)
+        {
+          exp = (*lang_expand_constant) (exp);
+          record_constant_1 (exp);
+        }
+      return;
     }
 
   /* Record constant contents.  */
@@ -3094,10 +3102,7 @@ output_constant_def (exp)
        = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
                       gen_rtx_SYMBOL_REF (Pmode, desc->label));
 
-      RTX_UNCHANGING_P (desc->rtl) = 1;
-      if (AGGREGATE_TYPE_P (TREE_TYPE (exp)))
-       MEM_SET_IN_STRUCT_P (desc->rtl, 1);
-
+      set_mem_attributes (desc->rtl, exp, 1);
       pop_obstacks ();
 
       found = 0;
@@ -3418,7 +3423,7 @@ decode_rtx_const (mode, x, value)
       case SYMBOL_REF:
        /* Use the string's address, not the SYMBOL_REF's address,
           for the sake of addresses of library routines.  */
-       value->un.addr.base = XSTR (value->un.addr.base, 0);
+       value->un.addr.base = (rtx) XSTR (value->un.addr.base, 0);
        break;
 
       case LABEL_REF:
@@ -3653,8 +3658,9 @@ force_const_mem (mode, x)
   /* We have a symbol name; construct the SYMBOL_REF and the MEM.  */
 
   def = gen_rtx_MEM (mode, gen_rtx_SYMBOL_REF (Pmode, found));
-
+  set_mem_attributes (def, type_for_mode (mode, 0), 1);
   RTX_UNCHANGING_P (def) = 1;
+
   /* Mark the symbol_ref as belonging to this constants pool.  */
   CONSTANT_POOL_ADDRESS_P (XEXP (def, 0)) = 1;
   current_function_uses_const_pool = 1;
@@ -3681,9 +3687,10 @@ find_pool_constant (f, addr)
      rtx addr;
 {
   struct pool_sym *sym;
-  char *label = XSTR (addr, 0);
+  const char *label = XSTR (addr, 0);
 
-  for (sym = f->varasm->x_const_rtx_sym_hash_table[SYMHASH (label)]; sym; sym = sym->next)
+  for (sym = f->varasm->x_const_rtx_sym_hash_table[SYMHASH (label)]; sym;
+       sym = sym->next)
     if (sym->label == label)
       return sym->pool;
 
@@ -3696,7 +3703,7 @@ rtx
 get_pool_constant (addr)
      rtx addr;
 {
-  return (find_pool_constant (current_function, addr))->constant;
+  return (find_pool_constant (cfun, addr))->constant;
 }
 
 /* Likewise, but for the constant pool of a specific function.  */
@@ -3715,7 +3722,7 @@ enum machine_mode
 get_pool_mode (addr)
      rtx addr;
 {
-  return (find_pool_constant (current_function, addr))->mode;
+  return (find_pool_constant (cfun, addr))->mode;
 }
 
 enum machine_mode
@@ -3732,7 +3739,7 @@ int
 get_pool_offset (addr)
      rtx addr;
 {
-  return (find_pool_constant (current_function, addr))->offset;
+  return (find_pool_constant (cfun, addr))->offset;
 }
 
 /* Return the size of the constant pool.  */
@@ -3765,6 +3772,8 @@ output_constant_pool (fnname, fndecl)
 
   for (pool = first_pool; pool; pool = pool->next)
     {
+      rtx tmp;
+
       x = pool->constant;
 
       if (! pool->mark)
@@ -3775,14 +3784,34 @@ output_constant_pool (fnname, fndecl)
         is eliminated by optimization.  If so, write a constant of zero
         instead.  Note that this can also happen by turning the
         CODE_LABEL into a NOTE.  */
-      if (((GET_CODE (x) == LABEL_REF
-           && (INSN_DELETED_P (XEXP (x, 0))
-               || GET_CODE (XEXP (x, 0)) == NOTE)))
-         || (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
-             && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF
-             && (INSN_DELETED_P (XEXP (XEXP (XEXP (x, 0), 0), 0))
-                 || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == NOTE)))
-       x = const0_rtx;
+      /* ??? This seems completely and utterly wrong.  Certainly it's
+        not true for NOTE_INSN_DELETED_LABEL, but I disbelieve proper
+        functioning even with INSN_DELETED_P and friends.  */
+
+      tmp = x;
+      switch (GET_CODE (x))
+       {
+       case CONST:
+         if (GET_CODE (XEXP (x, 0)) != PLUS
+             || GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
+           break;
+         tmp = XEXP (XEXP (x, 0), 0);
+         /* FALLTHRU */
+
+       case LABEL_REF:
+         tmp = XEXP (x, 0);
+         if (INSN_DELETED_P (tmp)
+             || (GET_CODE (tmp) == NOTE
+                 && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_DELETED))
+           {
+             abort ();
+             x = const0_rtx;
+           }
+         break;
+         
+       default:
+         break;
+       }
 
       /* First switch to correct section.  */
 #ifdef SELECT_RTX_SECTION
@@ -3852,13 +3881,13 @@ mark_constant_pool ()
     pool->mark = 0;
 
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-    if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+    if (INSN_P (insn))
       mark_constants (PATTERN (insn));
 
   for (insn = current_function_epilogue_delay_list;
        insn;
        insn = XEXP (insn, 1))
-    if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+    if (INSN_P (insn))
       mark_constants (PATTERN (insn));
 
   /* It's possible that the only reference to a symbol is in a symbol
@@ -3871,7 +3900,7 @@ mark_constant_pool ()
   for (pool = first_pool; pool; pool = pool->next)
     {
       struct pool_sym *sym;
-      char *label;
+      const char *label;
 
       /* skip unmarked entries; no insn refers to them. */
       if (!pool->mark)
@@ -3905,7 +3934,7 @@ mark_constants (x)
   if (GET_CODE (x) == SYMBOL_REF)
     {
       if (CONSTANT_POOL_ADDRESS_P (x))
-       find_pool_constant (current_function, x)->mark = 1;
+       find_pool_constant (cfun, x)->mark = 1;
       return;
     }
   /* Never search inside a CONST_DOUBLE, because CONST_DOUBLE_MEM may be
@@ -3916,7 +3945,7 @@ mark_constants (x)
   /* 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
      a constant just because it happens to appear in a REG_EQUIV note.  */
-  if (GET_RTX_CLASS (GET_CODE (x)) == 'i')
+  if (INSN_P (x))
     {
       mark_constants (PATTERN (x));
       return;
@@ -4029,6 +4058,11 @@ initializer_constant_valid_p (value, endtype)
      tree value;
      tree 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);
+
   switch (TREE_CODE (value))
     {
     case CONSTRUCTOR:
@@ -4049,7 +4083,7 @@ initializer_constant_valid_p (value, endtype)
       return null_pointer_node;
 
     case ADDR_EXPR:
-      return TREE_OPERAND (value, 0);
+      return staticp (TREE_OPERAND (value, 0)) ? TREE_OPERAND (value, 0) : 0;
 
     case NON_LVALUE_EXPR:
       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
@@ -4206,12 +4240,18 @@ output_constant (exp, size)
 
   /* 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.  */
+     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);
+    {
+      exp = TREE_OPERAND (exp, 0);
+      code = TREE_CODE (TREE_TYPE (exp));
+    }
 
   /* Allow a constructor with no elements for any data type.
      This means to fill the space with zeros.  */
@@ -4321,25 +4361,25 @@ output_constructor (exp, size)
      tree exp;
      int size;
 {
+  tree type = TREE_TYPE (exp);
   register tree link, field = 0;
-  HOST_WIDE_INT min_index = 0;
+  tree min_index = 0;
   /* Number of bytes output or skipped so far.
      In other words, current position within the constructor.  */
-  int total_bytes = 0;
+  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;
+  register int byte = 0;
 
   if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT)
     abort ();
 
-  if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
-    field = TYPE_FIELDS (TREE_TYPE (exp));
+  if (TREE_CODE (type) == RECORD_TYPE)
+    field = TYPE_FIELDS (type);
 
-  if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
-      && TYPE_DOMAIN (TREE_TYPE (exp)) != 0)
-    min_index
-      = TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (exp))));
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && TYPE_DOMAIN (type) != 0)
+    min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
 
   /* As LINK goes through the elements of the constant,
      FIELD goes through the structure fields, if the constant is a structure.
@@ -4358,17 +4398,14 @@ output_constructor (exp, size)
       tree val = TREE_VALUE (link);
       tree index = 0;
 
-      /* the element in a union constructor specifies the proper field.  */
-
-      if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
-         || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE)
-       {
-         /* if available, use the type given by link */
-         if (TREE_PURPOSE (link) != 0)
-           field = TREE_PURPOSE (link);
-       }
+      /* The element in a union constructor specifies the proper field
+        or index.  */
+      if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
+          || TREE_CODE (type) == QUAL_UNION_TYPE)
+         && TREE_PURPOSE (link) != 0)
+       field = TREE_PURPOSE (link);
 
-      if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+      else if (TREE_CODE (type) == ARRAY_TYPE)
        index = TREE_PURPOSE (link);
 
       /* Eliminate the marker that makes a cast not be an lvalue.  */
@@ -4378,10 +4415,11 @@ output_constructor (exp, size)
       if (index && TREE_CODE (index) == RANGE_EXPR)
        {
          register int fieldsize
-           = int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp)));
-         HOST_WIDE_INT lo_index = TREE_INT_CST_LOW (TREE_OPERAND (index, 0));
-         HOST_WIDE_INT hi_index = TREE_INT_CST_LOW (TREE_OPERAND (index, 1));
+           = int_size_in_bytes (TREE_TYPE (type));
+         HOST_WIDE_INT lo_index = tree_low_cst (TREE_OPERAND (index, 0), 0);
+         HOST_WIDE_INT hi_index = tree_low_cst (TREE_OPERAND (index, 1), 0);
          HOST_WIDE_INT index;
+
          for (index = lo_index; index <= hi_index; index++)
            {
              /* Output the element's initial value.  */
@@ -4401,13 +4439,11 @@ output_constructor (exp, size)
          register int fieldsize;
          /* Since this structure is static,
             we know the positions are constant.  */
-         int bitpos = (field ? (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field))
-                                / BITS_PER_UNIT)
-                       : 0);
+         HOST_WIDE_INT pos = field ? int_byte_position (field) : 0;
+
          if (index != 0)
-           bitpos = (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (val)))
-                     / BITS_PER_UNIT
-                     * (TREE_INT_CST_LOW (index) - min_index));
+           pos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)
+                  * (tree_low_cst (index, 0) - tree_low_cst (min_index, 0)));
 
          /* Output any buffered-up bit-fields preceding this element.  */
          if (byte_buffer_in_use)
@@ -4420,33 +4456,24 @@ output_constructor (exp, size)
          /* Advance to offset of this element.
             Note no alignment needed in an array, since that is guaranteed
             if each element has the proper size.  */
-         if ((field != 0 || index != 0) && bitpos != total_bytes)
+         if ((field != 0 || index != 0) && pos != total_bytes)
            {
-             assemble_zeros (bitpos - total_bytes);
-             total_bytes = bitpos;
+             assemble_zeros (pos - total_bytes);
+             total_bytes = pos;
            }
 
+          else if (field != 0 && DECL_PACKED (field))
+           /* Some assemblers automaticallly align a datum according to its
+              size if no align directive is specified.  The datum, however,
+              may be declared with 'packed' attribute, so we have to disable
+              such a feature.  */
+           ASM_OUTPUT_ALIGN (asm_out_file, 0);
+
          /* Determine size this element should occupy.  */
          if (field)
-           {
-             if (TREE_CODE (DECL_SIZE (field)) != INTEGER_CST)
-               abort ();
-             if (TREE_INT_CST_LOW (DECL_SIZE (field)) > 100000)
-               {
-                 /* This avoids overflow trouble.  */
-                 tree size_tree = size_binop (CEIL_DIV_EXPR,
-                                              DECL_SIZE (field),
-                                              size_int (BITS_PER_UNIT));
-                 fieldsize = TREE_INT_CST_LOW (size_tree);
-               }
-             else
-               {
-                 fieldsize = TREE_INT_CST_LOW (DECL_SIZE (field));
-                 fieldsize = (fieldsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
-               }
-           }
+           fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
          else
-           fieldsize = int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp)));
+           fieldsize = int_size_in_bytes (TREE_TYPE (type));
 
          /* Output the element's initial value.  */
          if (val == 0)
@@ -4464,9 +4491,9 @@ output_constructor (exp, size)
        {
          /* Element that is a bit-field.  */
 
-         int next_offset = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
-         int end_offset
-           = (next_offset + TREE_INT_CST_LOW (DECL_SIZE (field)));
+         HOST_WIDE_INT next_offset = int_bit_position (field);
+         HOST_WIDE_INT end_offset
+           = (next_offset + tree_low_cst (DECL_SIZE (field), 1));
 
          if (val == 0)
            val = integer_zero_node;
@@ -4507,8 +4534,8 @@ output_constructor (exp, size)
              int this_time;
              int shift;
              HOST_WIDE_INT value;
-             int next_byte = next_offset / BITS_PER_UNIT;
-             int next_bit = next_offset % BITS_PER_UNIT;
+             HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
+             HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
 
              /* Advance from byte to byte
                 within this element when necessary.  */
@@ -4529,6 +4556,7 @@ output_constructor (exp, size)
                     first (of the bits that are significant)
                     and put them into bytes from the most significant end.  */
                  shift = end_offset - next_offset - this_time;
+
                  /* Don't try to take a bunch of bits that cross
                     the word boundary in the INTEGER_CST. We can
                     only select bits from the LOW or HIGH part
@@ -4542,9 +4570,7 @@ output_constructor (exp, size)
 
                  /* Now get the bits from the appropriate constant word.  */
                  if (shift < HOST_BITS_PER_WIDE_INT)
-                   {
-                     value = TREE_INT_CST_LOW (val);
-                   }
+                   value = TREE_INT_CST_LOW (val);
                  else if (shift < 2 * HOST_BITS_PER_WIDE_INT)
                    {
                      value = TREE_INT_CST_HIGH (val);
@@ -4552,6 +4578,7 @@ output_constructor (exp, size)
                    }
                  else
                    abort ();
+
                  /* Get the result. This works only when:
                     1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
                  byte |= (((value >> shift)
@@ -4564,17 +4591,15 @@ output_constructor (exp, size)
                     take first the least significant bits of the value
                     and pack them starting at the least significant
                     bits of the bytes.  */
-                 shift = (next_offset
-                          - TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)));
+                 shift = next_offset - int_bit_position (field);
+
                  /* Don't try to take a bunch of bits that cross
                     the word boundary in the INTEGER_CST. We can
                     only select bits from the LOW or HIGH part
                     not from both.  */
                  if (shift < HOST_BITS_PER_WIDE_INT
                      && shift + this_time > HOST_BITS_PER_WIDE_INT)
-                   {
-                     this_time = (HOST_BITS_PER_WIDE_INT - shift);
-                   }
+                   this_time = (HOST_BITS_PER_WIDE_INT - shift);
 
                  /* Now get the bits from the appropriate constant word.  */
                  if (shift < HOST_BITS_PER_WIDE_INT)
@@ -4586,22 +4611,26 @@ output_constructor (exp, size)
                    }
                  else
                    abort ();
+
                  /* Get the result. This works only when:
                     1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
                  byte |= (((value >> shift)
                            & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
                           << next_bit);
                }
+
              next_offset += this_time;
              byte_buffer_in_use = 1;
            }
        }
     }
+
   if (byte_buffer_in_use)
     {
       ASM_OUTPUT_BYTE (asm_out_file, byte);
       total_bytes++;
     }
+
   if (total_bytes < size)
     assemble_zeros (size - total_bytes);
 }
@@ -4612,8 +4641,8 @@ output_constructor (exp, size)
    
 int
 add_weak (name, value)
-     char *name;
-     char *value;
+     const char *name;
+     const char *value;
 {
   struct weak_syms *weak;
 
@@ -4680,7 +4709,7 @@ weak_finish ()
 #ifdef ASM_WEAKEN_LABEL
 static void
 remove_from_pending_weak_list (name)
-     char *name ATTRIBUTE_UNUSED;
+     const char *name ATTRIBUTE_UNUSED;
 {
 #ifdef HANDLE_PRAGMA_WEAK
   if (HANDLE_PRAGMA_WEAK)
@@ -4700,7 +4729,7 @@ void
 assemble_alias (decl, target)
      tree decl, target ATTRIBUTE_UNUSED;
 {
-  char *name;
+  const char *name;
 
   make_decl_rtl (decl, (char *) 0, 1);
   name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
@@ -4800,3 +4829,74 @@ init_varasm_once ()
                mark_const_hash_entry);
   ggc_add_string_root (&in_named_name, 1);
 }
+
+/* Extra support for EH values.  */
+void
+assemble_eh_label (name)
+     const char *name;
+{
+#ifdef ASM_OUTPUT_EH_LABEL
+  ASM_OUTPUT_EH_LABEL (asm_out_file, name);
+#else
+  assemble_label (name);
+#endif
+}
+
+/* Assemble an alignment pseudo op for an ALIGN-bit boundary.  */
+
+void
+assemble_eh_align (align)
+     int align;
+{
+#ifdef ASM_OUTPUT_EH_ALIGN
+  if (align > BITS_PER_UNIT)
+    ASM_OUTPUT_EH_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
+#else
+  assemble_align (align);
+#endif
+}
+
+
+/* On some platforms, we may want to specify a special mechansim to
+   output EH data when generating with a function..  */
+int
+assemble_eh_integer (x, size, force)
+     rtx x;
+     int size;
+     int force;
+{
+
+  switch (size)
+    {
+#ifdef ASM_OUTPUT_EH_CHAR
+    case 1:
+      ASM_OUTPUT_EH_CHAR (asm_out_file, x);
+      return 1;
+#endif
+
+#ifdef ASM_OUTPUT_EH_SHORT
+    case 2:
+      ASM_OUTPUT_EH_SHORT (asm_out_file, x);
+      return 1;
+#endif
+
+#ifdef ASM_OUTPUT_EH_INT
+    case 4:
+      ASM_OUTPUT_EH_INT (asm_out_file, x);
+      return 1;
+#endif
+
+#ifdef ASM_OUTPUT_EH_DOUBLE_INT
+    case 8:
+      ASM_OUTPUT_EH_DOUBLE_INT (asm_out_file, x);
+      return 1;
+#endif
+
+    default:
+      break;
+    }
+  return (assemble_integer (x, size, force));
+}
+
+
+
This page took 0.079928 seconds and 5 git commands to generate.