d: Refactor use of built-in memcmp/memcpy/memset into helper functions.
Generating calls to memset, memcpy, and memcmp is frequent enough that it becomes beneficial to put them into their own routine. All parts of the front-end have been updated to call the new helper functions instead of doing it themselves. gcc/d/ChangeLog: * d-codegen.cc (build_memcmp_call): New function. (build_memcpy_call): New function. (build_memset_call): New function. (build_float_identity): Call build_memcmp_call. (lower_struct_comparison): Likewise. (build_struct_comparison): Likewise. * d-tree.h (build_memcmp_call): Declare. (build_memcpy_call): Declare. (build_memset_call): Declare. * expr.cc (ExprVisitor::visit (EqualExp *)): Call build_memcmp_call. (ExprVisitor::visit (AssignExp *)): Call build_memset_call. (ExprVisitor::visit (ArrayLiteralExp *)): Call build_memcpy_call. (ExprVisitor::visit (StructLiteralExp *)): Call build_memset_call.
This commit is contained in:
parent
dc60d67674
commit
ab0edbcb37
|
@ -794,6 +794,41 @@ d_mark_read (tree exp)
|
||||||
return exp;
|
return exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Build a call to memcmp(), compares the first NUM bytes of PTR1 with PTR2. */
|
||||||
|
|
||||||
|
tree
|
||||||
|
build_memcmp_call (tree ptr1, tree ptr2, tree num)
|
||||||
|
{
|
||||||
|
return build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP), 3,
|
||||||
|
ptr1, ptr2, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build a call to memcpy(), copies the first NUM bytes of SRC into DST. */
|
||||||
|
|
||||||
|
tree
|
||||||
|
build_memcpy_call (tree dst, tree src, tree num)
|
||||||
|
{
|
||||||
|
return build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
|
||||||
|
dst, src, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build a call to memset(), fills the first NUM bytes of PTR with zeros.
|
||||||
|
If NUM is NULL, then we expect PTR to be object that requires filling. */
|
||||||
|
|
||||||
|
tree
|
||||||
|
build_memset_call (tree ptr, tree num)
|
||||||
|
{
|
||||||
|
if (num == NULL_TREE)
|
||||||
|
{
|
||||||
|
gcc_assert (TREE_CODE (ptr) != ADDR_EXPR);
|
||||||
|
num = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
|
||||||
|
ptr = build_address (ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return build_call_expr (builtin_decl_explicit (BUILT_IN_MEMSET), 3,
|
||||||
|
ptr, integer_zero_node, num);
|
||||||
|
}
|
||||||
|
|
||||||
/* Return TRUE if the struct SD is suitable for comparison using memcmp.
|
/* Return TRUE if the struct SD is suitable for comparison using memcmp.
|
||||||
This is because we don't guarantee that padding is zero-initialized for
|
This is because we don't guarantee that padding is zero-initialized for
|
||||||
a stack variable, so we can't use memcmp to compare struct values. */
|
a stack variable, so we can't use memcmp to compare struct values. */
|
||||||
|
@ -846,11 +881,9 @@ identity_compare_p (StructDeclaration *sd)
|
||||||
tree
|
tree
|
||||||
build_float_identity (tree_code code, tree t1, tree t2)
|
build_float_identity (tree_code code, tree t1, tree t2)
|
||||||
{
|
{
|
||||||
tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP);
|
|
||||||
tree size = size_int (TYPE_PRECISION (TREE_TYPE (t1)) / BITS_PER_UNIT);
|
tree size = size_int (TYPE_PRECISION (TREE_TYPE (t1)) / BITS_PER_UNIT);
|
||||||
|
tree result = build_memcmp_call (build_address (t1),
|
||||||
tree result = build_call_expr (tmemcmp, 3, build_address (t1),
|
build_address (t2), size);
|
||||||
build_address (t2), size);
|
|
||||||
return build_boolop (code, result, integer_zero_node);
|
return build_boolop (code, result, integer_zero_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,10 +912,8 @@ lower_struct_comparison (tree_code code, StructDeclaration *sd,
|
||||||
/* Let back-end take care of union comparisons. */
|
/* Let back-end take care of union comparisons. */
|
||||||
if (sd->isUnionDeclaration ())
|
if (sd->isUnionDeclaration ())
|
||||||
{
|
{
|
||||||
tmemcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP), 3,
|
tmemcmp = build_memcmp_call (build_address (t1), build_address (t2),
|
||||||
build_address (t1), build_address (t2),
|
size_int (sd->structsize));
|
||||||
size_int (sd->structsize));
|
|
||||||
|
|
||||||
return build_boolop (code, tmemcmp, integer_zero_node);
|
return build_boolop (code, tmemcmp, integer_zero_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -943,11 +974,9 @@ lower_struct_comparison (tree_code code, StructDeclaration *sd,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Simple memcmp between types. */
|
/* Simple memcmp between types. */
|
||||||
tcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP),
|
tcmp = build_memcmp_call (build_address (t1ref),
|
||||||
3, build_address (t1ref),
|
build_address (t2ref),
|
||||||
build_address (t2ref),
|
TYPE_SIZE_UNIT (stype));
|
||||||
TYPE_SIZE_UNIT (stype));
|
|
||||||
|
|
||||||
tcmp = build_boolop (code, tcmp, integer_zero_node);
|
tcmp = build_boolop (code, tcmp, integer_zero_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -995,11 +1024,8 @@ build_struct_comparison (tree_code code, StructDeclaration *sd,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Do bit compare of structs. */
|
/* Do bit compare of structs. */
|
||||||
tree size = size_int (sd->structsize);
|
tree tmemcmp = build_memcmp_call (build_address (t1), build_address (t2),
|
||||||
tree tmemcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP),
|
size_int (sd->structsize));
|
||||||
3, build_address (t1),
|
|
||||||
build_address (t2), size);
|
|
||||||
|
|
||||||
result = build_boolop (code, tmemcmp, integer_zero_node);
|
result = build_boolop (code, tmemcmp, integer_zero_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -530,6 +530,9 @@ extern tree build_address (tree);
|
||||||
extern tree d_mark_addressable (tree);
|
extern tree d_mark_addressable (tree);
|
||||||
extern tree d_mark_used (tree);
|
extern tree d_mark_used (tree);
|
||||||
extern tree d_mark_read (tree);
|
extern tree d_mark_read (tree);
|
||||||
|
extern tree build_memcmp_call (tree, tree, tree);
|
||||||
|
extern tree build_memcpy_call (tree, tree, tree);
|
||||||
|
extern tree build_memset_call (tree, tree = NULL_TREE);
|
||||||
extern bool identity_compare_p (StructDeclaration *);
|
extern bool identity_compare_p (StructDeclaration *);
|
||||||
extern tree build_float_identity (tree_code, tree, tree);
|
extern tree build_float_identity (tree_code, tree, tree);
|
||||||
extern tree build_struct_comparison (tree_code, StructDeclaration *,
|
extern tree build_struct_comparison (tree_code, StructDeclaration *,
|
||||||
|
|
|
@ -378,9 +378,8 @@ public:
|
||||||
|| identity_compare_p (t1elem->isTypeStruct ()->sym))
|
|| identity_compare_p (t1elem->isTypeStruct ()->sym))
|
||||||
{
|
{
|
||||||
tree size = size_mult_expr (t1len, size_int (t1elem->size ()));
|
tree size = size_mult_expr (t1len, size_int (t1elem->size ()));
|
||||||
tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP);
|
|
||||||
|
|
||||||
result = build_call_expr (tmemcmp, 3, t1ptr, t2ptr, size);
|
result = build_memcmp_call (t1ptr, t2ptr, size);
|
||||||
result = build_boolop (code, result, integer_zero_node);
|
result = build_boolop (code, result, integer_zero_node);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -948,12 +947,9 @@ public:
|
||||||
|
|
||||||
if (integer_zerop (t2))
|
if (integer_zerop (t2))
|
||||||
{
|
{
|
||||||
tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
|
|
||||||
tree size = size_mult_expr (d_array_length (t1),
|
tree size = size_mult_expr (d_array_length (t1),
|
||||||
size_int (etype->size ()));
|
size_int (etype->size ()));
|
||||||
|
result = build_memset_call (d_array_ptr (t1), size);
|
||||||
result = build_call_expr (tmemset, 3, d_array_ptr (t1),
|
|
||||||
integer_zero_node, size);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = build_array_set (d_array_ptr (t1),
|
result = build_array_set (d_array_ptr (t1),
|
||||||
|
@ -970,12 +966,10 @@ public:
|
||||||
{
|
{
|
||||||
tree t1 = d_save_expr (d_array_convert (e->e1));
|
tree t1 = d_save_expr (d_array_convert (e->e1));
|
||||||
tree t2 = d_array_convert (e->e2);
|
tree t2 = d_array_convert (e->e2);
|
||||||
tree tmemcpy = builtin_decl_explicit (BUILT_IN_MEMCPY);
|
|
||||||
tree size = size_mult_expr (d_array_length (t1),
|
tree size = size_mult_expr (d_array_length (t1),
|
||||||
size_int (etype->size ()));
|
size_int (etype->size ()));
|
||||||
|
tree result = build_memcpy_call (d_array_ptr (t1),
|
||||||
tree result = build_call_expr (tmemcpy, 3, d_array_ptr (t1),
|
d_array_ptr (t2), size);
|
||||||
d_array_ptr (t2), size);
|
|
||||||
this->result_ = compound_expr (result, t1);
|
this->result_ = compound_expr (result, t1);
|
||||||
}
|
}
|
||||||
else if ((postblit || destructor) && e->op != TOKblit)
|
else if ((postblit || destructor) && e->op != TOKblit)
|
||||||
|
@ -1042,9 +1036,7 @@ public:
|
||||||
{
|
{
|
||||||
/* Use memset to fill struct. */
|
/* Use memset to fill struct. */
|
||||||
gcc_assert (e->op == TOKblit);
|
gcc_assert (e->op == TOKblit);
|
||||||
tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
|
tree result = build_memset_call (t1);
|
||||||
tree result = build_call_expr (tmemset, 3, build_address (t1),
|
|
||||||
t2, size_int (sd->structsize));
|
|
||||||
|
|
||||||
/* Maybe set-up hidden pointer to outer scope context. */
|
/* Maybe set-up hidden pointer to outer scope context. */
|
||||||
if (sd->isNested ())
|
if (sd->isNested ())
|
||||||
|
@ -1065,12 +1057,7 @@ public:
|
||||||
|
|
||||||
/* Fill any alignment holes in the struct using memset. */
|
/* Fill any alignment holes in the struct using memset. */
|
||||||
if (e->op == TOKconstruct && !identity_compare_p (sd))
|
if (e->op == TOKconstruct && !identity_compare_p (sd))
|
||||||
{
|
init = build_memset_call (t1);
|
||||||
tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
|
|
||||||
init = build_call_expr (tmemset, 3, build_address (t1),
|
|
||||||
integer_zero_node,
|
|
||||||
size_int (sd->structsize));
|
|
||||||
}
|
|
||||||
|
|
||||||
tree result = build_assign (modifycode, t1, t2);
|
tree result = build_assign (modifycode, t1, t2);
|
||||||
this->result_ = compound_expr (init, result);
|
this->result_ = compound_expr (init, result);
|
||||||
|
@ -1087,15 +1074,7 @@ public:
|
||||||
{
|
{
|
||||||
/* Use memset to fill the array. */
|
/* Use memset to fill the array. */
|
||||||
gcc_assert (e->op == TOKblit);
|
gcc_assert (e->op == TOKblit);
|
||||||
|
this->result_ = build_memset_call (build_expr (e->e1));
|
||||||
tree t1 = build_expr (e->e1);
|
|
||||||
tree t2 = convert_for_assignment (build_expr (e->e2),
|
|
||||||
e->e2->type, e->e1->type);
|
|
||||||
tree size = size_int (e->e1->type->size ());
|
|
||||||
|
|
||||||
tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
|
|
||||||
this->result_ = build_call_expr (tmemset, 3, build_address (t1),
|
|
||||||
t2, size);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2753,12 +2732,10 @@ public:
|
||||||
mem = d_save_expr (mem);
|
mem = d_save_expr (mem);
|
||||||
|
|
||||||
/* Now copy the constructor into memory. */
|
/* Now copy the constructor into memory. */
|
||||||
tree tmemcpy = builtin_decl_explicit (BUILT_IN_MEMCPY);
|
|
||||||
tree size = size_mult_expr (size_int (e->elements->length),
|
tree size = size_mult_expr (size_int (e->elements->length),
|
||||||
size_int (tb->nextOf ()->size ()));
|
size_int (tb->nextOf ()->size ()));
|
||||||
|
|
||||||
tree result = build_call_expr (tmemcpy, 3, mem,
|
tree result = build_memcpy_call (mem, build_address (ctor), size);
|
||||||
build_address (ctor), size);
|
|
||||||
|
|
||||||
/* Return the array pointed to by MEM. */
|
/* Return the array pointed to by MEM. */
|
||||||
result = compound_expr (result, mem);
|
result = compound_expr (result, mem);
|
||||||
|
@ -2935,10 +2912,7 @@ public:
|
||||||
{
|
{
|
||||||
/* For unions, use memset to fill holes in the object. */
|
/* For unions, use memset to fill holes in the object. */
|
||||||
tree var = build_local_temp (TREE_TYPE (ctor));
|
tree var = build_local_temp (TREE_TYPE (ctor));
|
||||||
tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
|
tree init = build_memset_call (var);
|
||||||
tree init = build_call_expr (tmemset, 3, build_address (var),
|
|
||||||
size_zero_node,
|
|
||||||
size_int (e->sd->structsize));
|
|
||||||
|
|
||||||
init = compound_expr (init, saved_elems);
|
init = compound_expr (init, saved_elems);
|
||||||
init = compound_expr (init, modify_expr (var, ctor));
|
init = compound_expr (init, modify_expr (var, ctor));
|
||||||
|
|
Loading…
Reference in New Issue