aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2019-12-01 11:56:08 +0000
committergingerBill <bill@gingerbill.org>2019-12-01 11:56:08 +0000
commit7fbe0a6f2385e618ea4d3a724d2ed6147b6921bf (patch)
tree9e032434af0afa47f66a40aac3605ef7f14505d2
parent3fd5c3cd851d8f4dfd441141ca7e96889f069933 (diff)
Fix nil comparisons for soa slices and dynamic arrays
-rw-r--r--core/os/os.odin7
-rw-r--r--examples/demo/demo.odin4
-rw-r--r--src/ir.cpp39
-rw-r--r--src/types.cpp7
4 files changed, 50 insertions, 7 deletions
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;