Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/gnu/dist/gcc From the egcs development tree:



details:   https://anonhg.NetBSD.org/src/rev/362895a23615
branches:  trunk
changeset: 475010:362895a23615
user:      mycroft <mycroft%NetBSD.org@localhost>
date:      Thu Jul 29 09:09:18 1999 +0000

description:
>From the egcs development tree:
Fix problems with autoincrement/autodecrement caused by changes to the way
memcpy() calls are generated between egcs 1.1.1 and 1.1.2.

diffstat:

 gnu/dist/gcc/expr.c |  186 +++++++++++++++++++++++++++++++++------------------
 1 files changed, 121 insertions(+), 65 deletions(-)

diffs (223 lines):

diff -r 30a13e8b582b -r 362895a23615 gnu/dist/gcc/expr.c
--- a/gnu/dist/gcc/expr.c       Thu Jul 29 08:58:46 1999 +0000
+++ b/gnu/dist/gcc/expr.c       Thu Jul 29 09:09:18 1999 +0000
@@ -1694,6 +1694,37 @@
            }
        }
 
+      /* X, Y, or SIZE may have been passed through protect_from_queue.
+
+        It is unsafe to save the value generated by protect_from_queue
+        and reuse it later.  Consider what happens if emit_queue is
+        called before the return value from protect_from_queue is used.
+
+        Expansion of the CALL_EXPR below will call emit_queue before
+        we are finished emitting RTL for argument setup.  So if we are
+        not careful we could get the wrong value for an argument.
+
+        To avoid this problem we go ahead and emit code to copy X, Y &
+        SIZE into new pseudos.  We can then place those new pseudos
+        into an RTL_EXPR and use them later, even after a call to
+        emit_queue. 
+
+        Note this is not strictly needed for library calls since they
+        do not call emit_queue before loading their arguments.  However,
+        we may need to have library calls call emit_queue in the future
+        since failing to do so could cause problems for targets which
+        define SMALL_REGISTER_CLASSES and pass arguments in registers.  */
+      x = copy_to_mode_reg (Pmode, XEXP (x, 0));
+      y = copy_to_mode_reg (Pmode, XEXP (y, 0));
+
+#ifdef TARGET_MEM_FUNCTIONS
+      size = copy_to_mode_reg (TYPE_MODE (sizetype), size);
+#else
+      size = convert_to_mode (TYPE_MODE (integer_type_node), size,
+                             TREE_UNSIGNED (integer_type_node));
+      size = copy_to_mode_reg (TYPE_MODE (integer_type_node), size);
+#endif
+
 #ifdef TARGET_MEM_FUNCTIONS
       /* It is incorrect to use the libcall calling conventions to call
         memcpy in this context.
@@ -1732,12 +1763,10 @@
         the last is a size_t byte count for the copy.  */
       arg_list
        = build_tree_list (NULL_TREE,
-                           make_tree (build_pointer_type (void_type_node),
-                                      XEXP (x, 0)));
+                          make_tree (build_pointer_type (void_type_node), x));
       TREE_CHAIN (arg_list)
        = build_tree_list (NULL_TREE,
-                          make_tree (build_pointer_type (void_type_node),
-                                     XEXP (y, 0)));
+                          make_tree (build_pointer_type (void_type_node), y));
       TREE_CHAIN (TREE_CHAIN (arg_list))
         = build_tree_list (NULL_TREE, make_tree (sizetype, size));
       TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
@@ -1751,8 +1780,7 @@
       retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
 #else
       emit_library_call (bcopy_libfunc, 0,
-                        VOIDmode, 3, XEXP (y, 0), Pmode,
-                        XEXP (x, 0), Pmode,
+                        VOIDmode, 3, y, Pmode, x, Pmode,
                         convert_to_mode (TYPE_MODE (integer_type_node), size,
                                          TREE_UNSIGNED (integer_type_node)),
                         TYPE_MODE (integer_type_node));
@@ -2330,69 +2358,97 @@
                }
            }
 
+         /* OBJECT or SIZE may have been passed through protect_from_queue.
+
+            It is unsafe to save the value generated by protect_from_queue
+            and reuse it later.  Consider what happens if emit_queue is
+            called before the return value from protect_from_queue is used.
+
+            Expansion of the CALL_EXPR below will call emit_queue before
+            we are finished emitting RTL for argument setup.  So if we are
+            not careful we could get the wrong value for an argument.
+
+            To avoid this problem we go ahead and emit code to copy OBJECT
+            and SIZE into new pseudos.  We can then place those new pseudos
+            into an RTL_EXPR and use them later, even after a call to
+            emit_queue.
+
+            Note this is not strictly needed for library calls since they
+            do not call emit_queue before loading their arguments.  However,
+            we may need to have library calls call emit_queue in the future
+            since failing to do so could cause problems for targets which
+            define SMALL_REGISTER_CLASSES and pass arguments in registers.  */
+         object = copy_to_mode_reg (Pmode, XEXP (object, 0));
+
+#ifdef TARGET_MEM_FUNCTIONS
+         size = copy_to_mode_reg (TYPE_MODE (sizetype), size);
+#else
+         size = convert_to_mode (TYPE_MODE (integer_type_node), size,
+                                 TREE_UNSIGNED (integer_type_node));
+         size = copy_to_mode_reg (TYPE_MODE (integer_type_node), size);
+#endif
+
 
 #ifdef TARGET_MEM_FUNCTIONS
