| ... | @@ -3091,7 +3091,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t | ... | @@ -3091,7 +3091,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3091 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 3091 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 3092 | results[ReturnKindUnconditional] = 0; | 3092 | results[ReturnKindUnconditional] = 0; |
| 3093 | results[ReturnKindError] = 0; | 3093 | results[ReturnKindError] = 0; |
| 3094 | results[ReturnKindMaybe] = 0; | | |
| 3095 | | 3094 | |
| 3096 | while (inner_scope != outer_scope) { | 3095 | while (inner_scope != outer_scope) { |
| 3097 | assert(inner_scope); | 3096 | assert(inner_scope); |
| ... | @@ -3111,9 +3110,7 @@ static IrInstruction *ir_mark_gen(IrInstruction *instruction) { | ... | @@ -3111,9 +3110,7 @@ static IrInstruction *ir_mark_gen(IrInstruction *instruction) { |
| 3111 | return instruction; | 3110 | return instruction; |
| 3112 | } | 3111 | } |
| 3113 | | 3112 | |
| 3114 | static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, | 3113 | static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, bool gen_error_defers) { |
| 3115 | bool gen_error_defers, bool gen_maybe_defers) | | |
| 3116 | { | | |
| 3117 | Scope *scope = inner_scope; | 3114 | Scope *scope = inner_scope; |
| 3118 | while (scope != outer_scope) { | 3115 | while (scope != outer_scope) { |
| 3119 | if (!scope) | 3116 | if (!scope) |
| ... | @@ -3124,8 +3121,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o | ... | @@ -3124,8 +3121,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o |
| 3124 | assert(defer_node->type == NodeTypeDefer); | 3121 | assert(defer_node->type == NodeTypeDefer); |
| 3125 | ReturnKind defer_kind = defer_node->data.defer.kind; | 3122 | ReturnKind defer_kind = defer_node->data.defer.kind; |
| 3126 | if (defer_kind == ReturnKindUnconditional || | 3123 | if (defer_kind == ReturnKindUnconditional || |
| 3127 | (gen_error_defers && defer_kind == ReturnKindError) || | 3124 | (gen_error_defers && defer_kind == ReturnKindError)) |
| 3128 | (gen_maybe_defers && defer_kind == ReturnKindMaybe)) | | |
| 3129 | { | 3125 | { |
| 3130 | AstNode *defer_expr_node = defer_node->data.defer.expr; | 3126 | AstNode *defer_expr_node = defer_node->data.defer.expr; |
| 3131 | ir_gen_node(irb, defer_expr_node, defer_node->data.defer.expr_scope); | 3127 | ir_gen_node(irb, defer_expr_node, defer_node->data.defer.expr_scope); |
| ... | @@ -3188,7 +3184,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -3188,7 +3184,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3188 | return_value = ir_build_const_void(irb, scope, node); | 3184 | return_value = ir_build_const_void(irb, scope, node); |
| 3189 | } | 3185 | } |
| 3190 | | 3186 | |
| 3191 | size_t defer_counts[3]; | 3187 | size_t defer_counts[2]; |
| 3192 | ir_count_defers(irb, scope, outer_scope, defer_counts); | 3188 | ir_count_defers(irb, scope, outer_scope, defer_counts); |
| 3193 | if (defer_counts[ReturnKindError] > 0) { | 3189 | if (defer_counts[ReturnKindError] > 0) { |
| 3194 | IrBasicBlock *err_block = ir_build_basic_block(irb, scope, "ErrRetErr"); | 3190 | IrBasicBlock *err_block = ir_build_basic_block(irb, scope, "ErrRetErr"); |
| ... | @@ -3206,37 +3202,15 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -3206,37 +3202,15 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3206 | ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime)); | 3202 | ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime)); |
| 3207 | | 3203 | |
| 3208 | ir_set_cursor_at_end(irb, err_block); | 3204 | ir_set_cursor_at_end(irb, err_block); |
| 3209 | ir_gen_defers_for_block(irb, scope, outer_scope, true, false); | 3205 | ir_gen_defers_for_block(irb, scope, outer_scope, true); |
| 3210 | ir_build_return(irb, scope, node, return_value); | | |
| 3211 | | | |
| 3212 | ir_set_cursor_at_end(irb, ok_block); | | |
| 3213 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); | | |
| 3214 | return ir_build_return(irb, scope, node, return_value); | | |
| 3215 | } else if (defer_counts[ReturnKindMaybe] > 0) { | | |
| 3216 | IrBasicBlock *null_block = ir_build_basic_block(irb, scope, "MaybeRetNull"); | | |
| 3217 | IrBasicBlock *ok_block = ir_build_basic_block(irb, scope, "MaybeRetOk"); | | |
| 3218 | | | |
| 3219 | IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, return_value); | | |
| 3220 | | | |
| 3221 | IrInstruction *is_comptime; | | |
| 3222 | if (ir_should_inline(irb->exec, scope)) { | | |
| 3223 | is_comptime = ir_build_const_bool(irb, scope, node, true); | | |
| 3224 | } else { | | |
| 3225 | is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null); | | |
| 3226 | } | | |
| 3227 | | | |
| 3228 | ir_mark_gen(ir_build_cond_br(irb, scope, node, is_non_null, ok_block, null_block, is_comptime)); | | |
| 3229 | | | |
| 3230 | ir_set_cursor_at_end(irb, null_block); | | |
| 3231 | ir_gen_defers_for_block(irb, scope, outer_scope, false, true); | | |
| 3232 | ir_build_return(irb, scope, node, return_value); | 3206 | ir_build_return(irb, scope, node, return_value); |
| 3233 | | 3207 | |
| 3234 | ir_set_cursor_at_end(irb, ok_block); | 3208 | ir_set_cursor_at_end(irb, ok_block); |
| 3235 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); | 3209 | ir_gen_defers_for_block(irb, scope, outer_scope, false); |
| 3236 | return ir_build_return(irb, scope, node, return_value); | 3210 | return ir_build_return(irb, scope, node, return_value); |
| 3237 | } else { | 3211 | } else { |
| 3238 | // generate unconditional defers | 3212 | // generate unconditional defers |
| 3239 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); | 3213 | ir_gen_defers_for_block(irb, scope, outer_scope, false); |
| 3240 | return ir_build_return(irb, scope, node, return_value); | 3214 | return ir_build_return(irb, scope, node, return_value); |
| 3241 | } | 3215 | } |
| 3242 | } | 3216 | } |
| ... | @@ -3255,7 +3229,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -3255,7 +3229,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3255 | ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime)); | 3229 | ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime)); |
| 3256 | | 3230 | |
| 3257 | ir_set_cursor_at_end(irb, return_block); | 3231 | ir_set_cursor_at_end(irb, return_block); |
| 3258 | ir_gen_defers_for_block(irb, scope, outer_scope, true, false); | 3232 | ir_gen_defers_for_block(irb, scope, outer_scope, true); |
| 3259 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr); | 3233 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr); |
| 3260 | ir_build_return(irb, scope, node, err_val); | 3234 | ir_build_return(irb, scope, node, err_val); |
| 3261 | | 3235 | |
| ... | @@ -3266,32 +3240,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -3266,32 +3240,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3266 | else | 3240 | else |
| 3267 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); | 3241 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); |
| 3268 | } | 3242 | } |
| 3269 | case ReturnKindMaybe: | | |
| 3270 | { | | |
| 3271 | assert(expr_node); | | |
| 3272 | IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LVAL_PTR); | | |
| 3273 | if (maybe_val_ptr == irb->codegen->invalid_instruction) | | |
| 3274 | return irb->codegen->invalid_instruction; | | |
| 3275 | IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); | | |
| 3276 | IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_val); | | |
| 3277 | | | |
| 3278 | IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "MaybeRetReturn"); | | |
| 3279 | IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "MaybeRetContinue"); | | |
| 3280 | IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb->exec, scope)); | | |
| 3281 | ir_mark_gen(ir_build_cond_br(irb, scope, node, is_non_null, continue_block, return_block, is_comptime)); | | |
| 3282 | | | |
| 3283 | ir_set_cursor_at_end(irb, return_block); | | |
| 3284 | ir_gen_defers_for_block(irb, scope, outer_scope, false, true); | | |
| 3285 | IrInstruction *null = ir_build_const_null(irb, scope, node); | | |
| 3286 | ir_build_return(irb, scope, node, null); | | |
| 3287 | | | |
| 3288 | ir_set_cursor_at_end(irb, continue_block); | | |
| 3289 | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_val_ptr, false); | | |
| 3290 | if (lval.is_ptr) | | |
| 3291 | return unwrapped_ptr; | | |
| 3292 | else | | |
| 3293 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); | | |
| 3294 | } | | |
| 3295 | } | 3243 | } |
| 3296 | zig_unreachable(); | 3244 | zig_unreachable(); |
| 3297 | } | 3245 | } |
| ... | @@ -3490,7 +3438,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode | ... | @@ -3490,7 +3438,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3490 | return_value = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); | 3438 | return_value = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); |
| 3491 | } | 3439 | } |
| 3492 | | 3440 | |
| 3493 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false, false); | 3441 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); |
| 3494 | } | 3442 | } |
| 3495 | | 3443 | |
| 3496 | assert(return_value != nullptr); | 3444 | assert(return_value != nullptr); |
| ... | @@ -5420,7 +5368,7 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node) | ... | @@ -5420,7 +5368,7 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node) |
| 5420 | } | 5368 | } |
| 5421 | | 5369 | |
| 5422 | IrBasicBlock *dest_block = loop_stack_item->break_block; | 5370 | IrBasicBlock *dest_block = loop_stack_item->break_block; |
| 5423 | ir_gen_defers_for_block(irb, scope, dest_block->scope, false, false); | 5371 | ir_gen_defers_for_block(irb, scope, dest_block->scope, false); |
| 5424 | return ir_build_br(irb, scope, node, dest_block, is_comptime); | 5372 | return ir_build_br(irb, scope, node, dest_block, is_comptime); |
| 5425 | } | 5373 | } |
| 5426 | | 5374 | |
| ... | @@ -5443,7 +5391,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -5443,7 +5391,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5443 | } | 5391 | } |
| 5444 | | 5392 | |
| 5445 | IrBasicBlock *dest_block = loop_stack_item->continue_block; | 5393 | IrBasicBlock *dest_block = loop_stack_item->continue_block; |
| 5446 | ir_gen_defers_for_block(irb, scope, dest_block->scope, false, false); | 5394 | ir_gen_defers_for_block(irb, scope, dest_block->scope, false); |
| 5447 | return ir_build_br(irb, scope, node, dest_block, is_comptime); | 5395 | return ir_build_br(irb, scope, node, dest_block, is_comptime); |
| 5448 | } | 5396 | } |
| 5449 | | 5397 | |
| ... | @@ -5784,7 +5732,7 @@ static bool ir_goto_pass2(IrBuilder *irb) { | ... | @@ -5784,7 +5732,7 @@ static bool ir_goto_pass2(IrBuilder *irb) { |
| 5784 | | 5732 | |
| 5785 | IrInstruction *is_comptime = ir_build_const_bool(irb, goto_item->scope, source_node, | 5733 | IrInstruction *is_comptime = ir_build_const_bool(irb, goto_item->scope, source_node, |
| 5786 | ir_should_inline(irb->exec, goto_item->scope) || source_node->data.goto_expr.is_inline); | 5734 | ir_should_inline(irb->exec, goto_item->scope) || source_node->data.goto_expr.is_inline); |
| 5787 | if (!ir_gen_defers_for_block(irb, goto_item->scope, label->bb->scope, false, false)) { | 5735 | if (!ir_gen_defers_for_block(irb, goto_item->scope, label->bb->scope, false)) { |
| 5788 | add_node_error(irb->codegen, source_node, | 5736 | add_node_error(irb->codegen, source_node, |
| 5789 | buf_sprintf("no label in scope named '%s'", buf_ptr(label_name))); | 5737 | buf_sprintf("no label in scope named '%s'", buf_ptr(label_name))); |
| 5790 | return false; | 5738 | return false; |