tree.def (VIEW_CONVERT_EXPR): New tree code.
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>
Mon, 19 Nov 2001 20:38:07 +0000 (20:38 +0000)
committerRichard Kenner <kenner@gcc.gnu.org>
Mon, 19 Nov 2001 20:38:07 +0000 (15:38 -0500)
* tree.def (VIEW_CONVERT_EXPR): New tree code.
* tree.h (handled_component_p): New declaration.
* alias.c (handled_component_p): Move function from here ...
* expr.c (handled_component_p): ... to here and non longer static.
(is_zeros_p, case VIEW_CONVERT_EXPR): New case.
(store_field): Remove unneeded MEM_COPY_ATTRIBUTES call.
(get_inner_reference): Handle VIEW_CONVERT_EXPR.
(expand_expr, case VAR_DECL): Clean up handling of re-layout case.
(expand_expr, case VIEW_CONVERT_EXPR): New case.
(expand_expr, cse ADDR_EXPR): No need to copy if already
BIGGEST_ALIGNMENT.
* fold-const.c (fold, case VIEW_CONVERT_EXPR): New case.
* varasm.c (initializer_constant_value_p, case VIEW_CONVERT_EXPR): New.
(output_constant): Handle VIEW_CONVERT_EXPR.
* dwarf2out.c (loc-descriptor_from_tree, add_bound_info):
Add new case for VIEW_CONVERT_EXPR.

From-SVN: r47179

gcc/ChangeLog
gcc/alias.c
gcc/dwarf2out.c
gcc/expr.c
gcc/fold-const.c
gcc/tree.def
gcc/tree.h
gcc/varasm.c

index 63bbd149ff01da201b4403459e712ba6fddd8455..6cae9dc73eef8d8e2484ac87f47f49dc1df3c42e 100644 (file)
@@ -1,3 +1,22 @@
+Mon Nov 19 15:13:43 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * tree.def (VIEW_CONVERT_EXPR): New tree code.
+       * tree.h (handled_component_p): New declaration.
+       * alias.c (handled_component_p): Move function from here ...
+       * expr.c (handled_component_p): ... to here and non longer static.
+       (is_zeros_p, case VIEW_CONVERT_EXPR): New case.
+       (store_field): Remove unneeded MEM_COPY_ATTRIBUTES call.
+       (get_inner_reference): Handle VIEW_CONVERT_EXPR.
+       (expand_expr, case VAR_DECL): Clean up handling of re-layout case.
+       (expand_expr, case VIEW_CONVERT_EXPR): New case.
+       (expand_expr, cse ADDR_EXPR): No need to copy if already
+       BIGGEST_ALIGNMENT.
+       * fold-const.c (fold, case VIEW_CONVERT_EXPR): New case.
+       * varasm.c (initializer_constant_value_p, case VIEW_CONVERT_EXPR): New.
+       (output_constant): Handle VIEW_CONVERT_EXPR.
+       * dwarf2out.c (loc-descriptor_from_tree, add_bound_info):
+       Add new case for VIEW_CONVERT_EXPR.
+
 2001-11-19  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * a29k/unix.h (ASM_FILE_START): Const-ify.
index 27e7e3903fd20a0b46cfddd0fd141ecb85fffebd..a92cf857844f63de38cd86ad0ae65296eef51423 100644 (file)
@@ -95,7 +95,6 @@ static void record_set                        PARAMS ((rtx, rtx, void *));
 static rtx find_base_term              PARAMS ((rtx));
 static int base_alias_check            PARAMS ((rtx, rtx, enum machine_mode,
                                                 enum machine_mode));
-static int handled_component_p         PARAMS ((tree));
 static rtx find_base_value             PARAMS ((rtx));
 static int mems_in_disjoint_alias_sets_p PARAMS ((rtx, rtx));
 static int insert_subset_children       PARAMS ((splay_tree_node, void*));
@@ -399,31 +398,6 @@ find_base_decl (t)
     }
 }
 
