| ... | ... | @@ -1683,7 +1683,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 1683 | 1683 | const defer_scope = scope.cast(Scope.Defer).?; |
| 1684 | 1684 | scope = defer_scope.parent; |
| 1685 | 1685 | const expr_node = node_datas[defer_scope.defer_node].rhs; |
| 1686 | | _ = try unusedResultExpr(parent_gz, defer_scope.parent, expr_node); |
| 1686 | try unusedResultDeferExpr(parent_gz, defer_scope, defer_scope.parent, expr_node); |
| 1687 | 1687 | }, |
| 1688 | 1688 | .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 1689 | 1689 | .top => unreachable, |
| ... | ... | @@ -1736,7 +1736,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 1736 | 1736 | const defer_scope = scope.cast(Scope.Defer).?; |
| 1737 | 1737 | scope = defer_scope.parent; |
| 1738 | 1738 | const expr_node = node_datas[defer_scope.defer_node].rhs; |
| 1739 | | _ = try unusedResultExpr(parent_gz, defer_scope.parent, expr_node); |
| 1739 | try unusedResultDeferExpr(parent_gz, defer_scope, defer_scope.parent, expr_node); |
| 1740 | 1740 | }, |
| 1741 | 1741 | .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 1742 | 1742 | .namespace => break, |
| ... | ... | @@ -1922,8 +1922,8 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 1922 | 1922 | .simple_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.simpleVarDecl(statement)), |
| 1923 | 1923 | .aligned_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.alignedVarDecl(statement)), |
| 1924 | 1924 | |
| 1925 | | .@"defer" => scope = try makeDeferScope(scope, statement, &block_arena.allocator, .defer_normal), |
| 1926 | | .@"errdefer" => scope = try makeDeferScope(scope, statement, &block_arena.allocator, .defer_error), |
| 1925 | .@"defer" => scope = try makeDeferScope(gz.astgen, scope, statement, &block_arena.allocator, .defer_normal), |
| 1926 | .@"errdefer" => scope = try makeDeferScope(gz.astgen, scope, statement, &block_arena.allocator, .defer_error), |
| 1927 | 1927 | |
| 1928 | 1928 | .assign => try assign(gz, scope, statement), |
| 1929 | 1929 | |
| ... | ... | @@ -1951,6 +1951,22 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 1951 | 1951 | try checkUsed(gz, parent_scope, scope); |
| 1952 | 1952 | } |
| 1953 | 1953 | |
| 1954 | fn unusedResultDeferExpr(gz: *GenZir, defer_scope: *Scope.Defer, expr_scope: *Scope, expr_node: Ast.Node.Index) InnerError!void { |
| 1955 | const astgen = gz.astgen; |
| 1956 | const prev_offset = astgen.source_offset; |
| 1957 | const prev_line = astgen.source_line; |
| 1958 | const prev_column = astgen.source_column; |
| 1959 | defer { |
| 1960 | astgen.source_offset = prev_offset; |
| 1961 | astgen.source_line = prev_line; |
| 1962 | astgen.source_column = prev_column; |
| 1963 | } |
| 1964 | astgen.source_offset = defer_scope.source_offset; |
| 1965 | astgen.source_line = defer_scope.source_line; |
| 1966 | astgen.source_column = defer_scope.source_column; |
| 1967 | _ = try unusedResultExpr(gz, expr_scope, expr_node); |
| 1968 | } |
| 1969 | |
| 1954 | 1970 | /// Returns AST source node of the thing that is noreturn if the statement is definitely `noreturn`. |
| 1955 | 1971 | /// Otherwise returns 0. |
| 1956 | 1972 | fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.Index { |
| ... | ... | @@ -2333,7 +2349,7 @@ fn genDefers( |
| 2333 | 2349 | const prev_in_defer = gz.in_defer; |
| 2334 | 2350 | gz.in_defer = true; |
| 2335 | 2351 | defer gz.in_defer = prev_in_defer; |
| 2336 | | _ = try unusedResultExpr(gz, defer_scope.parent, expr_node); |
| 2352 | try unusedResultDeferExpr(gz, defer_scope, defer_scope.parent, expr_node); |
| 2337 | 2353 | }, |
| 2338 | 2354 | .defer_error => { |
| 2339 | 2355 | const defer_scope = scope.cast(Scope.Defer).?; |
| ... | ... | @@ -2344,7 +2360,7 @@ fn genDefers( |
| 2344 | 2360 | const prev_in_defer = gz.in_defer; |
| 2345 | 2361 | gz.in_defer = true; |
| 2346 | 2362 | defer gz.in_defer = prev_in_defer; |
| 2347 | | _ = try unusedResultExpr(gz, defer_scope.parent, expr_node); |
| 2363 | try unusedResultDeferExpr(gz, defer_scope, defer_scope.parent, expr_node); |
| 2348 | 2364 | }, |
| 2349 | 2365 | .both => |err_code| { |
| 2350 | 2366 | const expr_node = node_datas[defer_scope.defer_node].rhs; |
| ... | ... | @@ -2365,7 +2381,7 @@ fn genDefers( |
| 2365 | 2381 | }; |
| 2366 | 2382 | break :blk &local_val_scope.base; |
| 2367 | 2383 | }; |
| 2368 | | _ = try unusedResultExpr(gz, sub_scope, expr_node); |
| 2384 | try unusedResultDeferExpr(gz, defer_scope, sub_scope, expr_node); |
| 2369 | 2385 | }, |
| 2370 | 2386 | .normal_only => continue, |
| 2371 | 2387 | } |
| ... | ... | @@ -2409,16 +2425,27 @@ fn checkUsed( |
| 2409 | 2425 | } |
| 2410 | 2426 | |
| 2411 | 2427 | fn makeDeferScope( |
| 2428 | astgen: *AstGen, |
| 2412 | 2429 | scope: *Scope, |
| 2413 | 2430 | node: Ast.Node.Index, |
| 2414 | 2431 | block_arena: *Allocator, |
| 2415 | 2432 | scope_tag: Scope.Tag, |
| 2416 | 2433 | ) InnerError!*Scope { |
| 2434 | const tree = astgen.tree; |
| 2435 | const node_datas = tree.nodes.items(.data); |
| 2436 | const expr_node = node_datas[node].rhs; |
| 2437 | const token_starts = tree.tokens.items(.start); |
| 2438 | const node_start = token_starts[tree.firstToken(expr_node)]; |
| 2417 | 2439 | const defer_scope = try block_arena.create(Scope.Defer); |
| 2440 | astgen.advanceSourceCursor(tree.source, node_start); |
| 2441 | |
| 2418 | 2442 | defer_scope.* = .{ |
| 2419 | 2443 | .base = .{ .tag = scope_tag }, |
| 2420 | 2444 | .parent = scope, |
| 2421 | 2445 | .defer_node = node, |
| 2446 | .source_offset = astgen.source_offset, |
| 2447 | .source_line = astgen.source_line, |
| 2448 | .source_column = astgen.source_column, |
| 2422 | 2449 | }; |
| 2423 | 2450 | return &defer_scope.base; |
| 2424 | 2451 | } |
| ... | ... | @@ -3184,6 +3211,12 @@ fn fnDecl( |
| 3184 | 3211 | astgen.fn_block = &fn_gz; |
| 3185 | 3212 | defer astgen.fn_block = prev_fn_block; |
| 3186 | 3213 | |
| 3214 | const token_starts = tree.tokens.items(.start); |
| 3215 | const lbrace_start = token_starts[tree.firstToken(body_node)]; |
| 3216 | astgen.advanceSourceCursor(tree.source, lbrace_start); |
| 3217 | const lbrace_line = @intCast(u32, astgen.source_line); |
| 3218 | const lbrace_column = @intCast(u32, astgen.source_column); |
| 3219 | |
| 3187 | 3220 | _ = try expr(&fn_gz, params_scope, .none, body_node); |
| 3188 | 3221 | try checkUsed(gz, &fn_gz.base, params_scope); |
| 3189 | 3222 | |
| ... | ... | @@ -3202,6 +3235,8 @@ fn fnDecl( |
| 3202 | 3235 | |
| 3203 | 3236 | break :func try decl_gz.addFunc(.{ |
| 3204 | 3237 | .src_node = decl_node, |
| 3238 | .lbrace_line = lbrace_line, |
| 3239 | .lbrace_column = lbrace_column, |
| 3205 | 3240 | .param_block = block_inst, |
| 3206 | 3241 | .ret_ty = ret_gz.instructions.items, |
| 3207 | 3242 | .ret_br = ret_br, |
| ... | ... | @@ -3544,6 +3579,12 @@ fn testDecl( |
| 3544 | 3579 | astgen.fn_block = &fn_block; |
| 3545 | 3580 | defer astgen.fn_block = prev_fn_block; |
| 3546 | 3581 | |
| 3582 | const token_starts = tree.tokens.items(.start); |
| 3583 | const lbrace_start = token_starts[tree.firstToken(body_node)]; |
| 3584 | astgen.advanceSourceCursor(tree.source, lbrace_start); |
| 3585 | const lbrace_line = @intCast(u32, astgen.source_line); |
| 3586 | const lbrace_column = @intCast(u32, astgen.source_column); |
| 3587 | |
| 3547 | 3588 | const block_result = try expr(&fn_block, &fn_block.base, .none, body_node); |
| 3548 | 3589 | if (fn_block.instructions.items.len == 0 or !fn_block.refIsNoReturn(block_result)) { |
| 3549 | 3590 | // Since we are adding the return instruction here, we must handle the coercion. |
| ... | ... | @@ -3553,6 +3594,8 @@ fn testDecl( |
| 3553 | 3594 | |
| 3554 | 3595 | const func_inst = try decl_block.addFunc(.{ |
| 3555 | 3596 | .src_node = node, |
| 3597 | .lbrace_line = lbrace_line, |
| 3598 | .lbrace_column = lbrace_column, |
| 3556 | 3599 | .param_block = block_inst, |
| 3557 | 3600 | .ret_ty = &.{}, |
| 3558 | 3601 | .ret_br = 0, |
| ... | ... | @@ -5935,10 +5978,11 @@ fn switchExpr( |
| 5935 | 5978 | const operand_ty_inst = try parent_gz.addUnNode(typeof_tag, operand, operand_node); |
| 5936 | 5979 | const item_rl: ResultLoc = .{ .ty = operand_ty_inst }; |
| 5937 | 5980 | |
| 5938 | | // Contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti. |
| 5939 | | // This is the header as well as the optional else prong body, as well as all the |
| 5940 | | // scalar cases. |
| 5941 | | // At the end we will memcpy this into place. |
| 5981 | // These contain the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti. |
| 5982 | // This is the optional else prong body. |
| 5983 | var special_case_payload = ArrayListUnmanaged(u32){}; |
| 5984 | defer special_case_payload.deinit(gpa); |
| 5985 | // This is all the scalar cases. |
| 5942 | 5986 | var scalar_cases_payload = ArrayListUnmanaged(u32){}; |
| 5943 | 5987 | defer scalar_cases_payload.deinit(gpa); |
| 5944 | 5988 | // Same deal, but this is only the `extra` data for the multi cases. |
| ... | ... | @@ -5956,86 +6000,10 @@ fn switchExpr( |
| 5956 | 6000 | var case_scope = parent_gz.makeSubBlock(&block_scope.base); |
| 5957 | 6001 | defer case_scope.instructions.deinit(gpa); |
| 5958 | 6002 | |
| 5959 | | // Do the else/`_` first because it goes first in the payload. |
| 5960 | | var capture_val_scope: Scope.LocalVal = undefined; |
| 5961 | | if (special_node != 0) { |
| 5962 | | const case = switch (node_tags[special_node]) { |
| 5963 | | .switch_case_one => tree.switchCaseOne(special_node), |
| 5964 | | .switch_case => tree.switchCase(special_node), |
| 5965 | | else => unreachable, |
| 5966 | | }; |
| 5967 | | const sub_scope = blk: { |
| 5968 | | const payload_token = case.payload_token orelse break :blk &case_scope.base; |
| 5969 | | const ident = if (token_tags[payload_token] == .asterisk) |
| 5970 | | payload_token + 1 |
| 5971 | | else |
| 5972 | | payload_token; |
| 5973 | | const is_ptr = ident != payload_token; |
| 5974 | | if (mem.eql(u8, tree.tokenSlice(ident), "_")) { |
| 5975 | | if (is_ptr) { |
| 5976 | | return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{}); |
| 5977 | | } |
| 5978 | | break :blk &case_scope.base; |
| 5979 | | } |
| 5980 | | const capture_tag: Zir.Inst.Tag = if (is_ptr) |
| 5981 | | .switch_capture_else_ref |
| 5982 | | else |
| 5983 | | .switch_capture_else; |
| 5984 | | const capture = try case_scope.add(.{ |
| 5985 | | .tag = capture_tag, |
| 5986 | | .data = .{ .switch_capture = .{ |
| 5987 | | .switch_inst = switch_block, |
| 5988 | | .prong_index = undefined, |
| 5989 | | } }, |
| 5990 | | }); |
| 5991 | | const capture_name = try astgen.identAsString(payload_token); |
| 5992 | | capture_val_scope = .{ |
| 5993 | | .parent = &case_scope.base, |
| 5994 | | .gen_zir = &case_scope, |
| 5995 | | .name = capture_name, |
| 5996 | | .inst = capture, |
| 5997 | | .token_src = payload_token, |
| 5998 | | .id_cat = .@"capture", |
| 5999 | | }; |
| 6000 | | break :blk &capture_val_scope.base; |
| 6001 | | }; |
| 6002 | | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 6003 | | try checkUsed(parent_gz, &case_scope.base, sub_scope); |
| 6004 | | if (!parent_gz.refIsNoReturn(case_result)) { |
| 6005 | | block_scope.break_count += 1; |
| 6006 | | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| 6007 | | } |
| 6008 | | // Documentation for this: `Zir.Inst.SwitchBlock` and `Zir.Inst.SwitchBlockMulti`. |
| 6009 | | try scalar_cases_payload.ensureUnusedCapacity(gpa, case_scope.instructions.items.len + |
| 6010 | | 3 + // operand, scalar_cases_len, else body len |
| 6011 | | @boolToInt(multi_cases_len != 0)); |
| 6012 | | scalar_cases_payload.appendAssumeCapacity(@enumToInt(operand)); |
| 6013 | | scalar_cases_payload.appendAssumeCapacity(scalar_cases_len); |
| 6014 | | if (multi_cases_len != 0) { |
| 6015 | | scalar_cases_payload.appendAssumeCapacity(multi_cases_len); |
| 6016 | | } |
| 6017 | | scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len)); |
| 6018 | | scalar_cases_payload.appendSliceAssumeCapacity(case_scope.instructions.items); |
| 6019 | | } else { |
| 6020 | | // Documentation for this: `Zir.Inst.SwitchBlock` and `Zir.Inst.SwitchBlockMulti`. |
| 6021 | | try scalar_cases_payload.ensureUnusedCapacity( |
| 6022 | | gpa, |
| 6023 | | @as(usize, 2) + // operand, scalar_cases_len |
| 6024 | | @boolToInt(multi_cases_len != 0), |
| 6025 | | ); |
| 6026 | | scalar_cases_payload.appendAssumeCapacity(@enumToInt(operand)); |
| 6027 | | scalar_cases_payload.appendAssumeCapacity(scalar_cases_len); |
| 6028 | | if (multi_cases_len != 0) { |
| 6029 | | scalar_cases_payload.appendAssumeCapacity(multi_cases_len); |
| 6030 | | } |
| 6031 | | } |
| 6032 | | |
| 6033 | | // In this pass we generate all the item and prong expressions except the special case. |
| 6003 | // In this pass we generate all the item and prong expressions. |
| 6034 | 6004 | var multi_case_index: u32 = 0; |
| 6035 | 6005 | var scalar_case_index: u32 = 0; |
| 6036 | 6006 | for (case_nodes) |case_node| { |
| 6037 | | if (case_node == special_node) |
| 6038 | | continue; |
| 6039 | 6007 | const case = switch (node_tags[case_node]) { |
| 6040 | 6008 | .switch_case_one => tree.switchCaseOne(case_node), |
| 6041 | 6009 | .switch_case => tree.switchCase(case_node), |
| ... | ... | @@ -6045,9 +6013,10 @@ fn switchExpr( |
| 6045 | 6013 | // Reset the scope. |
| 6046 | 6014 | case_scope.instructions.shrinkRetainingCapacity(0); |
| 6047 | 6015 | |
| 6048 | | const is_multi_case = case.ast.values.len != 1 or |
| 6049 | | node_tags[case.ast.values[0]] == .switch_range; |
| 6016 | const is_multi_case = case.ast.values.len > 1 or |
| 6017 | (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range); |
| 6050 | 6018 | |
| 6019 | var capture_val_scope: Scope.LocalVal = undefined; |
| 6051 | 6020 | const sub_scope = blk: { |
| 6052 | 6021 | const payload_token = case.payload_token orelse break :blk &case_scope.base; |
| 6053 | 6022 | const ident = if (token_tags[payload_token] == .asterisk) |
| ... | ... | @@ -6061,28 +6030,42 @@ fn switchExpr( |
| 6061 | 6030 | } |
| 6062 | 6031 | break :blk &case_scope.base; |
| 6063 | 6032 | } |
| 6064 | | const is_multi_case_bits: u2 = @boolToInt(is_multi_case); |
| 6065 | | const is_ptr_bits: u2 = @boolToInt(is_ptr); |
| 6066 | | const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) { |
| 6067 | | 0b00 => .switch_capture, |
| 6068 | | 0b01 => .switch_capture_ref, |
| 6069 | | 0b10 => .switch_capture_multi, |
| 6070 | | 0b11 => .switch_capture_multi_ref, |
| 6071 | | }; |
| 6072 | | const capture_index = if (is_multi_case) ci: { |
| 6073 | | multi_case_index += 1; |
| 6074 | | break :ci multi_case_index - 1; |
| 6075 | | } else ci: { |
| 6076 | | scalar_case_index += 1; |
| 6077 | | break :ci scalar_case_index - 1; |
| 6033 | const capture = if (case_node == special_node) capture: { |
| 6034 | const capture_tag: Zir.Inst.Tag = if (is_ptr) |
| 6035 | .switch_capture_else_ref |
| 6036 | else |
| 6037 | .switch_capture_else; |
| 6038 | break :capture try case_scope.add(.{ |
| 6039 | .tag = capture_tag, |
| 6040 | .data = .{ .switch_capture = .{ |
| 6041 | .switch_inst = switch_block, |
| 6042 | .prong_index = undefined, |
| 6043 | } }, |
| 6044 | }); |
| 6045 | } else capture: { |
| 6046 | const is_multi_case_bits: u2 = @boolToInt(is_multi_case); |
| 6047 | const is_ptr_bits: u2 = @boolToInt(is_ptr); |
| 6048 | const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) { |
| 6049 | 0b00 => .switch_capture, |
| 6050 | 0b01 => .switch_capture_ref, |
| 6051 | 0b10 => .switch_capture_multi, |
| 6052 | 0b11 => .switch_capture_multi_ref, |
| 6053 | }; |
| 6054 | const capture_index = if (is_multi_case) ci: { |
| 6055 | multi_case_index += 1; |
| 6056 | break :ci multi_case_index - 1; |
| 6057 | } else ci: { |
| 6058 | scalar_case_index += 1; |
| 6059 | break :ci scalar_case_index - 1; |
| 6060 | }; |
| 6061 | break :capture try case_scope.add(.{ |
| 6062 | .tag = capture_tag, |
| 6063 | .data = .{ .switch_capture = .{ |
| 6064 | .switch_inst = switch_block, |
| 6065 | .prong_index = capture_index, |
| 6066 | } }, |
| 6067 | }); |
| 6078 | 6068 | }; |
| 6079 | | const capture = try case_scope.add(.{ |
| 6080 | | .tag = capture_tag, |
| 6081 | | .data = .{ .switch_capture = .{ |
| 6082 | | .switch_inst = switch_block, |
| 6083 | | .prong_index = capture_index, |
| 6084 | | } }, |
| 6085 | | }); |
| 6086 | 6069 | const capture_name = try astgen.identAsString(ident); |
| 6087 | 6070 | capture_val_scope = .{ |
| 6088 | 6071 | .parent = &case_scope.base, |
| ... | ... | @@ -6134,6 +6117,17 @@ fn switchExpr( |
| 6134 | 6117 | multi_cases_payload.items[header_index + 1] = ranges_len; |
| 6135 | 6118 | multi_cases_payload.items[header_index + 2] = @intCast(u32, case_scope.instructions.items.len); |
| 6136 | 6119 | try multi_cases_payload.appendSlice(gpa, case_scope.instructions.items); |
| 6120 | } else if (case_node == special_node) { |
| 6121 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 6122 | try checkUsed(parent_gz, &case_scope.base, sub_scope); |
| 6123 | if (!parent_gz.refIsNoReturn(case_result)) { |
| 6124 | block_scope.break_count += 1; |
| 6125 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| 6126 | } |
| 6127 | try special_case_payload.ensureUnusedCapacity(gpa, 1 + // body_len |
| 6128 | case_scope.instructions.items.len); |
| 6129 | special_case_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len)); |
| 6130 | special_case_payload.appendSliceAssumeCapacity(case_scope.instructions.items); |
| 6137 | 6131 | } else { |
| 6138 | 6132 | const item_node = case.ast.values[0]; |
| 6139 | 6133 | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); |
| ... | ... | @@ -6143,7 +6137,7 @@ fn switchExpr( |
| 6143 | 6137 | block_scope.break_count += 1; |
| 6144 | 6138 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| 6145 | 6139 | } |
| 6146 | | try scalar_cases_payload.ensureUnusedCapacity(gpa, 2 + |
| 6140 | try scalar_cases_payload.ensureUnusedCapacity(gpa, 2 + // item + body_len |
| 6147 | 6141 | case_scope.instructions.items.len); |
| 6148 | 6142 | scalar_cases_payload.appendAssumeCapacity(@enumToInt(item_inst)); |
| 6149 | 6143 | scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len)); |
| ... | ... | @@ -6180,8 +6174,17 @@ fn switchExpr( |
| 6180 | 6174 | const payload_index = astgen.extra.items.len; |
| 6181 | 6175 | const zir_datas = astgen.instructions.items(.data); |
| 6182 | 6176 | zir_datas[switch_block].pl_node.payload_index = @intCast(u32, payload_index); |
| 6183 | | try astgen.extra.ensureUnusedCapacity(gpa, scalar_cases_payload.items.len + |
| 6177 | // Documentation for this: `Zir.Inst.SwitchBlock` and `Zir.Inst.SwitchBlockMulti`. |
| 6178 | try astgen.extra.ensureUnusedCapacity(gpa, @as(usize, 2) + // operand, scalar_cases_len |
| 6179 | @boolToInt(multi_cases_len != 0) + |
| 6180 | special_case_payload.items.len + |
| 6181 | scalar_cases_payload.items.len + |
| 6184 | 6182 | multi_cases_payload.items.len); |
| 6183 | astgen.extra.appendAssumeCapacity(@enumToInt(operand)); |
| 6184 | astgen.extra.appendAssumeCapacity(scalar_cases_len); |
| 6185 | if (multi_cases_len != 0) { |
| 6186 | astgen.extra.appendAssumeCapacity(multi_cases_len); |
| 6187 | } |
| 6185 | 6188 | const strat = rl.strategy(&block_scope); |
| 6186 | 6189 | switch (strat.tag) { |
| 6187 | 6190 | .break_operand => { |
| ... | ... | @@ -6189,6 +6192,7 @@ fn switchExpr( |
| 6189 | 6192 | // `elide_store_to_block_ptr_instructions` will either be true, |
| 6190 | 6193 | // or all prongs are noreturn. |
| 6191 | 6194 | if (!strat.elide_store_to_block_ptr_instructions) { |
| 6195 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items); |
| 6192 | 6196 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items); |
| 6193 | 6197 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items); |
| 6194 | 6198 | return indexToRef(switch_block); |
| ... | ... | @@ -6204,32 +6208,30 @@ fn switchExpr( |
| 6204 | 6208 | // it as the break operand. |
| 6205 | 6209 | |
| 6206 | 6210 | var extra_index: usize = 0; |
| 6207 | | extra_index += 2; |
| 6208 | | extra_index += @boolToInt(multi_cases_len != 0); |
| 6209 | 6211 | if (special_prong != .none) special_prong: { |
| 6210 | 6212 | const body_len_index = extra_index; |
| 6211 | | const body_len = scalar_cases_payload.items[extra_index]; |
| 6213 | const body_len = special_case_payload.items[extra_index]; |
| 6212 | 6214 | extra_index += 1; |
| 6213 | 6215 | if (body_len < 2) { |
| 6214 | 6216 | extra_index += body_len; |
| 6215 | | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]); |
| 6217 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); |
| 6216 | 6218 | break :special_prong; |
| 6217 | 6219 | } |
| 6218 | 6220 | extra_index += body_len - 2; |
| 6219 | | const store_inst = scalar_cases_payload.items[extra_index]; |
| 6221 | const store_inst = special_case_payload.items[extra_index]; |
| 6220 | 6222 | if (zir_tags[store_inst] != .store_to_block_ptr or |
| 6221 | 6223 | zir_datas[store_inst].bin.lhs != block_scope.rl_ptr) |
| 6222 | 6224 | { |
| 6223 | 6225 | extra_index += 2; |
| 6224 | | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]); |
| 6226 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); |
| 6225 | 6227 | break :special_prong; |
| 6226 | 6228 | } |
| 6227 | 6229 | assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr); |
| 6228 | 6230 | if (block_scope.rl_ty_inst != .none) { |
| 6229 | 6231 | extra_index += 1; |
| 6230 | | const break_inst = scalar_cases_payload.items[extra_index]; |
| 6232 | const break_inst = special_case_payload.items[extra_index]; |
| 6231 | 6233 | extra_index += 1; |
| 6232 | | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]); |
| 6234 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); |
| 6233 | 6235 | zir_tags[store_inst] = .as; |
| 6234 | 6236 | zir_datas[store_inst].bin = .{ |
| 6235 | 6237 | .lhs = block_scope.rl_ty_inst, |
| ... | ... | @@ -6237,15 +6239,16 @@ fn switchExpr( |
| 6237 | 6239 | }; |
| 6238 | 6240 | zir_datas[break_inst].@"break".operand = indexToRef(store_inst); |
| 6239 | 6241 | } else { |
| 6240 | | scalar_cases_payload.items[body_len_index] -= 1; |
| 6241 | | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]); |
| 6242 | special_case_payload.items[body_len_index] -= 1; |
| 6243 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); |
| 6242 | 6244 | extra_index += 1; |
| 6243 | | astgen.extra.appendAssumeCapacity(scalar_cases_payload.items[extra_index]); |
| 6245 | astgen.extra.appendAssumeCapacity(special_case_payload.items[extra_index]); |
| 6244 | 6246 | extra_index += 1; |
| 6245 | 6247 | } |
| 6246 | 6248 | } else { |
| 6247 | | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]); |
| 6249 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); |
| 6248 | 6250 | } |
| 6251 | extra_index = 0; |
| 6249 | 6252 | var scalar_i: u32 = 0; |
| 6250 | 6253 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| 6251 | 6254 | const start_index = extra_index; |
| ... | ... | @@ -6342,6 +6345,7 @@ fn switchExpr( |
| 6342 | 6345 | }, |
| 6343 | 6346 | .break_void => { |
| 6344 | 6347 | assert(!strat.elide_store_to_block_ptr_instructions); |
| 6348 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items); |
| 6345 | 6349 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items); |
| 6346 | 6350 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items); |
| 6347 | 6351 | // Modify all the terminating instruction tags to become `break` variants. |
| ... | ... | @@ -9282,6 +9286,9 @@ const Scope = struct { |
| 9282 | 9286 | /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`, `Namespace`. |
| 9283 | 9287 | parent: *Scope, |
| 9284 | 9288 | defer_node: Ast.Node.Index, |
| 9289 | source_offset: u32, |
| 9290 | source_line: u32, |
| 9291 | source_column: u32, |
| 9285 | 9292 | }; |
| 9286 | 9293 | |
| 9287 | 9294 | /// Represents a global scope that has any number of declarations in it. |
| ... | ... | @@ -9563,6 +9570,8 @@ const GenZir = struct { |
| 9563 | 9570 | |
| 9564 | 9571 | fn addFunc(gz: *GenZir, args: struct { |
| 9565 | 9572 | src_node: Ast.Node.Index, |
| 9573 | lbrace_line: u32 = 0, |
| 9574 | lbrace_column: u32 = 0, |
| 9566 | 9575 | body: []const Zir.Inst.Index, |
| 9567 | 9576 | param_block: Zir.Inst.Index, |
| 9568 | 9577 | ret_ty: []const Zir.Inst.Index, |
| ... | ... | @@ -9592,19 +9601,13 @@ const GenZir = struct { |
| 9592 | 9601 | const fn_decl = args.src_node; |
| 9593 | 9602 | assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl); |
| 9594 | 9603 | const block = node_datas[fn_decl].rhs; |
| 9595 | | const lbrace_start = token_starts[tree.firstToken(block)]; |
| 9596 | 9604 | const rbrace_start = token_starts[tree.lastToken(block)]; |
| 9597 | | |
| 9598 | | astgen.advanceSourceCursor(tree.source, lbrace_start); |
| 9599 | | const lbrace_line = @intCast(u32, astgen.source_line); |
| 9600 | | const lbrace_column = @intCast(u32, astgen.source_column); |
| 9601 | | |
| 9602 | 9605 | astgen.advanceSourceCursor(tree.source, rbrace_start); |
| 9603 | 9606 | const rbrace_line = @intCast(u32, astgen.source_line); |
| 9604 | 9607 | const rbrace_column = @intCast(u32, astgen.source_column); |
| 9605 | 9608 | |
| 9606 | | const columns = lbrace_column | (rbrace_column << 16); |
| 9607 | | src_locs_buffer[0] = lbrace_line; |
| 9609 | const columns = args.lbrace_column | (rbrace_column << 16); |
| 9610 | src_locs_buffer[0] = args.lbrace_line; |
| 9608 | 9611 | src_locs_buffer[1] = rbrace_line; |
| 9609 | 9612 | src_locs_buffer[2] = columns; |
| 9610 | 9613 | src_locs = &src_locs_buffer; |
| ... | ... | @@ -10577,6 +10580,7 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void { |
| 10577 | 10580 | var i = astgen.source_offset; |
| 10578 | 10581 | var line = astgen.source_line; |
| 10579 | 10582 | var column = astgen.source_column; |
| 10583 | assert(i <= end); |
| 10580 | 10584 | while (i < end) : (i += 1) { |
| 10581 | 10585 | if (source[i] == '\n') { |
| 10582 | 10586 | line += 1; |