From 9cd5ea59dd091083555d7aea691fcd889e67fb67 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 27 Jul 2021 20:45:50 +0100 Subject: Big simplification and improvement of the entity collection system, reducing unneeded steps for packages --- src/llvm_backend.cpp | 253 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 148 insertions(+), 105 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index efc589e05..a59e1baa9 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -7778,6 +7778,18 @@ lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { case Token_CmpEq: case Token_NotEq: + if (is_type_untyped_nil(be->right->tav.type)) { + lbValue left = lb_build_expr(p, be->left); + lbValue cmp = lb_emit_comp_against_nil(p, be->op.kind, left); + Type *type = default_type(tv.type); + return lb_emit_conv(p, cmp, type); + } else if (is_type_untyped_nil(be->left->tav.type)) { + lbValue right = lb_build_expr(p, be->right); + lbValue cmp = lb_emit_comp_against_nil(p, be->op.kind, right); + Type *type = default_type(tv.type); + return lb_emit_conv(p, cmp, type); + } + /*fallthrough*/ case Token_Lt: case Token_LtEq: case Token_Gt: @@ -11337,133 +11349,164 @@ lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, lbValue x) { lbValue res = {}; res.type = t_llvm_bool; Type *t = x.type; - if (is_type_enum(t)) { - if (op_kind == Token_CmpEq) { - res.value = LLVMBuildIsNull(p->builder, x.value, ""); - } else if (op_kind == Token_NotEq) { - res.value = LLVMBuildIsNotNull(p->builder, x.value, ""); - } - return res; - } else if (is_type_pointer(t)) { - if (op_kind == Token_CmpEq) { - res.value = LLVMBuildIsNull(p->builder, x.value, ""); - } else if (op_kind == Token_NotEq) { - res.value = LLVMBuildIsNotNull(p->builder, x.value, ""); - } - return res; - } else if (is_type_cstring(t)) { - lbValue ptr = lb_emit_conv(p, x, t_u8_ptr); - if (op_kind == Token_CmpEq) { - res.value = LLVMBuildIsNull(p->builder, ptr.value, ""); - } else if (op_kind == Token_NotEq) { - res.value = LLVMBuildIsNotNull(p->builder, ptr.value, ""); + Type *bt = base_type(t); + TypeKind type_kind = bt->kind; + + switch (type_kind) { + case Type_Basic: + switch (bt->Basic.kind) { + case Basic_rawptr: + case Basic_cstring: + if (op_kind == Token_CmpEq) { + res.value = LLVMBuildIsNull(p->builder, x.value, ""); + } else if (op_kind == Token_NotEq) { + res.value = LLVMBuildIsNotNull(p->builder, x.value, ""); + } + return res; + case Basic_any: + { + // TODO(bill): is this correct behaviour for nil comparison for any? + lbValue data = lb_emit_struct_ev(p, x, 0); + lbValue ti = lb_emit_struct_ev(p, x, 1); + if (op_kind == Token_CmpEq) { + LLVMValueRef a = LLVMBuildIsNull(p->builder, data.value, ""); + LLVMValueRef b = LLVMBuildIsNull(p->builder, ti.value, ""); + res.value = LLVMBuildOr(p->builder, a, b, ""); + return res; + } else if (op_kind == Token_NotEq) { + LLVMValueRef a = LLVMBuildIsNotNull(p->builder, data.value, ""); + LLVMValueRef b = LLVMBuildIsNotNull(p->builder, ti.value, ""); + res.value = LLVMBuildAnd(p->builder, a, b, ""); + return res; + } + } + break; + case Basic_typeid: + lbValue invalid_typeid = lb_const_value(p->module, t_typeid, exact_value_i64(0)); + return lb_emit_comp(p, op_kind, x, invalid_typeid); } - return res; - } else if (is_type_proc(t)) { + break; + + case Type_Enum: + case Type_Pointer: + case Type_Proc: + case Type_BitSet: if (op_kind == Token_CmpEq) { res.value = LLVMBuildIsNull(p->builder, x.value, ""); } else if (op_kind == Token_NotEq) { res.value = LLVMBuildIsNotNull(p->builder, x.value, ""); } return res; - } else if (is_type_any(t)) { - // TODO(bill): is this correct behaviour for nil comparison for any? - lbValue data = lb_emit_struct_ev(p, x, 0); - lbValue ti = lb_emit_struct_ev(p, x, 1); - if (op_kind == Token_CmpEq) { - LLVMValueRef a = LLVMBuildIsNull(p->builder, data.value, ""); - LLVMValueRef b = LLVMBuildIsNull(p->builder, ti.value, ""); - res.value = LLVMBuildOr(p->builder, a, b, ""); - return res; - } else if (op_kind == Token_NotEq) { - LLVMValueRef a = LLVMBuildIsNotNull(p->builder, data.value, ""); - LLVMValueRef b = LLVMBuildIsNotNull(p->builder, ti.value, ""); - res.value = LLVMBuildAnd(p->builder, a, b, ""); - return res; - } - } else if (is_type_slice(t)) { - lbValue data = lb_emit_struct_ev(p, x, 0); - if (op_kind == Token_CmpEq) { - res.value = LLVMBuildIsNull(p->builder, data.value, ""); - return res; - } else if (op_kind == Token_NotEq) { - res.value = LLVMBuildIsNotNull(p->builder, data.value, ""); - return res; - } - } else if (is_type_dynamic_array(t)) { - lbValue data = lb_emit_struct_ev(p, x, 0); - if (op_kind == Token_CmpEq) { - res.value = LLVMBuildIsNull(p->builder, data.value, ""); - return res; - } else if (op_kind == Token_NotEq) { - res.value = LLVMBuildIsNotNull(p->builder, data.value, ""); - return res; - } - } else if (is_type_map(t)) { - lbValue hashes = lb_emit_struct_ev(p, x, 0); - lbValue data = lb_emit_struct_ev(p, hashes, 0); - return lb_emit_comp(p, op_kind, data, lb_zero(p->module, data.type)); - } else if (is_type_union(t)) { - if (type_size_of(t) == 0) { + + case Type_Slice: + { + lbValue data = lb_emit_struct_ev(p, x, 0); if (op_kind == Token_CmpEq) { - return lb_const_bool(p->module, t_llvm_bool, true); + res.value = LLVMBuildIsNull(p->builder, data.value, ""); + return res; } else if (op_kind == Token_NotEq) { - return lb_const_bool(p->module, t_llvm_bool, false); + res.value = LLVMBuildIsNotNull(p->builder, data.value, ""); + return res; } - } else if (is_type_union_maybe_pointer(t)) { - lbValue tag = lb_emit_transmute(p, x, t_rawptr); - return lb_emit_comp_against_nil(p, op_kind, tag); - } else { - lbValue tag = lb_emit_union_tag_value(p, x); - return lb_emit_comp(p, op_kind, tag, lb_zero(p->module, tag.type)); } - } else if (is_type_typeid(t)) { - lbValue invalid_typeid = lb_const_value(p->module, t_typeid, exact_value_i64(0)); - return lb_emit_comp(p, op_kind, x, invalid_typeid); - } else if (is_type_soa_struct(t)) { - Type *bt = base_type(t); - if (bt->Struct.soa_kind == StructSoa_Slice) { - LLVMValueRef the_value = {}; - if (bt->Struct.fields.count == 0) { - lbValue len = lb_soa_struct_len(p, x); - the_value = len.value; - } else { - lbValue first_field = lb_emit_struct_ev(p, x, 0); - the_value = first_field.value; - } + break; + + case Type_DynamicArray: + { + lbValue data = lb_emit_struct_ev(p, x, 0); if (op_kind == Token_CmpEq) { - res.value = LLVMBuildIsNull(p->builder, the_value, ""); + res.value = LLVMBuildIsNull(p->builder, data.value, ""); return res; } else if (op_kind == Token_NotEq) { - res.value = LLVMBuildIsNotNull(p->builder, the_value, ""); + res.value = LLVMBuildIsNotNull(p->builder, data.value, ""); return res; } - } else if (bt->Struct.soa_kind == StructSoa_Dynamic) { - LLVMValueRef the_value = {}; - if (bt->Struct.fields.count == 0) { - lbValue cap = lb_soa_struct_cap(p, x); - the_value = cap.value; - } else { - lbValue first_field = lb_emit_struct_ev(p, x, 0); - the_value = first_field.value; - } + } + break; + + case Type_Map: + { + lbValue map_ptr = lb_address_from_load_or_generate_local(p, x); + + unsigned indices[2] = {0, 0}; + LLVMValueRef hashes_data = LLVMBuildStructGEP(p->builder, map_ptr.value, 0, ""); + LLVMValueRef hashes_data_ptr_ptr = LLVMBuildStructGEP(p->builder, hashes_data, 0, ""); + LLVMValueRef hashes_data_ptr = LLVMBuildLoad(p->builder, hashes_data_ptr_ptr, ""); + if (op_kind == Token_CmpEq) { - res.value = LLVMBuildIsNull(p->builder, the_value, ""); + res.value = LLVMBuildIsNull(p->builder, hashes_data_ptr, ""); return res; - } else if (op_kind == Token_NotEq) { - res.value = LLVMBuildIsNotNull(p->builder, the_value, ""); + } else { + res.value = LLVMBuildIsNotNull(p->builder, hashes_data_ptr, ""); return res; } } - } else if (is_type_struct(t) && type_has_nil(t)) { - auto args = array_make(permanent_allocator(), 2); - lbValue lhs = lb_address_from_load_or_generate_local(p, x); - args[0] = lb_emit_conv(p, lhs, t_rawptr); - args[1] = lb_const_int(p->module, t_int, type_size_of(t)); - lbValue val = lb_emit_runtime_call(p, "memory_compare_zero", args); - lbValue res = lb_emit_comp(p, op_kind, val, lb_const_int(p->module, t_int, 0)); - return res; + break; + + case Type_Union: + { + if (type_size_of(t) == 0) { + if (op_kind == Token_CmpEq) { + return lb_const_bool(p->module, t_llvm_bool, true); + } else if (op_kind == Token_NotEq) { + return lb_const_bool(p->module, t_llvm_bool, false); + } + } else if (is_type_union_maybe_pointer(t)) { + lbValue tag = lb_emit_transmute(p, x, t_rawptr); + return lb_emit_comp_against_nil(p, op_kind, tag); + } else { + lbValue tag = lb_emit_union_tag_value(p, x); + return lb_emit_comp(p, op_kind, tag, lb_zero(p->module, tag.type)); + } + } + case Type_Struct: + if (is_type_soa_struct(t)) { + Type *bt = base_type(t); + if (bt->Struct.soa_kind == StructSoa_Slice) { + LLVMValueRef the_value = {}; + if (bt->Struct.fields.count == 0) { + lbValue len = lb_soa_struct_len(p, x); + the_value = len.value; + } else { + lbValue first_field = lb_emit_struct_ev(p, x, 0); + the_value = first_field.value; + } + if (op_kind == Token_CmpEq) { + res.value = LLVMBuildIsNull(p->builder, the_value, ""); + return res; + } else if (op_kind == Token_NotEq) { + res.value = LLVMBuildIsNotNull(p->builder, the_value, ""); + return res; + } + } else if (bt->Struct.soa_kind == StructSoa_Dynamic) { + LLVMValueRef the_value = {}; + if (bt->Struct.fields.count == 0) { + lbValue cap = lb_soa_struct_cap(p, x); + the_value = cap.value; + } else { + lbValue first_field = lb_emit_struct_ev(p, x, 0); + the_value = first_field.value; + } + if (op_kind == Token_CmpEq) { + res.value = LLVMBuildIsNull(p->builder, the_value, ""); + return res; + } else if (op_kind == Token_NotEq) { + res.value = LLVMBuildIsNotNull(p->builder, the_value, ""); + return res; + } + } + } else if (is_type_struct(t) && type_has_nil(t)) { + auto args = array_make(permanent_allocator(), 2); + lbValue lhs = lb_address_from_load_or_generate_local(p, x); + args[0] = lb_emit_conv(p, lhs, t_rawptr); + args[1] = lb_const_int(p->module, t_int, type_size_of(t)); + lbValue val = lb_emit_runtime_call(p, "memory_compare_zero", args); + lbValue res = lb_emit_comp(p, op_kind, val, lb_const_int(p->module, t_int, 0)); + return res; + } + break; } + GB_PANIC("Unknown handled type: %s -> %s", type_to_string(t), type_to_string(bt)); return {}; } -- cgit v1.2.3