-/* Return 1 if T is an expression that get_inner_reference handles.  */
-
-static int
-handled_component_p (t)
-     tree t;
-{
-  switch (TREE_CODE (t))
-    {
-    case BIT_FIELD_REF:
-    case COMPONENT_REF:
-    case ARRAY_REF:
-    case ARRAY_RANGE_REF:
-    case NON_LVALUE_EXPR:
-      return 1;
-
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-      return (TYPE_MODE (TREE_TYPE (t))
-             == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))));
-
-    default:
-      return 0;
-    }
-}
-
 /* Return 1 if all the nested component references handled by
    get_inner_reference in T are such that we can address the object in T.  */
 
index 86a3a6a396131a423603638e388afe7cb928df42..164b05112813145645ebac6b4e19fee69924cd41 100644 (file)
@@ -7929,6 +7929,7 @@ loc_descriptor_from_tree (loc, addressp)
     case NOP_EXPR:
     case CONVERT_EXPR:
     case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
     case SAVE_EXPR:
       return loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp);
 
@@ -8849,6 +8850,7 @@ add_bound_info (subrange_die, bound_attr, bound)
     case CONVERT_EXPR:
     case NOP_EXPR:
     case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
       add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0));
       break;
 
index 324f5cd106c9fa42a5e23016b30da0eab8cf3337..0c5429ec1873180781e8c0a667888a723df9b49b 100644 (file)
@@ -4360,6 +4360,7 @@ is_zeros_p (exp)
     case CONVERT_EXPR:
     case NOP_EXPR:
     case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
       return is_zeros_p (TREE_OPERAND (exp, 0));
 
     case INTEGER_CST:
@@ -5151,7 +5152,6 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type,
       rtx blk_object = copy_rtx (object);
 
       PUT_MODE (blk_object, BLKmode);
-      MEM_COPY_ATTRIBUTES (blk_object, object);
 
       if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
        emit_move_insn (object, target);
@@ -5451,6 +5451,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
          continue;
        }
       else if (TREE_CODE (exp) != NON_LVALUE_EXPR
+              && TREE_CODE (exp) != VIEW_CONVERT_EXPR
               && ! ((TREE_CODE (exp) == NOP_EXPR
                      || TREE_CODE (exp) == CONVERT_EXPR)
                     && (TYPE_MODE (TREE_TYPE (exp))
@@ -5479,6 +5480,32 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
   return exp;
 }
 
+/* Return 1 if T is an expression that get_inner_reference handles.  */
+
+int
+handled_component_p (t)
+     tree t;
+{
+  switch (TREE_CODE (t))
+    {
+    case BIT_FIELD_REF:
+    case COMPONENT_REF:
+    case ARRAY_REF:
+    case ARRAY_RANGE_REF:
+    case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
+      return 1;
+
+    case NOP_EXPR:
+    case CONVERT_EXPR:
+      return (TYPE_MODE (TREE_TYPE (t))
+             == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))));
+
+    default:
+      return 0;
+    }
+}
+
 /* Subroutine of expand_exp: compute memory_usage from modifier.  */
 
 static enum memory_use_mode
