| ... | @@ -832,6 +832,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) { | ... | @@ -832,6 +832,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) { |
| 832 | return IrInstructionIdSqrt; | 832 | return IrInstructionIdSqrt; |
| 833 | } | 833 | } |
| 834 | | 834 | |
| | 835 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) { |
| | 836 | return IrInstructionIdCheckRuntimeScope; |
| | 837 | } |
| | 838 | |
| 835 | template<typename T> | 839 | template<typename T> |
| 836 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 840 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 837 | T *special_instruction = allocate<T>(1); | 841 | T *special_instruction = allocate<T>(1); |
| ... | @@ -2974,6 +2978,17 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc | ... | @@ -2974,6 +2978,17 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc |
| 2974 | return &instruction->base; | 2978 | return &instruction->base; |
| 2975 | } | 2979 | } |
| 2976 | | 2980 | |
| | 2981 | static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) { |
| | 2982 | IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node); |
| | 2983 | instruction->scope_is_comptime = scope_is_comptime; |
| | 2984 | instruction->is_comptime = is_comptime; |
| | 2985 | |
| | 2986 | ir_ref_instruction(scope_is_comptime, irb->current_basic_block); |
| | 2987 | ir_ref_instruction(is_comptime, irb->current_basic_block); |
| | 2988 | |
| | 2989 | return &instruction->base; |
| | 2990 | } |
| | 2991 | |
| 2977 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 2992 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2978 | results[ReturnKindUnconditional] = 0; | 2993 | results[ReturnKindUnconditional] = 0; |
| 2979 | results[ReturnKindError] = 0; | 2994 | results[ReturnKindError] = 0; |
| ... | @@ -2999,6 +3014,7 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco | ... | @@ -2999,6 +3014,7 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco |
| 2999 | case ScopeIdLoop: | 3014 | case ScopeIdLoop: |
| 3000 | case ScopeIdSuspend: | 3015 | case ScopeIdSuspend: |
| 3001 | case ScopeIdCompTime: | 3016 | case ScopeIdCompTime: |
| | 3017 | case ScopeIdRuntime: |
| 3002 | scope = scope->parent; | 3018 | scope = scope->parent; |
| 3003 | continue; | 3019 | continue; |
| 3004 | case ScopeIdDeferExpr: | 3020 | case ScopeIdDeferExpr: |
| ... | @@ -3051,6 +3067,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o | ... | @@ -3051,6 +3067,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o |
| 3051 | case ScopeIdLoop: | 3067 | case ScopeIdLoop: |
| 3052 | case ScopeIdSuspend: | 3068 | case ScopeIdSuspend: |
| 3053 | case ScopeIdCompTime: | 3069 | case ScopeIdCompTime: |
| | 3070 | case ScopeIdRuntime: |
| 3054 | scope = scope->parent; | 3071 | scope = scope->parent; |
| 3055 | continue; | 3072 | continue; |
| 3056 | case ScopeIdDeferExpr: | 3073 | case ScopeIdDeferExpr: |
| ... | @@ -4980,7 +4997,8 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -4980,7 +4997,8 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 4980 | | 4997 | |
| 4981 | ir_set_cursor_at_end_and_append_block(irb, then_block); | 4998 | ir_set_cursor_at_end_and_append_block(irb, then_block); |
| 4982 | | 4999 | |
| 4983 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, scope); | 5000 | Scope *subexpr_scope = create_runtime_scope(node, scope, is_comptime); |
| | 5001 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope); |
| 4984 | if (then_expr_result == irb->codegen->invalid_instruction) | 5002 | if (then_expr_result == irb->codegen->invalid_instruction) |
| 4985 | return then_expr_result; | 5003 | return then_expr_result; |
| 4986 | IrBasicBlock *after_then_block = irb->current_basic_block; | 5004 | IrBasicBlock *after_then_block = irb->current_basic_block; |
| ... | @@ -4990,7 +5008,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -4990,7 +5008,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 4990 | ir_set_cursor_at_end_and_append_block(irb, else_block); | 5008 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 4991 | IrInstruction *else_expr_result; | 5009 | IrInstruction *else_expr_result; |
| 4992 | if (else_node) { | 5010 | if (else_node) { |
| 4993 | else_expr_result = ir_gen_node(irb, else_node, scope); | 5011 | else_expr_result = ir_gen_node(irb, else_node, subexpr_scope); |
| 4994 | if (else_expr_result == irb->codegen->invalid_instruction) | 5012 | if (else_expr_result == irb->codegen->invalid_instruction) |
| 4995 | return else_expr_result; | 5013 | return else_expr_result; |
| 4996 | } else { | 5014 | } else { |
| ... | @@ -5271,6 +5289,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5271,6 +5289,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5271 | ir_should_inline(irb->exec, scope) || node->data.while_expr.is_inline); | 5289 | ir_should_inline(irb->exec, scope) || node->data.while_expr.is_inline); |
| 5272 | ir_build_br(irb, scope, node, cond_block, is_comptime); | 5290 | ir_build_br(irb, scope, node, cond_block, is_comptime); |
| 5273 | | 5291 | |
| | 5292 | Scope *subexpr_scope = create_runtime_scope(node, scope, is_comptime); |
| 5274 | Buf *var_symbol = node->data.while_expr.var_symbol; | 5293 | Buf *var_symbol = node->data.while_expr.var_symbol; |
| 5275 | Buf *err_symbol = node->data.while_expr.err_symbol; | 5294 | Buf *err_symbol = node->data.while_expr.err_symbol; |
| 5276 | if (err_symbol != nullptr) { | 5295 | if (err_symbol != nullptr) { |
| ... | @@ -5281,13 +5300,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5281,13 +5300,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5281 | VariableTableEntry *payload_var; | 5300 | VariableTableEntry *payload_var; |
| 5282 | if (var_symbol) { | 5301 | if (var_symbol) { |
| 5283 | // TODO make it an error to write to payload variable | 5302 | // TODO make it an error to write to payload variable |
| 5284 | payload_var = ir_create_var(irb, symbol_node, scope, var_symbol, | 5303 | payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol, |
| 5285 | true, false, false, is_comptime); | 5304 | true, false, false, is_comptime); |
| 5286 | payload_scope = payload_var->child_scope; | 5305 | payload_scope = payload_var->child_scope; |
| 5287 | } else { | 5306 | } else { |
| 5288 | payload_scope = scope; | 5307 | payload_scope = subexpr_scope; |
| 5289 | } | 5308 | } |
| 5290 | IrInstruction *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, scope, LValPtr); | 5309 | IrInstruction *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, LValPtr); |
| 5291 | if (err_val_ptr == irb->codegen->invalid_instruction) | 5310 | if (err_val_ptr == irb->codegen->invalid_instruction) |
| 5292 | return err_val_ptr; | 5311 | return err_val_ptr; |
| 5293 | IrInstruction *err_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, err_val_ptr); | 5312 | IrInstruction *err_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, err_val_ptr); |
| ... | @@ -5367,12 +5386,14 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5367,12 +5386,14 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5367 | return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items); | 5386 | return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items); |
| 5368 | } else if (var_symbol != nullptr) { | 5387 | } else if (var_symbol != nullptr) { |
| 5369 | ir_set_cursor_at_end_and_append_block(irb, cond_block); | 5388 | ir_set_cursor_at_end_and_append_block(irb, cond_block); |
| | 5389 | Scope *subexpr_scope = create_runtime_scope(node, scope, is_comptime); |
| 5370 | // TODO make it an error to write to payload variable | 5390 | // TODO make it an error to write to payload variable |
| 5371 | AstNode *symbol_node = node; // TODO make more accurate | 5391 | AstNode *symbol_node = node; // TODO make more accurate |
| 5372 | VariableTableEntry *payload_var = ir_create_var(irb, symbol_node, scope, var_symbol, | 5392 | |
| | 5393 | VariableTableEntry *payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol, |
| 5373 | true, false, false, is_comptime); | 5394 | true, false, false, is_comptime); |
| 5374 | Scope *child_scope = payload_var->child_scope; | 5395 | Scope *child_scope = payload_var->child_scope; |
| 5375 | IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, scope, LValPtr); | 5396 | IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, LValPtr); |
| 5376 | if (maybe_val_ptr == irb->codegen->invalid_instruction) | 5397 | if (maybe_val_ptr == irb->codegen->invalid_instruction) |
| 5377 | return maybe_val_ptr; | 5398 | return maybe_val_ptr; |
| 5378 | IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr); | 5399 | IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr); |
| ... | @@ -5456,7 +5477,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5456,7 +5477,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5456 | ZigList<IrInstruction *> incoming_values = {0}; | 5477 | ZigList<IrInstruction *> incoming_values = {0}; |
| 5457 | ZigList<IrBasicBlock *> incoming_blocks = {0}; | 5478 | ZigList<IrBasicBlock *> incoming_blocks = {0}; |
| 5458 | | 5479 | |
| 5459 | ScopeLoop *loop_scope = create_loop_scope(node, scope); | 5480 | Scope *subexpr_scope = create_runtime_scope(node, scope, is_comptime); |
| | 5481 | |
| | 5482 | ScopeLoop *loop_scope = create_loop_scope(node, subexpr_scope); |
| 5460 | loop_scope->break_block = end_block; | 5483 | loop_scope->break_block = end_block; |
| 5461 | loop_scope->continue_block = continue_block; | 5484 | loop_scope->continue_block = continue_block; |
| 5462 | loop_scope->is_comptime = is_comptime; | 5485 | loop_scope->is_comptime = is_comptime; |
| ... | @@ -5474,7 +5497,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5474,7 +5497,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5474 | | 5497 | |
| 5475 | if (continue_expr_node) { | 5498 | if (continue_expr_node) { |
| 5476 | ir_set_cursor_at_end_and_append_block(irb, continue_block); | 5499 | ir_set_cursor_at_end_and_append_block(irb, continue_block); |
| 5477 | IrInstruction *expr_result = ir_gen_node(irb, continue_expr_node, scope); | 5500 | IrInstruction *expr_result = ir_gen_node(irb, continue_expr_node, subexpr_scope); |
| 5478 | if (expr_result == irb->codegen->invalid_instruction) | 5501 | if (expr_result == irb->codegen->invalid_instruction) |
| 5479 | return expr_result; | 5502 | return expr_result; |
| 5480 | if (!instr_is_unreachable(expr_result)) | 5503 | if (!instr_is_unreachable(expr_result)) |
| ... | @@ -5485,7 +5508,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5485,7 +5508,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5485 | if (else_node) { | 5508 | if (else_node) { |
| 5486 | ir_set_cursor_at_end_and_append_block(irb, else_block); | 5509 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 5487 | | 5510 | |
| 5488 | else_result = ir_gen_node(irb, else_node, scope); | 5511 | else_result = ir_gen_node(irb, else_node, subexpr_scope); |
| 5489 | if (else_result == irb->codegen->invalid_instruction) | 5512 | if (else_result == irb->codegen->invalid_instruction) |
| 5490 | return else_result; | 5513 | return else_result; |
| 5491 | if (!instr_is_unreachable(else_result)) | 5514 | if (!instr_is_unreachable(else_result)) |
| ... | @@ -5828,20 +5851,21 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no | ... | @@ -5828,20 +5851,21 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no |
| 5828 | | 5851 | |
| 5829 | ir_set_cursor_at_end_and_append_block(irb, then_block); | 5852 | ir_set_cursor_at_end_and_append_block(irb, then_block); |
| 5830 | | 5853 | |
| | 5854 | Scope *subexpr_scope = create_runtime_scope(node, scope, is_comptime); |
| 5831 | Scope *var_scope; | 5855 | Scope *var_scope; |
| 5832 | if (var_symbol) { | 5856 | if (var_symbol) { |
| 5833 | IrInstruction *var_type = nullptr; | 5857 | IrInstruction *var_type = nullptr; |
| 5834 | bool is_shadowable = false; | 5858 | bool is_shadowable = false; |
| 5835 | bool is_const = true; | 5859 | bool is_const = true; |
| 5836 | VariableTableEntry *var = ir_create_var(irb, node, scope, | 5860 | VariableTableEntry *var = ir_create_var(irb, node, subexpr_scope, |
| 5837 | var_symbol, is_const, is_const, is_shadowable, is_comptime); | 5861 | var_symbol, is_const, is_const, is_shadowable, is_comptime); |
| 5838 | | 5862 | |
| 5839 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, maybe_val_ptr, false); | 5863 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, subexpr_scope, node, maybe_val_ptr, false); |
| 5840 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value); | 5864 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value); |
| 5841 | ir_build_var_decl(irb, scope, node, var, var_type, nullptr, var_value); | 5865 | ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value); |
| 5842 | var_scope = var->child_scope; | 5866 | var_scope = var->child_scope; |
| 5843 | } else { | 5867 | } else { |
| 5844 | var_scope = scope; | 5868 | var_scope = subexpr_scope; |
| 5845 | } | 5869 | } |
| 5846 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var_scope); | 5870 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var_scope); |
| 5847 | if (then_expr_result == irb->codegen->invalid_instruction) | 5871 | if (then_expr_result == irb->codegen->invalid_instruction) |
| ... | @@ -5853,7 +5877,7 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no | ... | @@ -5853,7 +5877,7 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no |
| 5853 | ir_set_cursor_at_end_and_append_block(irb, else_block); | 5877 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 5854 | IrInstruction *else_expr_result; | 5878 | IrInstruction *else_expr_result; |
| 5855 | if (else_node) { | 5879 | if (else_node) { |
| 5856 | else_expr_result = ir_gen_node(irb, else_node, scope); | 5880 | else_expr_result = ir_gen_node(irb, else_node, subexpr_scope); |
| 5857 | if (else_expr_result == irb->codegen->invalid_instruction) | 5881 | if (else_expr_result == irb->codegen->invalid_instruction) |
| 5858 | return else_expr_result; | 5882 | return else_expr_result; |
| 5859 | } else { | 5883 | } else { |
| ... | @@ -5902,20 +5926,21 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -5902,20 +5926,21 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 5902 | | 5926 | |
| 5903 | ir_set_cursor_at_end_and_append_block(irb, ok_block); | 5927 | ir_set_cursor_at_end_and_append_block(irb, ok_block); |
| 5904 | | 5928 | |
| | 5929 | Scope *subexpr_scope = create_runtime_scope(node, scope, is_comptime); |
| 5905 | Scope *var_scope; | 5930 | Scope *var_scope; |
| 5906 | if (var_symbol) { | 5931 | if (var_symbol) { |
| 5907 | IrInstruction *var_type = nullptr; | 5932 | IrInstruction *var_type = nullptr; |
| 5908 | bool is_shadowable = false; | 5933 | bool is_shadowable = false; |
| 5909 | IrInstruction *var_is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, err_val); | 5934 | IrInstruction *var_is_comptime = force_comptime ? ir_build_const_bool(irb, subexpr_scope, node, true) : ir_build_test_comptime(irb, subexpr_scope, node, err_val); |
| 5910 | VariableTableEntry *var = ir_create_var(irb, node, scope, | 5935 | VariableTableEntry *var = ir_create_var(irb, node, subexpr_scope, |
| 5911 | var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime); | 5936 | var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime); |
| 5912 | | 5937 | |
| 5913 | IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, scope, node, err_val_ptr, false); | 5938 | IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false); |
| 5914 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value); | 5939 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value); |
| 5915 | ir_build_var_decl(irb, scope, node, var, var_type, nullptr, var_value); | 5940 | ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value); |
| 5916 | var_scope = var->child_scope; | 5941 | var_scope = var->child_scope; |
| 5917 | } else { | 5942 | } else { |
| 5918 | var_scope = scope; | 5943 | var_scope = subexpr_scope; |
| 5919 | } | 5944 | } |
| 5920 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var_scope); | 5945 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var_scope); |
| 5921 | if (then_expr_result == irb->codegen->invalid_instruction) | 5946 | if (then_expr_result == irb->codegen->invalid_instruction) |
| ... | @@ -5933,14 +5958,14 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -5933,14 +5958,14 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 5933 | IrInstruction *var_type = nullptr; | 5958 | IrInstruction *var_type = nullptr; |
| 5934 | bool is_shadowable = false; | 5959 | bool is_shadowable = false; |
| 5935 | bool is_const = true; | 5960 | bool is_const = true; |
| 5936 | VariableTableEntry *var = ir_create_var(irb, node, scope, | 5961 | VariableTableEntry *var = ir_create_var(irb, node, subexpr_scope, |
| 5937 | err_symbol, is_const, is_const, is_shadowable, is_comptime); | 5962 | err_symbol, is_const, is_const, is_shadowable, is_comptime); |
| 5938 | | 5963 | |
| 5939 | IrInstruction *var_value = ir_build_unwrap_err_code(irb, scope, node, err_val_ptr); | 5964 | IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr); |
| 5940 | ir_build_var_decl(irb, scope, node, var, var_type, nullptr, var_value); | 5965 | ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value); |
| 5941 | err_var_scope = var->child_scope; | 5966 | err_var_scope = var->child_scope; |
| 5942 | } else { | 5967 | } else { |
| 5943 | err_var_scope = scope; | 5968 | err_var_scope = subexpr_scope; |
| 5944 | } | 5969 | } |
| 5945 | else_expr_result = ir_gen_node(irb, else_node, err_var_scope); | 5970 | else_expr_result = ir_gen_node(irb, else_node, err_var_scope); |
| 5946 | if (else_expr_result == irb->codegen->invalid_instruction) | 5971 | if (else_expr_result == irb->codegen->invalid_instruction) |
| ... | @@ -6037,6 +6062,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -6037,6 +6062,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6037 | ZigList<IrInstructionCheckSwitchProngsRange> check_ranges = {0}; | 6062 | ZigList<IrInstructionCheckSwitchProngsRange> check_ranges = {0}; |
| 6038 | | 6063 | |
| 6039 | // First do the else and the ranges | 6064 | // First do the else and the ranges |
| | 6065 | Scope *subexpr_scope = create_runtime_scope(node, scope, is_comptime); |
| 6040 | Scope *comptime_scope = create_comptime_scope(node, scope); | 6066 | Scope *comptime_scope = create_comptime_scope(node, scope); |
| 6041 | AstNode *else_prong = nullptr; | 6067 | AstNode *else_prong = nullptr; |
| 6042 | for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { | 6068 | for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { |
| ... | @@ -6054,7 +6080,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -6054,7 +6080,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6054 | | 6080 | |
| 6055 | IrBasicBlock *prev_block = irb->current_basic_block; | 6081 | IrBasicBlock *prev_block = irb->current_basic_block; |
| 6056 | ir_set_cursor_at_end_and_append_block(irb, else_block); | 6082 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 6057 | if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block, | 6083 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, |
| 6058 | is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values)) | 6084 | is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values)) |
| 6059 | { | 6085 | { |
| 6060 | return irb->codegen->invalid_instruction; | 6086 | return irb->codegen->invalid_instruction; |
| ... | @@ -6121,7 +6147,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -6121,7 +6147,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6121 | range_block_no, is_comptime)); | 6147 | range_block_no, is_comptime)); |
| 6122 | | 6148 | |
| 6123 | ir_set_cursor_at_end_and_append_block(irb, range_block_yes); | 6149 | ir_set_cursor_at_end_and_append_block(irb, range_block_yes); |
| 6124 | if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block, | 6150 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, |
| 6125 | is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values)) | 6151 | is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values)) |
| 6126 | { | 6152 | { |
| 6127 | return irb->codegen->invalid_instruction; | 6153 | return irb->codegen->invalid_instruction; |
| ... | @@ -6165,7 +6191,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -6165,7 +6191,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6165 | | 6191 | |
| 6166 | IrBasicBlock *prev_block = irb->current_basic_block; | 6192 | IrBasicBlock *prev_block = irb->current_basic_block; |
| 6167 | ir_set_cursor_at_end_and_append_block(irb, prong_block); | 6193 | ir_set_cursor_at_end_and_append_block(irb, prong_block); |
| 6168 | if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block, | 6194 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, |
| 6169 | is_comptime, var_is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values)) | 6195 | is_comptime, var_is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values)) |
| 6170 | { | 6196 | { |
| 6171 | return irb->codegen->invalid_instruction; | 6197 | return irb->codegen->invalid_instruction; |
| ... | @@ -6308,6 +6334,8 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast | ... | @@ -6308,6 +6334,8 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast |
| 6308 | // * defer expression scope => error, cannot break out of defer expression | 6334 | // * defer expression scope => error, cannot break out of defer expression |
| 6309 | // * loop scope => OK | 6335 | // * loop scope => OK |
| 6310 | | 6336 | |
| | 6337 | ZigList<ScopeRuntime *> runtime_scopes = {}; |
| | 6338 | |
| 6311 | Scope *search_scope = continue_scope; | 6339 | Scope *search_scope = continue_scope; |
| 6312 | ScopeLoop *loop_scope; | 6340 | ScopeLoop *loop_scope; |
| 6313 | for (;;) { | 6341 | for (;;) { |
| ... | @@ -6330,6 +6358,9 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast | ... | @@ -6330,6 +6358,9 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast |
| 6330 | loop_scope = this_loop_scope; | 6358 | loop_scope = this_loop_scope; |
| 6331 | break; | 6359 | break; |
| 6332 | } | 6360 | } |
| | 6361 | } else if (search_scope->id == ScopeIdRuntime) { |
| | 6362 | ScopeRuntime *scope_runtime = (ScopeRuntime *)search_scope; |
| | 6363 | runtime_scopes.append(scope_runtime); |
| 6333 | } | 6364 | } |
| 6334 | search_scope = search_scope->parent; | 6365 | search_scope = search_scope->parent; |
| 6335 | } | 6366 | } |
| ... | @@ -6341,6 +6372,11 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast | ... | @@ -6341,6 +6372,11 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast |
| 6341 | is_comptime = loop_scope->is_comptime; | 6372 | is_comptime = loop_scope->is_comptime; |
| 6342 | } | 6373 | } |
| 6343 | | 6374 | |
| | 6375 | for (size_t i = 0; i < runtime_scopes.length; i += 1) { |
| | 6376 | ScopeRuntime *scope_runtime = runtime_scopes.at(i); |
| | 6377 | ir_mark_gen(ir_build_check_runtime_scope(irb, continue_scope, node, scope_runtime->is_comptime, is_comptime)); |
| | 6378 | } |
| | 6379 | |
| 6344 | IrBasicBlock *dest_block = loop_scope->continue_block; | 6380 | IrBasicBlock *dest_block = loop_scope->continue_block; |
| 6345 | ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, false); | 6381 | ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, false); |
| 6346 | return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime)); | 6382 | return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime)); |
| ... | @@ -20910,6 +20946,29 @@ static TypeTableEntry *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInst | ... | @@ -20910,6 +20946,29 @@ static TypeTableEntry *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInst |
| 20910 | return result->value.type; | 20946 | return result->value.type; |
| 20911 | } | 20947 | } |
| 20912 | | 20948 | |
| | 20949 | static TypeTableEntry *ir_analyze_instruction_check_runtime_scope(IrAnalyze *ira, IrInstructionCheckRuntimeScope *instruction) { |
| | 20950 | IrInstruction *block_comptime_inst = instruction->scope_is_comptime->other; |
| | 20951 | bool scope_is_comptime; |
| | 20952 | if (!ir_resolve_bool(ira, block_comptime_inst, &scope_is_comptime)) |
| | 20953 | return ira->codegen->builtin_types.entry_invalid; |
| | 20954 | |
| | 20955 | IrInstruction *is_comptime_inst = instruction->is_comptime->other; |
| | 20956 | bool is_comptime; |
| | 20957 | if (!ir_resolve_bool(ira, is_comptime_inst, &is_comptime)) |
| | 20958 | return ira->codegen->builtin_types.entry_invalid; |
| | 20959 | |
| | 20960 | if (!scope_is_comptime && is_comptime) { |
| | 20961 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, |
| | 20962 | buf_sprintf("comptime control flow inside runtime block")); |
| | 20963 | add_error_note(ira->codegen, msg, block_comptime_inst->source_node, |
| | 20964 | buf_sprintf("runtime block created here")); |
| | 20965 | return ira->codegen->builtin_types.entry_invalid; |
| | 20966 | } |
| | 20967 | |
| | 20968 | ir_build_const_from(ira, &instruction->base); |
| | 20969 | return ira->codegen->builtin_types.entry_void; |
| | 20970 | } |
| | 20971 | |
| 20913 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 20972 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 20914 | switch (instruction->id) { | 20973 | switch (instruction->id) { |
| 20915 | case IrInstructionIdInvalid: | 20974 | case IrInstructionIdInvalid: |
| ... | @@ -21186,6 +21245,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -21186,6 +21245,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 21186 | return ir_analyze_instruction_int_to_enum(ira, (IrInstructionIntToEnum *)instruction); | 21245 | return ir_analyze_instruction_int_to_enum(ira, (IrInstructionIntToEnum *)instruction); |
| 21187 | case IrInstructionIdEnumToInt: | 21246 | case IrInstructionIdEnumToInt: |
| 21188 | return ir_analyze_instruction_enum_to_int(ira, (IrInstructionEnumToInt *)instruction); | 21247 | return ir_analyze_instruction_enum_to_int(ira, (IrInstructionEnumToInt *)instruction); |
| | 21248 | case IrInstructionIdCheckRuntimeScope: |
| | 21249 | return ir_analyze_instruction_check_runtime_scope(ira, (IrInstructionCheckRuntimeScope *)instruction); |
| 21189 | } | 21250 | } |
| 21190 | zig_unreachable(); | 21251 | zig_unreachable(); |
| 21191 | } | 21252 | } |
| ... | @@ -21301,6 +21362,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -21301,6 +21362,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21301 | case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free | 21362 | case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free |
| 21302 | case IrInstructionIdCheckSwitchProngs: | 21363 | case IrInstructionIdCheckSwitchProngs: |
| 21303 | case IrInstructionIdCheckStatementIsVoid: | 21364 | case IrInstructionIdCheckStatementIsVoid: |
| | 21365 | case IrInstructionIdCheckRuntimeScope: |
| 21304 | case IrInstructionIdPanic: | 21366 | case IrInstructionIdPanic: |
| 21305 | case IrInstructionIdSetEvalBranchQuota: | 21367 | case IrInstructionIdSetEvalBranchQuota: |
| 21306 | case IrInstructionIdPtrType: | 21368 | case IrInstructionIdPtrType: |