aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2020-08-25 11:05:57 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2020-08-26 10:03:55 +0200
commit1db88844a22f75b13ced224415f645680784d354 (patch)
treea4485d214e8b889e877596535d9a7d0de971b27b /gcc/d
parent312ad889e99ff9458c01518325775e75ab57f272 (diff)
downloadgcc-1db88844a22f75b13ced224415f645680784d354.zip
gcc-1db88844a22f75b13ced224415f645680784d354.tar.gz
gcc-1db88844a22f75b13ced224415f645680784d354.tar.bz2
d: Fix small struct literals that have non-deterministic hash values
Same issue as the initial commit that addressed PR96153, only this time to fix it also for structs that are not returned in memory. Tests have been added that triggered an assertion on x86_64, however the original test was failing on SPARC 64-bit targets. gcc/d/ChangeLog: PR d/96153 * d-codegen.cc (build_address): Create a temporary for CALL_EXPRs returning trivial aggregates, pre-filling it with zeroes. (build_memset_call): Use build_zero_cst if setting the entire object. gcc/testsuite/ChangeLog: PR d/96153 * gdc.dg/pr96153.d: Add new tests.
Diffstat (limited to 'gcc/d')
-rw-r--r--gcc/d/d-codegen.cc31
1 files changed, 29 insertions, 2 deletions
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 6a7ecc5..4050b85 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -668,9 +668,23 @@ build_address (tree exp)
/* Some expression lowering may request an address of a compile-time constant,
or other non-lvalue expression. Make sure it is assigned to a location we
can reference. */
- if ((CONSTANT_CLASS_P (exp) && TREE_CODE (exp) != STRING_CST)
- || TREE_CODE (exp) == CALL_EXPR)
+ if (CONSTANT_CLASS_P (exp) && TREE_CODE (exp) != STRING_CST)
exp = force_target_expr (exp);
+ else if (TREE_CODE (exp) == CALL_EXPR)
+ {
+ /* When a struct or array is returned in registers, we need to again fill
+ in all alignment holes. */
+ if (AGGREGATE_TYPE_P (TREE_TYPE (exp))
+ && !aggregate_value_p (TREE_TYPE (exp), exp))
+ {
+ tree tmp = build_local_temp (TREE_TYPE (exp));
+ init = compound_expr (init, build_memset_call (tmp));
+ init = compound_expr (init, modify_expr (tmp, exp));
+ exp = tmp;
+ }
+ else
+ exp = force_target_expr (exp);
+ }
d_mark_addressable (exp);
exp = build_fold_addr_expr_with_type_loc (input_location, exp, ptrtype);
@@ -825,6 +839,19 @@ build_memset_call (tree ptr, tree num)
ptr = build_address (ptr);
}
+ /* Use a zero constant to fill the destination if setting the entire object.
+ For CONSTRUCTORs, the memcpy() is lowered to a ref-all pointer assignment,
+ which can then be merged with other stores to the object. */
+ tree valtype = TREE_TYPE (TREE_TYPE (ptr));
+ if (tree_int_cst_equal (TYPE_SIZE_UNIT (valtype), num))
+ {
+ tree cst = build_zero_cst (valtype);
+ if (TREE_CODE (cst) == CONSTRUCTOR)
+ return build_memcpy_call (ptr, build_address (cst), num);
+
+ return modify_expr (build_deref (ptr), cst);
+ }
+
return build_call_expr (builtin_decl_explicit (BUILT_IN_MEMSET), 3,
ptr, integer_zero_node, num);
}