OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / explow.c
index 155404d..c1cd34c 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines for manipulating rtx's in semantically interesting ways.
    Copyright (C) 1987, 1991, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -50,8 +50,7 @@ trunc_int_for_mode (HOST_WIDE_INT c, enum machine_mode mode)
   int width = GET_MODE_BITSIZE (mode);
 
   /* You want to truncate to a _what_?  */
-  if (! SCALAR_INT_MODE_P (mode))
-    abort ();
+  gcc_assert (SCALAR_INT_MODE_P (mode));
 
   /* Canonicalize BImode to 0 and STORE_FLAG_VALUE.  */
   if (mode == BImode)
@@ -71,12 +70,10 @@ trunc_int_for_mode (HOST_WIDE_INT c, enum machine_mode mode)
   return c;
 }
 
-/* Return an rtx for the sum of X and the integer C.
-
-   This function should be used via the `plus_constant' macro.  */
+/* Return an rtx for the sum of X and the integer C.  */
 
 rtx
-plus_constant_wide (rtx x, HOST_WIDE_INT c)
+plus_constant (rtx x, HOST_WIDE_INT c)
 {
   RTX_CODE code;
   rtx y;
@@ -240,7 +237,12 @@ eliminate_constant_term (rtx x, rtx *constptr)
 rtx
 expr_size (tree exp)
 {
-  tree size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
+  tree size;
+
+  if (TREE_CODE (exp) == WITH_SIZE_EXPR)
+    size = TREE_OPERAND (exp, 1);
+  else
+    size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
 
   return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
 }
@@ -251,17 +253,17 @@ expr_size (tree exp)
 HOST_WIDE_INT
 int_expr_size (tree exp)
 {
-  tree t = lang_hooks.expr_size (exp);
-
-  if (t == 0
-      || TREE_CODE (t) != INTEGER_CST
-      || TREE_OVERFLOW (t)
-      || TREE_INT_CST_HIGH (t) != 0
-      /* If the result would appear negative, it's too big to represent.  */
-      || (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0)
+  tree size;
+
+  if (TREE_CODE (exp) == WITH_SIZE_EXPR)
+    size = TREE_OPERAND (exp, 1);
+  else
+    size = lang_hooks.expr_size (exp);
+
+  if (size == 0 || !host_integerp (size, 0))
     return -1;
 
-  return TREE_INT_CST_LOW (t);
+  return tree_low_cst (size, 0);
 }
 \f
 /* Return a copy of X in which all memory references
@@ -283,7 +285,7 @@ int_expr_size (tree exp)
 static rtx
 break_out_memory_refs (rtx x)
 {
-  if (GET_CODE (x) == MEM
+  if (MEM_P (x)
       || (CONSTANT_P (x) && CONSTANT_ADDRESS_P (x)
          && GET_MODE (x) != VOIDmode))
     x = force_reg (GET_MODE (x), x);
@@ -388,44 +390,6 @@ convert_memory_address (enum machine_mode to_mode ATTRIBUTE_UNUSED,
                        x, POINTERS_EXTEND_UNSIGNED);
 #endif /* defined(POINTERS_EXTEND_UNSIGNED) */
 }
-
-/* Given a memory address or facsimile X, construct a new address,
-   currently equivalent, that is stable: future stores won't change it.
-
-   X must be composed of constants, register and memory references
-   combined with addition, subtraction and multiplication:
-   in other words, just what you can get from expand_expr if sum_ok is 1.
-
-   Works by making copies of all regs and memory locations used
-   by X and combining them the same way X does.
-   You could also stabilize the reference to this address
-   by copying the address to a register with copy_to_reg;
-   but then you wouldn't get indexed addressing in the reference.  */
-
-rtx
-copy_all_regs (rtx x)
-{
-  if (GET_CODE (x) == REG)
-    {
-      if (REGNO (x) != FRAME_POINTER_REGNUM
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
-         && REGNO (x) != HARD_FRAME_POINTER_REGNUM
-#endif
-         )
-       x = copy_to_reg (x);
-    }
-  else if (GET_CODE (x) == MEM)
-    x = copy_to_reg (x);
-  else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
-          || GET_CODE (x) == MULT)
-    {
-      rtx op0 = copy_all_regs (XEXP (x, 0));
-      rtx op1 = copy_all_regs (XEXP (x, 1));
-      if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
-       x = gen_rtx_fmt_ee (GET_CODE (x), Pmode, op0, op1);
-    }
-  return x;
-}
 \f
 /* Return something equivalent to X but valid as a memory address
    for something of mode MODE.  When X is not itself valid, this
@@ -436,9 +400,6 @@ memory_address (enum machine_mode mode, rtx x)
 {
   rtx oldx = x;
 
-  if (GET_CODE (x) == ADDRESSOF)
-    return x;
-
   x = convert_memory_address (Pmode, x);
 
   /* By passing constant addresses through registers
@@ -446,25 +407,18 @@ memory_address (enum machine_mode mode, rtx x)
   if (! cse_not_expected && CONSTANT_P (x) && CONSTANT_ADDRESS_P (x))
     x = force_reg (Pmode, x);
 
-  /* Accept a QUEUED that refers to a REG
-     even though that isn't a valid address.
-     On attempting to put this in an insn we will call protect_from_queue
-     which will turn it into a REG, which is valid.  */
-  else if (GET_CODE (x) == QUEUED
-      && GET_CODE (QUEUED_VAR (x)) == REG)
-    ;
-
   /* We get better cse by rejecting indirect addressing at this stage.
      Let the combiner create indirect addresses where appropriate.
      For now, generate the code so that the subexpressions useful to share
      are visible.  But not if cse won't be done!  */
   else
     {
-      if (! cse_not_expected && GET_CODE (x) != REG)
+      if (! cse_not_expected && !REG_P (x))
        x = break_out_memory_refs (x);
 
       /* At this point, any valid address is accepted.  */
-      GO_IF_LEGITIMATE_ADDRESS (mode, x, win);
+      if (memory_address_p (mode, x))
+       goto win;
 
       /* If it was valid before but breaking out memory refs invalidated it,
         use it the old way.  */
@@ -508,7 +462,7 @@ memory_address (enum machine_mode mode, rtx x)
 
       /* If we have a register that's an invalid address,
         it must be a hard reg of the wrong class.  Copy it to a pseudo.  */
-      else if (GET_CODE (x) == REG)
+      else if (REG_P (x))
        x = copy_to_reg (x);
 
       /* Last resort: copy the value to a register, since
@@ -521,7 +475,7 @@ memory_address (enum machine_mode mode, rtx x)
     win2:
       x = oldx;
     win:
-      if (flag_force_addr && ! cse_not_expected && GET_CODE (x) != REG
+      if (flag_force_addr && ! cse_not_expected && !REG_P (x)
          /* Don't copy an addr via a reg if it is one of our stack slots.  */
          && ! (GET_CODE (x) == PLUS
                && (XEXP (x, 0) == virtual_stack_vars_rtx
@@ -540,10 +494,10 @@ memory_address (enum machine_mode mode, rtx x)
      a reg as a pointer if we have REG or REG + CONST_INT.  */
   if (oldx == x)
     return x;
-  else if (GET_CODE (x) == REG)
+  else if (REG_P (x))
     mark_reg_pointer (x, BITS_PER_UNIT);
   else if (GET_CODE (x) == PLUS
-          && GET_CODE (XEXP (x, 0)) == REG
+          && REG_P (XEXP (x, 0))
           && GET_CODE (XEXP (x, 1)) == CONST_INT)
     mark_reg_pointer (XEXP (x, 0), BITS_PER_UNIT);
 
@@ -574,7 +528,7 @@ memory_address_noforce (enum machine_mode mode, rtx x)
 rtx
 validize_mem (rtx ref)
 {
-  if (GET_CODE (ref) != MEM)
+  if (!MEM_P (ref))
     return ref;
   if (! (flag_force_addr && CONSTANT_ADDRESS_P (XEXP (ref, 0)))
       && memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
@@ -584,50 +538,6 @@ validize_mem (rtx ref)
   return replace_equiv_address (ref, XEXP (ref, 0));
 }
 \f
-/* Given REF, either a MEM or a REG, and T, either the type of X or
-   the expression corresponding to REF, set RTX_UNCHANGING_P if
-   appropriate.  */
-
-void
-maybe_set_unchanging (rtx ref, tree t)
-{
-  /* We can set RTX_UNCHANGING_P from TREE_READONLY for decls whose
-     initialization is only executed once, or whose initializer always
-     has the same value.  Currently we simplify this to PARM_DECLs in the
-     first case, and decls with TREE_CONSTANT initializers in the second.
-
-     We cannot do this for non-static aggregates, because of the double
-     writes that can be generated by store_constructor, depending on the
-     contents of the initializer.  Yes, this does eliminate a good fraction
-     of the number of uses of RTX_UNCHANGING_P for a language like Ada.
-     It also eliminates a good quantity of bugs.  Let this be incentive to
-     eliminate RTX_UNCHANGING_P entirely in favor of a more reliable
-     solution, perhaps based on alias sets.  */
-
-  if ((TREE_READONLY (t) && DECL_P (t)
-       && (TREE_STATIC (t) || ! AGGREGATE_TYPE_P (TREE_TYPE (t)))
-       && (TREE_CODE (t) == PARM_DECL
-          || (DECL_INITIAL (t) && TREE_CONSTANT (DECL_INITIAL (t)))))
-      || TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
-    RTX_UNCHANGING_P (ref) = 1;
-}
-\f
-/* Return a modified copy of X with its memory address copied
-   into a temporary register to protect it from side effects.
-   If X is not a MEM, it is returned unchanged (and not copied).
-   Perhaps even if it is a MEM, if there is no need to change it.  */
-
-rtx
-stabilize (rtx x)
-{
-  if (GET_CODE (x) != MEM
-      || ! rtx_unstable_p (XEXP (x, 0)))
-    return x;
-
-  return
-    replace_equiv_address (x, force_reg (Pmode, copy_all_regs (XEXP (x, 0))));
-}
-\f
 /* Copy the value or contents of X to a new temp reg and return that reg.  */
 
 rtx
@@ -668,8 +578,7 @@ copy_to_mode_reg (enum machine_mode mode, rtx x)
   if (! general_operand (x, VOIDmode))
     x = force_operand (x, temp);
 
-  if (GET_MODE (x) != mode && GET_MODE (x) != VOIDmode)
-    abort ();
+  gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);
   if (x != temp)
     emit_move_insn (temp, x);
   return temp;
@@ -688,7 +597,7 @@ force_reg (enum machine_mode mode, rtx x)
 {
   rtx temp, insn, set;
 
-  if (GET_CODE (x) == REG)
+  if (REG_P (x))
     return x;
 
   if (general_operand (x, mode))
@@ -699,7 +608,7 @@ force_reg (enum machine_mode mode, rtx x)
   else
     {
       temp = force_operand (x, NULL_RTX);
-      if (GET_CODE (temp) == REG)
+      if (REG_P (temp))
        insn = get_last_insn ();
       else
        {
@@ -763,7 +672,7 @@ force_not_mem (rtx x)
 {
   rtx temp;
 
-  if (GET_CODE (x) != MEM || GET_MODE (x) == BLKmode)
+  if (!MEM_P (x) || GET_MODE (x) == BLKmode)
     return x;
 
   temp = gen_reg_rtx (GET_MODE (x));
@@ -784,7 +693,7 @@ copy_to_suggested_reg (rtx x, rtx target, enum machine_mode mode)
 {
   rtx temp;
 
-  if (target && GET_CODE (target) == REG)
+  if (target && REG_P (target))
     temp = target;
   else
     temp = gen_reg_rtx (mode);
@@ -858,7 +767,6 @@ void
 adjust_stack (rtx adjust)
 {
   rtx temp;
-  adjust = protect_from_queue (adjust, 0);
 
   if (adjust == const0_rtx)
     return;
@@ -888,7 +796,6 @@ void
 anti_adjust_stack (rtx adjust)
 {
   rtx temp;
-  adjust = protect_from_queue (adjust, 0);
 
   if (adjust == const0_rtx)
     return;
@@ -914,7 +821,7 @@ anti_adjust_stack (rtx adjust)
 /* Round the size of a block to be pushed up to the boundary required
    by this machine.  SIZE is the desired size, which need not be constant.  */
 
-rtx
+static rtx
 round_push (rtx size)
 {
   int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
@@ -1004,6 +911,7 @@ emit_stack_save (enum save_level save_level, rtx *psave, rtx after)
       rtx seq;
 
       start_sequence ();
+      do_pending_stack_adjust ();
       /* We must validize inside the sequence, to ensure that any instructions
         created by the validize call also get moved to the right place.  */
       if (sa != 0)
@@ -1015,6 +923,7 @@ emit_stack_save (enum save_level save_level, rtx *psave, rtx after)
     }
   else
     {
+      do_pending_stack_adjust ();
       if (sa != 0)
        sa = validize_mem (sa);
       emit_insn (fcn (sa, stack_pointer_rtx));
@@ -1071,6 +980,8 @@ emit_stack_restore (enum save_level save_level, rtx sa, rtx after)
                    gen_rtx_MEM (BLKmode, stack_pointer_rtx)));
     }
 
+  discard_pending_stack_adjust ();
+
   if (after)
     {
       rtx seq;
@@ -1099,8 +1010,8 @@ update_nonlocal_goto_save_area (void)
      first one is used for the frame pointer save; the rest are sized by
      STACK_SAVEAREA_MODE.  Create a reference to array index 1, the first
      of the stack save area slots.  */
-  t_save = build (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area,
-                 integer_one_node);
+  t_save = build4 (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area,
+                  integer_one_node, NULL_TREE, NULL_TREE);
   r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE);
 
   emit_stack_save (SAVE_NONLOCAL, &r_save, NULL_RTX);
@@ -1113,15 +1024,15 @@ update_nonlocal_goto_save_area (void)
    frame, thus causing a crash if a longjmp unwinds to it.  */
 
 void
-optimize_save_area_alloca (rtx insns)
+optimize_save_area_alloca (void)
 {
   rtx insn;
 
-  for (insn = insns; insn; insn = NEXT_INSN(insn))
+  for (insn = get_insns (); insn; insn = NEXT_INSN(insn))
     {
       rtx note;
 
-      if (GET_CODE (insn) != INSN)
+      if (!NONJUMP_INSN_P (insn))
        continue;
 
       for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
@@ -1143,11 +1054,10 @@ optimize_save_area_alloca (rtx insns)
 
                 Right now only supported port with stack that grow upward
                 is the HPPA and it does not define SETJMP_VIA_SAVE_AREA.  */
-             if (GET_CODE (pat) != SET
-                 || SET_DEST (pat) != stack_pointer_rtx
-                 || GET_CODE (SET_SRC (pat)) != MINUS
-                 || XEXP (SET_SRC (pat), 0) != stack_pointer_rtx)
-               abort ();
+             gcc_assert (GET_CODE (pat) == SET
+                         && SET_DEST (pat) == stack_pointer_rtx
+                         && GET_CODE (SET_SRC (pat)) == MINUS
+                         && XEXP (SET_SRC (pat), 0) == stack_pointer_rtx);
 
              /* This will now be transformed into a (set REG REG)
                 so we can just blow away all the other notes.  */
@@ -1171,8 +1081,7 @@ optimize_save_area_alloca (rtx insns)
                    if (XEXP (srch, 1) == note)
                      break;
 
-                 if (srch == NULL_RTX)
-                   abort ();
+                 gcc_assert (srch);
 
                  XEXP (srch, 1) = XEXP (note, 1);
                }
@@ -1266,8 +1175,7 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
 
        /* ??? Code below assumes that the save area needs maximal
           alignment.  This constraint may be too strong.  */
-       if (PREFERRED_STACK_BOUNDARY != BIGGEST_ALIGNMENT)
-         abort ();
+       gcc_assert (PREFERRED_STACK_BOUNDARY == BIGGEST_ALIGNMENT);
 
        if (GET_CODE (size) == CONST_INT)
          {
@@ -1324,8 +1232,8 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
 
  /* We ought to be called always on the toplevel and stack ought to be aligned
     properly.  */
-  if (stack_pointer_delta % (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT))
-    abort ();
+  gcc_assert (!(stack_pointer_delta
+               % (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)));
 
   /* If needed, check that we have the required amount of stack.  Take into
      account what has already been checked.  */
@@ -1333,7 +1241,7 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
     probe_stack_range (STACK_CHECK_MAX_FRAME_SIZE + STACK_CHECK_PROTECT, size);
 
   /* Don't use a TARGET that isn't a pseudo or is the wrong mode.  */
-  if (target == 0 || GET_CODE (target) != REG
+  if (target == 0 || !REG_P (target)
       || REGNO (target) < FIRST_PSEUDO_REGISTER
       || GET_MODE (target) != Pmode)
     target = gen_reg_rtx (Pmode);
@@ -1557,7 +1465,7 @@ probe_stack_range (HOST_WIDE_INT first, rtx size)
       rtx end_lab = gen_label_rtx ();
       rtx temp;
 
-      if (GET_CODE (test_addr) != REG
+      if (!REG_P (test_addr)
          || REGNO (test_addr) < FIRST_PSEUDO_REGISTER)
        test_addr = force_reg (Pmode, test_addr);
 
@@ -1576,8 +1484,7 @@ probe_stack_range (HOST_WIDE_INT first, rtx size)
                           1, OPTAB_WIDEN);
 #endif
 
-      if (temp != test_addr)
-       abort ();
+      gcc_assert (temp == test_addr);
 
       emit_label (test_lab);
       emit_cmp_and_jump_insns (test_addr, last_addr, CMP_OPCODE,
@@ -1611,7 +1518,7 @@ hard_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
 #endif
     val = FUNCTION_VALUE (valtype, func);
 
-  if (GET_CODE (val) == REG
+  if (REG_P (val)
       && GET_MODE (val) == BLKmode)
     {
       unsigned HOST_WIDE_INT bytes = int_size_in_bytes (valtype);
@@ -1631,8 +1538,7 @@ hard_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
        }
 
       /* No suitable mode found.  */
-      if (tmpmode == VOIDmode)
-       abort ();
+      gcc_assert (tmpmode != VOIDmode);
 
       PUT_MODE (val, tmpmode);
     }