| ... | @@ -1934,10 +1934,27 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -1934,10 +1934,27 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 1934 | size_t defer_counts[3]; | 1934 | size_t defer_counts[3]; |
| 1935 | ir_count_defers(irb, scope, outer_scope, defer_counts); | 1935 | ir_count_defers(irb, scope, outer_scope, defer_counts); |
| 1936 | if (defer_counts[ReturnKindError] > 0) { | 1936 | if (defer_counts[ReturnKindError] > 0) { |
| 1937 | // TODO in this situation we need to make a conditional | 1937 | IrBasicBlock *err_block = ir_build_basic_block(irb, scope, "ErrRetErr"); |
| 1938 | // branch on the return value. we potentially must make multiple conditional branches, | 1938 | IrBasicBlock *ok_block = ir_build_basic_block(irb, scope, "ErrRetOk"); |
| 1939 | // if unconditional defers are interleaved with error defers. | 1939 | |
| 1940 | zig_panic("TODO handle error defers"); | 1940 | IrInstruction *is_err = ir_build_test_err(irb, scope, node, return_value); |
| | 1941 | |
| | 1942 | IrInstruction *is_comptime; |
| | 1943 | if (ir_should_inline(irb)) { |
| | 1944 | is_comptime = ir_build_const_bool(irb, scope, node, true); |
| | 1945 | } else { |
| | 1946 | is_comptime = ir_build_test_comptime(irb, scope, node, is_err); |
| | 1947 | } |
| | 1948 | |
| | 1949 | ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime); |
| | 1950 | |
| | 1951 | ir_set_cursor_at_end(irb, err_block); |
| | 1952 | ir_gen_defers_for_block(irb, scope, outer_scope, true, false); |
| | 1953 | ir_build_return(irb, scope, node, return_value); |
| | 1954 | |
| | 1955 | ir_set_cursor_at_end(irb, ok_block); |
| | 1956 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); |
| | 1957 | return ir_build_return(irb, scope, node, return_value); |
| 1941 | } else if (defer_counts[ReturnKindMaybe] > 0) { | 1958 | } else if (defer_counts[ReturnKindMaybe] > 0) { |
| 1942 | // TODO in this situation we need to make a conditional | 1959 | // TODO in this situation we need to make a conditional |
| 1943 | // branch on the maybe value. we potentially must make multiple conditional branches, | 1960 | // branch on the maybe value. we potentially must make multiple conditional branches, |
| ... | @@ -1946,8 +1963,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -1946,8 +1963,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 1946 | } else { | 1963 | } else { |
| 1947 | // generate unconditional defers | 1964 | // generate unconditional defers |
| 1948 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); | 1965 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); |
| | 1966 | return ir_build_return(irb, scope, node, return_value); |
| 1949 | } | 1967 | } |
| 1950 | return ir_build_return(irb, scope, node, return_value); | | |
| 1951 | } | 1968 | } |
| 1952 | case ReturnKindError: | 1969 | case ReturnKindError: |
| 1953 | { | 1970 | { |
| ... | @@ -1955,7 +1972,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -1955,7 +1972,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 1955 | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); | 1972 | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); |
| 1956 | if (err_union_ptr == irb->codegen->invalid_instruction) | 1973 | if (err_union_ptr == irb->codegen->invalid_instruction) |
| 1957 | return irb->codegen->invalid_instruction; | 1974 | return irb->codegen->invalid_instruction; |
| 1958 | IrInstruction *is_err_val = ir_build_test_err(irb, scope, node, err_union_ptr); | 1975 | IrInstruction *err_union_val = ir_build_load_ptr(irb, scope, node, err_union_ptr); |
| | 1976 | IrInstruction *is_err_val = ir_build_test_err(irb, scope, node, err_union_val); |
| 1959 | | 1977 | |
| 1960 | IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "ErrRetReturn"); | 1978 | IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "ErrRetReturn"); |
| 1961 | IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "ErrRetContinue"); | 1979 | IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "ErrRetContinue"); |
| ... | @@ -3932,7 +3950,8 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN | ... | @@ -3932,7 +3950,8 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN |
| 3932 | if (err_union_ptr == irb->codegen->invalid_instruction) | 3950 | if (err_union_ptr == irb->codegen->invalid_instruction) |
| 3933 | return irb->codegen->invalid_instruction; | 3951 | return irb->codegen->invalid_instruction; |
| 3934 | | 3952 | |
| 3935 | IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_ptr); | 3953 | IrInstruction *err_union_val = ir_build_load_ptr(irb, parent_scope, node, err_union_ptr); |
| | 3954 | IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_val); |
| 3936 | | 3955 | |
| 3937 | IrInstruction *is_comptime; | 3956 | IrInstruction *is_comptime; |
| 3938 | if (ir_should_inline(irb)) { | 3957 | if (ir_should_inline(irb)) { |
| ... | @@ -9443,26 +9462,20 @@ static TypeTableEntry *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruc | ... | @@ -9443,26 +9462,20 @@ static TypeTableEntry *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruc |
| 9443 | if (value->type_entry->id == TypeTableEntryIdInvalid) | 9462 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| 9444 | return ira->codegen->builtin_types.entry_invalid; | 9463 | return ira->codegen->builtin_types.entry_invalid; |
| 9445 | | 9464 | |
| 9446 | TypeTableEntry *ptr_type = value->type_entry; | 9465 | TypeTableEntry *non_canon_type = value->type_entry; |
| 9447 | | | |
| 9448 | // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing. | | |
| 9449 | assert(ptr_type->id == TypeTableEntryIdPointer); | | |
| 9450 | | 9466 | |
| 9451 | TypeTableEntry *non_canon_type = ptr_type->data.pointer.child_type; | | |
| 9452 | TypeTableEntry *canon_type = get_underlying_type(non_canon_type); | 9467 | TypeTableEntry *canon_type = get_underlying_type(non_canon_type); |
| 9453 | if (canon_type->id == TypeTableEntryIdInvalid) { | 9468 | if (canon_type->id == TypeTableEntryIdInvalid) { |
| 9454 | return ira->codegen->builtin_types.entry_invalid; | 9469 | return ira->codegen->builtin_types.entry_invalid; |
| 9455 | } else if (canon_type->id == TypeTableEntryIdErrorUnion) { | 9470 | } else if (canon_type->id == TypeTableEntryIdErrorUnion) { |
| 9456 | if (instr_is_comptime(value)) { | 9471 | if (instr_is_comptime(value)) { |
| 9457 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); | 9472 | ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad); |
| 9458 | if (!ptr_val) | 9473 | if (!err_union_val) |
| 9459 | return ira->codegen->builtin_types.entry_invalid; | 9474 | return ira->codegen->builtin_types.entry_invalid; |
| 9460 | ConstExprValue *err_union_val = ptr_val->data.x_ptr.base_ptr; | | |
| 9461 | assert(ptr_val->data.x_ptr.index == SIZE_MAX); | | |
| 9462 | | 9475 | |
| 9463 | if (err_union_val->special != ConstValSpecialRuntime) { | 9476 | if (err_union_val->special != ConstValSpecialRuntime) { |
| 9464 | bool depends_on_compile_var = ptr_val->depends_on_compile_var || err_union_val->depends_on_compile_var; | 9477 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, |
| 9465 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var); | 9478 | err_union_val->depends_on_compile_var); |
| 9466 | out_val->data.x_bool = (err_union_val->data.x_err_union.err != nullptr); | 9479 | out_val->data.x_bool = (err_union_val->data.x_err_union.err != nullptr); |
| 9467 | return ira->codegen->builtin_types.entry_bool; | 9480 | return ira->codegen->builtin_types.entry_bool; |
| 9468 | } | 9481 | } |
| ... | @@ -9470,11 +9483,14 @@ static TypeTableEntry *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruc | ... | @@ -9470,11 +9483,14 @@ static TypeTableEntry *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruc |
| 9470 | | 9483 | |
| 9471 | ir_build_test_err_from(&ira->new_irb, &instruction->base, value); | 9484 | ir_build_test_err_from(&ira->new_irb, &instruction->base, value); |
| 9472 | return ira->codegen->builtin_types.entry_bool; | 9485 | return ira->codegen->builtin_types.entry_bool; |
| | 9486 | } else if (canon_type->id == TypeTableEntryIdPureError) { |
| | 9487 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, false); |
| | 9488 | out_val->data.x_bool = true; |
| | 9489 | return ira->codegen->builtin_types.entry_bool; |
| 9473 | } else { | 9490 | } else { |
| 9474 | ir_add_error(ira, value, | 9491 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, false); |
| 9475 | buf_sprintf("expected error union type, found '%s'", buf_ptr(&non_canon_type->name))); | 9492 | out_val->data.x_bool = false; |
| 9476 | // TODO if this is a typedecl, add error note showing the declaration of the type decl | 9493 | return ira->codegen->builtin_types.entry_bool; |
| 9477 | return ira->codegen->builtin_types.entry_invalid; | | |
| 9478 | } | 9494 | } |
| 9479 | } | 9495 | } |
| 9480 | | 9496 | |