-      /* It is incorrect to use the libcall calling conventions to call
-        memset in this context.
-
-        This could be a user call to memset and the user may wish to
-        examine the return value from memset.
-
-        For targets where libcalls and normal calls have different conventions
-        for returning pointers, we could end up generating incorrect code. 
-
-        So instead of using a libcall sequence we build up a suitable
-        CALL_EXPR and expand the call in the normal fashion.  */
-      if (fn == NULL_TREE)
-       {
-         tree fntype;
-
-         /* This was copied from except.c, I don't know if all this is
-            necessary in this context or not.  */
-         fn = get_identifier ("memset");
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
-         fntype = build_pointer_type (void_type_node);
-         fntype = build_function_type (fntype, NULL_TREE);
-         fn = build_decl (FUNCTION_DECL, fn, fntype);
-         DECL_EXTERNAL (fn) = 1;
-         TREE_PUBLIC (fn) = 1;
-         DECL_ARTIFICIAL (fn) = 1;
-         make_decl_rtl (fn, NULL_PTR, 1);
-         assemble_external (fn);
-         pop_obstacks ();
-       }
-
-      /* We need to make an argument list for the function call. 
-
-        memset has three arguments, the first is a void * addresses, the
-        second a integer with the initialization value, the last is a size_t
-        byte count for the copy.  */
-      arg_list
-       = build_tree_list (NULL_TREE,
-                           make_tree (build_pointer_type (void_type_node),
-                                      XEXP (object, 0)));
-      TREE_CHAIN (arg_list)
-       = build_tree_list (NULL_TREE,
-                          make_tree (integer_type_node, const0_rtx));
-      TREE_CHAIN (TREE_CHAIN (arg_list))
-        = build_tree_list (NULL_TREE, make_tree (sizetype, size));
-      TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
-
-      /* Now we have to build up the CALL_EXPR itself.  */
-      call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
-      call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
-                        call_expr, arg_list, NULL_TREE);
-      TREE_SIDE_EFFECTS (call_expr) = 1;
-
-      retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
+         /* It is incorrect to use the libcall calling conventions to call
+            memset in this context.
+
+            This could be a user call to memset and the user may wish to
+            examine the return value from memset.
+
+            For targets where libcalls and normal calls have different
+            conventions for returning pointers, we could end up generating
+             incorrect code. 
+
+            So instead of using a libcall sequence we build up a suitable
+            CALL_EXPR and expand the call in the normal fashion.  */
+         if (fn == NULL_TREE)
+           {
+             tree fntype;
+
+             /* This was copied from except.c, I don't know if all this is
+                necessary in this context or not.  */
+             fn = get_identifier ("memset");
+             push_obstacks_nochange ();
+             end_temporary_allocation ();
+             fntype = build_pointer_type (void_type_node);
+             fntype = build_function_type (fntype, NULL_TREE);
+             fn = build_decl (FUNCTION_DECL, fn, fntype);
+             DECL_EXTERNAL (fn) = 1;
+             TREE_PUBLIC (fn) = 1;
+             DECL_ARTIFICIAL (fn) = 1;
+             make_decl_rtl (fn, NULL_PTR, 1);
+             assemble_external (fn);
+             pop_obstacks ();
+           }
+
+         /* We need to make an argument list for the function call. 
+
+            memset has three arguments, the first is a void * addresses, the
+            second a integer with the initialization value, the last is a
+            size_t byte count for the copy.  */
+         arg_list
+           = build_tree_list (NULL_TREE,
+                              make_tree (build_pointer_type (void_type_node),
+                                         object));
+         TREE_CHAIN (arg_list)
+           = build_tree_list (NULL_TREE,
+                               make_tree (integer_type_node, const0_rtx));
+         TREE_CHAIN (TREE_CHAIN (arg_list))
+           = build_tree_list (NULL_TREE, make_tree (sizetype, size));
+         TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
+
+         /* Now we have to build up the CALL_EXPR itself.  */
+         call_expr = build1 (ADDR_EXPR,
+                             build_pointer_type (TREE_TYPE (fn)), fn);
+         call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+                            call_expr, arg_list, NULL_TREE);
+         TREE_SIDE_EFFECTS (call_expr) = 1;
+
+         retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
 #else
          emit_library_call (bzero_libfunc, 0,
-                            VOIDmode, 2,
-                            XEXP (object, 0), Pmode,   
-                            convert_to_mode
-                            (TYPE_MODE (integer_type_node), size,
-                             TREE_UNSIGNED (integer_type_node)),
+                            VOIDmode, 2, object, Pmode, size,
                             TYPE_MODE (integer_type_node));
 #endif
        }



Home | Main Index | Thread Index | Old Index