Commit 52cf7115 by Jeffrey A Law Committed by Jeff Law

expr.c (emit_block_move): Do not call memcpy as a libcall instead build up a…

expr.c (emit_block_move): Do not call memcpy as a libcall instead build up a CALL_EXPR and call it like...

        * expr.c (emit_block_move): Do not call memcpy as a libcall
        instead build up a CALL_EXPR and call it like any other
        function.
        (clear_storage): Similarly for memset.

From-SVN: r21831
parent e27a5106
......@@ -5,6 +5,11 @@ Tue Aug 18 12:40:27 1998 Richard Henderson <rth@cygnus.com>
Tue Aug 18 10:33:30 1998 Jeffrey A Law (law@cygnus.com)
* expr.c (emit_block_move): Do not call memcpy as a libcall
instead build up a CALL_EXPR and call it like any other
function.
(clear_storage): Similarly for memset.
* regmove.c (fixup_match_2): Do not call reg_overlap_mentioned_p
on notes.
......
......@@ -1616,6 +1616,10 @@ emit_block_move (x, y, size, align)
int align;
{
rtx retval = 0;
#ifdef TARGET_MEM_FUNCTIONS
static tree fn;
tree call_expr, arg_list;
#endif
if (GET_MODE (x) != BLKmode)
abort ();
......@@ -1689,13 +1693,60 @@ emit_block_move (x, y, size, align)
}
#ifdef TARGET_MEM_FUNCTIONS
retval
= emit_library_call_value (memcpy_libfunc, NULL_RTX, 0,
ptr_mode, 3, XEXP (x, 0), Pmode,
XEXP (y, 0), Pmode,
convert_to_mode (TYPE_MODE (sizetype), size,
TREE_UNSIGNED (sizetype)),
TYPE_MODE (sizetype));
/* It is incorrect to use the libcall calling conventions to call
memcpy in this context.
This could be a user call to memcpy and the user may wish to
examine the return value from memcpy.
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 ("memcpy");
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.
memcpy has three arguments, the first two are void * addresses and
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)));
TREE_CHAIN (arg_list)
= build_tree_list (NULL_TREE,
make_tree (build_pointer_type (void_type_node),
XEXP (y, 0)));
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 (bcopy_libfunc, 0,
VOIDmode, 3, XEXP (y, 0), Pmode,
......@@ -2211,6 +2262,10 @@ clear_storage (object, size, align)
rtx size;
int align;
{
#ifdef TARGET_MEM_FUNCTIONS
static tree fn;
tree call_expr, arg_list;
#endif
rtx retval = 0;
if (GET_MODE (object) == BLKmode)
......@@ -2275,16 +2330,60 @@ clear_storage (object, size, align)
#ifdef TARGET_MEM_FUNCTIONS
retval
= emit_library_call_value (memset_libfunc, NULL_RTX, 0,
ptr_mode, 3,
XEXP (object, 0), Pmode,
const0_rtx,
TYPE_MODE (integer_type_node),
convert_to_mode
(TYPE_MODE (sizetype), size,
TREE_UNSIGNED (sizetype)),
TYPE_MODE (sizetype));
/* 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);
#else
emit_library_call (bzero_libfunc, 0,
VOIDmode, 2,
......
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