Merge pull request #6539 from k-nrd/fix/field-first-writes-into-dynamic-soa

fix #6344: field-first index writes on #soa[dynamic]T and #soa[]T
This commit is contained in:
gingerBill
2026-04-11 11:45:19 +01:00
committed by GitHub
3 changed files with 78 additions and 2 deletions

View File

@@ -4680,6 +4680,8 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) {
}
}
lbValue val = lb_emit_ptr_offset(p, field, index);
// make sure it's ^T and not [^]T
val.type = alloc_type_multi_pointer_to_pointer(val.type);
return lb_addr(val);
}
@@ -6092,8 +6094,8 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
if (sub_sel.index.count > 0) {
item = lb_emit_deep_field_gep(p, item, sub_sel);
}
// make sure it's ^T and not [^]T
item.type = alloc_type_multi_pointer_to_pointer(item.type);
// make sure it's ^T and not [^]T
item.type = alloc_type_multi_pointer_to_pointer(item.type);
return lb_addr(item);
} else if (addr.kind == lbAddr_Swizzle) {

View File

@@ -36,6 +36,8 @@ $ODIN test ../test_issue_5699.odin $COMMON
$ODIN test ../test_issue_6068.odin $COMMON
$ODIN test ../test_issue_6101.odin $COMMON
$ODIN test ../test_issue_6165.odin $COMMON
$ODIN test ../test_issue_6344.odin $COMMON
$ODIN test ../test_issue_6344.odin $COMMON -o:speed
$ODIN test ../test_issue_6396.odin $COMMON
$ODIN test ../test_pr_6476.odin $COMMON

View File

@@ -0,0 +1,72 @@
// Tests issue #6344 https://github.com/odin-lang/Odin/issues/6344
package test_issues
import "core:testing"
@(test)
test_soa_dynamic_field_write :: proc(t: ^testing.T) {
V :: struct {
x: f32,
y: f32,
}
array := make(#soa[dynamic]V, 4, 8)
defer delete(array)
for i in 0 ..< 4 {
array[i] = V{f32(i), f32(i) * 2}
}
// Simple write through field-first indexing (was: compiler panic)
for i in 0 ..< 4 {
array.x[i] = f32(i) * 10
}
testing.expect_value(t, array[0].x, 0)
testing.expect_value(t, array[1].x, 10)
testing.expect_value(t, array[2].x, 20)
testing.expect_value(t, array[3].x, 30)
// Compound write through field-first indexing (was: compiler panic)
for i in 0 ..< 4 {
array.x[i] += array.y[i]
}
testing.expect_value(t, array[0].x, 0)
testing.expect_value(t, array[1].x, 12)
testing.expect_value(t, array[2].x, 24)
testing.expect_value(t, array[3].x, 36)
}
@(test)
test_soa_slice_field_write :: proc(t: ^testing.T) {
V :: struct {
x: f32,
y: f32,
}
array := make(#soa[dynamic]V, 4, 8)
defer delete(array)
for i in 0 ..< 4 {
array[i] = V{f32(i), f32(i) * 2}
}
slice := array[:]
// Write through slice field-first indexing (was: compiler panic)
for i in 0 ..< 4 {
slice.x[i] = f32(i) * 10
}
testing.expect_value(t, array[0].x, 0)
testing.expect_value(t, array[1].x, 10)
testing.expect_value(t, array[2].x, 20)
testing.expect_value(t, array[3].x, 30)
// Compound write through slice field-first indexing
for i in 0 ..< 4 {
slice.x[i] += slice.y[i]
}
testing.expect_value(t, array[0].x, 0)
testing.expect_value(t, array[1].x, 12)
testing.expect_value(t, array[2].x, 24)
testing.expect_value(t, array[3].x, 36)
}