From 06b8e3dbbb3f7ac9742a8d0a44d403f7215cdee6 Mon Sep 17 00:00:00 2001 From: law Date: Tue, 29 Jun 1999 00:42:41 +0000 Subject: [PATCH] =?utf8?q?=EF=BF=BD=20=20=20=20=20=20=20=20=20*=20expr.c?= =?utf8?q?=20(emit=5Fblock=5Fmove):=20Properly=20handle=20case=20where=20o?= =?utf8?q?ne=20of=20the=20=20=20=20=20=20=20=20=20block=20move=20arguments?= =?utf8?q?=20has=20a=20queued=20increment=20or=20decrement.=20=20=20=20=20?= =?utf8?q?=20=20=20=20(clear=5Fstorage):=20Similarly.=20=20Fix=20formattin?= =?utf8?q?g=20goof.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@27822 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/expr.c | 172 ++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 114 insertions(+), 58 deletions(-) diff --git a/gcc/expr.c b/gcc/expr.c index b350c70de40..075ddd3728b 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -1710,6 +1710,37 @@ emit_block_move (x, y, size, align) } } + /* 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_reg (size); +#endif + #ifdef TARGET_MEM_FUNCTIONS /* It is incorrect to use the libcall calling conventions to call memcpy in this context. @@ -1748,12 +1779,10 @@ emit_block_move (x, y, size, align) 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; @@ -1767,8 +1796,7 @@ emit_block_move (x, y, size, align) 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)); @@ -2444,69 +2472,97 @@ clear_storage (object, size, align) } } + /* OBJECT or SIZE may have been passed through protect_from_queue. -#ifdef TARGET_MEM_FUNCTIONS - /* It is incorrect to use the libcall calling conventions to call - memset in this context. + 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. - This could be a user call to memset and the user may wish to - examine the return value from memset. + 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. - For targets where libcalls and normal calls have different conventions - for returning pointers, we could end up generating incorrect code. + 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. - 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; + 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)); - /* 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 (); - } +#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_reg (size); +#endif - /* 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; +#ifdef TARGET_MEM_FUNCTIONS + /* It is incorrect to use the libcall calling conventions to call + memset in this context. - /* 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; + This could be a user call to memset and the user may wish to + examine the return value from memset. - retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0); + 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 } -- 2.11.4.GIT