mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-23 21:41:34 +00:00
Merge pull request #7361 from ssenthilnathan3/fix/recursive-soa-sigbus
Fix: SIGBUS/segfault when compiling recursive #soa slice/dynamic array types
This commit is contained in:
@@ -2617,6 +2617,22 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
return struct_type;
|
||||
}
|
||||
|
||||
bool is_soa_struct = type->Struct.soa_kind != StructSoa_None;
|
||||
LLVMTypeRef named_struct_type = nullptr;
|
||||
if (is_soa_struct) {
|
||||
// NOTE(bill): SOA structs are anonymous and may be recursive
|
||||
// (e.g. `#soa[]T` where `T` itself contains a field of type
|
||||
// `#soa[]T`). Register an opaque named struct up front so that any
|
||||
// recursive field references resolve to it instead of recursing
|
||||
// infinitely.
|
||||
gbString soa_name = temp_canonical_string(type);
|
||||
named_struct_type = LLVMGetTypeByName(m->mod, soa_name);
|
||||
if (named_struct_type == nullptr) {
|
||||
named_struct_type = LLVMStructCreateNamed(ctx, soa_name);
|
||||
}
|
||||
map_set(&m->types, type, named_struct_type);
|
||||
}
|
||||
|
||||
lbStructFieldRemapping field_remapping = {};
|
||||
slice_init(&field_remapping, permanent_allocator(), type->Struct.fields.count);
|
||||
|
||||
@@ -2669,7 +2685,13 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
GB_ASSERT(fields[i] != nullptr);
|
||||
}
|
||||
|
||||
LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, requires_packing);
|
||||
LLVMTypeRef struct_type = nullptr;
|
||||
if (is_soa_struct) {
|
||||
struct_type = named_struct_type;
|
||||
LLVMStructSetBody(struct_type, fields.data, cast(unsigned)fields.count, requires_packing);
|
||||
} else {
|
||||
struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, requires_packing);
|
||||
}
|
||||
map_set(&m->struct_field_remapping, cast(void *)struct_type, field_remapping);
|
||||
map_set(&m->struct_field_remapping, cast(void *)type, field_remapping);
|
||||
#if 0
|
||||
|
||||
@@ -90,6 +90,7 @@ fi
|
||||
$ODIN check ../test_issue_6979.odin -no-entry-point $COMMON_CHECK
|
||||
$ODIN check ../test_issue_7012.odin -no-entry-point $COMMON_CHECK
|
||||
$ODIN build ../test_issue_7037.odin $COMMON -o:none
|
||||
$ODIN test ../test_issue_7356.odin $COMMON
|
||||
$ODIN build ../test_issue_7167.odin $COMMON
|
||||
$ODIN build ../test_issue_7188.odin $COMMON
|
||||
|
||||
|
||||
43
tests/issues/test_issue_7356.odin
Normal file
43
tests/issues/test_issue_7356.odin
Normal file
@@ -0,0 +1,43 @@
|
||||
// Tests issue #7356 https://github.com/odin-lang/Odin/issues/7356
|
||||
// The compiler used to terminate with a SIGBUS/SIGSEGV when compiling a
|
||||
// recursive `#soa` slice/dynamic array contained within its own element type.
|
||||
|
||||
package test_issues
|
||||
|
||||
import "core:testing"
|
||||
|
||||
Bookmark :: struct {
|
||||
name: string,
|
||||
children: #soa[]Bookmark,
|
||||
}
|
||||
|
||||
DynamicBookmark :: struct {
|
||||
name: string,
|
||||
children: #soa[dynamic]Bookmark,
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_recursive_soa_slice :: proc(t: ^testing.T) {
|
||||
b: Bookmark
|
||||
b.name = "root"
|
||||
b.children = make(#soa[]Bookmark, 2)
|
||||
defer delete(b.children)
|
||||
|
||||
b.children[0].name = "child0"
|
||||
b.children[1].name = "child1"
|
||||
|
||||
testing.expect_value(t, len(b.children), 2)
|
||||
testing.expect_value(t, b.children[0].name, "child0")
|
||||
testing.expect_value(t, b.children[1].name, "child1")
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_recursive_soa_dynamic :: proc(t: ^testing.T) {
|
||||
b: DynamicBookmark
|
||||
b.name = "root"
|
||||
append_soa(&b.children, Bookmark{name = "child0"})
|
||||
defer delete(b.children)
|
||||
|
||||
testing.expect_value(t, len(b.children), 1)
|
||||
testing.expect_value(t, b.children[0].name, "child0")
|
||||
}
|
||||
Reference in New Issue
Block a user