OSDN Git Service

In gcc/objc/:
[pf3gnuchains/gcc-fork.git] / gcc / emit-rtl.c
index eb3ea93..16032e9 100644 (file)
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "rtl.h"
 #include "tree.h"
@@ -60,6 +61,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "params.h"
 #include "target.h"
 
+struct target_rtl default_target_rtl;
+#if SWITCHABLE_TARGET
+struct target_rtl *this_target_rtl = &default_target_rtl;
+#endif
+
+#define initial_regno_reg_rtx (this_target_rtl->x_initial_regno_reg_rtx)
+
 /* Commonly used modes.  */
 
 enum machine_mode byte_mode;   /* Mode whose width is BITS_PER_UNIT.  */
@@ -83,19 +91,6 @@ rtx * regno_reg_rtx;
 
 static GTY(()) int label_num = 1;
 
-/* Commonly used rtx's, so that we only need space for one copy.
-   These are initialized once for the entire compilation.
-   All of these are unique; no other rtx-object will be equal to any
-   of these.  */
-
-rtx global_rtl[GR_MAX];
-
-/* Commonly used RTL for hard registers.  These objects are not necessarily
-   unique, so we allocate them separately from global_rtl.  They are
-   initialized once per compilation unit, then copied into regno_reg_rtx
-   at the beginning of each function.  */
-static GTY(()) rtx static_regno_reg_rtx[FIRST_PSEUDO_REGISTER];
-
 /* We record floating-point CONST_DOUBLEs in each floating-point mode for
    the values of 0, 1, and 2.  For the integer entries and VOIDmode, we
    record a copy of const[012]_rtx.  */
@@ -114,30 +109,6 @@ REAL_VALUE_TYPE dconsthalf;
 FIXED_VALUE_TYPE fconst0[MAX_FCONST0];
 FIXED_VALUE_TYPE fconst1[MAX_FCONST1];
 
-/* All references to the following fixed hard registers go through
-   these unique rtl objects.  On machines where the frame-pointer and
-   arg-pointer are the same register, they use the same unique object.
-
-   After register allocation, other rtl objects which used to be pseudo-regs
-   may be clobbered to refer to the frame-pointer register.
-   But references that were originally to the frame-pointer can be
-   distinguished from the others because they contain frame_pointer_rtx.
-
-   When to use frame_pointer_rtx and hard_frame_pointer_rtx is a little
-   tricky: until register elimination has taken place hard_frame_pointer_rtx
-   should be used if it is being set, and frame_pointer_rtx otherwise.  After
-   register elimination hard_frame_pointer_rtx should always be used.
-   On machines where the two registers are same (most) then these are the
-   same.
-
-   In an inline procedure, the stack and frame pointer rtxs may not be
-   used for anything else.  */
-rtx pic_offset_table_rtx;      /* (REG:Pmode PIC_OFFSET_TABLE_REGNUM) */
-
-/* This is used to implement __builtin_return_address for some machines.
-   See for instance the MIPS port.  */
-rtx return_address_pointer_rtx;        /* (REG:Pmode RETURN_ADDRESS_POINTER_REGNUM) */
-
 /* We make one copy of (const_int C) where C is in
    [- MAX_SAVED_CONST_INT, MAX_SAVED_CONST_INT]
    to save space during the compilation and simplify comparisons of
@@ -1488,7 +1459,8 @@ get_mem_align_offset (rtx mem, unsigned int align)
   /* This function can't use
      if (!MEM_EXPR (mem) || !MEM_OFFSET (mem)
         || !CONST_INT_P (MEM_OFFSET (mem))
-        || (get_object_alignment (MEM_EXPR (mem), MEM_ALIGN (mem), align)
+        || (MAX (MEM_ALIGN (mem),
+                 get_object_alignment (MEM_EXPR (mem), align))
             < align))
        return -1;
      else
@@ -1610,19 +1582,43 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
 
   /* We can set the alignment from the type if we are making an object,
      this is an INDIRECT_REF, or if TYPE_ALIGN_OK.  */
