OSDN Git Service

* alias.c (get_alias_set): Try to replace PLACEHOLDER_EXPR.
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index ffb46cb..52f9cc0 100644 (file)
@@ -2,22 +2,22 @@
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
    2000, 2001 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -163,9 +163,6 @@ static rtx store_field              PARAMS ((rtx, HOST_WIDE_INT,
                                         unsigned int, HOST_WIDE_INT, int));
 static enum memory_use_mode
   get_memory_usage_from_modifier PARAMS ((enum expand_modifier));
-static tree save_noncopied_parts PARAMS ((tree, tree));
-static tree init_noncopied_parts PARAMS ((tree, tree));
-static int fixed_type_p                PARAMS ((tree));
 static rtx var_rtx             PARAMS ((tree));
 static rtx expand_expr_unaligned PARAMS ((tree, unsigned int *));
 static rtx expand_increment    PARAMS ((tree, int, int));
@@ -3102,18 +3099,11 @@ push_block (size, extra, below)
     }
 
 #ifndef STACK_GROWS_DOWNWARD
-#ifdef ARGS_GROW_DOWNWARD
-  if (!ACCUMULATE_OUTGOING_ARGS)
-#else
   if (0)
-#endif
 #else
   if (1)
 #endif
     {
-      /* Return the lowest stack address when STACK or ARGS grow downward and
-        we are not aaccumulating outgoing arguments (the c4x port uses such
-        conventions).  */
       temp = virtual_outgoing_args_rtx;
       if (extra != 0 && below)
        temp = plus_constant (temp, extra);
@@ -3273,8 +3263,9 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
      Default is below for small data on big-endian machines; else above.  */
   enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);
 
-  /* Invert direction if stack is post-update.  */
-  if (STACK_PUSH_CODE == POST_INC || STACK_PUSH_CODE == POST_DEC)
+  /* Invert direction if stack is post-decrement. 
+     FIXME: why?  */
+  if (STACK_PUSH_CODE == POST_DEC)
     if (where_pad != none)
       where_pad = (where_pad == downward ? upward : downward);
 
@@ -4719,7 +4710,9 @@ store_constructor (exp, target, align, cleared, size)
       int need_to_clear;
       tree domain = TYPE_DOMAIN (type);
       tree elttype = TREE_TYPE (type);
-      int const_bounds_p = (host_integerp (TYPE_MIN_VALUE (domain), 0)
+      int const_bounds_p = (TYPE_MIN_VALUE (domain)
+                           && TYPE_MAX_VALUE (domain)
+                           && host_integerp (TYPE_MIN_VALUE (domain), 0)
                            && host_integerp (TYPE_MAX_VALUE (domain), 0));
       HOST_WIDE_INT minelt = 0;
       HOST_WIDE_INT maxelt = 0;
@@ -5665,68 +5658,6 @@ force_operand (value, target)
   return value;
 }
 \f