@@ -6287,9 +6314,19 @@ expand_expr (exp, target, tmode, modifier)
       if (DECL_SIZE (exp) == 0 && COMPLETE_TYPE_P (TREE_TYPE (exp))
          && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
        {
+         rtx value = DECL_RTL_IF_SET (exp);
+
          layout_decl (exp, 0);
-         PUT_MODE (DECL_RTL (exp), DECL_MODE (exp));
-         set_mem_align (DECL_RTL (exp), DECL_ALIGN (exp));
+
+         /* If the RTL was already set, update its mode and memory
+            attributes.  */
+         if (value != 0)
+           {
+             PUT_MODE (value, DECL_MODE (exp));
+             SET_DECL_RTL (exp, 0);
+             set_mem_attributes (value, exp, 1);
+             SET_DECL_RTL (exp, value);
+           }
        }
 
       /* Although static-storage variables start off initialized, according to
@@ -7500,6 +7537,79 @@ expand_expr (exp, target, tmode, modifier)
                      TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
       return target;
 
+    case VIEW_CONVERT_EXPR:
+      op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, 0);
+
+      /* If the input and output modes are both the same, we are done.
+        Otherwise, if neither mode is BLKmode and both are within a word, we
+        can use gen_lowpart.  If neither is true, store the operand into
+        memory and convert the MEM to the new mode.  */
+      if (TYPE_MODE (type) == GET_MODE (op0))
+       ;
+      else if (TYPE_MODE (type) != BLKmode && GET_MODE (op0) != BLKmode
+              && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD
+              && GET_MODE_SIZE (GET_MODE (op0)) <= UNITS_PER_WORD)
+       op0 = gen_lowpart (TYPE_MODE (type), op0);
+      else
+       {
+         tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+         enum machine_mode non_blkmode
+           = GET_MODE (op0) == BLKmode ? TYPE_MODE (type) : GET_MODE (op0);
+
+         if (CONSTANT_P (op0))
+           op0 = validize_mem (force_const_mem (TYPE_MODE (inner_type), op0));
+         else
+           {
+             if (target == 0 || GET_MODE (target) != TYPE_MODE (inner_type))
+               target
+                 = assign_stack_temp_for_type (TYPE_MODE (inner_type),
+                                               GET_MODE_SIZE (non_blkmode),
+                                               0, inner_type);
+
+             if (GET_MODE (target) == BLKmode)
+               emit_block_move (target, op0,
+                                expr_size (TREE_OPERAND (exp, 0)));
+             else
+               emit_move_insn (target, op0);
+
+             op0 = target;
+           }
+       }
+
+      if (GET_CODE (op0) == MEM)
+       {
+         op0 = copy_rtx (op0);
+
+         /* If the output type is such that the operand is known to be
+            aligned, indicate that it is.  Otherwise, we need only be
+            concerned about alignment for non-BLKmode results.  */
+         if (TYPE_ALIGN_OK (type))
+           set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
+         else if (TYPE_MODE (type) != BLKmode && STRICT_ALIGNMENT
+                  && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
+           {
+             tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+             HOST_WIDE_INT temp_size = MAX (int_size_in_bytes (inner_type),
+                                            GET_MODE_SIZE (TYPE_MODE (type)));
+             rtx new = assign_stack_temp_for_type (TYPE_MODE (type),
+                                                   temp_size, 0, type);
+             rtx new_with_op0_mode = copy_rtx (new);
+
+             PUT_MODE (new_with_op0_mode, GET_MODE (op0));
+             if (GET_MODE (op0) == BLKmode)
+               emit_block_move (new_with_op0_mode, op0,
+                                GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))));
+             else
+               emit_move_insn (new_with_op0_mode, op0);
+
+             op0 = new;
+           }
+      
+         PUT_MODE (op0, TYPE_MODE (type));
+       }
+
+      return op0;
+
     case PLUS_EXPR:
       /* We come here from MINUS_EXPR when the second operand is a
          constant.  */
@@ -8668,7 +8778,8 @@ expand_expr (exp, target, tmode, modifier)
             strict alignment.  */
          if (STRICT_ALIGNMENT && GET_MODE (op0) == BLKmode
              && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
-                 > MEM_ALIGN (op0)))
+                 > MEM_ALIGN (op0))
+             && MEM_ALIGN (op0) < BIGGEST_ALIGNMENT)
            {
              tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
              rtx new
index f7cdc57d42133d8cafa7329bf1a35caea902f289..2083c55abfaba78ee51da7b14fc34a846c1a3e18 100644 (file)
@@ -5308,6 +5308,12 @@ fold (expr)
        }
       return fold_convert (t, arg0);
 
