| ... | @@ -275,8 +275,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSizeOf *) { | ... | @@ -275,8 +275,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSizeOf *) { |
| 275 | return IrInstructionIdSizeOf; | 275 | return IrInstructionIdSizeOf; |
| 276 | } | 276 | } |
| 277 | | 277 | |
| 278 | static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNull *) { | 278 | static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) { |
| 279 | return IrInstructionIdTestNull; | 279 | return IrInstructionIdTestNonNull; |
| 280 | } | 280 | } |
| 281 | | 281 | |
| 282 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapMaybe *) { | 282 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapMaybe *) { |
| ... | @@ -1200,7 +1200,7 @@ static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *so | ... | @@ -1200,7 +1200,7 @@ static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *so |
| 1200 | } | 1200 | } |
| 1201 | | 1201 | |
| 1202 | static IrInstruction *ir_build_test_null(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { | 1202 | static IrInstruction *ir_build_test_null(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1203 | IrInstructionTestNull *instruction = ir_build_instruction<IrInstructionTestNull>(irb, scope, source_node); | 1203 | IrInstructionTestNonNull *instruction = ir_build_instruction<IrInstructionTestNonNull>(irb, scope, source_node); |
| 1204 | instruction->value = value; | 1204 | instruction->value = value; |
| 1205 | | 1205 | |
| 1206 | ir_ref_instruction(value); | 1206 | ir_ref_instruction(value); |
| ... | @@ -1956,10 +1956,27 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -1956,10 +1956,27 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 1956 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); | 1956 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); |
| 1957 | return ir_build_return(irb, scope, node, return_value); | 1957 | return ir_build_return(irb, scope, node, return_value); |
| 1958 | } else if (defer_counts[ReturnKindMaybe] > 0) { | 1958 | } else if (defer_counts[ReturnKindMaybe] > 0) { |
| 1959 | // TODO in this situation we need to make a conditional | 1959 | IrBasicBlock *null_block = ir_build_basic_block(irb, scope, "MaybeRetNull"); |
| 1960 | // branch on the maybe value. we potentially must make multiple conditional branches, | 1960 | IrBasicBlock *ok_block = ir_build_basic_block(irb, scope, "MaybeRetOk"); |
| 1961 | // if unconditional defers are interleaved with error defers. | 1961 | |
| 1962 | zig_panic("TODO handle maybe defers"); | 1962 | IrInstruction *is_non_null = ir_build_test_null(irb, scope, node, return_value); |
| | 1963 | |
| | 1964 | IrInstruction *is_comptime; |
| | 1965 | if (ir_should_inline(irb)) { |
| | 1966 | is_comptime = ir_build_const_bool(irb, scope, node, true); |
| | 1967 | } else { |
| | 1968 | is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null); |
| | 1969 | } |
| | 1970 | |
| | 1971 | ir_build_cond_br(irb, scope, node, is_non_null, ok_block, null_block, is_comptime); |
| | 1972 | |
| | 1973 | ir_set_cursor_at_end(irb, null_block); |
| | 1974 | ir_gen_defers_for_block(irb, scope, outer_scope, false, true); |
| | 1975 | ir_build_return(irb, scope, node, return_value); |
| | 1976 | |
| | 1977 | ir_set_cursor_at_end(irb, ok_block); |
| | 1978 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); |
| | 1979 | return ir_build_return(irb, scope, node, return_value); |
| 1963 | } else { | 1980 | } else { |
| 1964 | // generate unconditional defers | 1981 | // generate unconditional defers |
| 1965 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); | 1982 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); |
| ... | @@ -1998,12 +2015,13 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -1998,12 +2015,13 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 1998 | IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); | 2015 | IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); |
| 1999 | if (maybe_val_ptr == irb->codegen->invalid_instruction) | 2016 | if (maybe_val_ptr == irb->codegen->invalid_instruction) |
| 2000 | return irb->codegen->invalid_instruction; | 2017 | return irb->codegen->invalid_instruction; |
| 2001 | IrInstruction *is_nonnull_val = ir_build_test_null(irb, scope, node, maybe_val_ptr); | 2018 | IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); |
| | 2019 | IrInstruction *is_non_null = ir_build_test_null(irb, scope, node, maybe_val); |
| 2002 | | 2020 | |
| 2003 | IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "MaybeRetReturn"); | 2021 | IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "MaybeRetReturn"); |
| 2004 | IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "MaybeRetContinue"); | 2022 | IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "MaybeRetContinue"); |
| 2005 | IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb)); | 2023 | IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb)); |
| 2006 | ir_build_cond_br(irb, scope, node, is_nonnull_val, continue_block, return_block, is_comptime); | 2024 | ir_build_cond_br(irb, scope, node, is_non_null, continue_block, return_block, is_comptime); |
| 2007 | | 2025 | |
| 2008 | ir_set_cursor_at_end(irb, return_block); | 2026 | ir_set_cursor_at_end(irb, return_block); |
| 2009 | ir_gen_defers_for_block(irb, scope, outer_scope, false, true); | 2027 | ir_gen_defers_for_block(irb, scope, outer_scope, false, true); |
| ... | @@ -2247,7 +2265,8 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As | ... | @@ -2247,7 +2265,8 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As |
| 2247 | if (maybe_ptr == irb->codegen->invalid_instruction) | 2265 | if (maybe_ptr == irb->codegen->invalid_instruction) |
| 2248 | return irb->codegen->invalid_instruction; | 2266 | return irb->codegen->invalid_instruction; |
| 2249 | | 2267 | |
| 2250 | IrInstruction *is_non_null = ir_build_test_null(irb, parent_scope, node, maybe_ptr); | 2268 | IrInstruction *maybe_val = ir_build_load_ptr(irb, parent_scope, node, maybe_ptr); |
| | 2269 | IrInstruction *is_non_null = ir_build_test_null(irb, parent_scope, node, maybe_val); |
| 2251 | | 2270 | |
| 2252 | IrInstruction *is_comptime; | 2271 | IrInstruction *is_comptime; |
| 2253 | if (ir_should_inline(irb)) { | 2272 | if (ir_should_inline(irb)) { |
| ... | @@ -3514,11 +3533,12 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -3514,11 +3533,12 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 3514 | AstNode *else_node = node->data.if_var_expr.else_node; | 3533 | AstNode *else_node = node->data.if_var_expr.else_node; |
| 3515 | bool var_is_ptr = node->data.if_var_expr.var_is_ptr; | 3534 | bool var_is_ptr = node->data.if_var_expr.var_is_ptr; |
| 3516 | | 3535 | |
| 3517 | IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); | 3536 | IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); |
| 3518 | if (expr_value == irb->codegen->invalid_instruction) | 3537 | if (maybe_val_ptr == irb->codegen->invalid_instruction) |
| 3519 | return expr_value; | 3538 | return maybe_val_ptr; |
| 3520 | | 3539 | |
| 3521 | IrInstruction *is_nonnull_value = ir_build_test_null(irb, scope, node, expr_value); | 3540 | IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); |
| | 3541 | IrInstruction *is_non_null = ir_build_test_null(irb, scope, node, maybe_val); |
| 3522 | | 3542 | |
| 3523 | IrBasicBlock *then_block = ir_build_basic_block(irb, scope, "MaybeThen"); | 3543 | IrBasicBlock *then_block = ir_build_basic_block(irb, scope, "MaybeThen"); |
| 3524 | IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "MaybeElse"); | 3544 | IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "MaybeElse"); |
| ... | @@ -3528,9 +3548,9 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -3528,9 +3548,9 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 3528 | if (ir_should_inline(irb) || node->data.if_var_expr.is_inline) { | 3548 | if (ir_should_inline(irb) || node->data.if_var_expr.is_inline) { |
| 3529 | is_comptime = ir_build_const_bool(irb, scope, node, true); | 3549 | is_comptime = ir_build_const_bool(irb, scope, node, true); |
| 3530 | } else { | 3550 | } else { |
| 3531 | is_comptime = ir_build_test_comptime(irb, scope, node, is_nonnull_value); | 3551 | is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null); |
| 3532 | } | 3552 | } |
| 3533 | ir_build_cond_br(irb, scope, node, is_nonnull_value, then_block, else_block, is_comptime); | 3553 | ir_build_cond_br(irb, scope, node, is_non_null, then_block, else_block, is_comptime); |
| 3534 | | 3554 | |
| 3535 | ir_set_cursor_at_end(irb, then_block); | 3555 | ir_set_cursor_at_end(irb, then_block); |
| 3536 | IrInstruction *var_type = nullptr; | 3556 | IrInstruction *var_type = nullptr; |
| ... | @@ -3544,7 +3564,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -3544,7 +3564,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 3544 | VariableTableEntry *var = ir_create_var(irb, node, scope, | 3564 | VariableTableEntry *var = ir_create_var(irb, node, scope, |
| 3545 | var_decl->symbol, is_const, is_const, is_shadowable, is_comptime); | 3565 | var_decl->symbol, is_const, is_const, is_shadowable, is_comptime); |
| 3546 | | 3566 | |
| 3547 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, expr_value, false); | 3567 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, maybe_val_ptr, false); |
| 3548 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value); | 3568 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value); |
| 3549 | ir_build_var_decl(irb, scope, node, var, var_type, var_value); | 3569 | ir_build_var_decl(irb, scope, node, var, var_type, var_value); |
| 3550 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var->child_scope); | 3570 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var->child_scope); |
| ... | @@ -4440,7 +4460,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, | ... | @@ -4440,7 +4460,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, |
| 4440 | } | 4460 | } |
| 4441 | | 4461 | |
| 4442 | // implicitly take a const pointer to something | 4462 | // implicitly take a const pointer to something |
| 4443 | { | 4463 | if (!type_requires_comptime(actual_type)) { |
| 4444 | TypeTableEntry *const_ptr_actual = get_pointer_to_type(ira->codegen, actual_type, true); | 4464 | TypeTableEntry *const_ptr_actual = get_pointer_to_type(ira->codegen, actual_type, true); |
| 4445 | if (types_match_const_cast_only(expected_type, const_ptr_actual)) { | 4465 | if (types_match_const_cast_only(expected_type, const_ptr_actual)) { |
| 4446 | return ImplicitCastMatchResultYes; | 4466 | return ImplicitCastMatchResultYes; |
| ... | @@ -5230,7 +5250,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -5230,7 +5250,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 5230 | } | 5250 | } |
| 5231 | | 5251 | |
| 5232 | // explicit cast from something to const pointer of it | 5252 | // explicit cast from something to const pointer of it |
| 5233 | { | 5253 | if (!type_requires_comptime(actual_type)) { |
| 5234 | TypeTableEntry *const_ptr_actual = get_pointer_to_type(ira->codegen, actual_type, true); | 5254 | TypeTableEntry *const_ptr_actual = get_pointer_to_type(ira->codegen, actual_type, true); |
| 5235 | if (types_match_const_cast_only(wanted_type, const_ptr_actual)) { | 5255 | if (types_match_const_cast_only(wanted_type, const_ptr_actual)) { |
| 5236 | return ir_analyze_cast_ref(ira, source_instr, value, wanted_type); | 5256 | return ir_analyze_cast_ref(ira, source_instr, value, wanted_type); |
| ... | @@ -7763,39 +7783,36 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, | ... | @@ -7763,39 +7783,36 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 7763 | zig_unreachable(); | 7783 | zig_unreachable(); |
| 7764 | } | 7784 | } |
| 7765 | | 7785 | |
| 7766 | static TypeTableEntry *ir_analyze_instruction_test_null(IrAnalyze *ira, | 7786 | static TypeTableEntry *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) { |
| 7767 | IrInstructionTestNull *test_null_instruction) | 7787 | IrInstruction *value = instruction->value->other; |
| 7768 | { | | |
| 7769 | IrInstruction *value = test_null_instruction->value->other; | | |
| 7770 | if (value->type_entry->id == TypeTableEntryIdInvalid) | 7788 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| 7771 | return ira->codegen->builtin_types.entry_invalid; | 7789 | return ira->codegen->builtin_types.entry_invalid; |
| 7772 | | 7790 | |
| 7773 | // This will be a pointer type because test null IR instruction operates on a pointer to a thing. | 7791 | TypeTableEntry *type_entry = value->type_entry; |
| 7774 | TypeTableEntry *ptr_type = value->type_entry; | | |
| 7775 | assert(ptr_type->id == TypeTableEntryIdPointer); | | |
| 7776 | | | |
| 7777 | TypeTableEntry *type_entry = ptr_type->data.pointer.child_type; | | |
| 7778 | if (type_entry->id != TypeTableEntryIdMaybe) { | | |
| 7779 | add_node_error(ira->codegen, test_null_instruction->base.source_node, | | |
| 7780 | buf_sprintf("expected nullable type, found '%s'", buf_ptr(&type_entry->name))); | | |
| 7781 | return ira->codegen->builtin_types.entry_invalid; | | |
| 7782 | } | | |
| 7783 | | 7792 | |
| 7784 | if (value->static_value.special != ConstValSpecialRuntime) { | 7793 | if (type_entry->id == TypeTableEntryIdMaybe) { |
| 7785 | ConstExprValue *maybe_val = value->static_value.data.x_ptr.base_ptr; | 7794 | if (instr_is_comptime(value)) { |
| 7786 | assert(value->static_value.data.x_ptr.index == SIZE_MAX); | 7795 | ConstExprValue *maybe_val = ir_resolve_const(ira, value, UndefBad); |
| | 7796 | if (!maybe_val) |
| | 7797 | return ira->codegen->builtin_types.entry_invalid; |
| 7787 | | 7798 | |
| 7788 | if (maybe_val->special != ConstValSpecialRuntime) { | 7799 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, |
| 7789 | bool depends_on_compile_var = maybe_val->depends_on_compile_var; | 7800 | maybe_val->depends_on_compile_var); |
| 7790 | ConstExprValue *out_val = ir_build_const_from(ira, &test_null_instruction->base, | 7801 | out_val->data.x_bool = (maybe_val->data.x_maybe != nullptr); |
| 7791 | depends_on_compile_var); | | |
| 7792 | out_val->data.x_bool = (maybe_val->data.x_maybe == nullptr); | | |
| 7793 | return ira->codegen->builtin_types.entry_bool; | 7802 | return ira->codegen->builtin_types.entry_bool; |
| 7794 | } | 7803 | } |
| 7795 | } | | |
| 7796 | | 7804 | |
| 7797 | ir_build_test_null_from(&ira->new_irb, &test_null_instruction->base, value); | 7805 | ir_build_test_null_from(&ira->new_irb, &instruction->base, value); |
| 7798 | return ira->codegen->builtin_types.entry_bool; | 7806 | return ira->codegen->builtin_types.entry_bool; |
| | 7807 | } else if (type_entry->id == TypeTableEntryIdNullLit) { |
| | 7808 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, false); |
| | 7809 | out_val->data.x_bool = false; |
| | 7810 | return ira->codegen->builtin_types.entry_bool; |
| | 7811 | } else { |
| | 7812 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, false); |
| | 7813 | out_val->data.x_bool = true; |
| | 7814 | return ira->codegen->builtin_types.entry_bool; |
| | 7815 | } |
| 7799 | } | 7816 | } |
| 7800 | | 7817 | |
| 7801 | static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, | 7818 | static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| ... | @@ -9689,8 +9706,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -9689,8 +9706,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 9689 | return ir_analyze_instruction_compile_var(ira, (IrInstructionCompileVar *)instruction); | 9706 | return ir_analyze_instruction_compile_var(ira, (IrInstructionCompileVar *)instruction); |
| 9690 | case IrInstructionIdSizeOf: | 9707 | case IrInstructionIdSizeOf: |
| 9691 | return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction); | 9708 | return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction); |
| 9692 | case IrInstructionIdTestNull: | 9709 | case IrInstructionIdTestNonNull: |
| 9693 | return ir_analyze_instruction_test_null(ira, (IrInstructionTestNull *)instruction); | 9710 | return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction); |
| 9694 | case IrInstructionIdUnwrapMaybe: | 9711 | case IrInstructionIdUnwrapMaybe: |
| 9695 | return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapMaybe *)instruction); | 9712 | return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapMaybe *)instruction); |
| 9696 | case IrInstructionIdClz: | 9713 | case IrInstructionIdClz: |
| ... | @@ -9908,7 +9925,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -9908,7 +9925,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 9908 | case IrInstructionIdSliceType: | 9925 | case IrInstructionIdSliceType: |
| 9909 | case IrInstructionIdCompileVar: | 9926 | case IrInstructionIdCompileVar: |
| 9910 | case IrInstructionIdSizeOf: | 9927 | case IrInstructionIdSizeOf: |
| 9911 | case IrInstructionIdTestNull: | 9928 | case IrInstructionIdTestNonNull: |
| 9912 | case IrInstructionIdUnwrapMaybe: | 9929 | case IrInstructionIdUnwrapMaybe: |
| 9913 | case IrInstructionIdClz: | 9930 | case IrInstructionIdClz: |
| 9914 | case IrInstructionIdCtz: | 9931 | case IrInstructionIdCtz: |