| ... | ... | @@ -3350,6 +3350,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3350 | 3350 | } |
| 3351 | 3351 | |
| 3352 | 3352 | bool is_continuation_unreachable = false; |
| 3353 | IrInstruction *noreturn_return_value = nullptr; |
| 3353 | 3354 | IrInstruction *return_value = nullptr; |
| 3354 | 3355 | for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { |
| 3355 | 3356 | AstNode *statement_node = block_node->data.block.statements.at(i); |
| ... | ... | @@ -3383,16 +3384,15 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3383 | 3384 | |
| 3384 | 3385 | // a label is an entry point |
| 3385 | 3386 | is_continuation_unreachable = false; |
| 3386 | | return_value = nullptr; |
| 3387 | 3387 | continue; |
| 3388 | 3388 | } |
| 3389 | 3389 | |
| 3390 | 3390 | IrInstruction *statement_value = ir_gen_node(irb, statement_node, child_scope); |
| 3391 | 3391 | is_continuation_unreachable = instr_is_unreachable(statement_value); |
| 3392 | | if (is_continuation_unreachable) |
| 3393 | | return_value = statement_value; |
| 3394 | | else |
| 3395 | | return_value = nullptr; |
| 3392 | if (is_continuation_unreachable) { |
| 3393 | // keep the last noreturn statement value around in case we need to return it |
| 3394 | noreturn_return_value = statement_value; |
| 3395 | } |
| 3396 | 3396 | if (statement_node->type == NodeTypeDefer && statement_value != irb->codegen->invalid_instruction) { |
| 3397 | 3397 | // defer starts a new scope |
| 3398 | 3398 | child_scope = statement_node->data.defer.child_scope; |
| ... | ... | @@ -3420,18 +3420,23 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3420 | 3420 | } |
| 3421 | 3421 | } |
| 3422 | 3422 | |
| 3423 | | if (!is_continuation_unreachable) { |
| 3424 | | // control flow falls out of block |
| 3425 | | |
| 3426 | | if (!block_node->data.block.last_statement_is_result_expression) { |
| 3427 | | assert(return_value == nullptr); |
| 3428 | | return_value = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); |
| 3429 | | } |
| 3423 | if (is_continuation_unreachable) { |
| 3424 | assert(noreturn_return_value != nullptr); |
| 3425 | return noreturn_return_value; |
| 3426 | } |
| 3427 | // control flow falls out of block |
| 3430 | 3428 | |
| 3431 | | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); |
| 3429 | if (block_node->data.block.last_statement_is_result_expression) { |
| 3430 | // return value was determined by the last statement |
| 3431 | assert(return_value != nullptr); |
| 3432 | } else { |
| 3433 | // return value is implicitly void |
| 3434 | assert(return_value == nullptr); |
| 3435 | return_value = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); |
| 3432 | 3436 | } |
| 3433 | 3437 | |
| 3434 | | assert(return_value != nullptr); |
| 3438 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); |
| 3439 | |
| 3435 | 3440 | return return_value; |
| 3436 | 3441 | } |
| 3437 | 3442 | |