+    case VIEW_CONVERT_EXPR:
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == VIEW_CONVERT_EXPR)
+       return build1 (VIEW_CONVERT_EXPR, type,
+                      TREE_OPERAND (TREE_OPERAND (t, 0), 0));
+      return t;
+
 #if 0  /* This loses on &"foo"[0].  */
     case ARRAY_REF:
        {
index 8a02e5b2f601ca47cfe4b34ddd374ba9e8d9a510..c4f08cf5f0d2fa426d97232d793b54dd6b63c2d1 100644 (file)
@@ -691,6 +691,13 @@ DEFTREECODE (NOP_EXPR, "nop_expr", '1', 1)
 /* Value is same as argument, but guaranteed not an lvalue.  */
 DEFTREECODE (NON_LVALUE_EXPR, "non_lvalue_expr", '1', 1)
 
+/* Represents viewing something of one type as being of a second type.
+   This corresponds to an "Unchecked Conversion" in Ada and roughly to
+   the idiom *(type2 *)&X in C.  The only operand is the value to be
+   viewed as being of another type.  It is undefined if the type of the
+   input and of the expression have different sizes.  */
+DEFTREECODE (VIEW_CONVERT_EXPR, "view_convert_expr", '1', 1)
+
 /* Represents something we computed once and will use multiple times.
    First operand is that expression.  Second is the function decl
    in which the SAVE_EXPR was created.  The third operand is the RTL,
index 9c45fb851adaa8f917765194060510d00725f8be..c28edf12df6160744e03f82d0aa06c6031dcd253 100644 (file)
@@ -2587,6 +2587,10 @@ extern tree get_inner_reference          PARAMS ((tree, HOST_WIDE_INT *,
                                                 enum machine_mode *, int *,
                                                 int *));
 
+/* Return 1 if T is an expression that get_inner_reference handles.  */
+
+extern int handled_component_p         PARAMS ((tree));
+
 /* Given a DECL or TYPE, return the scope in which it was declared, or
    NUL_TREE if there is no containing scope.  */
 
index 697276234b04aa8c58e39df7daa6a85545158770..32dabe82d0824931d1b7661de50eaf6b35899759 100644 (file)
@@ -4288,6 +4288,7 @@ initializer_constant_valid_p (value, endtype)
     case FDESC_EXPR:
       return staticp (TREE_OPERAND (value, 0)) ? TREE_OPERAND (value, 0) : 0;
 
+    case VIEW_CONVERT_EXPR:
     case NON_LVALUE_EXPR:
       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
 
@@ -4442,10 +4443,9 @@ output_constant (exp, size, align)
 {
   enum tree_code code = TREE_CODE (TREE_TYPE (exp));
 
-  /* Some front-ends use constants other than the standard
-     language-indepdent varieties, but which may still be output
-     directly.  Give the front-end a chance to convert EXP to a
-     language-independent representation.  */
+  /* Some front-ends use constants other than the standard language-indepdent
+     varieties, but which may still be output directly.  Give the front-end a
+     chance to convert EXP to a language-independent representation.  */
   if (lang_expand_constant)
     {
       exp = (*lang_expand_constant) (exp);
@@ -4462,9 +4462,9 @@ output_constant (exp, size, align)
   while ((TREE_CODE (exp) == NOP_EXPR
          && (TREE_TYPE (exp) == TREE_TYPE (TREE_OPERAND (exp, 0))
              || AGGREGATE_TYPE_P (TREE_TYPE (exp))))
-        || (TREE_CODE (exp) == CONVERT_EXPR
-            && code == UNION_TYPE)
-        || TREE_CODE (exp) == NON_LVALUE_EXPR)
+        || (TREE_CODE (exp) == CONVERT_EXPR && code == UNION_TYPE)
+        || TREE_CODE (exp) == NON_LVALUE_EXPR
+        || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
     {
       exp = TREE_OPERAND (exp, 0);
       code = TREE_CODE (TREE_TYPE (exp));