authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-10 05:26:59-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-06-10 05:26:59-04:00
logfcfeafe99a3ecc694a3475735c81a0d75b6da6d0
tree55eefb8b42d39c7ead40f9a92e5c494c9b2226b1
parent5816d3eaec3f3bb04e70c89aa402ba9e0e5e7b2c
parent436aafd3e2ef1a8f5998b974a9791b59939f57ad
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11819 from ziglang/std.debug.Trace

introduce std.debug.Trace and use it to debug a LazySrcLoc in stage2 that is set to a bogus value

17 files changed, 365 insertions(+), 136 deletions(-)

build.zig+3
......@@ -131,6 +131,7 @@ pub fn build(b: *Builder) !void {
131131 const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse enable_llvm;
132132 const strip = b.option(bool, "strip", "Omit debug information") orelse false;
133133 const use_zig0 = b.option(bool, "zig0", "Bootstrap using zig0") orelse false;
134 const value_tracing = b.option(bool, "value-tracing", "Enable extra state tracking to help troubleshoot bugs in the compiler (using the std.debug.Trace API)") orelse false;
134135
135136 const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse blk: {
136137 if (strip) break :blk @as(u32, 0);
......@@ -353,6 +354,7 @@ pub fn build(b: *Builder) !void {
353354 exe_options.addOption(bool, "enable_tracy", tracy != null);
354355 exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);
355356 exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation);
357 exe_options.addOption(bool, "value_tracing", value_tracing);
356358 exe_options.addOption(bool, "is_stage1", is_stage1);
357359 exe_options.addOption(bool, "omit_stage2", omit_stage2);
358360 if (tracy) |tracy_path| {
......@@ -402,6 +404,7 @@ pub fn build(b: *Builder) !void {
402404 test_cases_options.addOption(bool, "enable_rosetta", b.enable_rosetta);
403405 test_cases_options.addOption(bool, "enable_darling", b.enable_darling);
404406 test_cases_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2);
407 test_cases_options.addOption(bool, "value_tracing", value_tracing);
405408 test_cases_options.addOption(?[]const u8, "glibc_runtimes_dir", b.glibc_runtimes_dir);
406409 test_cases_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version));
407410 test_cases_options.addOption(std.SemanticVersion, "semver", semver);
ci/azure/build.zig+2
......@@ -99,6 +99,7 @@ pub fn build(b: *Builder) !void {
9999 const force_gpa = b.option(bool, "force-gpa", "Force the compiler to use GeneralPurposeAllocator") orelse false;
100100 const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse enable_llvm;
101101 const strip = b.option(bool, "strip", "Omit debug information") orelse false;
102 const value_tracing = b.option(bool, "value-tracing", "Enable extra state tracking to help troubleshoot bugs in the compiler (using the std.debug.Trace API)") orelse false;
102103
103104 const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse blk: {
104105 if (strip) break :blk @as(u32, 0);
......@@ -303,6 +304,7 @@ pub fn build(b: *Builder) !void {
303304 exe_options.addOption(bool, "enable_tracy", tracy != null);
304305 exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);
305306 exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation);
307 exe_options.addOption(bool, "value_tracing", value_tracing);
306308 exe_options.addOption(bool, "is_stage1", is_stage1);
307309 exe_options.addOption(bool, "omit_stage2", omit_stage2);
308310 if (tracy) |tracy_path| {
lib/std/debug.zig+82
......@@ -1943,3 +1943,85 @@ test "#4353: std.debug should manage resources correctly" {
19431943noinline fn showMyTrace() usize {
19441944 return @returnAddress();
19451945}
1946
1947/// This API helps you track where a value originated and where it was mutated,
1948/// or any other points of interest.
1949/// In debug mode, it adds a small size penalty (104 bytes on 64-bit architectures)
1950/// to the aggregate that you add it to.
1951/// In release mode, it is size 0 and all methods are no-ops.
1952/// This is a pre-made type with default settings.
1953/// For more advanced usage, see `ConfigurableTrace`.
1954pub const Trace = ConfigurableTrace(2, 4, builtin.mode == .Debug);
1955
1956pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize, comptime enabled: bool) type {
1957 return struct {
1958 addrs: [actual_size][stack_frame_count]usize = undefined,
1959 notes: [actual_size][]const u8 = undefined,
1960 index: Index = 0,
1961
1962 const actual_size = if (enabled) size else 0;
1963 const Index = if (enabled) usize else u0;
1964
1965 pub const enabled = enabled;
1966
1967 pub const add = if (enabled) addNoInline else addNoOp;
1968
1969 pub noinline fn addNoInline(t: *@This(), note: []const u8) void {
1970 comptime assert(enabled);
1971 return addAddr(t, @returnAddress(), note);
1972 }
1973
1974 pub inline fn addNoOp(t: *@This(), note: []const u8) void {
1975 _ = t;
1976 _ = note;
1977 comptime assert(!enabled);
1978 }
1979
1980 pub fn addAddr(t: *@This(), addr: usize, note: []const u8) void {
1981 if (!enabled) return;
1982
1983 if (t.index < size) {
1984 t.notes[t.index] = note;
1985 t.addrs[t.index] = [1]usize{0} ** stack_frame_count;
1986 var stack_trace: std.builtin.StackTrace = .{
1987 .index = 0,
1988 .instruction_addresses = &t.addrs[t.index],
1989 };
1990 captureStackTrace(addr, &stack_trace);
1991 }
1992 // Keep counting even if the end is reached so that the
1993 // user can find out how much more size they need.
1994 t.index += 1;
1995 }
1996
1997 pub fn dump(t: @This()) void {
1998 if (!enabled) return;
1999
2000 const tty_config = detectTTYConfig();
2001 const stderr = io.getStdErr().writer();
2002 const end = @maximum(t.index, size);
2003 const debug_info = getSelfDebugInfo() catch |err| {
2004 stderr.print(
2005 "Unable to dump stack trace: Unable to open debug info: {s}\n",
2006 .{@errorName(err)},
2007 ) catch return;
2008 return;
2009 };
2010 for (t.addrs[0..end]) |frames_array, i| {
2011 stderr.print("{s}:\n", .{t.notes[i]}) catch return;
2012 var frames_array_mutable = frames_array;
2013 const frames = mem.sliceTo(frames_array_mutable[0..], 0);
2014 const stack_trace: std.builtin.StackTrace = .{
2015 .index = frames.len,
2016 .instruction_addresses = frames,
2017 };
2018 writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, tty_config) catch continue;
2019 }
2020 if (t.index > end) {
2021 stderr.print("{d} more traces not shown; consider increasing trace size\n", .{
2022 t.index - end,
2023 }) catch return;
2024 }
2025 }
2026 };
2027}
src/Compilation.zig+95-6
......@@ -338,6 +338,8 @@ pub const AllErrors = struct {
338338 line: u32,
339339 column: u32,
340340 byte_offset: u32,
341 /// Usually one, but incremented for redundant messages.
342 count: u32 = 1,
341343 /// Does not include the trailing newline.
342344 source_line: ?[]const u8,
343345 notes: []Message = &.{},
......@@ -345,8 +347,21 @@ pub const AllErrors = struct {
345347 plain: struct {
346348 msg: []const u8,
347349 notes: []Message = &.{},
350 /// Usually one, but incremented for redundant messages.
351 count: u32 = 1,
348352 },
349353
354 pub fn incrementCount(msg: *Message) void {
355 switch (msg.*) {
356 .src => |*src| {
357 src.count += 1;
358 },
359 .plain => |*plain| {
360 plain.count += 1;
361 },
362 }
363 }
364
350365 pub fn renderToStdErr(msg: Message, ttyconf: std.debug.TTY.Config) void {
351366 std.debug.getStderrMutex().lock();
352367 defer std.debug.getStderrMutex().unlock();
......@@ -376,7 +391,13 @@ pub const AllErrors = struct {
376391 try stderr.writeAll(kind);
377392 ttyconf.setColor(stderr, .Reset);
378393 ttyconf.setColor(stderr, .Bold);
379 try stderr.print(" {s}\n", .{src.msg});
394 if (src.count == 1) {
395 try stderr.print(" {s}\n", .{src.msg});
396 } else {
397 try stderr.print(" {s}", .{src.msg});
398 ttyconf.setColor(stderr, .Dim);
399 try stderr.print(" ({d} times)\n", .{src.count});
400 }
380401 ttyconf.setColor(stderr, .Reset);
381402 if (ttyconf != .no_color) {
382403 if (src.source_line) |line| {
......@@ -400,7 +421,13 @@ pub const AllErrors = struct {
400421 try stderr.writeByteNTimes(' ', indent);
401422 try stderr.writeAll(kind);
402423 ttyconf.setColor(stderr, .Reset);
403 try stderr.print(" {s}\n", .{plain.msg});
424 if (plain.count == 1) {
425 try stderr.print(" {s}\n", .{plain.msg});
426 } else {
427 try stderr.print(" {s}", .{plain.msg});
428 ttyconf.setColor(stderr, .Dim);
429 try stderr.print(" ({d} times)\n", .{plain.count});
430 }
404431 ttyconf.setColor(stderr, .Reset);
405432 for (plain.notes) |note| {
406433 try note.renderToStdErrInner(ttyconf, stderr_file, "error:", .Red, indent + 4);
......@@ -408,6 +435,50 @@ pub const AllErrors = struct {
408435 },
409436 }
410437 }
438
439 pub const HashContext = struct {
440 pub fn hash(ctx: HashContext, key: *Message) u64 {
441 _ = ctx;
442 var hasher = std.hash.Wyhash.init(0);
443
444 switch (key.*) {
445 .src => |src| {
446 hasher.update(src.msg);
447 hasher.update(src.src_path);
448 std.hash.autoHash(&hasher, src.line);
449 std.hash.autoHash(&hasher, src.column);
450 std.hash.autoHash(&hasher, src.byte_offset);
451 },
452 .plain => |plain| {
453 hasher.update(plain.msg);
454 },
455 }
456
457 return hasher.final();
458 }
459
460 pub fn eql(ctx: HashContext, a: *Message, b: *Message) bool {
461 _ = ctx;
462 switch (a.*) {
463 .src => |a_src| switch (b.*) {
464 .src => |b_src| {
465 return mem.eql(u8, a_src.msg, b_src.msg) and
466 mem.eql(u8, a_src.src_path, b_src.src_path) and
467 a_src.line == b_src.line and
468 a_src.column == b_src.column and
469 a_src.byte_offset == b_src.byte_offset;
470 },
471 .plain => return false,
472 },
473 .plain => |a_plain| switch (b.*) {
474 .src => return false,
475 .plain => |b_plain| {
476 return mem.eql(u8, a_plain.msg, b_plain.msg);
477 },
478 },
479 }
480 }
481 };
411482 };
412483
413484 pub fn deinit(self: *AllErrors, gpa: Allocator) void {
......@@ -421,13 +492,25 @@ pub const AllErrors = struct {
421492 module_err_msg: Module.ErrorMsg,
422493 ) !void {
423494 const allocator = arena.allocator();
424 const notes = try allocator.alloc(Message, module_err_msg.notes.len);
425 for (notes) |*note, i| {
426 const module_note = module_err_msg.notes[i];
495
496 const notes_buf = try allocator.alloc(Message, module_err_msg.notes.len);
497 var note_i: usize = 0;
498
499 // De-duplicate error notes. The main use case in mind for this is
500 // too many "note: called from here" notes when eval branch quota is reached.
501 var seen_notes = std.HashMap(
502 *Message,
503 void,
504 Message.HashContext,
505 std.hash_map.default_max_load_percentage,
506 ).init(allocator);
507
508 for (module_err_msg.notes) |module_note| {
427509 const source = try module_note.src_loc.file_scope.getSource(module.gpa);
428510 const byte_offset = try module_note.src_loc.byteOffset(module.gpa);
429511 const loc = std.zig.findLineColumn(source.bytes, byte_offset);
430512 const file_path = try module_note.src_loc.file_scope.fullPath(allocator);
513 const note = &notes_buf[note_i];
431514 note.* = .{
432515 .src = .{
433516 .src_path = file_path,
......@@ -438,6 +521,12 @@ pub const AllErrors = struct {
438521 .source_line = try allocator.dupe(u8, loc.source_line),
439522 },
440523 };
524 const gop = try seen_notes.getOrPut(note);
525 if (gop.found_existing) {
526 gop.key_ptr.*.incrementCount();
527 } else {
528 note_i += 1;
529 }
441530 }
442531 if (module_err_msg.src_loc.lazy == .entire_file) {
443532 try errors.append(.{
......@@ -458,7 +547,7 @@ pub const AllErrors = struct {
458547 .byte_offset = byte_offset,
459548 .line = @intCast(u32, loc.line),
460549 .column = @intCast(u32, loc.column),
461 .notes = notes,
550 .notes = notes_buf[0..note_i],
462551 .source_line = try allocator.dupe(u8, loc.source_line),
463552 },
464553 });
src/Module.zig+61-30
......@@ -659,7 +659,7 @@ pub const Decl = struct {
659659 }
660660
661661 pub fn nodeSrcLoc(decl: Decl, node_index: Ast.Node.Index) LazySrcLoc {
662 return .{ .node_offset = decl.nodeIndexToRelative(node_index) };
662 return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(node_index));
663663 }
664664
665665 pub fn srcLoc(decl: Decl) SrcLoc {
......@@ -670,7 +670,7 @@ pub const Decl = struct {
670670 return .{
671671 .file_scope = decl.getFileScope(),
672672 .parent_decl_node = decl.src_node,
673 .lazy = .{ .node_offset = node_offset },
673 .lazy = LazySrcLoc.nodeOffset(node_offset),
674674 };
675675 }
676676
......@@ -861,7 +861,7 @@ pub const ErrorSet = struct {
861861 return .{
862862 .file_scope = owner_decl.getFileScope(),
863863 .parent_decl_node = owner_decl.src_node,
864 .lazy = .{ .node_offset = self.node_offset },
864 .lazy = LazySrcLoc.nodeOffset(self.node_offset),
865865 };
866866 }
867867
......@@ -947,7 +947,7 @@ pub const Struct = struct {
947947 return .{
948948 .file_scope = owner_decl.getFileScope(),
949949 .parent_decl_node = owner_decl.src_node,
950 .lazy = .{ .node_offset = s.node_offset },
950 .lazy = LazySrcLoc.nodeOffset(s.node_offset),
951951 };
952952 }
953953
......@@ -1066,7 +1066,7 @@ pub const EnumSimple = struct {
10661066 return .{
10671067 .file_scope = owner_decl.getFileScope(),
10681068 .parent_decl_node = owner_decl.src_node,
1069 .lazy = .{ .node_offset = self.node_offset },
1069 .lazy = LazySrcLoc.nodeOffset(self.node_offset),
10701070 };
10711071 }
10721072};
......@@ -1097,7 +1097,7 @@ pub const EnumNumbered = struct {
10971097 return .{
10981098 .file_scope = owner_decl.getFileScope(),
10991099 .parent_decl_node = owner_decl.src_node,
1100 .lazy = .{ .node_offset = self.node_offset },
1100 .lazy = LazySrcLoc.nodeOffset(self.node_offset),
11011101 };
11021102 }
11031103};
......@@ -1131,7 +1131,7 @@ pub const EnumFull = struct {
11311131 return .{
11321132 .file_scope = owner_decl.getFileScope(),
11331133 .parent_decl_node = owner_decl.src_node,
1134 .lazy = .{ .node_offset = self.node_offset },
1134 .lazy = LazySrcLoc.nodeOffset(self.node_offset),
11351135 };
11361136 }
11371137};
......@@ -1197,7 +1197,7 @@ pub const Union = struct {
11971197 return .{
11981198 .file_scope = owner_decl.getFileScope(),
11991199 .parent_decl_node = owner_decl.src_node,
1200 .lazy = .{ .node_offset = self.node_offset },
1200 .lazy = LazySrcLoc.nodeOffset(self.node_offset),
12011201 };
12021202 }
12031203
......@@ -1404,7 +1404,7 @@ pub const Opaque = struct {
14041404 return .{
14051405 .file_scope = owner_decl.getFileScope(),
14061406 .parent_decl_node = owner_decl.src_node,
1407 .lazy = .{ .node_offset = self.node_offset },
1407 .lazy = LazySrcLoc.nodeOffset(self.node_offset),
14081408 };
14091409 }
14101410
......@@ -2105,7 +2105,17 @@ pub const SrcLoc = struct {
21052105 const token_starts = tree.tokens.items(.start);
21062106 return token_starts[tok_index];
21072107 },
2108 .node_offset, .node_offset_bin_op => |node_off| {
2108 .node_offset => |traced_off| {
2109 const node_off = traced_off.x;
2110 const tree = try src_loc.file_scope.getTree(gpa);
2111 const node = src_loc.declRelativeToNodeIndex(node_off);
2112 assert(src_loc.file_scope.tree_loaded);
2113 const main_tokens = tree.nodes.items(.main_token);
2114 const tok_index = main_tokens[node];
2115 const token_starts = tree.tokens.items(.start);
2116 return token_starts[tok_index];
2117 },
2118 .node_offset_bin_op => |node_off| {
21092119 const tree = try src_loc.file_scope.getTree(gpa);
21102120 const node = src_loc.declRelativeToNodeIndex(node_off);
21112121 assert(src_loc.file_scope.tree_loaded);
......@@ -2515,6 +2525,15 @@ pub const SrcLoc = struct {
25152525 }
25162526};
25172527
2528/// This wraps a simple integer in debug builds so that later on we can find out
2529/// where in semantic analysis the value got set.
2530const TracedOffset = struct {
2531 x: i32,
2532 trace: std.debug.Trace = .{},
2533
2534 const want_tracing = build_options.value_tracing;
2535};
2536
25182537/// Resolving a source location into a byte offset may require doing work
25192538/// that we would rather not do unless the error actually occurs.
25202539/// Therefore we need a data structure that contains the information necessary
......@@ -2555,7 +2574,7 @@ pub const LazySrcLoc = union(enum) {
25552574 /// The source location points to an AST node, which is this value offset
25562575 /// from its containing Decl node AST index.
25572576 /// The Decl is determined contextually.
2558 node_offset: i32,
2577 node_offset: TracedOffset,
25592578 /// The source location points to two tokens left of the first token of an AST node,
25602579 /// which is this value offset from its containing Decl node AST index.
25612580 /// The Decl is determined contextually.
......@@ -2705,6 +2724,18 @@ pub const LazySrcLoc = union(enum) {
27052724 /// The Decl is determined contextually.
27062725 node_offset_array_type_elem: i32,
27072726
2727 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
2728
2729 noinline fn nodeOffsetDebug(node_offset: i32) LazySrcLoc {
2730 var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } };
2731 result.node_offset.trace.addAddr(@returnAddress(), "init");
2732 return result;
2733 }
2734
2735 fn nodeOffsetRelease(node_offset: i32) LazySrcLoc {
2736 return .{ .node_offset = .{ .x = node_offset } };
2737 }
2738
27082739 /// Upgrade to a `SrcLoc` based on the `Decl` provided.
27092740 pub fn toSrcLoc(lazy: LazySrcLoc, decl: *Decl) SrcLoc {
27102741 return switch (lazy) {
......@@ -4014,7 +4045,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
40144045 const body = zir.extra[extra.end..][0..extra.data.body_len];
40154046 const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;
40164047 try wip_captures.finalize();
4017 const src: LazySrcLoc = .{ .node_offset = 0 };
4048 const src = LazySrcLoc.nodeOffset(0);
40184049 const decl_tv = try sema.resolveInstValue(&block_scope, src, result_ref);
40194050 const decl_align: u32 = blk: {
40204051 const align_ref = decl.zirAlignRef();
......@@ -5044,7 +5075,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
50445075 // Crucially, this happens *after* we set the function state to success above,
50455076 // so that dependencies on the function body will now be satisfied rather than
50465077 // result in circular dependency errors.
5047 const src: LazySrcLoc = .{ .node_offset = 0 };
5078 const src = LazySrcLoc.nodeOffset(0);
50485079 sema.resolveFnTypes(&inner_block, src, fn_ty_info) catch |err| switch (err) {
50495080 error.NeededSourceLocation => unreachable,
50505081 error.GenericPoison => unreachable,
......@@ -5338,7 +5369,7 @@ pub const SwitchProngSrc = union(enum) {
53385369 log.warn("unable to load {s}: {s}", .{
53395370 decl.getFileScope().sub_file_path, @errorName(err),
53405371 });
5341 return LazySrcLoc{ .node_offset = 0 };
5372 return LazySrcLoc.nodeOffset(0);
53425373 };
53435374 const switch_node = decl.relativeToNodeIndex(switch_node_offset);
53445375 const main_tokens = tree.nodes.items(.main_token);
......@@ -5367,17 +5398,17 @@ pub const SwitchProngSrc = union(enum) {
53675398 node_tags[case.ast.values[0]] == .switch_range;
53685399
53695400 switch (prong_src) {
5370 .scalar => |i| if (!is_multi and i == scalar_i) return LazySrcLoc{
5371 .node_offset = decl.nodeIndexToRelative(case.ast.values[0]),
5372 },
5401 .scalar => |i| if (!is_multi and i == scalar_i) return LazySrcLoc.nodeOffset(
5402 decl.nodeIndexToRelative(case.ast.values[0]),
5403 ),
53735404 .multi => |s| if (is_multi and s.prong == multi_i) {
53745405 var item_i: u32 = 0;
53755406 for (case.ast.values) |item_node| {
53765407 if (node_tags[item_node] == .switch_range) continue;
53775408
5378 if (item_i == s.item) return LazySrcLoc{
5379 .node_offset = decl.nodeIndexToRelative(item_node),
5380 };
5409 if (item_i == s.item) return LazySrcLoc.nodeOffset(
5410 decl.nodeIndexToRelative(item_node),
5411 );
53815412 item_i += 1;
53825413 } else unreachable;
53835414 },
......@@ -5387,15 +5418,15 @@ pub const SwitchProngSrc = union(enum) {
53875418 if (node_tags[range] != .switch_range) continue;
53885419
53895420 if (range_i == s.item) switch (range_expand) {
5390 .none => return LazySrcLoc{
5391 .node_offset = decl.nodeIndexToRelative(range),
5392 },
5393 .first => return LazySrcLoc{
5394 .node_offset = decl.nodeIndexToRelative(node_datas[range].lhs),
5395 },
5396 .last => return LazySrcLoc{
5397 .node_offset = decl.nodeIndexToRelative(node_datas[range].rhs),
5398 },
5421 .none => return LazySrcLoc.nodeOffset(
5422 decl.nodeIndexToRelative(range),
5423 ),
5424 .first => return LazySrcLoc.nodeOffset(
5425 decl.nodeIndexToRelative(node_datas[range].lhs),
5426 ),
5427 .last => return LazySrcLoc.nodeOffset(
5428 decl.nodeIndexToRelative(node_datas[range].rhs),
5429 ),
53995430 };
54005431 range_i += 1;
54015432 } else unreachable;
......@@ -5450,7 +5481,7 @@ pub const PeerTypeCandidateSrc = union(enum) {
54505481 log.warn("unable to load {s}: {s}", .{
54515482 decl.getFileScope().sub_file_path, @errorName(err),
54525483 });
5453 return LazySrcLoc{ .node_offset = 0 };
5484 return LazySrcLoc.nodeOffset(0);
54545485 };
54555486 const node = decl.relativeToNodeIndex(node_offset);
54565487 const node_datas = tree.nodes.items(.data);
src/Sema.zig+45-46
......@@ -1154,7 +1154,7 @@ fn analyzeBodyInner(
11541154 .repeat => {
11551155 if (block.is_comptime) {
11561156 // Send comptime control flow back to the beginning of this block.
1157 const src: LazySrcLoc = .{ .node_offset = datas[inst].node };
1157 const src = LazySrcLoc.nodeOffset(datas[inst].node);
11581158 try sema.emitBackwardBranch(block, src);
11591159 if (wip_captures.scope.captures.count() != orig_captures) {
11601160 try wip_captures.reset(parent_capture_scope);
......@@ -1165,14 +1165,14 @@ fn analyzeBodyInner(
11651165 continue;
11661166 } else {
11671167 const src_node = sema.code.instructions.items(.data)[inst].node;
1168 const src: LazySrcLoc = .{ .node_offset = src_node };
1168 const src = LazySrcLoc.nodeOffset(src_node);
11691169 try sema.requireRuntimeBlock(block, src);
11701170 break always_noreturn;
11711171 }
11721172 },
11731173 .repeat_inline => {
11741174 // Send comptime control flow back to the beginning of this block.
1175 const src: LazySrcLoc = .{ .node_offset = datas[inst].node };
1175 const src = LazySrcLoc.nodeOffset(datas[inst].node);
11761176 try sema.emitBackwardBranch(block, src);
11771177 if (wip_captures.scope.captures.count() != orig_captures) {
11781178 try wip_captures.reset(parent_capture_scope);
......@@ -2087,7 +2087,7 @@ fn zirStructDecl(
20872087 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
20882088 const src: LazySrcLoc = if (small.has_src_node) blk: {
20892089 const node_offset = @bitCast(i32, sema.code.extra[extended.operand]);
2090 break :blk .{ .node_offset = node_offset };
2090 break :blk LazySrcLoc.nodeOffset(node_offset);
20912091 } else sema.src;
20922092
20932093 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
......@@ -2108,7 +2108,7 @@ fn zirStructDecl(
21082108 struct_obj.* = .{
21092109 .owner_decl = new_decl_index,
21102110 .fields = .{},
2111 .node_offset = src.node_offset,
2111 .node_offset = src.node_offset.x,
21122112 .zir_index = inst,
21132113 .layout = small.layout,
21142114 .status = .none,
......@@ -2210,7 +2210,7 @@ fn zirEnumDecl(
22102210 const src: LazySrcLoc = if (small.has_src_node) blk: {
22112211 const node_offset = @bitCast(i32, sema.code.extra[extra_index]);
22122212 extra_index += 1;
2213 break :blk .{ .node_offset = node_offset };
2213 break :blk LazySrcLoc.nodeOffset(node_offset);
22142214 } else sema.src;
22152215
22162216 const tag_type_ref = if (small.has_tag_type) blk: {
......@@ -2263,7 +2263,7 @@ fn zirEnumDecl(
22632263 .tag_ty_inferred = true,
22642264 .fields = .{},
22652265 .values = .{},
2266 .node_offset = src.node_offset,
2266 .node_offset = src.node_offset.x,
22672267 .namespace = .{
22682268 .parent = block.namespace,
22692269 .ty = enum_ty,
......@@ -2385,8 +2385,8 @@ fn zirEnumDecl(
23852385 const gop = enum_obj.fields.getOrPutAssumeCapacity(field_name);
23862386 if (gop.found_existing) {
23872387 const tree = try sema.getAstTree(block);
2388 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset, field_i);
2389 const other_tag_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset, gop.index);
2388 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);
2389 const other_tag_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop.index);
23902390 const msg = msg: {
23912391 const msg = try sema.errMsg(block, field_src, "duplicate enum tag", .{});
23922392 errdefer msg.destroy(gpa);
......@@ -2442,7 +2442,7 @@ fn zirUnionDecl(
24422442 const src: LazySrcLoc = if (small.has_src_node) blk: {
24432443 const node_offset = @bitCast(i32, sema.code.extra[extra_index]);
24442444 extra_index += 1;
2445 break :blk .{ .node_offset = node_offset };
2445 break :blk LazySrcLoc.nodeOffset(node_offset);
24462446 } else sema.src;
24472447
24482448 extra_index += @boolToInt(small.has_tag_type);
......@@ -2480,7 +2480,7 @@ fn zirUnionDecl(
24802480 .owner_decl = new_decl_index,
24812481 .tag_ty = Type.initTag(.@"null"),
24822482 .fields = .{},
2483 .node_offset = src.node_offset,
2483 .node_offset = src.node_offset.x,
24842484 .zir_index = inst,
24852485 .layout = small.layout,
24862486 .status = .none,
......@@ -2516,7 +2516,7 @@ fn zirOpaqueDecl(
25162516 const src: LazySrcLoc = if (small.has_src_node) blk: {
25172517 const node_offset = @bitCast(i32, sema.code.extra[extra_index]);
25182518 extra_index += 1;
2519 break :blk .{ .node_offset = node_offset };
2519 break :blk LazySrcLoc.nodeOffset(node_offset);
25202520 } else sema.src;
25212521
25222522 const decls_len = if (small.has_decls_len) blk: {
......@@ -2547,7 +2547,7 @@ fn zirOpaqueDecl(
25472547
25482548 opaque_obj.* = .{
25492549 .owner_decl = new_decl_index,
2550 .node_offset = src.node_offset,
2550 .node_offset = src.node_offset.x,
25512551 .namespace = .{
25522552 .parent = block.namespace,
25532553 .ty = opaque_ty,
......@@ -2623,7 +2623,7 @@ fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
26232623 defer tracy.end();
26242624
26252625 const inst_data = sema.code.instructions.items(.data)[inst].node;
2626 const src: LazySrcLoc = .{ .node_offset = inst_data };
2626 const src = LazySrcLoc.nodeOffset(inst_data);
26272627 try sema.requireFunctionBlock(block, src);
26282628
26292629 if (block.is_comptime or try sema.typeRequiresComptime(block, src, sema.fn_ret_ty)) {
......@@ -2661,7 +2661,7 @@ fn zirRetType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
26612661 defer tracy.end();
26622662
26632663 const inst_data = sema.code.instructions.items(.data)[inst].node;
2664 const src: LazySrcLoc = .{ .node_offset = inst_data };
2664 const src = LazySrcLoc.nodeOffset(inst_data);
26652665 try sema.requireFunctionBlock(block, src);
26662666 return sema.addType(sema.fn_ret_ty);
26672667}
......@@ -2750,7 +2750,7 @@ fn zirAllocExtended(
27502750 extended: Zir.Inst.Extended.InstData,
27512751) CompileError!Air.Inst.Ref {
27522752 const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand);
2753 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
2753 const src = LazySrcLoc.nodeOffset(extra.data.src_node);
27542754 const ty_src = src; // TODO better source location
27552755 const align_src = src; // TODO better source location
27562756 const small = @bitCast(Zir.Inst.AllocExtended.Small, extended.small);
......@@ -2903,7 +2903,7 @@ fn zirAllocInferredComptime(
29032903 inferred_alloc_ty: Type,
29042904) CompileError!Air.Inst.Ref {
29052905 const src_node = sema.code.instructions.items(.data)[inst].node;
2906 const src: LazySrcLoc = .{ .node_offset = src_node };
2906 const src = LazySrcLoc.nodeOffset(src_node);
29072907 sema.src = src;
29082908 return sema.addConstant(
29092909 inferred_alloc_ty,
......@@ -2967,7 +2967,7 @@ fn zirAllocInferred(
29672967 defer tracy.end();
29682968
29692969 const src_node = sema.code.instructions.items(.data)[inst].node;
2970 const src: LazySrcLoc = .{ .node_offset = src_node };
2970 const src = LazySrcLoc.nodeOffset(src_node);
29712971 sema.src = src;
29722972
29732973 if (block.is_comptime) {
......@@ -3718,7 +3718,7 @@ fn zirValidateArrayInit(
37183718
37193719 outer: for (instrs) |elem_ptr, i| {
37203720 const elem_ptr_data = sema.code.instructions.items(.data)[elem_ptr].pl_node;
3721 const elem_src: LazySrcLoc = .{ .node_offset = elem_ptr_data.src_node };
3721 const elem_src = LazySrcLoc.nodeOffset(elem_ptr_data.src_node);
37223722
37233723 // Determine whether the value stored to this pointer is comptime-known.
37243724
......@@ -4203,7 +4203,7 @@ fn zirCompileLog(
42034203
42044204 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
42054205 const src_node = extra.data.src_node;
4206 const src: LazySrcLoc = .{ .node_offset = src_node };
4206 const src = LazySrcLoc.nodeOffset(src_node);
42074207 const args = sema.code.refSlice(extra.end, extended.small);
42084208
42094209 for (args) |arg_ref, i| {
......@@ -4707,7 +4707,7 @@ pub fn analyzeExport(
47074707fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
47084708 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
47094709 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
4710 const src: LazySrcLoc = .{ .node_offset = extra.node };
4710 const src = LazySrcLoc.nodeOffset(extra.node);
47114711 const alignment = try sema.resolveAlign(block, operand_src, extra.operand);
47124712 if (alignment > 256) {
47134713 return sema.fail(block, src, "attempt to @setAlignStack({d}); maximum is 256", .{
......@@ -5312,7 +5312,7 @@ fn analyzeCall(
53125312 delete_memoized_call_key = true;
53135313 }
53145314
5315 try sema.emitBackwardBranch(&child_block, call_src);
5315 try sema.emitBackwardBranch(block, call_src);
53165316
53175317 // Whether this call should be memoized, set to false if the call can mutate
53185318 // comptime state.
......@@ -6988,7 +6988,7 @@ fn funcCommon(
69886988 const param_types = try sema.arena.alloc(Type, block.params.items.len);
69896989 const comptime_params = try sema.arena.alloc(bool, block.params.items.len);
69906990 for (block.params.items) |param, i| {
6991 const param_src: LazySrcLoc = .{ .node_offset = src_node_offset }; // TODO better src
6991 const param_src = LazySrcLoc.nodeOffset(src_node_offset); // TODO better src
69926992 param_types[i] = param.ty;
69936993 comptime_params[i] = param.is_comptime or
69946994 try sema.typeRequiresComptime(block, param_src, param.ty);
......@@ -7378,7 +7378,7 @@ fn zirFieldCallBindNamed(sema: *Sema, block: *Block, extended: Zir.Inst.Extended
73787378 defer tracy.end();
73797379
73807380 const extra = sema.code.extraData(Zir.Inst.FieldNamedNode, extended.operand).data;
7381 const src: LazySrcLoc = .{ .node_offset = extra.node };
7381 const src = LazySrcLoc.nodeOffset(extra.node);
73827382 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
73837383 const object_ptr = try sema.resolveInst(extra.lhs);
73847384 const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name);
......@@ -10088,7 +10088,7 @@ fn zirOverflowArithmetic(
1008810088 defer tracy.end();
1008910089
1009010090 const extra = sema.code.extraData(Zir.Inst.OverflowArithmetic, extended.operand).data;
10091 const src: LazySrcLoc = .{ .node_offset = extra.node };
10091 const src = LazySrcLoc.nodeOffset(extra.node);
1009210092
1009310093 const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
1009410094 const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
......@@ -11309,7 +11309,7 @@ fn zirAsm(
1130911309 defer tracy.end();
1131011310
1131111311 const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand);
11312 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
11312 const src = LazySrcLoc.nodeOffset(extra.data.src_node);
1131311313 const ret_ty_src: LazySrcLoc = .{ .node_offset_asm_ret_ty = extra.data.src_node };
1131411314 const outputs_len = @truncate(u5, extended.small);
1131511315 const inputs_len = @truncate(u5, extended.small >> 5);
......@@ -11761,7 +11761,7 @@ fn zirThis(
1176111761 extended: Zir.Inst.Extended.InstData,
1176211762) CompileError!Air.Inst.Ref {
1176311763 const this_decl_index = block.namespace.getDeclIndex();
11764 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
11764 const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand));
1176511765 return sema.analyzeDeclVal(block, src, this_decl_index);
1176611766}
1176711767
......@@ -11815,7 +11815,7 @@ fn zirRetAddr(
1181511815 block: *Block,
1181611816 extended: Zir.Inst.Extended.InstData,
1181711817) CompileError!Air.Inst.Ref {
11818 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
11818 const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand));
1181911819 try sema.requireRuntimeBlock(block, src);
1182011820 return try block.addNoOp(.ret_addr);
1182111821}
......@@ -11825,7 +11825,7 @@ fn zirFrameAddress(
1182511825 block: *Block,
1182611826 extended: Zir.Inst.Extended.InstData,
1182711827) CompileError!Air.Inst.Ref {
11828 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
11828 const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand));
1182911829 try sema.requireRuntimeBlock(block, src);
1183011830 return try block.addNoOp(.frame_addr);
1183111831}
......@@ -11838,7 +11838,7 @@ fn zirBuiltinSrc(
1183811838 const tracy = trace(@src());
1183911839 defer tracy.end();
1184011840
11841 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
11841 const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand));
1184211842 const extra = sema.code.extraData(Zir.Inst.LineColumn, extended.operand).data;
1184311843 const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{});
1184411844 const fn_owner_decl = sema.mod.declPtr(func.owner_decl);
......@@ -12842,7 +12842,7 @@ fn zirTypeofPeer(
1284212842 defer tracy.end();
1284312843
1284412844 const extra = sema.code.extraData(Zir.Inst.TypeOfPeer, extended.operand);
12845 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
12845 const src = LazySrcLoc.nodeOffset(extra.data.src_node);
1284612846 const body = sema.code.extra[extra.data.body_index..][0..extra.data.body_len];
1284712847
1284812848 var child_block: Block = .{
......@@ -14157,7 +14157,7 @@ fn zirErrorReturnTrace(
1415714157 block: *Block,
1415814158 extended: Zir.Inst.Extended.InstData,
1415914159) CompileError!Air.Inst.Ref {
14160 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
14160 const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand));
1416114161 return sema.getErrorReturnTrace(block, src);
1416214162}
1416314163
......@@ -14185,7 +14185,7 @@ fn zirFrame(
1418514185 block: *Block,
1418614186 extended: Zir.Inst.Extended.InstData,
1418714187) CompileError!Air.Inst.Ref {
14188 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
14188 const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand));
1418914189 return sema.fail(block, src, "TODO: Sema.zirFrame", .{});
1419014190}
1419114191
......@@ -14629,7 +14629,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1462914629 .tag_ty_inferred = false,
1463014630 .fields = .{},
1463114631 .values = .{},
14632 .node_offset = src.node_offset,
14632 .node_offset = src.node_offset.x,
1463314633 .namespace = .{
1463414634 .parent = block.namespace,
1463514635 .ty = enum_ty,
......@@ -14711,7 +14711,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1471114711
1471214712 opaque_obj.* = .{
1471314713 .owner_decl = new_decl_index,
14714 .node_offset = src.node_offset,
14714 .node_offset = src.node_offset.x,
1471514715 .namespace = .{
1471614716 .parent = block.namespace,
1471714717 .ty = opaque_ty,
......@@ -14763,7 +14763,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1476314763 .owner_decl = new_decl_index,
1476414764 .tag_ty = Type.initTag(.@"null"),
1476514765 .fields = .{},
14766 .node_offset = src.node_offset,
14766 .node_offset = src.node_offset.x,
1476714767 .zir_index = inst,
1476814768 .layout = layout_val.toEnum(std.builtin.Type.ContainerLayout),
1476914769 .status = .have_field_types,
......@@ -14930,7 +14930,7 @@ fn reifyStruct(
1493014930 struct_obj.* = .{
1493114931 .owner_decl = new_decl_index,
1493214932 .fields = .{},
14933 .node_offset = src.node_offset,
14933 .node_offset = src.node_offset.x,
1493414934 .zir_index = inst,
1493514935 .layout = layout_val.toEnum(std.builtin.Type.ContainerLayout),
1493614936 .status = .have_field_types,
......@@ -15130,7 +15130,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1513015130
1513115131fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
1513215132 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
15133 const src: LazySrcLoc = .{ .node_offset = extra.node };
15133 const src = LazySrcLoc.nodeOffset(extra.node);
1513415134 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
1513515135 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
1513615136 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
......@@ -17114,7 +17114,7 @@ fn zirAwaitNosuspend(
1711417114 extended: Zir.Inst.Extended.InstData,
1711517115) CompileError!Air.Inst.Ref {
1711617116 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
17117 const src: LazySrcLoc = .{ .node_offset = extra.node };
17117 const src = LazySrcLoc.nodeOffset(extra.node);
1711817118
1711917119 return sema.fail(block, src, "TODO: Sema.zirAwaitNosuspend", .{});
1712017120}
......@@ -17443,7 +17443,7 @@ fn zirWasmMemorySize(
1744317443) CompileError!Air.Inst.Ref {
1744417444 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
1744517445 const index_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
17446 const builtin_src: LazySrcLoc = .{ .node_offset = extra.node };
17446 const builtin_src = LazySrcLoc.nodeOffset(extra.node);
1744717447 const target = sema.mod.getTarget();
1744817448 if (!target.isWasm()) {
1744917449 return sema.fail(block, builtin_src, "builtin @wasmMemorySize is available when targeting WebAssembly; targeted CPU architecture is {s}", .{@tagName(target.cpu.arch)});
......@@ -17466,7 +17466,7 @@ fn zirWasmMemoryGrow(
1746617466 extended: Zir.Inst.Extended.InstData,
1746717467) CompileError!Air.Inst.Ref {
1746817468 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
17469 const builtin_src: LazySrcLoc = .{ .node_offset = extra.node };
17469 const builtin_src = LazySrcLoc.nodeOffset(extra.node);
1747017470 const index_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
1747117471 const delta_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
1747217472 const target = sema.mod.getTarget();
......@@ -17534,7 +17534,7 @@ fn zirBuiltinExtern(
1753417534 extended: Zir.Inst.Extended.InstData,
1753517535) CompileError!Air.Inst.Ref {
1753617536 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
17537 const src: LazySrcLoc = .{ .node_offset = extra.node };
17537 const src = LazySrcLoc.nodeOffset(extra.node);
1753817538 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
1753917539 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
1754017540
......@@ -18061,7 +18061,6 @@ fn safetyPanic(
1806118061fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
1806218062 sema.branch_count += 1;
1806318063 if (sema.branch_count > sema.branch_quota) {
18064 // TODO show the "called from here" stack
1806518064 return sema.fail(block, src, "evaluation exceeded {d} backwards branches", .{sema.branch_quota});
1806618065 }
1806718066}
......@@ -23586,7 +23585,7 @@ fn semaStructFields(
2358623585 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
2358723586 var extra_index: usize = extended.operand;
2358823587
23589 const src: LazySrcLoc = .{ .node_offset = struct_obj.node_offset };
23588 const src = LazySrcLoc.nodeOffset(struct_obj.node_offset);
2359023589 extra_index += @boolToInt(small.has_src_node);
2359123590
2359223591 const body_len = if (small.has_body_len) blk: {
......@@ -23773,7 +23772,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil
2377323772 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);
2377423773 var extra_index: usize = extended.operand;
2377523774
23776 const src: LazySrcLoc = .{ .node_offset = union_obj.node_offset };
23775 const src = LazySrcLoc.nodeOffset(union_obj.node_offset);
2377723776 extra_index += @boolToInt(small.has_src_node);
2377823777
2377923778 const tag_type_ref: Zir.Inst.Ref = if (small.has_tag_type) blk: {
......@@ -24459,7 +24458,7 @@ fn enumFieldSrcLoc(
2445924458 .container_field,
2446024459 => {
2446124460 if (it_index == field_index) {
24462 return .{ .node_offset = decl.nodeIndexToRelative(member_node) };
24461 return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(member_node));
2446324462 }
2446424463 it_index += 1;
2446524464 },
src/Zir.zig+5-5
......@@ -2427,7 +2427,7 @@ pub const Inst = struct {
24272427 operand: Ref,
24282428
24292429 pub fn src(self: @This()) LazySrcLoc {
2430 return .{ .node_offset = self.src_node };
2430 return LazySrcLoc.nodeOffset(self.src_node);
24312431 }
24322432 },
24332433 /// Used for unary operators, with a token source location.
......@@ -2450,7 +2450,7 @@ pub const Inst = struct {
24502450 payload_index: u32,
24512451
24522452 pub fn src(self: @This()) LazySrcLoc {
2453 return .{ .node_offset = self.src_node };
2453 return LazySrcLoc.nodeOffset(self.src_node);
24542454 }
24552455 },
24562456 pl_tok: struct {
......@@ -2526,7 +2526,7 @@ pub const Inst = struct {
25262526 bit_count: u16,
25272527
25282528 pub fn src(self: @This()) LazySrcLoc {
2529 return .{ .node_offset = self.src_node };
2529 return LazySrcLoc.nodeOffset(self.src_node);
25302530 }
25312531 },
25322532 bool_br: struct {
......@@ -2545,7 +2545,7 @@ pub const Inst = struct {
25452545 force_comptime: bool,
25462546
25472547 pub fn src(self: @This()) LazySrcLoc {
2548 return .{ .node_offset = self.src_node };
2548 return LazySrcLoc.nodeOffset(self.src_node);
25492549 }
25502550 },
25512551 @"break": struct {
......@@ -2566,7 +2566,7 @@ pub const Inst = struct {
25662566 inst: Index,
25672567
25682568 pub fn src(self: @This()) LazySrcLoc {
2569 return .{ .node_offset = self.src_node };
2569 return LazySrcLoc.nodeOffset(self.src_node);
25702570 }
25712571 },
25722572 str_op: struct {
src/arch/wasm/CodeGen.zig+1-1
......@@ -622,7 +622,7 @@ pub fn deinit(self: *Self) void {
622622
623623/// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig
624624fn fail(self: *Self, comptime fmt: []const u8, args: anytype) InnerError {
625 const src: LazySrcLoc = .{ .node_offset = 0 };
625 const src = LazySrcLoc.nodeOffset(0);
626626 const src_loc = src.toSrcLoc(self.decl);
627627 self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, fmt, args);
628628 return error.CodegenFail;
src/codegen/c.zig+1-1
......@@ -363,7 +363,7 @@ pub const DeclGen = struct {
363363
364364 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
365365 @setCold(true);
366 const src: LazySrcLoc = .{ .node_offset = 0 };
366 const src = LazySrcLoc.nodeOffset(0);
367367 const src_loc = src.toSrcLoc(dg.decl);
368368 dg.error_msg = try Module.ErrorMsg.create(dg.module.gpa, src_loc, format, args);
369369 return error.AnalysisFail;
src/codegen/llvm.zig+1-1
......@@ -2163,7 +2163,7 @@ pub const DeclGen = struct {
21632163 fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) Error {
21642164 @setCold(true);
21652165 assert(self.err_msg == null);
2166 const src_loc = @as(LazySrcLoc, .{ .node_offset = 0 }).toSrcLoc(self.decl);
2166 const src_loc = LazySrcLoc.nodeOffset(0).toSrcLoc(self.decl);
21672167 self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, "TODO (LLVM): " ++ format, args);
21682168 return error.CodegenFail;
21692169 }
src/codegen/spirv.zig+2-2
......@@ -184,7 +184,7 @@ pub const DeclGen = struct {
184184
185185 fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error {
186186 @setCold(true);
187 const src: LazySrcLoc = .{ .node_offset = 0 };
187 const src = LazySrcLoc.nodeOffset(0);
188188 const src_loc = src.toSrcLoc(self.decl);
189189 assert(self.error_msg == null);
190190 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args);
......@@ -193,7 +193,7 @@ pub const DeclGen = struct {
193193
194194 fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) Error {
195195 @setCold(true);
196 const src: LazySrcLoc = .{ .node_offset = 0 };
196 const src = LazySrcLoc.nodeOffset(0);
197197 const src_loc = src.toSrcLoc(self.decl);
198198 assert(self.error_msg == null);
199199 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, "TODO (SPIR-V): " ++ format, args);
src/config.zig.in+1
......@@ -8,6 +8,7 @@ pub const semver = @import("std").SemanticVersion.parse(version) catch unreachab
88pub const enable_logging: bool = @ZIG_ENABLE_LOGGING_BOOL@;
99pub const enable_link_snapshots: bool = false;
1010pub const enable_tracy = false;
11pub const value_tracing = false;
1112pub const is_stage1 = true;
1213pub const skip_non_native = false;
1314pub const omit_stage2: bool = @ZIG_OMIT_STAGE2_BOOL@;
src/print_zir.zig+10-10
......@@ -497,7 +497,7 @@ const Writer = struct {
497497 .wasm_memory_size,
498498 => {
499499 const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
500 const src: LazySrcLoc = .{ .node_offset = inst_data.node };
500 const src = LazySrcLoc.nodeOffset(inst_data.node);
501501 try self.writeInstRef(stream, inst_data.operand);
502502 try stream.writeAll(")) ");
503503 try self.writeSrc(stream, src);
......@@ -510,7 +510,7 @@ const Writer = struct {
510510 .prefetch,
511511 => {
512512 const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
513 const src: LazySrcLoc = .{ .node_offset = inst_data.node };
513 const src = LazySrcLoc.nodeOffset(inst_data.node);
514514 try self.writeInstRef(stream, inst_data.lhs);
515515 try stream.writeAll(", ");
516516 try self.writeInstRef(stream, inst_data.rhs);
......@@ -520,7 +520,7 @@ const Writer = struct {
520520
521521 .field_call_bind_named => {
522522 const extra = self.code.extraData(Zir.Inst.FieldNamedNode, extended.operand).data;
523 const src: LazySrcLoc = .{ .node_offset = extra.node };
523 const src = LazySrcLoc.nodeOffset(extra.node);
524524 try self.writeInstRef(stream, extra.lhs);
525525 try stream.writeAll(", ");
526526 try self.writeInstRef(stream, extra.field_name);
......@@ -531,7 +531,7 @@ const Writer = struct {
531531 }
532532
533533 fn writeExtNode(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
534 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
534 const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand));
535535 try stream.writeAll(")) ");
536536 try self.writeSrc(stream, src);
537537 }
......@@ -1050,7 +1050,7 @@ const Writer = struct {
10501050
10511051 fn writeNodeMultiOp(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
10521052 const extra = self.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
1053 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
1053 const src = LazySrcLoc.nodeOffset(extra.data.src_node);
10541054 const operands = self.code.refSlice(extra.end, extended.small);
10551055
10561056 for (operands) |operand, i| {
......@@ -1074,7 +1074,7 @@ const Writer = struct {
10741074
10751075 fn writeAsm(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
10761076 const extra = self.code.extraData(Zir.Inst.Asm, extended.operand);
1077 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
1077 const src = LazySrcLoc.nodeOffset(extra.data.src_node);
10781078 const outputs_len = @truncate(u5, extended.small);
10791079 const inputs_len = @truncate(u5, extended.small >> 5);
10801080 const clobbers_len = @truncate(u5, extended.small >> 10);
......@@ -1145,7 +1145,7 @@ const Writer = struct {
11451145
11461146 fn writeOverflowArithmetic(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
11471147 const extra = self.code.extraData(Zir.Inst.OverflowArithmetic, extended.operand).data;
1148 const src: LazySrcLoc = .{ .node_offset = extra.node };
1148 const src = LazySrcLoc.nodeOffset(extra.node);
11491149
11501150 try self.writeInstRef(stream, extra.lhs);
11511151 try stream.writeAll(", ");
......@@ -1898,7 +1898,7 @@ const Writer = struct {
18981898 inst: Zir.Inst.Index,
18991899 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
19001900 const src_node = self.code.instructions.items(.data)[inst].node;
1901 const src: LazySrcLoc = .{ .node_offset = src_node };
1901 const src = LazySrcLoc.nodeOffset(src_node);
19021902 try stream.writeAll(") ");
19031903 try self.writeSrc(stream, src);
19041904 }
......@@ -2117,7 +2117,7 @@ const Writer = struct {
21172117 fn writeAllocExtended(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
21182118 const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand);
21192119 const small = @bitCast(Zir.Inst.AllocExtended.Small, extended.small);
2120 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
2120 const src = LazySrcLoc.nodeOffset(extra.data.src_node);
21212121
21222122 var extra_index: usize = extra.end;
21232123 const type_inst: Zir.Inst.Ref = if (!small.has_type) .none else blk: {
......@@ -2351,7 +2351,7 @@ const Writer = struct {
23512351
23522352 fn writeSrcNode(self: *Writer, stream: anytype, src_node: ?i32) !void {
23532353 const node_offset = src_node orelse return;
2354 const src: LazySrcLoc = .{ .node_offset = node_offset };
2354 const src = LazySrcLoc.nodeOffset(node_offset);
23552355 try stream.writeAll(" ");
23562356 return self.writeSrc(stream, src);
23572357 }
src/test.zig+36-7
......@@ -61,10 +61,12 @@ const ErrorMsg = union(enum) {
6161 // this is a workaround for stage1 compiler bug I ran into when making it ?u32
6262 column: u32,
6363 kind: Kind,
64 count: u32,
6465 },
6566 plain: struct {
6667 msg: []const u8,
6768 kind: Kind,
69 count: u32,
6870 },
6971
7072 const Kind = enum {
......@@ -81,12 +83,14 @@ const ErrorMsg = union(enum) {
8183 .line = @intCast(u32, src.line),
8284 .column = @intCast(u32, src.column),
8385 .kind = kind,
86 .count = src.count,
8487 },
8588 },
8689 .plain => |plain| return .{
8790 .plain = .{
8891 .msg = plain.msg,
8992 .kind = kind,
93 .count = plain.count,
9094 },
9195 },
9296 }
......@@ -118,10 +122,16 @@ const ErrorMsg = union(enum) {
118122 try writer.writeAll("?: ");
119123 }
120124 }
121 return writer.print("{s}: {s}", .{ @tagName(src.kind), src.msg });
125 try writer.print("{s}: {s}", .{ @tagName(src.kind), src.msg });
126 if (src.count != 1) {
127 try writer.print(" ({d} times)", .{src.count});
128 }
122129 },
123130 .plain => |plain| {
124 return writer.print("{s}: {s}", .{ @tagName(plain.kind), plain.msg });
131 try writer.print("{s}: {s}", .{ @tagName(plain.kind), plain.msg });
132 if (plain.count != 1) {
133 try writer.print(" ({d} times)", .{plain.count});
134 }
125135 },
126136 }
127137 }
......@@ -647,12 +657,20 @@ pub const TestContext = struct {
647657 for (errors) |err_msg_line, i| {
648658 if (std.mem.startsWith(u8, err_msg_line, "error: ")) {
649659 array[i] = .{
650 .plain = .{ .msg = err_msg_line["error: ".len..], .kind = .@"error" },
660 .plain = .{
661 .msg = err_msg_line["error: ".len..],
662 .kind = .@"error",
663 .count = 1,
664 },
651665 };
652666 continue;
653667 } else if (std.mem.startsWith(u8, err_msg_line, "note: ")) {
654668 array[i] = .{
655 .plain = .{ .msg = err_msg_line["note: ".len..], .kind = .note },
669 .plain = .{
670 .msg = err_msg_line["note: ".len..],
671 .kind = .note,
672 .count = 1,
673 },
656674 };
657675 continue;
658676 }
......@@ -662,7 +680,7 @@ pub const TestContext = struct {
662680 const line_text = it.next() orelse @panic("missing line");
663681 const col_text = it.next() orelse @panic("missing column");
664682 const kind_text = it.next() orelse @panic("missing 'error'/'note'");
665 const msg = it.rest()[1..]; // skip over the space at end of "error: "
683 var msg = it.rest()[1..]; // skip over the space at end of "error: "
666684
667685 const line: ?u32 = if (std.mem.eql(u8, line_text, "?"))
668686 null
......@@ -695,6 +713,14 @@ pub const TestContext = struct {
695713 break :blk n - 1;
696714 } else std.math.maxInt(u32);
697715
716 const suffix = " times)";
717 const count = if (std.mem.endsWith(u8, msg, suffix)) count: {
718 const lparen = std.mem.lastIndexOfScalar(u8, msg, '(').?;
719 const count = std.fmt.parseInt(u32, msg[lparen + 1 .. msg.len - suffix.len], 10) catch @panic("bad error note count number");
720 msg = msg[0 .. lparen - 1];
721 break :count count;
722 } else 1;
723
698724 array[i] = .{
699725 .src = .{
700726 .src_path = src_path,
......@@ -702,6 +728,7 @@ pub const TestContext = struct {
702728 .line = line_0based,
703729 .column = column_0based,
704730 .kind = kind,
731 .count = count,
705732 },
706733 };
707734 }
......@@ -1606,7 +1633,8 @@ pub const TestContext = struct {
16061633 (case_msg.src.column == std.math.maxInt(u32) or
16071634 actual_msg.column == case_msg.src.column) and
16081635 std.mem.eql(u8, expected_msg, actual_msg.msg) and
1609 case_msg.src.kind == .@"error")
1636 case_msg.src.kind == .@"error" and
1637 actual_msg.count == case_msg.src.count)
16101638 {
16111639 handled_errors[i] = true;
16121640 break;
......@@ -1616,7 +1644,8 @@ pub const TestContext = struct {
16161644 if (ex_tag != .plain) continue;
16171645
16181646 if (std.mem.eql(u8, case_msg.plain.msg, plain.msg) and
1619 case_msg.plain.kind == .@"error")
1647 case_msg.plain.kind == .@"error" and
1648 case_msg.plain.count == plain.count)
16201649 {
16211650 handled_errors[i] = true;
16221651 break;
test/behavior/bugs/920.zig+17-3
......@@ -1,14 +1,24 @@
1const builtin = @import("builtin");
12const std = @import("std");
23const Random = std.rand.Random;
34
5const zeroCaseFn = switch (builtin.zig_backend) {
6 .stage1 => fn (*Random, f64) f64,
7 else => *const fn (*Random, f64) f64,
8};
9const pdfFn = switch (builtin.zig_backend) {
10 .stage1 => fn (f64) f64,
11 else => *const fn (f64) f64,
12};
13
414const ZigTable = struct {
515 r: f64,
616 x: [257]f64,
717 f: [257]f64,
818
9 pdf: fn (f64) f64,
19 pdf: pdfFn,
1020 is_symmetric: bool,
11 zero_case: fn (*Random, f64) f64,
21 zero_case: zeroCaseFn,
1222};
1323
1424fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn (f64) f64, comptime f_inv: fn (f64) f64, comptime zero_case: fn (*Random, f64) f64) ZigTable {
......@@ -56,7 +66,11 @@ const NormalDist = blk: {
5666};
5767
5868test "bug 920 fixed" {
59 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
69 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
70 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
71 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
72 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
73 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6074
6175 const NormalDist1 = blk: {
6276 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
test/cases/recursive_inline_function.1.zig+3
......@@ -14,3 +14,6 @@ inline fn fibonacci(n: usize) usize {
1414// error
1515//
1616// :11:21: error: evaluation exceeded 1000 backwards branches
17// :11:40: note: called from here (6 times)
18// :11:21: note: called from here (495 times)
19// :5:24: note: called from here
test/stage2/cbe.zig-24
......@@ -233,30 +233,6 @@ pub fn addCases(ctx: *TestContext) !void {
233233 \\}
234234 , "");
235235 }
236 // This will make a pretty deep call stack, so this test can only be enabled
237 // on hosts where Zig's linking strategy can honor the 16 MiB (default) we
238 // link the self-hosted compiler with.
239 const host_supports_custom_stack_size = @import("builtin").target.os.tag == .linux;
240 if (host_supports_custom_stack_size) {
241 var case = ctx.exeFromCompiledC("@setEvalBranchQuota", .{});
242
243 // TODO when adding result location support to function calls, revisit this test
244 // case. It can go back to what it was before, with `y` being comptime known.
245 // Because the ret_ptr will passed in with the inline fn call, and there will
246 // only be 1 store to it, and it will be comptime known.
247 case.addCompareOutput(
248 \\pub export fn main() i32 {
249 \\ @setEvalBranchQuota(1001);
250 \\ const y = rec(1001);
251 \\ return y - 1;
252 \\}
253 \\
254 \\inline fn rec(n: i32) i32 {
255 \\ if (n <= 1) return n;
256 \\ return rec(n - 1);
257 \\}
258 , "");
259 }
260236 {
261237 var case = ctx.exeFromCompiledC("control flow", .{});
262238