OSDN Git Service

* Makefile.in (distclean): Don't try to remove empty directories.
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index a3f89a1..989a5fa 100644 (file)
@@ -168,7 +168,6 @@ static void emit_single_push_insn (enum machine_mode, rtx, tree);
 #endif
 static void do_tablejump (rtx, enum machine_mode, rtx, rtx, rtx);
 static rtx const_vector_from_tree (tree);
-static void execute_expand (void);
 
 /* Record for each mode whether we can move a register directly to or
    from an object of that mode in memory.  If we can't, we won't try
@@ -5592,15 +5591,13 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
       else if (TREE_CODE (exp) == COMPONENT_REF)
        {
          tree field = TREE_OPERAND (exp, 1);
-         tree this_offset = DECL_FIELD_OFFSET (field);
+         tree this_offset = component_ref_field_offset (exp);
 
          /* If this field hasn't been filled in yet, don't go
             past it.  This should only happen when folding expressions
             made during type construction.  */
          if (this_offset == 0)
            break;
-         else
-           this_offset = SUBSTITUTE_PLACEHOLDER_IN_EXPR (this_offset, exp);
 
          offset = size_binop (PLUS_EXPR, offset, this_offset);
          bit_offset = size_binop (PLUS_EXPR, bit_offset,
@@ -5613,23 +5610,17 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
               || TREE_CODE (exp) == ARRAY_RANGE_REF)
        {
          tree index = TREE_OPERAND (exp, 1);
-         tree array = TREE_OPERAND (exp, 0);
-         tree domain = TYPE_DOMAIN (TREE_TYPE (array));
-         tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
-         tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array)));
+         tree low_bound = array_ref_low_bound (exp);
+         tree unit_size = array_ref_element_size (exp);
 
          /* We assume all arrays have sizes that are a multiple of a byte.
             First subtract the lower bound, if any, in the type of the
             index, then convert to sizetype and multiply by the size of the
             array element.  */
-         if (low_bound != 0 && ! integer_zerop (low_bound))
+         if (! integer_zerop (low_bound))
            index = fold (build (MINUS_EXPR, TREE_TYPE (index),
                                 index, low_bound));
 
-         /* If the index has a self-referential type, instantiate it with
-            the object; likewise for the component size.  */
-         index = SUBSTITUTE_PLACEHOLDER_IN_EXPR (index, exp);
-         unit_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (unit_size, array);
          offset = size_binop (PLUS_EXPR, offset,
                               size_binop (MULT_EXPR,
                                           convert (sizetype, index),
@@ -5677,6 +5668,70 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
   return exp;
 }
 
+/* Return a tree of sizetype representing the size, in bytes, of the element
+   of EXP, an ARRAY_REF.  */
+
+tree
+array_ref_element_size (tree exp)
+{
+  tree aligned_size = TREE_OPERAND (exp, 3);
+  tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+
+  /* If a size was specified in the ARRAY_REF, it's the size measured
+     in alignment units of the element type.  So multiply by that value.  */
+  if (aligned_size)
+    return size_binop (MULT_EXPR, aligned_size,
+                      size_int (TYPE_ALIGN (elmt_type) / BITS_PER_UNIT));
+
+  /* Otherwise, take the size from that of the element type.  Substitute 
+     any PLACEHOLDER_EXPR that we have.  */
+  else
+    return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp);
+}
+
+/* Return a tree representing the lower bound of the array mentioned in
+   EXP, an ARRAY_REF.  */
+
+tree
+array_ref_low_bound (tree exp)
+{
+  tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
+
+  /* If a lower bound is specified in EXP, use it.  */
+  if (TREE_OPERAND (exp, 2))
+    return TREE_OPERAND (exp, 2);
+
+  /* Otherwise, if there is a domain type and it has a lower bound, use it,
+     substituting for a PLACEHOLDER_EXPR as needed.  */
+  if (domain_type && TYPE_MIN_VALUE (domain_type))
+    return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), exp);
+
+  /* Otherwise, return a zero of the appropriate type.  */
+  return fold_convert (TREE_TYPE (TREE_OPERAND (exp, 1)), integer_zero_node);
+}
+
+/* Return a tree representing the offset, in bytes, of the field referenced
+   by EXP.  This does not include any offset in DECL_FIELD_BIT_OFFSET.  */
+
+tree
+component_ref_field_offset (tree exp)
+{
+  tree aligned_offset = TREE_OPERAND (exp, 2);
+  tree field = TREE_OPERAND (exp, 1);
+
+  /* If an offset was specified in the COMPONENT_REF, it's the offset measured
+     in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT.  So multiply by that
+     value.  */
+  if (aligned_offset)
+    return size_binop (MULT_EXPR, aligned_offset,
+                      size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT));
+
+  /* Otherwise, take the offset from that of the field.  Substitute 
+     any PLACEHOLDER_EXPR that we have.  */
+  else
+    return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
+}
+
 /* Return 1 if T is an expression that get_inner_reference handles.  */
 
 int
