authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-04 14:16:33-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-10-04 14:16:33-04:00
log2454459ef5435081abe82724e873a74bd33a79af
tree2b0784f261889bb5791be2b63e39ae233ca23e74
parentc41b989ab8c553bdba8e1aab606edbe27d730a3a
parentbb3ef76434bf365ca6beb6a0709bcde251b0f771
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #9882 from mattbork/astgen-cursor

astgen.zig: keep source cursor increasing monotonically as much as possible

2 files changed, 140 insertions(+), 136 deletions(-)

src/AstGen.zig+137-133
...@@ -1683,7 +1683,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -1683,7 +1683,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
1683 const defer_scope = scope.cast(Scope.Defer).?;1683 const defer_scope = scope.cast(Scope.Defer).?;
1684 scope = defer_scope.parent;1684 scope = defer_scope.parent;
1685 const expr_node = node_datas[defer_scope.defer_node].rhs;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 .defer_error => scope = scope.cast(Scope.Defer).?.parent,1688 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1689 .top => unreachable,1689 .top => unreachable,
...@@ -1736,7 +1736,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -1736,7 +1736,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
1736 const defer_scope = scope.cast(Scope.Defer).?;1736 const defer_scope = scope.cast(Scope.Defer).?;
1737 scope = defer_scope.parent;1737 scope = defer_scope.parent;
1738 const expr_node = node_datas[defer_scope.defer_node].rhs;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 .defer_error => scope = scope.cast(Scope.Defer).?.parent,1741 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1742 .namespace => break,1742 .namespace => break,
...@@ -1922,8 +1922,8 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -1922,8 +1922,8 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
1922 .simple_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.simpleVarDecl(statement)),1922 .simple_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.simpleVarDecl(statement)),
1923 .aligned_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.alignedVarDecl(statement)),1923 .aligned_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.alignedVarDecl(statement)),
19241924
1925 .@"defer" => scope = try makeDeferScope(scope, statement, &block_arena.allocator, .defer_normal),1925 .@"defer" => scope = try makeDeferScope(gz.astgen, scope, statement, &block_arena.allocator, .defer_normal),
1926 .@"errdefer" => scope = try makeDeferScope(scope, statement, &block_arena.allocator, .defer_error),1926 .@"errdefer" => scope = try makeDeferScope(gz.astgen, scope, statement, &block_arena.allocator, .defer_error),
19271927
1928 .assign => try assign(gz, scope, statement),1928 .assign => try assign(gz, scope, statement),
19291929
...@@ -1951,6 +1951,22 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -1951,6 +1951,22 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
1951 try checkUsed(gz, parent_scope, scope);1951 try checkUsed(gz, parent_scope, scope);
1952}1952}
19531953
1954fn 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/// Returns AST source node of the thing that is noreturn if the statement is definitely `noreturn`.1970/// Returns AST source node of the thing that is noreturn if the statement is definitely `noreturn`.
1955/// Otherwise returns 0.1971/// Otherwise returns 0.
1956fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.Index {1972fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.Index {
...@@ -2333,7 +2349,7 @@ fn genDefers(...@@ -2333,7 +2349,7 @@ fn genDefers(
2333 const prev_in_defer = gz.in_defer;2349 const prev_in_defer = gz.in_defer;
2334 gz.in_defer = true;2350 gz.in_defer = true;
2335 defer gz.in_defer = prev_in_defer;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 .defer_error => {2354 .defer_error => {
2339 const defer_scope = scope.cast(Scope.Defer).?;2355 const defer_scope = scope.cast(Scope.Defer).?;
...@@ -2344,7 +2360,7 @@ fn genDefers(...@@ -2344,7 +2360,7 @@ fn genDefers(
2344 const prev_in_defer = gz.in_defer;2360 const prev_in_defer = gz.in_defer;
2345 gz.in_defer = true;2361 gz.in_defer = true;
2346 defer gz.in_defer = prev_in_defer;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 .both => |err_code| {2365 .both => |err_code| {
2350 const expr_node = node_datas[defer_scope.defer_node].rhs;2366 const expr_node = node_datas[defer_scope.defer_node].rhs;
...@@ -2365,7 +2381,7 @@ fn genDefers(...@@ -2365,7 +2381,7 @@ fn genDefers(
2365 };2381 };
2366 break :blk &local_val_scope.base;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 .normal_only => continue,2386 .normal_only => continue,
2371 }2387 }
...@@ -2409,16 +2425,27 @@ fn checkUsed(...@@ -2409,16 +2425,27 @@ fn checkUsed(
2409}2425}
24102426
2411fn makeDeferScope(2427fn makeDeferScope(
2428 astgen: *AstGen,
2412 scope: *Scope,2429 scope: *Scope,
2413 node: Ast.Node.Index,2430 node: Ast.Node.Index,
2414 block_arena: *Allocator,2431 block_arena: *Allocator,
2415 scope_tag: Scope.Tag,2432 scope_tag: Scope.Tag,
2416) InnerError!*Scope {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 const defer_scope = try block_arena.create(Scope.Defer);2439 const defer_scope = try block_arena.create(Scope.Defer);
2440 astgen.advanceSourceCursor(tree.source, node_start);
2441
2418 defer_scope.* = .{2442 defer_scope.* = .{
2419 .base = .{ .tag = scope_tag },2443 .base = .{ .tag = scope_tag },
2420 .parent = scope,2444 .parent = scope,
2421 .defer_node = node,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 return &defer_scope.base;2450 return &defer_scope.base;
2424}2451}
...@@ -3184,6 +3211,12 @@ fn fnDecl(...@@ -3184,6 +3211,12 @@ fn fnDecl(
3184 astgen.fn_block = &fn_gz;3211 astgen.fn_block = &fn_gz;
3185 defer astgen.fn_block = prev_fn_block;3212 defer astgen.fn_block = prev_fn_block;
31863213
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 _ = try expr(&fn_gz, params_scope, .none, body_node);3220 _ = try expr(&fn_gz, params_scope, .none, body_node);
3188 try checkUsed(gz, &fn_gz.base, params_scope);3221 try checkUsed(gz, &fn_gz.base, params_scope);
31893222
...@@ -3202,6 +3235,8 @@ fn fnDecl(...@@ -3202,6 +3235,8 @@ fn fnDecl(
32023235
3203 break :func try decl_gz.addFunc(.{3236 break :func try decl_gz.addFunc(.{
3204 .src_node = decl_node,3237 .src_node = decl_node,
3238 .lbrace_line = lbrace_line,
3239 .lbrace_column = lbrace_column,
3205 .param_block = block_inst,3240 .param_block = block_inst,
3206 .ret_ty = ret_gz.instructions.items,3241 .ret_ty = ret_gz.instructions.items,
3207 .ret_br = ret_br,3242 .ret_br = ret_br,
...@@ -3544,6 +3579,12 @@ fn testDecl(...@@ -3544,6 +3579,12 @@ fn testDecl(
3544 astgen.fn_block = &fn_block;3579 astgen.fn_block = &fn_block;
3545 defer astgen.fn_block = prev_fn_block;3580 defer astgen.fn_block = prev_fn_block;
35463581
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 const block_result = try expr(&fn_block, &fn_block.base, .none, body_node);3588 const block_result = try expr(&fn_block, &fn_block.base, .none, body_node);
3548 if (fn_block.instructions.items.len == 0 or !fn_block.refIsNoReturn(block_result)) {3589 if (fn_block.instructions.items.len == 0 or !fn_block.refIsNoReturn(block_result)) {
3549 // Since we are adding the return instruction here, we must handle the coercion.3590 // Since we are adding the return instruction here, we must handle the coercion.
...@@ -3553,6 +3594,8 @@ fn testDecl(...@@ -3553,6 +3594,8 @@ fn testDecl(
35533594
3554 const func_inst = try decl_block.addFunc(.{3595 const func_inst = try decl_block.addFunc(.{
3555 .src_node = node,3596 .src_node = node,
3597 .lbrace_line = lbrace_line,
3598 .lbrace_column = lbrace_column,
3556 .param_block = block_inst,3599 .param_block = block_inst,
3557 .ret_ty = &.{},3600 .ret_ty = &.{},
3558 .ret_br = 0,3601 .ret_br = 0,
...@@ -5935,10 +5978,11 @@ fn switchExpr(...@@ -5935,10 +5978,11 @@ fn switchExpr(
5935 const operand_ty_inst = try parent_gz.addUnNode(typeof_tag, operand, operand_node);5978 const operand_ty_inst = try parent_gz.addUnNode(typeof_tag, operand, operand_node);
5936 const item_rl: ResultLoc = .{ .ty = operand_ty_inst };5979 const item_rl: ResultLoc = .{ .ty = operand_ty_inst };
59375980
5938 // Contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti.5981 // These contain 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 the5982 // This is the optional else prong body.
5940 // scalar cases.5983 var special_case_payload = ArrayListUnmanaged(u32){};
5941 // At the end we will memcpy this into place.5984 defer special_case_payload.deinit(gpa);
5985 // This is all the scalar cases.
5942 var scalar_cases_payload = ArrayListUnmanaged(u32){};5986 var scalar_cases_payload = ArrayListUnmanaged(u32){};
5943 defer scalar_cases_payload.deinit(gpa);5987 defer scalar_cases_payload.deinit(gpa);
5944 // Same deal, but this is only the `extra` data for the multi cases.5988 // Same deal, but this is only the `extra` data for the multi cases.
...@@ -5956,86 +6000,10 @@ fn switchExpr(...@@ -5956,86 +6000,10 @@ fn switchExpr(
5956 var case_scope = parent_gz.makeSubBlock(&block_scope.base);6000 var case_scope = parent_gz.makeSubBlock(&block_scope.base);
5957 defer case_scope.instructions.deinit(gpa);6001 defer case_scope.instructions.deinit(gpa);
59586002
5959 // Do the else/`_` first because it goes first in the payload.6003 // In this pass we generate all the item and prong expressions.
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.
6034 var multi_case_index: u32 = 0;6004 var multi_case_index: u32 = 0;
6035 var scalar_case_index: u32 = 0;6005 var scalar_case_index: u32 = 0;
6036 for (case_nodes) |case_node| {6006 for (case_nodes) |case_node| {
6037 if (case_node == special_node)
6038 continue;
6039 const case = switch (node_tags[case_node]) {6007 const case = switch (node_tags[case_node]) {
6040 .switch_case_one => tree.switchCaseOne(case_node),6008 .switch_case_one => tree.switchCaseOne(case_node),
6041 .switch_case => tree.switchCase(case_node),6009 .switch_case => tree.switchCase(case_node),
...@@ -6045,9 +6013,10 @@ fn switchExpr(...@@ -6045,9 +6013,10 @@ fn switchExpr(
6045 // Reset the scope.6013 // Reset the scope.
6046 case_scope.instructions.shrinkRetainingCapacity(0);6014 case_scope.instructions.shrinkRetainingCapacity(0);
60476015
6048 const is_multi_case = case.ast.values.len != 1 or6016 const is_multi_case = case.ast.values.len > 1 or
6049 node_tags[case.ast.values[0]] == .switch_range;6017 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);
60506018
6019 var capture_val_scope: Scope.LocalVal = undefined;
6051 const sub_scope = blk: {6020 const sub_scope = blk: {
6052 const payload_token = case.payload_token orelse break :blk &case_scope.base;6021 const payload_token = case.payload_token orelse break :blk &case_scope.base;
6053 const ident = if (token_tags[payload_token] == .asterisk)6022 const ident = if (token_tags[payload_token] == .asterisk)
...@@ -6061,28 +6030,42 @@ fn switchExpr(...@@ -6061,28 +6030,42 @@ fn switchExpr(
6061 }6030 }
6062 break :blk &case_scope.base;6031 break :blk &case_scope.base;
6063 }6032 }
6064 const is_multi_case_bits: u2 = @boolToInt(is_multi_case);6033 const capture = if (case_node == special_node) capture: {
6065 const is_ptr_bits: u2 = @boolToInt(is_ptr);6034 const capture_tag: Zir.Inst.Tag = if (is_ptr)
6066 const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) {6035 .switch_capture_else_ref
6067 0b00 => .switch_capture,6036 else
6068 0b01 => .switch_capture_ref,6037 .switch_capture_else;
6069 0b10 => .switch_capture_multi,6038 break :capture try case_scope.add(.{
6070 0b11 => .switch_capture_multi_ref,6039 .tag = capture_tag,
6071 };6040 .data = .{ .switch_capture = .{
6072 const capture_index = if (is_multi_case) ci: {6041 .switch_inst = switch_block,
6073 multi_case_index += 1;6042 .prong_index = undefined,
6074 break :ci multi_case_index - 1;6043 } },
6075 } else ci: {6044 });
6076 scalar_case_index += 1;6045 } else capture: {
6077 break :ci scalar_case_index - 1;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 const capture_name = try astgen.identAsString(ident);6069 const capture_name = try astgen.identAsString(ident);
6087 capture_val_scope = .{6070 capture_val_scope = .{
6088 .parent = &case_scope.base,6071 .parent = &case_scope.base,
...@@ -6134,6 +6117,17 @@ fn switchExpr(...@@ -6134,6 +6117,17 @@ fn switchExpr(
6134 multi_cases_payload.items[header_index + 1] = ranges_len;6117 multi_cases_payload.items[header_index + 1] = ranges_len;
6135 multi_cases_payload.items[header_index + 2] = @intCast(u32, case_scope.instructions.items.len);6118 multi_cases_payload.items[header_index + 2] = @intCast(u32, case_scope.instructions.items.len);
6136 try multi_cases_payload.appendSlice(gpa, case_scope.instructions.items);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 } else {6131 } else {
6138 const item_node = case.ast.values[0];6132 const item_node = case.ast.values[0];
6139 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);6133 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);
...@@ -6143,7 +6137,7 @@ fn switchExpr(...@@ -6143,7 +6137,7 @@ fn switchExpr(
6143 block_scope.break_count += 1;6137 block_scope.break_count += 1;
6144 _ = try case_scope.addBreak(.@"break", switch_block, case_result);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 case_scope.instructions.items.len);6141 case_scope.instructions.items.len);
6148 scalar_cases_payload.appendAssumeCapacity(@enumToInt(item_inst));6142 scalar_cases_payload.appendAssumeCapacity(@enumToInt(item_inst));
6149 scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len));6143 scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len));
...@@ -6180,8 +6174,17 @@ fn switchExpr(...@@ -6180,8 +6174,17 @@ fn switchExpr(
6180 const payload_index = astgen.extra.items.len;6174 const payload_index = astgen.extra.items.len;
6181 const zir_datas = astgen.instructions.items(.data);6175 const zir_datas = astgen.instructions.items(.data);
6182 zir_datas[switch_block].pl_node.payload_index = @intCast(u32, payload_index);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 multi_cases_payload.items.len);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 const strat = rl.strategy(&block_scope);6188 const strat = rl.strategy(&block_scope);
6186 switch (strat.tag) {6189 switch (strat.tag) {
6187 .break_operand => {6190 .break_operand => {
...@@ -6189,6 +6192,7 @@ fn switchExpr(...@@ -6189,6 +6192,7 @@ fn switchExpr(
6189 // `elide_store_to_block_ptr_instructions` will either be true,6192 // `elide_store_to_block_ptr_instructions` will either be true,
6190 // or all prongs are noreturn.6193 // or all prongs are noreturn.
6191 if (!strat.elide_store_to_block_ptr_instructions) {6194 if (!strat.elide_store_to_block_ptr_instructions) {
6195 astgen.extra.appendSliceAssumeCapacity(special_case_payload.items);
6192 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items);6196 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items);
6193 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items);6197 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items);
6194 return indexToRef(switch_block);6198 return indexToRef(switch_block);
...@@ -6204,32 +6208,30 @@ fn switchExpr(...@@ -6204,32 +6208,30 @@ fn switchExpr(
6204 // it as the break operand.6208 // it as the break operand.
62056209
6206 var extra_index: usize = 0;6210 var extra_index: usize = 0;
6207 extra_index += 2;
6208 extra_index += @boolToInt(multi_cases_len != 0);
6209 if (special_prong != .none) special_prong: {6211 if (special_prong != .none) special_prong: {
6210 const body_len_index = extra_index;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 extra_index += 1;6214 extra_index += 1;
6213 if (body_len < 2) {6215 if (body_len < 2) {
6214 extra_index += body_len;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 break :special_prong;6218 break :special_prong;
6217 }6219 }
6218 extra_index += body_len - 2;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 if (zir_tags[store_inst] != .store_to_block_ptr or6222 if (zir_tags[store_inst] != .store_to_block_ptr or
6221 zir_datas[store_inst].bin.lhs != block_scope.rl_ptr)6223 zir_datas[store_inst].bin.lhs != block_scope.rl_ptr)
6222 {6224 {
6223 extra_index += 2;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 break :special_prong;6227 break :special_prong;
6226 }6228 }
6227 assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr);6229 assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr);
6228 if (block_scope.rl_ty_inst != .none) {6230 if (block_scope.rl_ty_inst != .none) {
6229 extra_index += 1;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 extra_index += 1;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 zir_tags[store_inst] = .as;6235 zir_tags[store_inst] = .as;
6234 zir_datas[store_inst].bin = .{6236 zir_datas[store_inst].bin = .{
6235 .lhs = block_scope.rl_ty_inst,6237 .lhs = block_scope.rl_ty_inst,
...@@ -6237,15 +6239,16 @@ fn switchExpr(...@@ -6237,15 +6239,16 @@ fn switchExpr(
6237 };6239 };
6238 zir_datas[break_inst].@"break".operand = indexToRef(store_inst);6240 zir_datas[break_inst].@"break".operand = indexToRef(store_inst);
6239 } else {6241 } else {
6240 scalar_cases_payload.items[body_len_index] -= 1;6242 special_case_payload.items[body_len_index] -= 1;
6241 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]);6243 astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]);
6242 extra_index += 1;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 extra_index += 1;6246 extra_index += 1;
6245 }6247 }
6246 } else {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 var scalar_i: u32 = 0;6252 var scalar_i: u32 = 0;
6250 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {6253 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
6251 const start_index = extra_index;6254 const start_index = extra_index;
...@@ -6342,6 +6345,7 @@ fn switchExpr(...@@ -6342,6 +6345,7 @@ fn switchExpr(
6342 },6345 },
6343 .break_void => {6346 .break_void => {
6344 assert(!strat.elide_store_to_block_ptr_instructions);6347 assert(!strat.elide_store_to_block_ptr_instructions);
6348 astgen.extra.appendSliceAssumeCapacity(special_case_payload.items);
6345 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items);6349 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items);
6346 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items);6350 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items);
6347 // Modify all the terminating instruction tags to become `break` variants.6351 // Modify all the terminating instruction tags to become `break` variants.
...@@ -9282,6 +9286,9 @@ const Scope = struct {...@@ -9282,6 +9286,9 @@ const Scope = struct {
9282 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`, `Namespace`.9286 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`, `Namespace`.
9283 parent: *Scope,9287 parent: *Scope,
9284 defer_node: Ast.Node.Index,9288 defer_node: Ast.Node.Index,
9289 source_offset: u32,
9290 source_line: u32,
9291 source_column: u32,
9285 };9292 };
92869293
9287 /// Represents a global scope that has any number of declarations in it.9294 /// Represents a global scope that has any number of declarations in it.
...@@ -9563,6 +9570,8 @@ const GenZir = struct {...@@ -9563,6 +9570,8 @@ const GenZir = struct {
95639570
9564 fn addFunc(gz: *GenZir, args: struct {9571 fn addFunc(gz: *GenZir, args: struct {
9565 src_node: Ast.Node.Index,9572 src_node: Ast.Node.Index,
9573 lbrace_line: u32 = 0,
9574 lbrace_column: u32 = 0,
9566 body: []const Zir.Inst.Index,9575 body: []const Zir.Inst.Index,
9567 param_block: Zir.Inst.Index,9576 param_block: Zir.Inst.Index,
9568 ret_ty: []const Zir.Inst.Index,9577 ret_ty: []const Zir.Inst.Index,
...@@ -9592,19 +9601,13 @@ const GenZir = struct {...@@ -9592,19 +9601,13 @@ const GenZir = struct {
9592 const fn_decl = args.src_node;9601 const fn_decl = args.src_node;
9593 assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl);9602 assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl);
9594 const block = node_datas[fn_decl].rhs;9603 const block = node_datas[fn_decl].rhs;
9595 const lbrace_start = token_starts[tree.firstToken(block)];
9596 const rbrace_start = token_starts[tree.lastToken(block)];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 astgen.advanceSourceCursor(tree.source, rbrace_start);9605 astgen.advanceSourceCursor(tree.source, rbrace_start);
9603 const rbrace_line = @intCast(u32, astgen.source_line);9606 const rbrace_line = @intCast(u32, astgen.source_line);
9604 const rbrace_column = @intCast(u32, astgen.source_column);9607 const rbrace_column = @intCast(u32, astgen.source_column);
96059608
9606 const columns = lbrace_column | (rbrace_column << 16);9609 const columns = args.lbrace_column | (rbrace_column << 16);
9607 src_locs_buffer[0] = lbrace_line;9610 src_locs_buffer[0] = args.lbrace_line;
9608 src_locs_buffer[1] = rbrace_line;9611 src_locs_buffer[1] = rbrace_line;
9609 src_locs_buffer[2] = columns;9612 src_locs_buffer[2] = columns;
9610 src_locs = &src_locs_buffer;9613 src_locs = &src_locs_buffer;
...@@ -10577,6 +10580,7 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void {...@@ -10577,6 +10580,7 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void {
10577 var i = astgen.source_offset;10580 var i = astgen.source_offset;
10578 var line = astgen.source_line;10581 var line = astgen.source_line;
10579 var column = astgen.source_column;10582 var column = astgen.source_column;
10583 assert(i <= end);
10580 while (i < end) : (i += 1) {10584 while (i < end) : (i += 1) {
10581 if (source[i] == '\n') {10585 if (source[i] == '\n') {
10582 line += 1;10586 line += 1;
src/print_zir.zig+3-3
...@@ -1913,8 +1913,8 @@ const Writer = struct {...@@ -1913,8 +1913,8 @@ const Writer = struct {
1913 try stream.writeAll(") ");1913 try stream.writeAll(") ");
1914 if (body.len != 0) {1914 if (body.len != 0) {
1915 try stream.print("(lbrace={d}:{d},rbrace={d}:{d}) ", .{1915 try stream.print("(lbrace={d}:{d},rbrace={d}:{d}) ", .{
1916 src_locs.lbrace_line, @truncate(u16, src_locs.columns),1916 src_locs.lbrace_line + 1, @truncate(u16, src_locs.columns) + 1,
1917 src_locs.rbrace_line, @truncate(u16, src_locs.columns >> 16),1917 src_locs.rbrace_line + 1, @truncate(u16, src_locs.columns >> 16) + 1,
1918 });1918 });
1919 }1919 }
1920 try self.writeSrc(stream, src);1920 try self.writeSrc(stream, src);
...@@ -1928,7 +1928,7 @@ const Writer = struct {...@@ -1928,7 +1928,7 @@ const Writer = struct {
19281928
1929 fn writeDbgStmt(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1929 fn writeDbgStmt(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
1930 const inst_data = self.code.instructions.items(.data)[inst].dbg_stmt;1930 const inst_data = self.code.instructions.items(.data)[inst].dbg_stmt;
1931 try stream.print("{d}, {d})", .{ inst_data.line, inst_data.column });1931 try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 });
1932 }1932 }
19331933
1934 fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void {1934 fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void {