Commit 4bc973ae by Jeff Law

expr.c (emit_block_move): Properly handle case where one of the block move…

expr.c (emit_block_move): Properly handle case where one of the block move arguments has a queued...

�
        * expr.c (emit_block_move): Properly handle case where one of the
        block move arguments has a queued increment or decrement.
        (clear_storage): Similarly.  Fix formatting goof.

From-SVN: r27822
parent 5dd29219
......@@ -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,6 +2472,36 @@ clear_storage (object, size, align)
}
}
/* 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_reg (size);
#endif
#ifdef TARGET_MEM_FUNCTIONS
/* It is incorrect to use the libcall calling conventions to call
......@@ -2452,8 +2510,9 @@ clear_storage (object, size, align)
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.
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. */
......@@ -2480,12 +2539,12 @@ clear_storage (object, size, align)
/* 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. */
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)));
object));
TREE_CHAIN (arg_list)
= build_tree_list (NULL_TREE,
make_tree (integer_type_node, const0_rtx));
......@@ -2494,7 +2553,8 @@ clear_storage (object, size, align)
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 = 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;
......@@ -2502,11 +2562,7 @@ clear_storage (object, size, align)
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
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment