| ... | ... | @@ -1225,7 +1225,7 @@ static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *so |
| 1225 | 1225 | return &instruction->base; |
| 1226 | 1226 | } |
| 1227 | 1227 | |
| 1228 | | static IrInstruction *ir_build_test_null(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1228 | static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1229 | 1229 | IrInstructionTestNonNull *instruction = ir_build_instruction<IrInstructionTestNonNull>(irb, scope, source_node); |
| 1230 | 1230 | instruction->value = value; |
| 1231 | 1231 | |
| ... | ... | @@ -1234,10 +1234,10 @@ static IrInstruction *ir_build_test_null(IrBuilder *irb, Scope *scope, AstNode * |
| 1234 | 1234 | return &instruction->base; |
| 1235 | 1235 | } |
| 1236 | 1236 | |
| 1237 | | static IrInstruction *ir_build_test_null_from(IrBuilder *irb, IrInstruction *old_instruction, |
| 1237 | static IrInstruction *ir_build_test_nonnull_from(IrBuilder *irb, IrInstruction *old_instruction, |
| 1238 | 1238 | IrInstruction *value) |
| 1239 | 1239 | { |
| 1240 | | IrInstruction *new_instruction = ir_build_test_null(irb, old_instruction->scope, |
| 1240 | IrInstruction *new_instruction = ir_build_test_nonnull(irb, old_instruction->scope, |
| 1241 | 1241 | old_instruction->source_node, value); |
| 1242 | 1242 | ir_link_new_instruction(new_instruction, old_instruction); |
| 1243 | 1243 | return new_instruction; |
| ... | ... | @@ -2923,7 +2923,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 2923 | 2923 | IrBasicBlock *null_block = ir_build_basic_block(irb, scope, "MaybeRetNull"); |
| 2924 | 2924 | IrBasicBlock *ok_block = ir_build_basic_block(irb, scope, "MaybeRetOk"); |
| 2925 | 2925 | |
| 2926 | | IrInstruction *is_non_null = ir_build_test_null(irb, scope, node, return_value); |
| 2926 | IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, return_value); |
| 2927 | 2927 | |
| 2928 | 2928 | IrInstruction *is_comptime; |
| 2929 | 2929 | if (ir_should_inline(irb)) { |
| ... | ... | @@ -2980,7 +2980,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 2980 | 2980 | if (maybe_val_ptr == irb->codegen->invalid_instruction) |
| 2981 | 2981 | return irb->codegen->invalid_instruction; |
| 2982 | 2982 | IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); |
| 2983 | | IrInstruction *is_non_null = ir_build_test_null(irb, scope, node, maybe_val); |
| 2983 | IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_val); |
| 2984 | 2984 | |
| 2985 | 2985 | IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "MaybeRetReturn"); |
| 2986 | 2986 | IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "MaybeRetContinue"); |
| ... | ... | @@ -3293,7 +3293,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As |
| 3293 | 3293 | return irb->codegen->invalid_instruction; |
| 3294 | 3294 | |
| 3295 | 3295 | IrInstruction *maybe_val = ir_build_load_ptr(irb, parent_scope, node, maybe_ptr); |
| 3296 | | IrInstruction *is_non_null = ir_build_test_null(irb, parent_scope, node, maybe_val); |
| 3296 | IrInstruction *is_non_null = ir_build_test_nonnull(irb, parent_scope, node, maybe_val); |
| 3297 | 3297 | |
| 3298 | 3298 | IrInstruction *is_comptime; |
| 3299 | 3299 | if (ir_should_inline(irb)) { |
| ... | ... | @@ -4595,7 +4595,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 4595 | 4595 | return maybe_val_ptr; |
| 4596 | 4596 | |
| 4597 | 4597 | IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); |
| 4598 | | IrInstruction *is_non_null = ir_build_test_null(irb, scope, node, maybe_val); |
| 4598 | IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_val); |
| 4599 | 4599 | |
| 4600 | 4600 | IrBasicBlock *then_block = ir_build_basic_block(irb, scope, "MaybeThen"); |
| 4601 | 4601 | IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "MaybeElse"); |
| ... | ... | @@ -6839,13 +6839,55 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 6839 | 6839 | static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| 6840 | 6840 | IrInstruction *op1 = bin_op_instruction->op1->other; |
| 6841 | 6841 | IrInstruction *op2 = bin_op_instruction->op2->other; |
| 6842 | |
| 6843 | IrBinOp op_id = bin_op_instruction->op_id; |
| 6844 | bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq); |
| 6845 | if (is_equality_cmp && |
| 6846 | ((op1->value.type->id == TypeTableEntryIdNullLit && op2->value.type->id == TypeTableEntryIdMaybe) || |
| 6847 | (op2->value.type->id == TypeTableEntryIdNullLit && op1->value.type->id == TypeTableEntryIdMaybe) || |
| 6848 | (op1->value.type->id == TypeTableEntryIdNullLit && op2->value.type->id == TypeTableEntryIdNullLit))) |
| 6849 | { |
| 6850 | bool depends_on_compile_var = op1->value.depends_on_compile_var || op2->value.depends_on_compile_var; |
| 6851 | if (op1->value.type->id == TypeTableEntryIdNullLit && op2->value.type->id == TypeTableEntryIdNullLit) { |
| 6852 | ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base, depends_on_compile_var); |
| 6853 | out_val->data.x_bool = (op_id == IrBinOpCmpEq); |
| 6854 | return ira->codegen->builtin_types.entry_bool; |
| 6855 | } |
| 6856 | IrInstruction *maybe_op; |
| 6857 | if (op1->value.type->id == TypeTableEntryIdNullLit) { |
| 6858 | maybe_op = op2; |
| 6859 | } else if (op2->value.type->id == TypeTableEntryIdNullLit) { |
| 6860 | maybe_op = op1; |
| 6861 | } else { |
| 6862 | zig_unreachable(); |
| 6863 | } |
| 6864 | if (instr_is_comptime(maybe_op)) { |
| 6865 | ConstExprValue *maybe_val = ir_resolve_const(ira, maybe_op, UndefBad); |
| 6866 | if (!maybe_val) |
| 6867 | return ira->codegen->builtin_types.entry_invalid; |
| 6868 | bool is_null = (maybe_val->data.x_maybe == nullptr); |
| 6869 | ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base, depends_on_compile_var); |
| 6870 | out_val->data.x_bool = (op_id == IrBinOpCmpEq) ? is_null : !is_null; |
| 6871 | return ira->codegen->builtin_types.entry_bool; |
| 6872 | } |
| 6873 | |
| 6874 | IrInstruction *is_non_null = ir_build_test_nonnull(&ira->new_irb, bin_op_instruction->base.scope, |
| 6875 | bin_op_instruction->base.source_node, maybe_op); |
| 6876 | is_non_null->value.type = ira->codegen->builtin_types.entry_bool; |
| 6877 | |
| 6878 | if (op_id == IrBinOpCmpEq) { |
| 6879 | ir_build_bool_not_from(&ira->new_irb, &bin_op_instruction->base, is_non_null); |
| 6880 | } else { |
| 6881 | ir_link_new_instruction(is_non_null, &bin_op_instruction->base); |
| 6882 | } |
| 6883 | return ira->codegen->builtin_types.entry_bool; |
| 6884 | } |
| 6885 | |
| 6842 | 6886 | IrInstruction *instructions[] = {op1, op2}; |
| 6843 | 6887 | TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2); |
| 6844 | 6888 | if (resolved_type->id == TypeTableEntryIdInvalid) |
| 6845 | 6889 | return resolved_type; |
| 6846 | | IrBinOp op_id = bin_op_instruction->op_id; |
| 6847 | 6890 | |
| 6848 | | bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq); |
| 6849 | 6891 | AstNode *source_node = bin_op_instruction->base.source_node; |
| 6850 | 6892 | switch (resolved_type->id) { |
| 6851 | 6893 | case TypeTableEntryIdInvalid: |
| ... | ... | @@ -9240,7 +9282,7 @@ static TypeTableEntry *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIn |
| 9240 | 9282 | return ira->codegen->builtin_types.entry_bool; |
| 9241 | 9283 | } |
| 9242 | 9284 | |
| 9243 | | ir_build_test_null_from(&ira->new_irb, &instruction->base, value); |
| 9285 | ir_build_test_nonnull_from(&ira->new_irb, &instruction->base, value); |
| 9244 | 9286 | return ira->codegen->builtin_types.entry_bool; |
| 9245 | 9287 | } else if (type_entry->id == TypeTableEntryIdNullLit) { |
| 9246 | 9288 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, false); |