-/* Subroutine of expand_expr:
-   save the non-copied parts (LIST) of an expr (LHS), and return a list
-   which can restore these values to their previous values,
-   should something modify their storage.  */
-
-static tree
-save_noncopied_parts (lhs, list)
-     tree lhs;
-     tree list;
-{
-  tree tail;
-  tree parts = 0;
-
-  for (tail = list; tail; tail = TREE_CHAIN (tail))
-    if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
-      parts = chainon (parts, save_noncopied_parts (lhs, TREE_VALUE (tail)));
-    else
-      {
-       tree part = TREE_VALUE (tail);
-       tree part_type = TREE_TYPE (part);
-       tree to_be_saved = build (COMPONENT_REF, part_type, lhs, part);
-       rtx target
-         = assign_temp (build_qualified_type (part_type,
-                                              (TYPE_QUALS (part_type)
-                                               | TYPE_QUAL_CONST)),
-                        0, 1, 1);
-
-       parts = tree_cons (to_be_saved,
-                          build (RTL_EXPR, part_type, NULL_TREE,
-                                 (tree) validize_mem (target)),
-                          parts);
-       store_expr (TREE_PURPOSE (parts),
-                   RTL_EXPR_RTL (TREE_VALUE (parts)), 0);
-      }
-  return parts;
-}
-
-/* Subroutine of expand_expr:
-   record the non-copied parts (LIST) of an expr (LHS), and return a list
-   which specifies the initial values of these parts.  */
-
-static tree
-init_noncopied_parts (lhs, list)
-     tree lhs;
-     tree list;
-{
-  tree tail;
-  tree parts = 0;
-
-  for (tail = list; tail; tail = TREE_CHAIN (tail))
-    if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
-      parts = chainon (parts, init_noncopied_parts (lhs, TREE_VALUE (tail)));
-    else if (TREE_PURPOSE (tail))
-      {
-       tree part = TREE_VALUE (tail);
-       tree part_type = TREE_TYPE (part);
-       tree to_be_initialized = build (COMPONENT_REF, part_type, lhs, part);
-       parts = tree_cons (TREE_PURPOSE (tail), to_be_initialized, parts);
-      }
-  return parts;
-}
-
 /* Subroutine of expand_expr: return nonzero iff there is no way that
    EXP can reference X, which is being modified.  TOP_P is nonzero if this
    call is going to be used to determine whether we need a temporary
@@ -5951,22 +5882,6 @@ safe_from_p (x, exp, top_p)
   return 1;
 }
 
-/* Subroutine of expand_expr: return nonzero iff EXP is an
-   expression whose type is statically determinable.  */
-
-static int
-fixed_type_p (exp)
-     tree exp;
-{
-  if (TREE_CODE (exp) == PARM_DECL
-      || TREE_CODE (exp) == VAR_DECL
-      || TREE_CODE (exp) == CALL_EXPR || TREE_CODE (exp) == TARGET_EXPR
-      || TREE_CODE (exp) == COMPONENT_REF
-      || TREE_CODE (exp) == ARRAY_REF)
-    return 1;
-  return 0;
-}
-
 /* Subroutine of expand_expr: return rtx if EXP is a
    variable or parameter; else return 0.  */
 
@@ -6040,6 +5955,69 @@ check_max_integer_computation_mode (exp)
 }
 #endif
 \f
