OSDN Git Service

* alpha.md (addsi3, subsi3): No new temporaries once cse is
[pf3gnuchains/gcc-fork.git] / gcc / varasm.c
index b204b43..e47a0cd 100644 (file)
@@ -1,5 +1,5 @@
 /* Output variables, constants and external declarations, for GNU compiler.
-   Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -27,10 +27,7 @@ Boston, MA 02111-1307, USA.  */
    and are responsible for combining constants with the same value.  */
 
 #include "config.h"
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
+#include "system.h"
 #include <setjmp.h>
 /* #include <stab.h> */
 #include "rtl.h"
@@ -44,6 +41,9 @@ Boston, MA 02111-1307, USA.  */
 #include "regs.h"
 #include "defaults.h"
 #include "real.h"
+#include "toplev.h"
+#include "dbxout.h"
+#include "sdbout.h"
 
 #include "obstack.h"
 #include "c-pragma.h"
@@ -52,8 +52,6 @@ Boston, MA 02111-1307, USA.  */
 #include "xcoffout.h"
 #endif
 
-#include <ctype.h>
-
 #ifndef TRAMPOLINE_ALIGNMENT
 #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
 #endif
@@ -88,6 +86,7 @@ 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;
 
 extern struct obstack *current_obstack;
 extern struct obstack *saveable_obstack;
@@ -117,20 +116,6 @@ 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;
@@ -164,6 +149,14 @@ 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));
+#ifdef ASM_OUTPUT_BSS
+static void asm_output_bss             PROTO((FILE *, tree, 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));
+#endif
+#endif /* BSS_SECTION_ASM_OP */
 \f
 static enum in_section { no_section, in_text, in_data, in_named
 #ifdef BSS_SECTION_ASM_OP
@@ -602,7 +595,7 @@ decode_reg_name (asmspec)
        static struct { char *name; int number; } table[]
          = ADDITIONAL_REGISTER_NAMES;
 
-       for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+       for (i = 0; i < (int)(sizeof (table) / sizeof (table[0])); i++)
          if (! strcmp (asmspec, table[i].name))
            return table[i].number;
       }