@@ -7002,8 +7057,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
       {
        tree array = TREE_OPERAND (exp, 0);
-       tree domain = TYPE_DOMAIN (TREE_TYPE (array));
-       tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
+       tree low_bound = array_ref_low_bound (exp);
        tree index = convert (sizetype, TREE_OPERAND (exp, 1));
        HOST_WIDE_INT i;
 
@@ -8862,7 +8916,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        /* Mark it as expanded.  */
        TREE_OPERAND (exp, 1) = NULL_TREE;
 
-       store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0);
+       if (VOID_TYPE_P (TREE_TYPE (exp1)))
+         /* If the initializer is void, just expand it; it will initialize
+            the object directly.  */
+         expand_expr (exp1, const0_rtx, VOIDmode, 0);
+       else
+         store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0);
 
        expand_decl_cleanup_eh (NULL_TREE, cleanups, CLEANUP_EH_ONLY (exp));
 
@@ -10208,92 +10267,4 @@ const_vector_from_tree (tree exp)
 
   return gen_rtx_raw_CONST_VECTOR (mode, v);
 }
-\f
-/* Called to move the SAVE_EXPRs for parameter declarations in a
-   nested function into the nested function.  DATA is really the
-   nested FUNCTION_DECL.  */
-
-static tree
-set_save_expr_context (tree *tp,
-                       int *walk_subtrees,
-                       void *data)
-{
-  if (TREE_CODE (*tp) == SAVE_EXPR && !SAVE_EXPR_CONTEXT (*tp))
-    SAVE_EXPR_CONTEXT (*tp) = (tree) data;
-  /* Do not walk back into the SAVE_EXPR_CONTEXT; that will cause
-     circularity.  */
-  else if (DECL_P (*tp))
-    *walk_subtrees = 0;
-
-  return NULL;
-}
-
-
-static void
-execute_expand (void)
-{
-  /* If the function has a variably modified type, there may be
-     SAVE_EXPRs in the parameter types.  Their context must be set to
-     refer to this function; they cannot be expanded in the containing
-     function.  */
-  if (decl_function_context (current_function_decl) == current_function_decl
-      && variably_modified_type_p (TREE_TYPE (current_function_decl)))
-    walk_tree (&TREE_TYPE (current_function_decl), set_save_expr_context,
-              current_function_decl, NULL);
-
-  /* Expand the variables recorded during gimple lowering.  This must
-     occur before the call to expand_function_start to ensure that
-     all used variables are expanded before we expand anything on the
-     PENDING_SIZES list.  */
-  expand_used_vars ();
-
-  /* Set up parameters and prepare for return, for the function.  */
-  expand_function_start (current_function_decl, 0);
-
-  /* If this function is `main', emit a call to `__main'
-     to run global initializers, etc.  */
-  if (DECL_NAME (current_function_decl)
-      && MAIN_NAME_P (DECL_NAME (current_function_decl))
-      && DECL_FILE_SCOPE_P (current_function_decl))
-    expand_main_function ();
-
-  /* Generate the RTL for this function.  */
-  expand_expr_stmt_value (DECL_SAVED_TREE (current_function_decl), 0, 0);
-
-  /* We hard-wired immediate_size_expand to zero above.
-     expand_function_end will decrement this variable.  So, we set the
-     variable to one here, so that after the decrement it will remain
-     zero.  */
-  immediate_size_expand = 1;
-
-  /* Make sure the locus is set to the end of the function, so that
-     epilogue line numbers and warnings are set properly.  */
-  if (cfun->function_end_locus.file)
-    input_location = cfun->function_end_locus;
-
-  /* The following insns belong to the top scope.  */
-  record_block_change (DECL_INITIAL (current_function_decl));
-
-  /* Generate rtl for function exit.  */
-  expand_function_end ();
-}
-
-struct tree_opt_pass pass_expand =
-{
-  "expand",                            /* name */
-  NULL,                                 /* gate */
-  execute_expand,                      /* execute */
-  NULL,                                 /* sub */
-  NULL,                                 /* next */
-  0,                                    /* static_pass_number */
-  TV_EXPAND,                           /* tv_id */
-  /* ??? If TER is enabled, we actually receive GENERIC.  */
-  PROP_gimple_leh,                      /* properties_required */
-  PROP_rtl,                             /* properties_provided */
-  PROP_cfg | PROP_gimple_leh,           /* properties_destroyed */
-  0,                                    /* todo_flags_start */
-  0                                     /* todo_flags_finish */
-};
-
-
 #include "gt-expr.h"