/* 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);
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);
}