@@ -655,8 +648,6 @@ make_decl_rtl (decl, asmspec, top_level)
      same DECL node.  Don't discard the RTL already made.  */
   if (DECL_RTL (decl) == 0)
     {
-      DECL_RTL (decl) = 0;
-
       /* First detect errors in declaring global registers.  */
       if (TREE_CODE (decl) != FUNCTION_DECL
          && DECL_REGISTER (decl) && reg_number == -1)
@@ -760,7 +751,8 @@ make_decl_rtl (decl, asmspec, top_level)
 
          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
@@ -998,14 +990,19 @@ assemble_start_function (decl, fnname)
 
   if (TREE_PUBLIC (decl))
     {
-      if (!first_global_object_name && ! DECL_WEAK (decl)
-         && ! DECL_ONE_ONLY (decl))
+      if (! first_global_object_name)
        {
          char *p;
+         char **name;
+
+         if (! DECL_WEAK (decl) && ! DECL_ONE_ONLY (decl))
+           name = &first_global_object_name;
+         else
+           name = &weak_global_object_name;
 
          STRIP_NAME_ENCODING (p, fnname);
-         first_global_object_name = permalloc (strlen (p) + 1);
-         strcpy (first_global_object_name, p);
+         *name = permalloc (strlen (p) + 1);
+         strcpy (*name, p);
        }
 
 #ifdef ASM_WEAKEN_LABEL
@@ -1137,7 +1134,7 @@ assemble_string (p, size)
 void
 assemble_variable (decl, top_level, at_end, dont_output_data)
      tree decl;
-     int top_level;
+     int top_level ATTRIBUTE_UNUSED;
      int at_end;
      int dont_output_data;
 {
@@ -1263,6 +1260,43 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
       strcpy (first_global_object_name, p);
     }
 
+  /* Compute the alignment of this data.  */
+
+  align = DECL_ALIGN (decl);
+
+  /* In the case for initialing an array whose length isn't specified,
+     where we have not yet been able to do the layout,
+     figure out the proper alignment now.  */
+  if (dont_output_data && DECL_SIZE (decl) == 0
+      && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+    align = MAX (align, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
+
+  /* Some object file formats have a maximum alignment which they support.
+     In particular, a.out format supports a maximum alignment of 4.  */
+#ifndef MAX_OFILE_ALIGNMENT
+#define MAX_OFILE_ALIGNMENT BIGGEST_ALIGNMENT
+#endif
+  if (align > MAX_OFILE_ALIGNMENT)
+    {
+      warning_with_decl (decl,
+       "alignment of `%s' is greater than maximum object file alignment. Using %d.",
+                    MAX_OFILE_ALIGNMENT/BITS_PER_UNIT);
+      align = MAX_OFILE_ALIGNMENT;
+    }
+
+  /* On some machines, it is good to increase alignment sometimes.  */
+#ifdef DATA_ALIGNMENT
+  align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
+#endif
+#ifdef CONSTANT_ALIGNMENT
+  if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node)
+    align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align);
+#endif
+
+  /* Reset the alignment in case we have made it tighter, so we can benefit
+     from it in get_pointer_alignment.  */
+  DECL_ALIGN (decl) = align;
+
   /* Handle uninitialized definitions.  */
 
   if ((DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)
@@ -1284,7 +1318,13 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
       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)
+         warning_with_decl 
+           (decl, "requested alignment for %s is greater than implemented alignment of %d.",rounded);
+#endif
+       
 #ifdef DBX_DEBUGGING_INFO
       /* File-scope global variables are output here.  */
       if (write_symbols == DBX_DEBUG && top_level)
@@ -1410,7 +1450,9 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
     reloc = output_addressed_constants (DECL_INITIAL (decl));
 
 #ifdef ASM_OUTPUT_SECTION_NAME
-  if (UNIQUE_SECTION_P (decl))
+  if ((flag_data_sections != 0
+       && DECL_SECTION_NAME (decl) == NULL_TREE)
+      || UNIQUE_SECTION_P (decl))
     UNIQUE_SECTION (decl, reloc);
 #endif
 
@@ -1452,42 +1494,10 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
   if (in_section != saved_in_section)
     variable_section (decl, reloc);
 
-  /* Compute and output the alignment of this data.  */
-
-  align = DECL_ALIGN (decl);
-  /* In the case for initialing an array whose length isn't specified,
-     where we have not yet been able to do the layout,
-     figure out the proper alignment now.  */
-  if (dont_output_data && DECL_SIZE (decl) == 0
-      && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
-    align = MAX (align, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
-
-  /* Some object file formats have a maximum alignment which they support.
-     In particular, a.out format supports a maximum alignment of 4.  */
-#ifndef MAX_OFILE_ALIGNMENT
-#define MAX_OFILE_ALIGNMENT BIGGEST_ALIGNMENT
-#endif
-  if (align > MAX_OFILE_ALIGNMENT)
-    {
-      warning_with_decl (decl,
-         "alignment of `%s' is greater than maximum object file alignment");
-      align = MAX_OFILE_ALIGNMENT;
-    }
-#ifdef DATA_ALIGNMENT
-  /* On some machines, it is good to increase alignment sometimes.  */
-  align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
-#endif
-#ifdef CONSTANT_ALIGNMENT
-  if (DECL_INITIAL (decl))
-    align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align);
-#endif
-
-  /* Reset the alignment in case we have made it tighter, so we can benefit
-     from it in get_pointer_alignment.  */
-  DECL_ALIGN (decl) = align;
-
+  /* Output the alignment of this data.  */
   if (align > BITS_PER_UNIT)
-    ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
+    ASM_OUTPUT_ALIGN (asm_out_file,
+                     floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT));
 
   /* Do any machine/system dependent processing of the object.  */
 #ifdef ASM_DECLARE_OBJECT_NAME
@@ -1598,7 +1608,7 @@ assemble_external (decl)
 
 void
 assemble_external_libcall (fun)
-     rtx fun;
+     rtx fun ATTRIBUTE_UNUSED;
 {
 #ifdef ASM_OUTPUT_EXTERNAL_LIBCALL
   /* Declare library function name external when first used, if nec.  */
@@ -1667,11 +1677,6 @@ assemble_static_space (size)
   char name[12];
   char *namestring;
   rtx x;
-  /* Round size up to multiple of BIGGEST_ALIGNMENT bits
-     so that each uninitialized object starts on such a boundary.  */
-  int rounded = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
-                / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
-                * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
 
 #if 0
   if (flag_shared_data)
@@ -1694,7 +1699,14 @@ assemble_static_space (size)
 #ifdef ASM_OUTPUT_ALIGNED_LOCAL
   ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, BIGGEST_ALIGNMENT);
 #else
-  ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
+  {
+    /* Round size up to multiple of BIGGEST_ALIGNMENT bits
+       so that each uninitialized object starts on such a boundary.  */
+    int rounded = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
+                  / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
+                  * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
+    ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
+  }
 #endif
 #endif
   return x;
@@ -2046,6 +2058,8 @@ immed_real_const_1 (d, mode)
   else if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst1, d))
     return CONST1_RTX (mode);
 