-  if (objectp || TREE_CODE (t) == INDIRECT_REF
-      || TREE_CODE (t) == ALIGN_INDIRECT_REF
-      || TYPE_ALIGN_OK (type))
+  if (objectp || TREE_CODE (t) == INDIRECT_REF || TYPE_ALIGN_OK (type))
+    align = MAX (align, TYPE_ALIGN (type));
+
+  else if (TREE_CODE (t) == MEM_REF)
+    {
+      tree op0 = TREE_OPERAND (t, 0);
+      if (TREE_CODE (op0) == ADDR_EXPR
+         && (DECL_P (TREE_OPERAND (op0, 0))
+             || CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))))
+       {
+         if (DECL_P (TREE_OPERAND (op0, 0)))
+           align = DECL_ALIGN (TREE_OPERAND (op0, 0));
+         else if (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0)))
+           {
+             align = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (op0, 0)));
+#ifdef CONSTANT_ALIGNMENT
+             align = CONSTANT_ALIGNMENT (TREE_OPERAND (op0, 0), align);
+#endif
+           }
+         if (TREE_INT_CST_LOW (TREE_OPERAND (t, 1)) != 0)
+           {
+             unsigned HOST_WIDE_INT ioff
+               = TREE_INT_CST_LOW (TREE_OPERAND (t, 1));
+             unsigned HOST_WIDE_INT aoff = (ioff & -ioff) * BITS_PER_UNIT;
+             align = MIN (aoff, align);
+           }
+       }
+      else
+       /* ??? This isn't fully correct, we can't set the alignment from the
+          type in all cases.  */
+       align = MAX (align, TYPE_ALIGN (type));
+    }
+
+  else if (TREE_CODE (t) == TARGET_MEM_REF)
+    /* ??? This isn't fully correct, we can't set the alignment from the
+       type in all cases.  */
     align = MAX (align, TYPE_ALIGN (type));
-  else
-    if (TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
-      {
-       if (integer_zerop (TREE_OPERAND (t, 1)))
-         /* We don't know anything about the alignment.  */
-         align = BITS_PER_UNIT;
-       else
-         align = tree_low_cst (TREE_OPERAND (t, 1), 1);
-      }
 
   /* If the size is known, we can set that.  */
   if (TYPE_SIZE_UNIT (type) && host_integerp (TYPE_SIZE_UNIT (type), 1))
@@ -1654,6 +1650,9 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
             || TREE_CODE (base) == BIT_FIELD_REF)
        base = TREE_OPERAND (base, 0);
 
+      if (TREE_CODE (base) == MEM_REF
+         && TREE_CODE (TREE_OPERAND (base, 0)) == ADDR_EXPR)
+       base = TREE_OPERAND (TREE_OPERAND (base, 0), 0);
       if (DECL_P (base))
        {
          if (CODE_CONTAINS_STRUCT (TREE_CODE (base), TS_DECL_WITH_VIS))
@@ -1668,12 +1667,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
       if (base && DECL_P (base)
          && TREE_READONLY (base)
          && (TREE_STATIC (base) || DECL_EXTERNAL (base)))
-       {
-         tree base_type = TREE_TYPE (base);
-         gcc_assert (!(base_type && TYPE_NEEDS_CONSTRUCTING (base_type))
-                     || DECL_ARTIFICIAL (base));
-         MEM_READONLY_P (ref) = 1;
-       }
+       MEM_READONLY_P (ref) = 1;
 
       /* If this expression uses it's parent's alias set, mark it such
         that we won't change it.  */
@@ -1779,8 +1773,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
            }
 
          /* If this is an indirect reference, record it.  */
-         else if (TREE_CODE (t) == INDIRECT_REF
-                  || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
+         else if (TREE_CODE (t) == MEM_REF)
            {
              expr = t;
              offset = const0_rtx;
@@ -1789,8 +1782,8 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
        }
 
       /* If this is an indirect reference, record it.  */
-      else if (TREE_CODE (t) == INDIRECT_REF
-              || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
+      else if (TREE_CODE (t) == MEM_REF 
+              || TREE_CODE (t) == TARGET_MEM_REF)
        {
          expr = t;
          offset = const0_rtx;
@@ -1799,8 +1792,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
 
       if (!align_computed && !INDIRECT_REF_P (t))
        {
-         unsigned int obj_align
-           = get_object_alignment (t, align, BIGGEST_ALIGNMENT);
+         unsigned int obj_align = get_object_alignment (t, BIGGEST_ALIGNMENT);
          align = MAX (align, obj_align);
        }
     }
@@ -1815,14 +1807,6 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
        size = plus_constant (size, apply_bitpos / BITS_PER_UNIT);
     }
 
-  if (TREE_CODE (t) == ALIGN_INDIRECT_REF)
-    {
-      /* Force EXPR and OFFSET to NULL, since we don't know exactly what
-        we're overlapping.  */
-      offset = NULL;
-      expr = NULL;
-    }
-
   /* Now set the attributes we computed above.  */
   MEM_ATTRS (ref)
     = get_mem_attrs (alias, expr, offset, size, align,
@@ -2388,7 +2372,7 @@ unshare_all_rtl_again (rtx insn)
   set_used_decls (DECL_INITIAL (cfun->decl));
 
   /* Make sure that virtual parameters are not shared.  */
-  for (decl = DECL_ARGUMENTS (cfun->decl); decl; decl = TREE_CHAIN (decl))
+  for (decl = DECL_ARGUMENTS (cfun->decl); decl; decl = DECL_CHAIN (decl))
     set_used_flags (DECL_RTL (decl));
 
   reset_used_flags (stack_slot_list);
@@ -2598,7 +2582,7 @@ set_used_decls (tree blk)
   tree t;
 
   /* Mark decls.  */
-  for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (t))
+  for (t = BLOCK_VARS (blk); t; t = DECL_CHAIN (t))
     if (DECL_RTL_SET_P (t))
       set_used_flags (DECL_RTL (t));
 
@@ -3148,6 +3132,38 @@ prev_nondebug_insn (rtx insn)
   return insn;
 }
 
