diff options
| author | gingerBill <bill@gingerbill.org> | 2021-08-09 19:37:58 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2021-08-09 19:37:58 +0100 |
| commit | 01f431b01fea18b0844d0475839c68426e95fd2c (patch) | |
| tree | 7420e056934a923083249fa4863b168877b9855f /src/llvm_backend_stmt.cpp | |
| parent | aebfa4b28e5d92e493010593f4177f53249aa6b2 (diff) | |
Unify semantics of the built-in `swizzle` procedure with the selector expression semantics e.g. `.xyz`
Diffstat (limited to 'src/llvm_backend_stmt.cpp')
| -rw-r--r-- | src/llvm_backend_stmt.cpp | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 324b408c7..a220995a3 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1818,6 +1818,51 @@ void lb_build_assign_stmt_array(lbProcedure *p, TokenKind op, lbAddr const &lhs, lb_emit_store(p, lhs_ptrs[i], ops[i]); } return; + } else if (lhs.kind == lbAddr_SwizzleLarge) { + GB_ASSERT(is_type_array(lhs_type)); + + struct ValueAndIndex { + lbValue value; + u32 index; + }; + + Type *bt = base_type(lhs_type); + GB_ASSERT(bt->kind == Type_Array); + + auto indices_handled = slice_make<bool>(temporary_allocator(), bt->Array.count); + auto indices = slice_make<i32>(temporary_allocator(), bt->Array.count); + i32 index_count = 0; + for_array(i, lhs.swizzle_large.indices) { + i32 index = lhs.swizzle_large.indices[i]; + if (indices_handled[index]) { + continue; + } + indices[index_count++] = index; + } + gb_sort_array(indices.data, index_count, gb_i32_cmp(0)); + + lbValue lhs_ptrs[4] = {}; + lbValue x_loads[4] = {}; + lbValue y_loads[4] = {}; + lbValue ops[4] = {}; + + for (i32 i = 0; i < index_count; i++) { + lhs_ptrs[i] = lb_emit_array_epi(p, lhs.addr, indices[i]); + } + for (i32 i = 0; i < index_count; i++) { + x_loads[i] = lb_emit_load(p, lhs_ptrs[i]); + } + for (i32 i = 0; i < index_count; i++) { + y_loads[i].value = LLVMBuildExtractValue(p->builder, rhs.value, i, ""); + y_loads[i].type = elem_type; + } + for (i32 i = 0; i < index_count; i++) { + ops[i] = lb_emit_arith(p, op, x_loads[i], y_loads[i], elem_type); + } + for (i32 i = 0; i < index_count; i++) { + lb_emit_store(p, lhs_ptrs[i], ops[i]); + } + return; } |