From ec0a9a5f8a68e03650958acca19f96b3dfd4744e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 21 Jul 2023 13:05:39 +0100 Subject: Copy lvalues on multi-valued assignments to allow for `a, b = b, a` on large types (minor bodge) --- src/tilde_stmt.cpp | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'src/tilde_stmt.cpp') diff --git a/src/tilde_stmt.cpp b/src/tilde_stmt.cpp index c5aaa9161..6aa906288 100644 --- a/src/tilde_stmt.cpp +++ b/src/tilde_stmt.cpp @@ -850,11 +850,39 @@ gb_internal void cg_build_assignment(cgProcedure *p, Array 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 = 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); -- cgit v1.2.3