Copy lvalues on multi-valued assignments to allow for a, b = b, a on large types (minor bodge)

This commit is contained in:
gingerBill
2023-07-21 13:05:39 +01:00
parent 47b924990f
commit ec0a9a5f8a
3 changed files with 41 additions and 15 deletions

View File

@@ -850,11 +850,39 @@ gb_internal void cg_build_assignment(cgProcedure *p, Array<cgAddr> const &lvals,
p->in_multi_assignment = lval_count > 1;
GB_ASSERT(lvals.count == inits.count);
for_array(i, inits) {
if (inits.count > 1) for_array(i, inits) {
cgAddr lval = lvals[i];
cgValue init = inits[i];
cgValue init = cg_flatten_value(p, inits[i]);
GB_ASSERT(init.kind != cgValue_Multi);
if (init.type == nullptr) {
continue;
}
Type *type = cg_addr_type(lval);
GB_ASSERT(are_types_identical(type, init.type));
if (init.kind == cgValue_Addr &&
!cg_addr_is_empty(lval)) {
// NOTE(bill): This is needed for certain constructs such as this:
// a, b = b, a
// NOTE(bill): This is a bodge and not necessarily a good way of doing things whatsoever
TB_CharUnits size = cast(TB_CharUnits)type_size_of(type);
TB_CharUnits align = cast(TB_CharUnits)type_align_of(type);
TB_Node *copy = tb_inst_local(p->func, size, align);
tb_inst_memcpy(p->func, copy, init.node, tb_inst_uint(p->func, TB_TYPE_INT, size), align, false);
// use the copy instead
init.node = copy;
}
inits[i] = init;
}
for_array(i, inits) {
cgAddr lval = lvals[i];
cgValue init = inits[i];
GB_ASSERT(init.kind != cgValue_Multi);
if (init.type == nullptr) {
// TODO(bill): figure out how to do this
continue;
}
cg_addr_store(p, lval, init);