+/* Return the next insn after INSN that is not a NOTE nor DEBUG_INSN.
+   This routine does not look inside SEQUENCEs.  */
+
+rtx
+next_nonnote_nondebug_insn (rtx insn)
+{
+  while (insn)
+    {
+      insn = NEXT_INSN (insn);
+      if (insn == 0 || (!NOTE_P (insn) && !DEBUG_INSN_P (insn)))
+       break;
+    }
+
+  return insn;
+}
+
+/* Return the previous insn before INSN that is not a NOTE nor DEBUG_INSN.
+   This routine does not look inside SEQUENCEs.  */
+
+rtx
+prev_nonnote_nondebug_insn (rtx insn)
+{
+  while (insn)
+    {
+      insn = PREV_INSN (insn);
+      if (insn == 0 || (!NOTE_P (insn) && !DEBUG_INSN_P (insn)))
+       break;
+    }
+
+  return insn;
+}
+
 /* Return the next INSN, CALL_INSN or JUMP_INSN after INSN;
    or 0, if there is none.  This routine does not look inside
    SEQUENCEs.  */
@@ -3961,6 +3977,13 @@ delete_insns_since (rtx from)
 void
 reorder_insns_nobb (rtx from, rtx to, rtx after)
 {
+#ifdef ENABLE_CHECKING
+  rtx x;
+  for (x = from; x != to; x = NEXT_INSN (x))
+    gcc_assert (after != x);
+  gcc_assert (after != to);
+#endif
+
   /* Splice this bunch out of where it is now.  */
   if (PREV_INSN (from))
     NEXT_INSN (PREV_INSN (from)) = NEXT_INSN (to);
@@ -5360,6 +5383,8 @@ init_virtual_regs (void)
   regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx;
   regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx;
   regno_reg_rtx[VIRTUAL_CFA_REGNUM] = virtual_cfa_rtx;
+  regno_reg_rtx[VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM]
+    = virtual_preferred_stack_boundary_rtx;
 }
 
 \f
@@ -5559,7 +5584,7 @@ init_emit (void)
 
   /* Put copies of all the hard registers into regno_reg_rtx.  */
   memcpy (regno_reg_rtx,
-         static_regno_reg_rtx,
+         initial_regno_reg_rtx,
          FIRST_PSEUDO_REGISTER * sizeof (rtx));
 
   /* Put copies of all the virtual register rtx into regno_reg_rtx.  */
@@ -5682,11 +5707,13 @@ init_emit_regs (void)
   virtual_outgoing_args_rtx =
     gen_raw_REG (Pmode, VIRTUAL_OUTGOING_ARGS_REGNUM);
   virtual_cfa_rtx = gen_raw_REG (Pmode, VIRTUAL_CFA_REGNUM);
+  virtual_preferred_stack_boundary_rtx =
+    gen_raw_REG (Pmode, VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM);
 
   /* Initialize RTL for commonly used hard registers.  These are
      copied into regno_reg_rtx as we begin to compile each function.  */
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    static_regno_reg_rtx[i] = gen_raw_REG (reg_raw_mode[i], i);
+    initial_regno_reg_rtx[i] = gen_raw_REG (reg_raw_mode[i], i);
 
 #ifdef RETURN_ADDRESS_POINTER_REGNUM
   return_address_pointer_rtx