mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-28 16:01:31 +00:00
swizzle target multi-assignment
This commit is contained in:
@@ -994,7 +994,7 @@ gb_internal lbAddr lb_find_or_generate_context_ptr(lbProcedure *p) {
|
||||
}
|
||||
|
||||
gb_internal lbValue lb_address_from_load_or_generate_local(lbProcedure *p, lbValue value) {
|
||||
if (LLVMIsALoadInst(value.value)) {
|
||||
if (!p->in_multi_assignment && LLVMIsALoadInst(value.value)) {
|
||||
lbValue res = {};
|
||||
res.value = LLVMGetOperand(value.value, 0);
|
||||
res.type = alloc_type_pointer(value.type);
|
||||
|
||||
@@ -52,6 +52,7 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style -ignore-unused
|
||||
clang -c ..\test_issue_sysv_abi.c -o test_issue_sysv_abi_c.o || exit /b
|
||||
..\..\..\odin test ..\test_issue_sysv_abi.odin %COMMON% || exit /b
|
||||
..\..\..\odin build ..\test_issue_7073-1.odin %COMMON% 2>&1 | find /c "Error:" | findstr /x "2" || exit /b
|
||||
..\..\..\odin test ..\test_issue_swizzle_multi_assign.odin %COMMON% || exit /b
|
||||
|
||||
@echo off
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@ $ODIN build ../test_issue_7167.odin $COMMON
|
||||
$ODIN build ../test_issue_7188.odin $COMMON
|
||||
$ODIN check ../test_issue_7260.odin -no-entry-point $COMMON_CHECK
|
||||
$ODIN test ../test_issue_bool_to_be_conversion.odin $COMMON
|
||||
$ODIN test ../test_issue_swizzle_multi_assign.odin $COMMON
|
||||
|
||||
$ODIN check ../test_issue_foreign_redeclaration.odin -no-entry-point $COMMON_CHECK
|
||||
if [[ $($ODIN check ../test_issue_foreign_redeclaration_mismatch.odin -no-entry-point $COMMON_CHECK 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]]; then
|
||||
|
||||
80
tests/issues/test_issue_swizzle_multi_assign.odin
Normal file
80
tests/issues/test_issue_swizzle_multi_assign.odin
Normal file
@@ -0,0 +1,80 @@
|
||||
package test_issues
|
||||
|
||||
import "core:testing"
|
||||
|
||||
// A multi-assignment reads every right-hand side before it stores into any target, which is what
|
||||
// makes `a, b = b, a` a swap. Storing into a swizzle reused the address the source was loaded from
|
||||
// instead of the value read at that point, so a source that named a target written earlier in the
|
||||
// same statement read back the new contents.
|
||||
|
||||
@(test)
|
||||
swizzle_multi_assign_swap :: proc(t: ^testing.T) {
|
||||
v := [4]f32{1, 2, 3, 4}
|
||||
v.xy, v.zw = v.zw, v.xy
|
||||
testing.expect_value(t, v, [4]f32{3, 4, 1, 2})
|
||||
|
||||
// the other order happened to be correct already
|
||||
w := [4]f32{1, 2, 3, 4}
|
||||
w.zw, w.xy = w.xy, w.zw
|
||||
testing.expect_value(t, w, [4]f32{3, 4, 1, 2})
|
||||
|
||||
x := [4]f32{1, 2, 3, 4}
|
||||
x.xy, x.wz = x.wz, x.xy
|
||||
testing.expect_value(t, x, [4]f32{4, 3, 2, 1})
|
||||
}
|
||||
|
||||
@(test)
|
||||
swizzle_multi_assign_element_types :: proc(t: ^testing.T) {
|
||||
a := [4]i32{1, 2, 3, 4}
|
||||
a.xy, a.zw = a.zw, a.xy
|
||||
testing.expect_value(t, a, [4]i32{3, 4, 1, 2})
|
||||
|
||||
b := [4]f64{1, 2, 3, 4}
|
||||
b.xy, b.zw = b.zw, b.xy
|
||||
testing.expect_value(t, b, [4]f64{3, 4, 1, 2})
|
||||
|
||||
c := [4]u8{1, 2, 3, 4}
|
||||
c.xy, c.zw = c.zw, c.xy
|
||||
testing.expect_value(t, c, [4]u8{3, 4, 1, 2})
|
||||
}
|
||||
|
||||
@(test)
|
||||
swizzle_multi_assign_through_pointer :: proc(t: ^testing.T) {
|
||||
v := [4]f32{1, 2, 3, 4}
|
||||
p := &v
|
||||
p.xy, p.zw = p.zw, p.xy
|
||||
testing.expect_value(t, v, [4]f32{3, 4, 1, 2})
|
||||
}
|
||||
|
||||
@(test)
|
||||
swizzle_multi_assign_across_variables :: proc(t: ^testing.T) {
|
||||
// the source names a different variable, which an earlier store still writes to
|
||||
a := [4]f32{1, 2, 3, 4}
|
||||
b := [4]f32{5, 6, 7, 8}
|
||||
a.xy, b.xy = b.xy, a.xy
|
||||
testing.expect_value(t, a, [4]f32{5, 6, 3, 4})
|
||||
testing.expect_value(t, b, [4]f32{1, 2, 7, 8})
|
||||
}
|
||||
|
||||
@(test)
|
||||
swizzle_multi_assign_three_targets :: proc(t: ^testing.T) {
|
||||
v := [4]f32{1, 2, 3, 4}
|
||||
v.xy, v.zw, v.x = v.zw, v.xy, v.w
|
||||
testing.expect_value(t, v, [4]f32{4, 4, 1, 2})
|
||||
}
|
||||
|
||||
@(test)
|
||||
swizzle_single_assign_unchanged :: proc(t: ^testing.T) {
|
||||
// one target still reads every lane before it writes any of them
|
||||
v := [4]f32{1, 2, 3, 4}
|
||||
v.yzw = v.xyz
|
||||
testing.expect_value(t, v, [4]f32{1, 1, 2, 3})
|
||||
|
||||
w := [4]f32{1, 2, 3, 4}
|
||||
w.xy = w.zw
|
||||
testing.expect_value(t, w, [4]f32{3, 4, 3, 4})
|
||||
|
||||
x := [4]f32{1, 2, 3, 4}
|
||||
x.x, x.y = x.y, x.x
|
||||
testing.expect_value(t, x, [4]f32{2, 1, 3, 4})
|
||||
}
|
||||
Reference in New Issue
Block a user