OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / varasm.c
index 7805c1d..5162a6d 100644 (file)
@@ -35,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"
@@ -77,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;
@@ -156,7 +156,7 @@ 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                PARAMS ((tree, char *));
+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));
@@ -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));
@@ -561,9 +560,10 @@ make_function_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);
 #endif
@@ -799,29 +799,20 @@ make_decl_rtl (decl, asmspec, top_level)
              name = new_name;
            }
 
-         DECL_ASSEMBLER_NAME (decl) = get_identifier (name);
-         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 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;
-         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)));
+         DECL_ASSEMBLER_NAME (decl)
+           = get_identifier (name[0] == '*' ? name + 1 : name);
+         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.
@@ -1061,16 +1052,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
@@ -1289,7 +1280,7 @@ 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, NULL);
+    UNIQUE_SECTION (decl, 0);
 #endif
   
   switch (destination)
@@ -1331,7 +1322,6 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
 {
   register const char *name;
   unsigned int align;
-  tree size_tree = NULL_TREE;
   int reloc = 0;
   enum in_section saved_in_section;
 
@@ -1423,21 +1413,11 @@ 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))
     {
-      unsigned int size;
-
-      if (TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST)
-       goto finish;
-
-      size_tree = DECL_SIZE_UNIT (decl);
-      size = TREE_INT_CST_LOW (size_tree);
-
-      if (compare_tree_int (size_tree, size) != 0)
-       {
-         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);
@@ -1449,10 +1429,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.  */
@@ -1503,12 +1485,14 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
       && 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;
@@ -1516,7 +1500,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
                 * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
       
 #if !defined(ASM_OUTPUT_ALIGNED_COMMON) && !defined(ASM_OUTPUT_ALIGNED_BSS)
-      if ((DECL_ALIGN (decl) / BITS_PER_UNIT) > (unsigned int) rounded)
+      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
@@ -1650,10 +1634,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:
@@ -1726,8 +1711,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);
 
@@ -2137,7 +2121,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.  */
@@ -2147,11 +2131,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;
 }
 
@@ -2171,15 +2150,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))
@@ -2213,12 +2196,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
@@ -2280,20 +2266,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
@@ -2347,7 +2329,7 @@ struct constant_descriptor
   struct constant_descriptor *next;
   char *label;
   rtx rtl;
-  char contents[1];
+  unsigned char contents[1];
 };
 
 #define HASHBITS 30
@@ -2364,7 +2346,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;
     }
@@ -2475,7 +2457,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 */
@@ -2508,12 +2491,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 const char *strp;
+  register const unsigned char *strp;
   register int len;
   register enum tree_code code = TREE_CODE (exp);
 
@@ -2530,7 +2513,7 @@ compare_constant_1 (exp, p)
       if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
        return 0;
 
-      strp = (char *) &TREE_INT_CST_LOW (exp);
+      strp = (unsigned char *) &TREE_INT_CST_LOW (exp);
       len = 2 * sizeof TREE_INT_CST_LOW (exp);
       break;
 
@@ -2539,7 +2522,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;
 
@@ -2550,7 +2533,7 @@ compare_constant_1 (exp, p)
       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)))
@@ -2572,8 +2555,8 @@ compare_constant_1 (exp, p)
          int xlen = len = int_size_in_bytes (TREE_TYPE (exp));
          unsigned char *tmp = (unsigned char *) alloca (len);
 
-         get_set_constructor_bytes (exp, (unsigned char *) tmp, len);
-         strp = tmp;
+         get_set_constructor_bytes (exp, tmp, len);
+         strp = (unsigned char *) tmp;
          if (bcmp ((char *) &xlen, p, sizeof xlen))
            return 0;
 
@@ -2685,7 +2668,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)
@@ -2693,8 +2676,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;
 
@@ -2713,7 +2696,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.  */
@@ -2754,7 +2742,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);
 
@@ -2764,13 +2752,13 @@ record_constant_1 (exp)
     {
     case INTEGER_CST:
       obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
-      strp = (char *) &TREE_INT_CST_LOW (exp);
+      strp = (unsigned char *) &TREE_INT_CST_LOW (exp);
       len = 2 * sizeof TREE_INT_CST_LOW (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;
 
@@ -2779,7 +2767,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));
@@ -2876,9 +2864,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;
 
@@ -2896,7 +2899,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.  */
@@ -3101,10 +3109,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;
@@ -3660,8 +3665,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;
@@ -3690,7 +3696,8 @@ find_pool_constant (f, addr)
   struct pool_sym *sym;
   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;
 
@@ -3772,6 +3779,8 @@ output_constant_pool (fnname, fndecl)
 
   for (pool = first_pool; pool; pool = pool->next)
     {
+      rtx tmp;
+
       x = pool->constant;
 
       if (! pool->mark)
@@ -3782,14 +3791,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
@@ -4061,7 +4090,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);
@@ -4419,13 +4448,12 @@ 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 bitpos = 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));
+           bitpos
+             = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)
+               * (tree_low_cst (index, 0) - min_index));
 
          /* Output any buffered-up bit-fields preceding this element.  */
          if (byte_buffer_in_use)
@@ -4471,9 +4499,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;
@@ -4571,17 +4599,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)
@@ -4593,6 +4619,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)
@@ -4807,3 +4834,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));
+}
+
+
+