+/* Return an object on the placeholder list that matches EXP, a
+   PLACEHOLDER_EXPR.  An object "matches" if it is of the type of the
+   PLACEHOLDER_EXPR or a pointer type to it.  For further information,
+   see tree.def.  If no such object is found, abort.  If PLIST is nonzero,
+   it is a location into which a pointer into the placeholder list at
+   which the object is found is placed.  */
+
+tree
+find_placeholder (exp, plist)
+     tree exp;
+     tree *plist;
+{
+  tree type = TREE_TYPE (exp);
+  tree placeholder_expr;
+
+  for (placeholder_expr = placeholder_list; placeholder_expr != 0;
+       placeholder_expr = TREE_CHAIN (placeholder_expr))
+    {
+      tree need_type = TYPE_MAIN_VARIANT (type);
+      tree elt;
+
+      /* Find the outermost reference that is of the type we want.  If none,
+        see if any object has a type that is a pointer to the type we
+        want.  */
+      for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
+          elt = ((TREE_CODE (elt) == COMPOUND_EXPR
+                  || TREE_CODE (elt) == COND_EXPR)
+                 ? TREE_OPERAND (elt, 1)
+                 : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
+                    || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
+                    || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
+                    || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
+                 ? TREE_OPERAND (elt, 0) : 0))
+       if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
+         {
+           if (plist)
+             *plist = placeholder_expr;
+           return elt;
+         }
+
+      for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
+          elt
+          = ((TREE_CODE (elt) == COMPOUND_EXPR
+              || TREE_CODE (elt) == COND_EXPR)
+             ? TREE_OPERAND (elt, 1)
+             : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
+                || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
+                || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
+                || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
+             ? TREE_OPERAND (elt, 0) : 0))
+       if (POINTER_TYPE_P (TREE_TYPE (elt))
+           && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
+               == need_type))
+         {
+           if (plist)
+             *plist = placeholder_expr;
+           return build1 (INDIRECT_REF, need_type, elt);
+         }
+    }
+
+  abort ();
+}
+\f
 /* expand_expr: generate code for computing expression EXP.
    An rtx for the computed value is returned.  The value is never null.
    In the case of a void EXP, const0_rtx is returned.
@@ -6567,66 +6545,14 @@ expand_expr (exp, target, tmode, modifier)
 
     case PLACEHOLDER_EXPR:
       {
+       tree old_list = placeholder_list;
        tree placeholder_expr;
 
-       /* If there is an object on the head of the placeholder list,
-          see if some object in it of type TYPE or a pointer to it.  For
-          further information, see tree.def.  */
-       for (placeholder_expr = placeholder_list;
-            placeholder_expr != 0;
-            placeholder_expr = TREE_CHAIN (placeholder_expr))
-         {
-           tree need_type = TYPE_MAIN_VARIANT (type);
-           tree object = 0;
-           tree old_list = placeholder_list;
-           tree elt;
-
-           /* Find the outermost reference that is of the type we want.
-              If none, see if any object has a type that is a pointer to
-              the type we want.  */
-           for (elt = TREE_PURPOSE (placeholder_expr);
-                elt != 0 && object == 0;
-                elt
-                = ((TREE_CODE (elt) == COMPOUND_EXPR
-                    || TREE_CODE (elt) == COND_EXPR)
-                   ? TREE_OPERAND (elt, 1)
-                   : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
-                      || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
-                      || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
-                      || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
-                   ? TREE_OPERAND (elt, 0) : 0))
-             if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
-               object = elt;
-
-           for (elt = TREE_PURPOSE (placeholder_expr);
-                elt != 0 && object == 0;
-                elt
-                = ((TREE_CODE (elt) == COMPOUND_EXPR
-                    || TREE_CODE (elt) == COND_EXPR)
-                   ? TREE_OPERAND (elt, 1)
-                   : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
-                      || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
-                      || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
-                      || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
-                   ? TREE_OPERAND (elt, 0) : 0))
-             if (POINTER_TYPE_P (TREE_TYPE (elt))
-                 && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
-                     == need_type))
-               object = build1 (INDIRECT_REF, need_type, elt);
-
-           if (object != 0)
-             {
-               /* Expand this object skipping the list entries before
-                  it was found in case it is also a PLACEHOLDER_EXPR.
-                  In that case, we want to translate it using subsequent
-                  entries.  */
-               placeholder_list = TREE_CHAIN (placeholder_expr);
-               temp = expand_expr (object, original_target, tmode,
-                                   ro_modifier);
-               placeholder_list = old_list;
-               return temp;
-             }
-         }
+       exp = find_placeholder (exp, &placeholder_expr);
+       placeholder_list = TREE_CHAIN (placeholder_expr);
+       temp = expand_expr (exp, original_target, tmode, ro_modifier);
+       placeholder_list = old_list;
+       return temp;
       }
 
       /* We can't find the object or there was a missing WITH_RECORD_EXPR.  */
@@ -7008,6 +6934,7 @@ expand_expr (exp, target, tmode, modifier)
        tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
                                        &mode1, &unsignedp, &volatilep,
                                        &alignment);
+       rtx orig_op0;
 
        /* If we got back the original object, something is wrong.  Perhaps
           we are evaluating an expression too early.  In any event, don't
@@ -7019,15 +6946,16 @@ expand_expr (exp, target, tmode, modifier)
           computation, since it will need a temporary and TARGET is known
           to have to do.  This occurs in unchecked conversion in Ada.  */
 
-       op0 = expand_expr (tem,
-                          (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
-                           && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
-                               != INTEGER_CST)
-                           ? target : NULL_RTX),
-                          VOIDmode,
-                          (modifier == EXPAND_INITIALIZER
-                           || modifier == EXPAND_CONST_ADDRESS)
-                          ? modifier : EXPAND_NORMAL);
+       orig_op0 = op0
+         = expand_expr (tem,
+                        (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
+                         && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
+                             != INTEGER_CST)
+                         ? target : NULL_RTX),
+                        VOIDmode,
+                        (modifier == EXPAND_INITIALIZER
+                         || modifier == EXPAND_CONST_ADDRESS)
+                        ? modifier : EXPAND_NORMAL);
 
        /* If this is a constant, put it into a register if it is a
           legitimate constant and OFFSET is 0 and memory if it isn't.  */
