diff options
| author | gingerBill <bill@gingerbill.org> | 2019-12-01 11:56:08 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2019-12-01 11:56:08 +0000 |
| commit | 7fbe0a6f2385e618ea4d3a724d2ed6147b6921bf (patch) | |
| tree | 9e032434af0afa47f66a40aac3605ef7f14505d2 /src | |
| parent | 3fd5c3cd851d8f4dfd441141ca7e96889f069933 (diff) | |
Fix nil comparisons for soa slices and dynamic arrays
Diffstat (limited to 'src')
| -rw-r--r-- | src/ir.cpp | 39 | ||||
| -rw-r--r-- | src/types.cpp | 7 |
2 files changed, 45 insertions, 1 deletions
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; |