builtins.c (stabilize_va_list): Stabilize array type va_list to a pointer type, not...
authorRichard Henderson <rth@cygnus.com>
Tue, 28 Sep 1999 08:15:38 +0000 (01:15 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 28 Sep 1999 08:15:38 +0000 (01:15 -0700)
        * builtins.c (stabilize_va_list): Stabilize array type va_list
        to a pointer type, not the base record type.
        (expand_builtin_va_copy): Dereference the pointers explicitly;
        use the correct size for the copy.

        * rs6000.c (rs6000_va_start): Dereference valist to get to the record.
        (rs6000_va_arg): Likewise.

From-SVN: r29690

gcc/ChangeLog
gcc/builtins.c
gcc/config/rs6000/rs6000.c

index c2e22a5..c1bbe79 100644 (file)
@@ -1,3 +1,13 @@
+Tue Sep 28 01:11:05 1999  Richard Henderson  <rth@cygnus.com>
+
+       * builtins.c (stabilize_va_list): Stabilize array type va_list
+       to a pointer type, not the base record type.
+       (expand_builtin_va_copy): Dereference the pointers explicitly;
+       use the correct size for the copy.
+
+       * rs6000.c (rs6000_va_start): Dereference valist to get to the record.
+       (rs6000_va_arg): Likewise.
+
 Mon Sep 27 23:27:21 1999  Richard Henderson  <rth@cygnus.com>
 
        * rtl.h (struct rtx_def): Move gc_mark to align mode field.
index 250177c..36a6493 100644 (file)
@@ -1826,40 +1826,64 @@ stabilize_va_list (valist, was_ptr)
      tree valist;
      int was_ptr;
 {
-  int is_array = TREE_CODE (va_list_type_node) == ARRAY_TYPE;
-
-  if (was_ptr)
+  if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
     {
       /* If stdarg.h took the address of an array-type valist that was passed
          as a parameter, we'll have taken the address of the parameter itself
          rather than the array as we'd intended.  Undo this mistake.  */
-      if (is_array
-         && TREE_CODE (valist) == ADDR_EXPR
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (valist, 0))) == POINTER_TYPE)
+
+      if (was_ptr)
        {
+         STRIP_NOPS (valist);
+
+         /* Two cases: either &array, which decomposed to 
+               <ptr <array <record> valist>>
+            or &ptr, which turned into
+               <ptr <ptr <record>>>
+            In the first case we'll need to put the ADDR_EXPR back
+            after frobbing the types as if &array[0].  */
+
+         if (TREE_CODE (valist) != ADDR_EXPR)
+           abort ();
          valist = TREE_OPERAND (valist, 0);
-         if (TREE_SIDE_EFFECTS (valist))
-           valist = save_expr (valist);
+       }
+
+      if (TYPE_MAIN_VARIANT (TREE_TYPE (valist))
+         == TYPE_MAIN_VARIANT (va_list_type_node))
+       {
+         tree pt = build_pointer_type (TREE_TYPE (va_list_type_node));
+         valist = build1 (ADDR_EXPR, pt, valist);
+         TREE_SIDE_EFFECTS (valist)
+           = TREE_SIDE_EFFECTS (TREE_OPERAND (valist, 0));
        }
       else
        {
-         if (TREE_SIDE_EFFECTS (valist))
-           valist = save_expr (valist);
-         valist = fold (build1 (INDIRECT_REF, va_list_type_node, valist));
+         if (! POINTER_TYPE_P (TREE_TYPE (valist))
+             || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (valist)))
+                 != TYPE_MAIN_VARIANT (TREE_TYPE (va_list_type_node))))
+           abort ();
        }
+
+      if (TREE_SIDE_EFFECTS (valist))
+       valist = save_expr (valist);
     }
-  else if (TREE_SIDE_EFFECTS (valist))
+  else
     {
-      if (is_array)
-       valist = save_expr (valist);
-      else
+      if (! was_ptr)
        {
-          valist = build1 (ADDR_EXPR, build_pointer_type (va_list_type_node),
-                          valist);
+         tree pt;
+
+         if (! TREE_SIDE_EFFECTS (valist))
+           return valist;
+
+         pt = build_pointer_type (va_list_type_node);
+          valist = fold (build1 (ADDR_EXPR, pt, valist));
          TREE_SIDE_EFFECTS (valist) = 1;
-         valist = save_expr (valist);
-         valist = fold (build1 (INDIRECT_REF, va_list_type_node, valist));
        }
+      if (TREE_SIDE_EFFECTS (valist))
+        valist = save_expr (valist);
+      valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
+                            valist));
     }
 
   return valist;
@@ -2095,10 +2119,22 @@ expand_builtin_va_copy (arglist)
     }
   else
     {
-      emit_block_move (expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL),
-                      expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL),
-                      expand_expr (TYPE_SIZE (va_list_type_node), NULL_RTX,
-                                   VOIDmode, EXPAND_NORMAL),
+      rtx dstb, srcb, size;
+
+      /* Evaluate to pointers.  */
+      dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
+      srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
+      size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
+                         VOIDmode, EXPAND_NORMAL);
+
+      /* "Dereference" to BLKmode memories.  */
+      dstb = gen_rtx_MEM (BLKmode, dstb);
+      MEM_ALIAS_SET (dstb) = get_alias_set (TREE_TYPE (TREE_TYPE (dst)));
+      srcb = gen_rtx_MEM (BLKmode, srcb);
+      MEM_ALIAS_SET (srcb) = get_alias_set (TREE_TYPE (TREE_TYPE (src)));
+
+      /* Copy.  */
+      emit_block_move (dstb, srcb, size, 
                       TYPE_ALIGN (va_list_type_node) / BITS_PER_UNIT);
     }
 
index a4c173d..a432461 100644 (file)
@@ -1833,6 +1833,7 @@ rs6000_va_start (stdarg_p, valist, nextarg)
   f_ovf = TREE_CHAIN (f_fpr);
   f_sav = TREE_CHAIN (f_ovf);
 
+  valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
   gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
   fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
   ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
@@ -1893,6 +1894,7 @@ rs6000_va_arg (valist, type)
   f_ovf = TREE_CHAIN (f_fpr);
   f_sav = TREE_CHAIN (f_ovf);
 
+  valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
   gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
   fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
   ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);