@@ -7116,7 +7044,9 @@ expand_expr (exp, target, tmode, modifier)
        /* Don't forget about volatility even if this is a bitfield.  */
        if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0))
          {
-           op0 = copy_rtx (op0);
+           if (op0 == orig_op0)
+             op0 = copy_rtx (op0);
+
            MEM_VOLATILE_P (op0) = 1;
          }
 
@@ -7258,6 +7188,9 @@ expand_expr (exp, target, tmode, modifier)
        else
          op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
 
+       if (op0 == orig_op0)
+         op0 = copy_rtx (op0);
+
        set_mem_attributes (op0, exp, 0);
        if (GET_CODE (XEXP (op0, 0)) == REG)
          mark_reg_pointer (XEXP (op0, 0), alignment);
@@ -8511,37 +8444,23 @@ expand_expr (exp, target, tmode, modifier)
       {
        tree lhs = TREE_OPERAND (exp, 0);
        tree rhs = TREE_OPERAND (exp, 1);
-       tree noncopied_parts = 0;
-       tree lhs_type = TREE_TYPE (lhs);
 
        temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
-       if (TYPE_NONCOPIED_PARTS (lhs_type) != 0 && !fixed_type_p (rhs))
-         noncopied_parts
-           = init_noncopied_parts (stabilize_reference (lhs),
-                                   TYPE_NONCOPIED_PARTS (lhs_type));
-
-       while (noncopied_parts != 0)
-         {
-           expand_assignment (TREE_VALUE (noncopied_parts),
-                              TREE_PURPOSE (noncopied_parts), 0, 0);
-           noncopied_parts = TREE_CHAIN (noncopied_parts);
-         }
        return temp;
       }
 
     case MODIFY_EXPR:
       {
        /* If lhs is complex, expand calls in rhs before computing it.
-          That's so we don't compute a pointer and save it over a call.
-          If lhs is simple, compute it first so we can give it as a
-          target if the rhs is just a call.  This avoids an extra temp and copy
-          and that prevents a partial-subsumption which makes bad code.
-          Actually we could treat component_ref's of vars like vars.  */
+          That's so we don't compute a pointer and save it over a
+          call.  If lhs is simple, compute it first so we can give it
+          as a target if the rhs is just a call.  This avoids an
+          extra temp and copy and that prevents a partial-subsumption
+          which makes bad code.  Actually we could treat
+          component_ref's of vars like vars.  */
 
        tree lhs = TREE_OPERAND (exp, 0);
        tree rhs = TREE_OPERAND (exp, 1);
-       tree noncopied_parts = 0;
-       tree lhs_type = TREE_TYPE (lhs);
 
        temp = 0;
 
@@ -8577,19 +8496,8 @@ expand_expr (exp, target, tmode, modifier)
            return const0_rtx;
          }
 
-       if (TYPE_NONCOPIED_PARTS (lhs_type) != 0
-           && ! (fixed_type_p (lhs) && fixed_type_p (rhs)))
-         noncopied_parts
-           = save_noncopied_parts (stabilize_reference (lhs),
-                                   TYPE_NONCOPIED_PARTS (lhs_type));
-
        temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
-       while (noncopied_parts != 0)
-         {
-           expand_assignment (TREE_PURPOSE (noncopied_parts),
-                              TREE_VALUE (noncopied_parts), 0, 0);
-           noncopied_parts = TREE_CHAIN (noncopied_parts);
-         }
+       
        return temp;
       }
 
@@ -8867,6 +8775,11 @@ expand_expr (exp, target, tmode, modifier)
     case EXC_PTR_EXPR:
       return get_exception_pointer (cfun);
 
+    case FDESC_EXPR:
+      /* Function descriptors are not valid except for as
+        initialization constants, and should not be expanded.  */
+      abort ();
+
     default:
       return (*lang_expand_expr) (exp, original_target, tmode, modifier);
     }