+  if (sizeof u == sizeof (HOST_WIDE_INT))
+    return immed_double_const (u.i[0], 0, mode);
   if (sizeof u == 2 * sizeof (HOST_WIDE_INT))
     return immed_double_const (u.i[0], u.i[1], mode);
 
@@ -2431,6 +2445,11 @@ compare_constant_1 (exp, p)
          register tree link;
          int length = list_length (CONSTRUCTOR_ELTS (exp));
          tree type;
+         int have_purpose = 0;
+
+         for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
+           if (TREE_PURPOSE (link))
+             have_purpose = 1;
 
          if (bcmp ((char *) &length, p, sizeof length))
            return 0;
@@ -2438,7 +2457,9 @@ compare_constant_1 (exp, p)
          p += sizeof length;
 
          /* For record constructors, insist that the types match.
-            For arrays, just verify both constructors are for arrays.  */
+            For arrays, just verify both constructors are for arrays. 
+            Then insist that either both or none have any TREE_PURPOSE
+            values.  */
          if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
            type = TREE_TYPE (exp);
          else
@@ -2449,10 +2470,16 @@ compare_constant_1 (exp, p)
 
          p += sizeof type;
 
+         if (bcmp ((char *) &have_purpose, p, sizeof have_purpose))
+           return 0;
+
+         p += sizeof have_purpose;
+
          /* For arrays, insist that the size in bytes match.  */
          if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
            {
-             int size = int_size_in_bytes (TREE_TYPE (exp));
+             HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
+
              if (bcmp ((char *) &size, p, sizeof size))
                return 0;
 
@@ -2475,6 +2502,30 @@ compare_constant_1 (exp, p)
 
                  p += sizeof zero;
                }
+
+             if (TREE_PURPOSE (link)
+                 && TREE_CODE (TREE_PURPOSE (link)) == FIELD_DECL)
+               {
+                 if (bcmp ((char *) &TREE_PURPOSE (link), p,
+                           sizeof TREE_PURPOSE (link)))
+                   return 0;
+
+                 p += sizeof TREE_PURPOSE (link);
+               }
+             else if (TREE_PURPOSE (link))
+               {
+                 if ((p = compare_constant_1 (TREE_PURPOSE (link), p)) == 0)
+                   return 0;
+               }
+             else if (have_purpose)
+               {
+                 int zero = 0;
+
+                 if (bcmp ((char *) &zero, p, sizeof zero))
+                   return 0;
+
+                 p += sizeof zero;
+               }
            }
 
          return p;
@@ -2500,6 +2551,7 @@ compare_constant_1 (exp, p)
 
     case PLUS_EXPR:
     case MINUS_EXPR:
+    case RANGE_EXPR:
       p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
       if (p == 0)
        return 0;
@@ -2603,21 +2655,30 @@ record_constant_1 (exp)
          register tree link;
          int length = list_length (CONSTRUCTOR_ELTS (exp));
          tree type;
+         int have_purpose = 0;
+
+         for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
+           if (TREE_PURPOSE (link))
+             have_purpose = 1;
 
          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.  */
+            For arrays, just verify both constructors are for arrays. 
+            Then insist that either both or none have any TREE_PURPOSE
+            values.  */
          if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
            type = TREE_TYPE (exp);
          else
            type = 0;
          obstack_grow (&permanent_obstack, (char *) &type, sizeof type);
+         obstack_grow (&permanent_obstack, (char *) &have_purpose,
+                       sizeof have_purpose);
 
          /* For arrays, insist that the size in bytes match.  */
          if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
            {
-             int size = int_size_in_bytes (TREE_TYPE (exp));
+             HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
              obstack_grow (&permanent_obstack, (char *) &size, sizeof size);
            }
 
@@ -2632,6 +2693,21 @@ record_constant_1 (exp)
                  obstack_grow (&permanent_obstack,
                                (char *) &zero, sizeof zero);
                }
+
+             if (TREE_PURPOSE (link)
+                 && TREE_CODE (TREE_PURPOSE (link)) == FIELD_DECL)
+               obstack_grow (&permanent_obstack,
+                             (char *) &TREE_PURPOSE (link),
+                             sizeof TREE_PURPOSE (link));
+             else if (TREE_PURPOSE (link))
+               record_constant_1 (TREE_PURPOSE (link));
+             else if (have_purpose)
+               {
+                 int zero = 0;
+
+                 obstack_grow (&permanent_obstack,
+                               (char *) &zero, sizeof zero);
+               }
            }
        }
       return;
@@ -2652,6 +2728,7 @@ record_constant_1 (exp)
 
     case PLUS_EXPR:
     case MINUS_EXPR:
+    case RANGE_EXPR:
       record_constant_1 (TREE_OPERAND (exp, 0));
       record_constant_1 (TREE_OPERAND (exp, 1));
       return;
@@ -3348,6 +3425,10 @@ force_const_mem (mode, x)
       align = (mode == VOIDmode) ? UNITS_PER_WORD : GET_MODE_SIZE (mode);
       if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
        align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+#ifdef CONSTANT_ALIGNMENT
+      align = CONSTANT_ALIGNMENT (make_tree (type_for_mode (mode, 0), x),
+                                align * BITS_PER_UNIT) / BITS_PER_UNIT;
+#endif
 
       pool_offset += align - 1;
       pool_offset &= ~ (align - 1);
@@ -3491,8 +3572,8 @@ get_pool_size ()
 
 void
 output_constant_pool (fnname, fndecl)
-     char *fnname;
-     tree fndecl;
+  char *fnname ATTRIBUTE_UNUSED;
+  tree fndecl ATTRIBUTE_UNUSED;
 {
   struct pool_constant *pool;
   rtx x;
@@ -4151,38 +4232,6 @@ output_constructor (exp, size)
     assemble_zeros (size - total_bytes);
 }
 
-/* Output asm to handle ``#pragma weak'' */
-
-void
-handle_pragma_weak (what, name, value)
-     enum pragma_state what;
-     char *name, *value;
-{
-#ifdef HANDLE_PRAGMA_WEAK
-  if (what == ps_name || what == ps_value)
-    {
-      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;
-
-      else
-       {
-         weak->value = permalloc (strlen (value) + 1);
-         strcpy (weak->value, 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
@@ -4199,6 +4248,10 @@ declare_weak (decl)
 
 /* Emit any pending weak declarations.  */
 
+#ifdef HANDLE_PRAGMA_WEAK
+struct weak_syms * weak_decls;
+#endif
+
 void
 weak_finish ()
 {