diff --git a/core/os/os.odin b/core/os/os.odin index 7d6f4451d..7b3eac764 100644 --- a/core/os/os.odin +++ b/core/os/os.odin @@ -164,9 +164,10 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, return aligned_heap_alloc(size, alignment); case .Free: - assert(old_memory != nil); - ptr := recover_original_pointer(old_memory); - heap_free(ptr); + if old_memory != nil { + ptr := recover_original_pointer(old_memory); + heap_free(ptr); + } return nil; case .Free_All: diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index 67435f4ea..1fce88ce9 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -1833,9 +1833,7 @@ main :: proc() { deprecated_attribute(); range_statements_with_multiple_return_values(); threading_example(); - - // TODO(tetra): When bill fixes SOA array comparison to nil in reserve_soa, we can re-enable this. - // soa_struct_layout(); + soa_struct_layout(); } } diff --git a/src/ir.cpp b/src/ir.cpp index 877979c4f..c9f42ea8e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4325,7 +4325,44 @@ irValue *ir_emit_comp_against_nil(irProcedure *proc, TokenKind op_kind, irValue irValue *val = ir_emit_runtime_call(proc, "memory_compare_zero", args); irValue *res = ir_emit_comp(proc, op_kind, val, v_zero); return ir_emit_conv(proc, res, t_bool); + } else if (is_type_soa_struct(t)) { + Type *bt = base_type(t); + if (bt->Struct.soa_kind == StructSoa_Slice) { + ir_emit_comment(proc, str_lit("soa-slice-nil-comp")); + irValue *len = ir_soa_struct_len(proc, x); + if (bt->Struct.fields.count > 1) { + irValue *data = ir_emit_struct_ev(proc, x, 0); + if (op_kind == Token_CmpEq) { + irValue *a = ir_emit_comp(proc, Token_CmpEq, data, v_raw_nil); + irValue *b = ir_emit_comp(proc, Token_CmpEq, len, v_zero); + return ir_emit_arith(proc, Token_Or, a, b, t_bool); + } else if (op_kind == Token_NotEq) { + irValue *a = ir_emit_comp(proc, Token_NotEq, data, v_raw_nil); + irValue *b = ir_emit_comp(proc, Token_NotEq, len, v_zero); + return ir_emit_arith(proc, Token_And, a, b, t_bool); + } + } else { + return ir_emit_comp(proc, op_kind, len, v_zero); + } + } else if (bt->Struct.soa_kind == StructSoa_Dynamic) { + ir_emit_comment(proc, str_lit("soa-dynamic-array-nil-comp")); + irValue *cap = ir_soa_struct_len(proc, x); + if (bt->Struct.fields.count > 1) { + irValue *data = ir_emit_struct_ev(proc, x, 0); + if (op_kind == Token_CmpEq) { + irValue *a = ir_emit_comp(proc, Token_CmpEq, data, v_raw_nil); + irValue *b = ir_emit_comp(proc, Token_CmpEq, cap, v_zero); + return ir_emit_arith(proc, Token_Or, a, b, t_bool); + } else if (op_kind == Token_NotEq) { + irValue *a = ir_emit_comp(proc, Token_NotEq, data, v_raw_nil); + irValue *b = ir_emit_comp(proc, Token_NotEq, cap, v_zero); + return ir_emit_arith(proc, Token_And, a, b, t_bool); + } + } else { + return ir_emit_comp(proc, op_kind, cap, v_zero); + } + } } return nullptr; } diff --git a/src/types.cpp b/src/types.cpp index 63647dcf3..e5f4f7957 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -1585,6 +1585,13 @@ bool type_has_nil(Type *t) { case Type_Union: return !t->Union.no_nil; case Type_Struct: + if (is_type_soa_struct(t)) { + switch (t->Struct.soa_kind) { + case StructSoa_Fixed: return false; + case StructSoa_Slice: return true; + case StructSoa_Dynamic: return true; + } + } return false; case Type_Opaque: return true;