| author | |
| committer | |
| log | fcfeafe99a3ecc694a3475735c81a0d75b6da6d0 |
| tree | 55eefb8b42d39c7ead40f9a92e5c494c9b2226b1 |
| parent | 5816d3eaec3f3bb04e70c89aa402ba9e0e5e7b2c |
| parent | 436aafd3e2ef1a8f5998b974a9791b59939f57ad |
| signature |
introduce std.debug.Trace and use it to debug a LazySrcLoc in stage2 that is set to a bogus value17 files changed, 365 insertions(+), 136 deletions(-)
build.zig+3| ... | ... | @@ -131,6 +131,7 @@ pub fn build(b: *Builder) !void { |
| 131 | 131 | const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse enable_llvm; |
| 132 | 132 | const strip = b.option(bool, "strip", "Omit debug information") orelse false; |
| 133 | 133 | 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; | |
| 134 | 135 | |
| 135 | 136 | 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: { |
| 136 | 137 | if (strip) break :blk @as(u32, 0); |
| ... | ... | @@ -353,6 +354,7 @@ pub fn build(b: *Builder) !void { |
| 353 | 354 | exe_options.addOption(bool, "enable_tracy", tracy != null); |
| 354 | 355 | exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack); |
| 355 | 356 | exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation); |
| 357 | exe_options.addOption(bool, "value_tracing", value_tracing); | |
| 356 | 358 | exe_options.addOption(bool, "is_stage1", is_stage1); |
| 357 | 359 | exe_options.addOption(bool, "omit_stage2", omit_stage2); |
| 358 | 360 | if (tracy) |tracy_path| { |
| ... | ... | @@ -402,6 +404,7 @@ pub fn build(b: *Builder) !void { |
| 402 | 404 | test_cases_options.addOption(bool, "enable_rosetta", b.enable_rosetta); |
| 403 | 405 | test_cases_options.addOption(bool, "enable_darling", b.enable_darling); |
| 404 | 406 | test_cases_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2); |
| 407 | test_cases_options.addOption(bool, "value_tracing", value_tracing); | |
| 405 | 408 | test_cases_options.addOption(?[]const u8, "glibc_runtimes_dir", b.glibc_runtimes_dir); |
| 406 | 409 | test_cases_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version)); |
| 407 | 410 | test_cases_options.addOption(std.SemanticVersion, "semver", semver); |
ci/azure/build.zig+2| ... | ... | @@ -99,6 +99,7 @@ pub fn build(b: *Builder) !void { |
| 99 | 99 | const force_gpa = b.option(bool, "force-gpa", "Force the compiler to use GeneralPurposeAllocator") orelse false; |
| 100 | 100 | const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse enable_llvm; |
| 101 | 101 | 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; | |
| 102 | 103 | |
| 103 | 104 | 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: { |
| 104 | 105 | if (strip) break :blk @as(u32, 0); |
| ... | ... | @@ -303,6 +304,7 @@ pub fn build(b: *Builder) !void { |
| 303 | 304 | exe_options.addOption(bool, "enable_tracy", tracy != null); |
| 304 | 305 | exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack); |
| 305 | 306 | exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation); |
| 307 | exe_options.addOption(bool, "value_tracing", value_tracing); | |
| 306 | 308 | exe_options.addOption(bool, "is_stage1", is_stage1); |
| 307 | 309 | exe_options.addOption(bool, "omit_stage2", omit_stage2); |
| 308 | 310 | if (tracy) |tracy_path| { |
lib/std/debug.zig+82| ... | ... | @@ -1943,3 +1943,85 @@ test "#4353: std.debug should manage resources correctly" { |
| 1943 | 1943 | noinline fn showMyTrace() usize { |
| 1944 | 1944 | return @returnAddress(); |
| 1945 | 1945 | } |
| 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`. | |
| 1954 | pub const Trace = ConfigurableTrace(2, 4, builtin.mode == .Debug); | |
| 1955 | ||
| 1956 | pub 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 { |
| 338 | 338 | line: u32, |
| 339 | 339 | column: u32, |
| 340 | 340 | byte_offset: u32, |
| 341 | /// Usually one, but incremented for redundant messages. | |
| 342 | count: u32 = 1, | |
| 341 | 343 | /// Does not include the trailing newline. |
| 342 | 344 | source_line: ?[]const u8, |
| 343 | 345 | notes: []Message = &.{}, |
| ... | ... | @@ -345,8 +347,21 @@ pub const AllErrors = struct { |
| 345 | 347 | plain: struct { |
| 346 | 348 | msg: []const u8, |
| 347 | 349 | notes: []Message = &.{}, |
| 350 | /// Usually one, but incremented for redundant messages. | |
| 351 | count: u32 = 1, | |
| 348 | 352 | }, |
| 349 | 353 | |
| 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 | ||
| 350 | 365 | pub fn renderToStdErr(msg: Message, ttyconf: std.debug.TTY.Config) void { |
| 351 | 366 | std.debug.getStderrMutex().lock(); |
| 352 | 367 | defer std.debug.getStderrMutex().unlock(); |
| ... | ... | @@ -376,7 +391,13 @@ pub const AllErrors = struct { |
| 376 | 391 | try stderr.writeAll(kind); |
| 377 | 392 | ttyconf.setColor(stderr, .Reset); |
| 378 | 393 | 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 | } | |
| 380 | 401 | ttyconf.setColor(stderr, .Reset); |
| 381 | 402 | if (ttyconf != .no_color) { |
| 382 | 403 | if (src.source_line) |line| { |
| ... | ... | @@ -400,7 +421,13 @@ pub const AllErrors = struct { |
| 400 | 421 | try stderr.writeByteNTimes(' ', indent); |
| 401 | 422 | try stderr.writeAll(kind); |
| 402 | 423 | 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 | } | |
| 404 | 431 | ttyconf.setColor(stderr, .Reset); |
| 405 | 432 | for (plain.notes) |note| { |
| 406 | 433 | try note.renderToStdErrInner(ttyconf, stderr_file, "error:", .Red, indent + 4); |
| ... | ... | @@ -408,6 +435,50 @@ pub const AllErrors = struct { |
| 408 | 435 | }, |
| 409 | 436 | } |
| 410 | 437 | } |
| 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 | }; | |
| 411 | 482 | }; |
| 412 | 483 | |
| 413 | 484 | pub fn deinit(self: *AllErrors, gpa: Allocator) void { |
| ... | ... | @@ -421,13 +492,25 @@ pub const AllErrors = struct { |
| 421 | 492 | module_err_msg: Module.ErrorMsg, |
| 422 | 493 | ) !void { |
| 423 | 494 | 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| { | |
| 427 | 509 | const source = try module_note.src_loc.file_scope.getSource(module.gpa); |
| 428 | 510 | const byte_offset = try module_note.src_loc.byteOffset(module.gpa); |
| 429 | 511 | const loc = std.zig.findLineColumn(source.bytes, byte_offset); |
| 430 | 512 | const file_path = try module_note.src_loc.file_scope.fullPath(allocator); |
| 513 | const note = &notes_buf[note_i]; | |
| 431 | 514 | note.* = .{ |
| 432 | 515 | .src = .{ |
| 433 | 516 | .src_path = file_path, |
| ... | ... | @@ -438,6 +521,12 @@ pub const AllErrors = struct { |
| 438 | 521 | .source_line = try allocator.dupe(u8, loc.source_line), |
| 439 | 522 | }, |
| 440 | 523 | }; |
| 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 | } | |
| 441 | 530 | } |
| 442 | 531 | if (module_err_msg.src_loc.lazy == .entire_file) { |
| 443 | 532 | try errors.append(.{ |
| ... | ... | @@ -458,7 +547,7 @@ pub const AllErrors = struct { |
| 458 | 547 | .byte_offset = byte_offset, |
| 459 | 548 | .line = @intCast(u32, loc.line), |
| 460 | 549 | .column = @intCast(u32, loc.column), |
| 461 | .notes = notes, | |
| 550 | .notes = notes_buf[0..note_i], | |
| 462 | 551 | .source_line = try allocator.dupe(u8, loc.source_line), |
| 463 | 552 | }, |
| 464 | 553 | }); |
src/Module.zig+61-30| ... | ... | @@ -659,7 +659,7 @@ pub const Decl = struct { |
| 659 | 659 | } |
| 660 | 660 | |
| 661 | 661 | 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)); | |
| 663 | 663 | } |
| 664 | 664 | |
| 665 | 665 | pub fn srcLoc(decl: Decl) SrcLoc { |
| ... | ... | @@ -670,7 +670,7 @@ pub const Decl = struct { |
| 670 | 670 | return .{ |
| 671 | 671 | .file_scope = decl.getFileScope(), |
| 672 | 672 | .parent_decl_node = decl.src_node, |
| 673 | .lazy = .{ .node_offset = node_offset }, | |
| 673 | .lazy = LazySrcLoc.nodeOffset(node_offset), | |
| 674 | 674 | }; |
| 675 | 675 | } |
| 676 | 676 | |
| ... | ... | @@ -861,7 +861,7 @@ pub const ErrorSet = struct { |
| 861 | 861 | return .{ |
| 862 | 862 | .file_scope = owner_decl.getFileScope(), |
| 863 | 863 | .parent_decl_node = owner_decl.src_node, |
| 864 | .lazy = .{ .node_offset = self.node_offset }, | |
| 864 | .lazy = LazySrcLoc.nodeOffset(self.node_offset), | |
| 865 | 865 | }; |
| 866 | 866 | } |
| 867 | 867 | |
| ... | ... | @@ -947,7 +947,7 @@ pub const Struct = struct { |
| 947 | 947 | return .{ |
| 948 | 948 | .file_scope = owner_decl.getFileScope(), |
| 949 | 949 | .parent_decl_node = owner_decl.src_node, |
| 950 | .lazy = .{ .node_offset = s.node_offset }, | |
| 950 | .lazy = LazySrcLoc.nodeOffset(s.node_offset), | |
| 951 | 951 | }; |
| 952 | 952 | } |
| 953 | 953 | |
| ... | ... | @@ -1066,7 +1066,7 @@ pub const EnumSimple = struct { |
| 1066 | 1066 | return .{ |
| 1067 | 1067 | .file_scope = owner_decl.getFileScope(), |
| 1068 | 1068 | .parent_decl_node = owner_decl.src_node, |
| 1069 | .lazy = .{ .node_offset = self.node_offset }, | |
| 1069 | .lazy = LazySrcLoc.nodeOffset(self.node_offset), | |
| 1070 | 1070 | }; |
| 1071 | 1071 | } |
| 1072 | 1072 | }; |
| ... | ... | @@ -1097,7 +1097,7 @@ pub const EnumNumbered = struct { |
| 1097 | 1097 | return .{ |
| 1098 | 1098 | .file_scope = owner_decl.getFileScope(), |
| 1099 | 1099 | .parent_decl_node = owner_decl.src_node, |
| 1100 | .lazy = .{ .node_offset = self.node_offset }, | |
| 1100 | .lazy = LazySrcLoc.nodeOffset(self.node_offset), | |
| 1101 | 1101 | }; |
| 1102 | 1102 | } |
| 1103 | 1103 | }; |
| ... | ... | @@ -1131,7 +1131,7 @@ pub const EnumFull = struct { |
| 1131 | 1131 | return .{ |
| 1132 | 1132 | .file_scope = owner_decl.getFileScope(), |
| 1133 | 1133 | .parent_decl_node = owner_decl.src_node, |
| 1134 | .lazy = .{ .node_offset = self.node_offset }, | |
| 1134 | .lazy = LazySrcLoc.nodeOffset(self.node_offset), | |
| 1135 | 1135 | }; |
| 1136 | 1136 | } |
| 1137 | 1137 | }; |
| ... | ... | @@ -1197,7 +1197,7 @@ pub const Union = struct { |
| 1197 | 1197 | return .{ |
| 1198 | 1198 | .file_scope = owner_decl.getFileScope(), |
| 1199 | 1199 | .parent_decl_node = owner_decl.src_node, |
| 1200 | .lazy = .{ .node_offset = self.node_offset }, | |
| 1200 | .lazy = LazySrcLoc.nodeOffset(self.node_offset), | |
| 1201 | 1201 | }; |
| 1202 | 1202 | } |
| 1203 | 1203 | |
| ... | ... | @@ -1404,7 +1404,7 @@ pub const Opaque = struct { |
| 1404 | 1404 | return .{ |
| 1405 | 1405 | .file_scope = owner_decl.getFileScope(), |
| 1406 | 1406 | .parent_decl_node = owner_decl.src_node, |
| 1407 | .lazy = .{ .node_offset = self.node_offset }, | |
| 1407 | .lazy = LazySrcLoc.nodeOffset(self.node_offset), | |
| 1408 | 1408 | }; |
| 1409 | 1409 | } |
| 1410 | 1410 | |
| ... | ... | @@ -2105,7 +2105,17 @@ pub const SrcLoc = struct { |
| 2105 | 2105 | const token_starts = tree.tokens.items(.start); |
| 2106 | 2106 | return token_starts[tok_index]; |
| 2107 | 2107 | }, |
| 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| { | |
| 2109 | 2119 | const tree = try src_loc.file_scope.getTree(gpa); |
| 2110 | 2120 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 2111 | 2121 | assert(src_loc.file_scope.tree_loaded); |
| ... | ... | @@ -2515,6 +2525,15 @@ pub const SrcLoc = struct { |
| 2515 | 2525 | } |
| 2516 | 2526 | }; |
| 2517 | 2527 | |
| 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. | |
| 2530 | const TracedOffset = struct { | |
| 2531 | x: i32, | |
| 2532 | trace: std.debug.Trace = .{}, | |
| 2533 | ||
| 2534 | const want_tracing = build_options.value_tracing; | |
| 2535 | }; | |
| 2536 | ||
| 2518 | 2537 | /// Resolving a source location into a byte offset may require doing work |
| 2519 | 2538 | /// that we would rather not do unless the error actually occurs. |
| 2520 | 2539 | /// Therefore we need a data structure that contains the information necessary |
| ... | ... | @@ -2555,7 +2574,7 @@ pub const LazySrcLoc = union(enum) { |
| 2555 | 2574 | /// The source location points to an AST node, which is this value offset |
| 2556 | 2575 | /// from its containing Decl node AST index. |
| 2557 | 2576 | /// The Decl is determined contextually. |
| 2558 | node_offset: i32, | |
| 2577 | node_offset: TracedOffset, | |
| 2559 | 2578 | /// The source location points to two tokens left of the first token of an AST node, |
| 2560 | 2579 | /// which is this value offset from its containing Decl node AST index. |
| 2561 | 2580 | /// The Decl is determined contextually. |
| ... | ... | @@ -2705,6 +2724,18 @@ pub const LazySrcLoc = union(enum) { |
| 2705 | 2724 | /// The Decl is determined contextually. |
| 2706 | 2725 | node_offset_array_type_elem: i32, |
| 2707 | 2726 | |
| 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 | ||
| 2708 | 2739 | /// Upgrade to a `SrcLoc` based on the `Decl` provided. |
| 2709 | 2740 | pub fn toSrcLoc(lazy: LazySrcLoc, decl: *Decl) SrcLoc { |
| 2710 | 2741 | return switch (lazy) { |
| ... | ... | @@ -4014,7 +4045,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4014 | 4045 | const body = zir.extra[extra.end..][0..extra.data.body_len]; |
| 4015 | 4046 | const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand; |
| 4016 | 4047 | try wip_captures.finalize(); |
| 4017 | const src: LazySrcLoc = .{ .node_offset = 0 }; | |
| 4048 | const src = LazySrcLoc.nodeOffset(0); | |
| 4018 | 4049 | const decl_tv = try sema.resolveInstValue(&block_scope, src, result_ref); |
| 4019 | 4050 | const decl_align: u32 = blk: { |
| 4020 | 4051 | const align_ref = decl.zirAlignRef(); |
| ... | ... | @@ -5044,7 +5075,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air { |
| 5044 | 5075 | // Crucially, this happens *after* we set the function state to success above, |
| 5045 | 5076 | // so that dependencies on the function body will now be satisfied rather than |
| 5046 | 5077 | // result in circular dependency errors. |
| 5047 | const src: LazySrcLoc = .{ .node_offset = 0 }; | |
| 5078 | const src = LazySrcLoc.nodeOffset(0); | |
| 5048 | 5079 | sema.resolveFnTypes(&inner_block, src, fn_ty_info) catch |err| switch (err) { |
| 5049 | 5080 | error.NeededSourceLocation => unreachable, |
| 5050 | 5081 | error.GenericPoison => unreachable, |
| ... | ... | @@ -5338,7 +5369,7 @@ pub const SwitchProngSrc = union(enum) { |
| 5338 | 5369 | log.warn("unable to load {s}: {s}", .{ |
| 5339 | 5370 | decl.getFileScope().sub_file_path, @errorName(err), |
| 5340 | 5371 | }); |
| 5341 | return LazySrcLoc{ .node_offset = 0 }; | |
| 5372 | return LazySrcLoc.nodeOffset(0); | |
| 5342 | 5373 | }; |
| 5343 | 5374 | const switch_node = decl.relativeToNodeIndex(switch_node_offset); |
| 5344 | 5375 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -5367,17 +5398,17 @@ pub const SwitchProngSrc = union(enum) { |
| 5367 | 5398 | node_tags[case.ast.values[0]] == .switch_range; |
| 5368 | 5399 | |
| 5369 | 5400 | 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 | ), | |
| 5373 | 5404 | .multi => |s| if (is_multi and s.prong == multi_i) { |
| 5374 | 5405 | var item_i: u32 = 0; |
| 5375 | 5406 | for (case.ast.values) |item_node| { |
| 5376 | 5407 | if (node_tags[item_node] == .switch_range) continue; |
| 5377 | 5408 | |
| 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 | ); | |
| 5381 | 5412 | item_i += 1; |
| 5382 | 5413 | } else unreachable; |
| 5383 | 5414 | }, |
| ... | ... | @@ -5387,15 +5418,15 @@ pub const SwitchProngSrc = union(enum) { |
| 5387 | 5418 | if (node_tags[range] != .switch_range) continue; |
| 5388 | 5419 | |
| 5389 | 5420 | 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 | ), | |
| 5399 | 5430 | }; |
| 5400 | 5431 | range_i += 1; |
| 5401 | 5432 | } else unreachable; |
| ... | ... | @@ -5450,7 +5481,7 @@ pub const PeerTypeCandidateSrc = union(enum) { |
| 5450 | 5481 | log.warn("unable to load {s}: {s}", .{ |
| 5451 | 5482 | decl.getFileScope().sub_file_path, @errorName(err), |
| 5452 | 5483 | }); |
| 5453 | return LazySrcLoc{ .node_offset = 0 }; | |
| 5484 | return LazySrcLoc.nodeOffset(0); | |
| 5454 | 5485 | }; |
| 5455 | 5486 | const node = decl.relativeToNodeIndex(node_offset); |
| 5456 | 5487 | const node_datas = tree.nodes.items(.data); |
src/Sema.zig+45-46| ... | ... | @@ -1154,7 +1154,7 @@ fn analyzeBodyInner( |
| 1154 | 1154 | .repeat => { |
| 1155 | 1155 | if (block.is_comptime) { |
| 1156 | 1156 | // 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); | |
| 1158 | 1158 | try sema.emitBackwardBranch(block, src); |
| 1159 | 1159 | if (wip_captures.scope.captures.count() != orig_captures) { |
| 1160 | 1160 | try wip_captures.reset(parent_capture_scope); |
| ... | ... | @@ -1165,14 +1165,14 @@ fn analyzeBodyInner( |
| 1165 | 1165 | continue; |
| 1166 | 1166 | } else { |
| 1167 | 1167 | 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); | |
| 1169 | 1169 | try sema.requireRuntimeBlock(block, src); |
| 1170 | 1170 | break always_noreturn; |
| 1171 | 1171 | } |
| 1172 | 1172 | }, |
| 1173 | 1173 | .repeat_inline => { |
| 1174 | 1174 | // 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); | |
| 1176 | 1176 | try sema.emitBackwardBranch(block, src); |
| 1177 | 1177 | if (wip_captures.scope.captures.count() != orig_captures) { |
| 1178 | 1178 | try wip_captures.reset(parent_capture_scope); |
| ... | ... | @@ -2087,7 +2087,7 @@ fn zirStructDecl( |
| 2087 | 2087 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); |
| 2088 | 2088 | const src: LazySrcLoc = if (small.has_src_node) blk: { |
| 2089 | 2089 | const node_offset = @bitCast(i32, sema.code.extra[extended.operand]); |
| 2090 | break :blk .{ .node_offset = node_offset }; | |
| 2090 | break :blk LazySrcLoc.nodeOffset(node_offset); | |
| 2091 | 2091 | } else sema.src; |
| 2092 | 2092 | |
| 2093 | 2093 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| ... | ... | @@ -2108,7 +2108,7 @@ fn zirStructDecl( |
| 2108 | 2108 | struct_obj.* = .{ |
| 2109 | 2109 | .owner_decl = new_decl_index, |
| 2110 | 2110 | .fields = .{}, |
| 2111 | .node_offset = src.node_offset, | |
| 2111 | .node_offset = src.node_offset.x, | |
| 2112 | 2112 | .zir_index = inst, |
| 2113 | 2113 | .layout = small.layout, |
| 2114 | 2114 | .status = .none, |
| ... | ... | @@ -2210,7 +2210,7 @@ fn zirEnumDecl( |
| 2210 | 2210 | const src: LazySrcLoc = if (small.has_src_node) blk: { |
| 2211 | 2211 | const node_offset = @bitCast(i32, sema.code.extra[extra_index]); |
| 2212 | 2212 | extra_index += 1; |
| 2213 | break :blk .{ .node_offset = node_offset }; | |
| 2213 | break :blk LazySrcLoc.nodeOffset(node_offset); | |
| 2214 | 2214 | } else sema.src; |
| 2215 | 2215 | |
| 2216 | 2216 | const tag_type_ref = if (small.has_tag_type) blk: { |
| ... | ... | @@ -2263,7 +2263,7 @@ fn zirEnumDecl( |
| 2263 | 2263 | .tag_ty_inferred = true, |
| 2264 | 2264 | .fields = .{}, |
| 2265 | 2265 | .values = .{}, |
| 2266 | .node_offset = src.node_offset, | |
| 2266 | .node_offset = src.node_offset.x, | |
| 2267 | 2267 | .namespace = .{ |
| 2268 | 2268 | .parent = block.namespace, |
| 2269 | 2269 | .ty = enum_ty, |
| ... | ... | @@ -2385,8 +2385,8 @@ fn zirEnumDecl( |
| 2385 | 2385 | const gop = enum_obj.fields.getOrPutAssumeCapacity(field_name); |
| 2386 | 2386 | if (gop.found_existing) { |
| 2387 | 2387 | 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); | |
| 2390 | 2390 | const msg = msg: { |
| 2391 | 2391 | const msg = try sema.errMsg(block, field_src, "duplicate enum tag", .{}); |
| 2392 | 2392 | errdefer msg.destroy(gpa); |
| ... | ... | @@ -2442,7 +2442,7 @@ fn zirUnionDecl( |
| 2442 | 2442 | const src: LazySrcLoc = if (small.has_src_node) blk: { |
| 2443 | 2443 | const node_offset = @bitCast(i32, sema.code.extra[extra_index]); |
| 2444 | 2444 | extra_index += 1; |
| 2445 | break :blk .{ .node_offset = node_offset }; | |
| 2445 | break :blk LazySrcLoc.nodeOffset(node_offset); | |
| 2446 | 2446 | } else sema.src; |
| 2447 | 2447 | |
| 2448 | 2448 | extra_index += @boolToInt(small.has_tag_type); |
| ... | ... | @@ -2480,7 +2480,7 @@ fn zirUnionDecl( |
| 2480 | 2480 | .owner_decl = new_decl_index, |
| 2481 | 2481 | .tag_ty = Type.initTag(.@"null"), |
| 2482 | 2482 | .fields = .{}, |
| 2483 | .node_offset = src.node_offset, | |
| 2483 | .node_offset = src.node_offset.x, | |
| 2484 | 2484 | .zir_index = inst, |
| 2485 | 2485 | .layout = small.layout, |
| 2486 | 2486 | .status = .none, |
| ... | ... | @@ -2516,7 +2516,7 @@ fn zirOpaqueDecl( |
| 2516 | 2516 | const src: LazySrcLoc = if (small.has_src_node) blk: { |
| 2517 | 2517 | const node_offset = @bitCast(i32, sema.code.extra[extra_index]); |
| 2518 | 2518 | extra_index += 1; |
| 2519 | break :blk .{ .node_offset = node_offset }; | |
| 2519 | break :blk LazySrcLoc.nodeOffset(node_offset); | |
| 2520 | 2520 | } else sema.src; |
| 2521 | 2521 | |
| 2522 | 2522 | const decls_len = if (small.has_decls_len) blk: { |
| ... | ... | @@ -2547,7 +2547,7 @@ fn zirOpaqueDecl( |
| 2547 | 2547 | |
| 2548 | 2548 | opaque_obj.* = .{ |
| 2549 | 2549 | .owner_decl = new_decl_index, |
| 2550 | .node_offset = src.node_offset, | |
| 2550 | .node_offset = src.node_offset.x, | |
| 2551 | 2551 | .namespace = .{ |
| 2552 | 2552 | .parent = block.namespace, |
| 2553 | 2553 | .ty = opaque_ty, |
| ... | ... | @@ -2623,7 +2623,7 @@ fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 2623 | 2623 | defer tracy.end(); |
| 2624 | 2624 | |
| 2625 | 2625 | 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); | |
| 2627 | 2627 | try sema.requireFunctionBlock(block, src); |
| 2628 | 2628 | |
| 2629 | 2629 | 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 |
| 2661 | 2661 | defer tracy.end(); |
| 2662 | 2662 | |
| 2663 | 2663 | 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); | |
| 2665 | 2665 | try sema.requireFunctionBlock(block, src); |
| 2666 | 2666 | return sema.addType(sema.fn_ret_ty); |
| 2667 | 2667 | } |
| ... | ... | @@ -2750,7 +2750,7 @@ fn zirAllocExtended( |
| 2750 | 2750 | extended: Zir.Inst.Extended.InstData, |
| 2751 | 2751 | ) CompileError!Air.Inst.Ref { |
| 2752 | 2752 | 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); | |
| 2754 | 2754 | const ty_src = src; // TODO better source location |
| 2755 | 2755 | const align_src = src; // TODO better source location |
| 2756 | 2756 | const small = @bitCast(Zir.Inst.AllocExtended.Small, extended.small); |
| ... | ... | @@ -2903,7 +2903,7 @@ fn zirAllocInferredComptime( |
| 2903 | 2903 | inferred_alloc_ty: Type, |
| 2904 | 2904 | ) CompileError!Air.Inst.Ref { |
| 2905 | 2905 | 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); | |
| 2907 | 2907 | sema.src = src; |
| 2908 | 2908 | return sema.addConstant( |
| 2909 | 2909 | inferred_alloc_ty, |
| ... | ... | @@ -2967,7 +2967,7 @@ fn zirAllocInferred( |
| 2967 | 2967 | defer tracy.end(); |
| 2968 | 2968 | |
| 2969 | 2969 | 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); | |
| 2971 | 2971 | sema.src = src; |
| 2972 | 2972 | |
| 2973 | 2973 | if (block.is_comptime) { |
| ... | ... | @@ -3718,7 +3718,7 @@ fn zirValidateArrayInit( |
| 3718 | 3718 | |
| 3719 | 3719 | outer: for (instrs) |elem_ptr, i| { |
| 3720 | 3720 | 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); | |
| 3722 | 3722 | |
| 3723 | 3723 | // Determine whether the value stored to this pointer is comptime-known. |
| 3724 | 3724 | |
| ... | ... | @@ -4203,7 +4203,7 @@ fn zirCompileLog( |
| 4203 | 4203 | |
| 4204 | 4204 | const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand); |
| 4205 | 4205 | const src_node = extra.data.src_node; |
| 4206 | const src: LazySrcLoc = .{ .node_offset = src_node }; | |
| 4206 | const src = LazySrcLoc.nodeOffset(src_node); | |
| 4207 | 4207 | const args = sema.code.refSlice(extra.end, extended.small); |
| 4208 | 4208 | |
| 4209 | 4209 | for (args) |arg_ref, i| { |
| ... | ... | @@ -4707,7 +4707,7 @@ pub fn analyzeExport( |
| 4707 | 4707 | fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| 4708 | 4708 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 4709 | 4709 | 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); | |
| 4711 | 4711 | const alignment = try sema.resolveAlign(block, operand_src, extra.operand); |
| 4712 | 4712 | if (alignment > 256) { |
| 4713 | 4713 | return sema.fail(block, src, "attempt to @setAlignStack({d}); maximum is 256", .{ |
| ... | ... | @@ -5312,7 +5312,7 @@ fn analyzeCall( |
| 5312 | 5312 | delete_memoized_call_key = true; |
| 5313 | 5313 | } |
| 5314 | 5314 | |
| 5315 | try sema.emitBackwardBranch(&child_block, call_src); | |
| 5315 | try sema.emitBackwardBranch(block, call_src); | |
| 5316 | 5316 | |
| 5317 | 5317 | // Whether this call should be memoized, set to false if the call can mutate |
| 5318 | 5318 | // comptime state. |
| ... | ... | @@ -6988,7 +6988,7 @@ fn funcCommon( |
| 6988 | 6988 | const param_types = try sema.arena.alloc(Type, block.params.items.len); |
| 6989 | 6989 | const comptime_params = try sema.arena.alloc(bool, block.params.items.len); |
| 6990 | 6990 | 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 | |
| 6992 | 6992 | param_types[i] = param.ty; |
| 6993 | 6993 | comptime_params[i] = param.is_comptime or |
| 6994 | 6994 | try sema.typeRequiresComptime(block, param_src, param.ty); |
| ... | ... | @@ -7378,7 +7378,7 @@ fn zirFieldCallBindNamed(sema: *Sema, block: *Block, extended: Zir.Inst.Extended |
| 7378 | 7378 | defer tracy.end(); |
| 7379 | 7379 | |
| 7380 | 7380 | 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); | |
| 7382 | 7382 | const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; |
| 7383 | 7383 | const object_ptr = try sema.resolveInst(extra.lhs); |
| 7384 | 7384 | const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name); |
| ... | ... | @@ -10088,7 +10088,7 @@ fn zirOverflowArithmetic( |
| 10088 | 10088 | defer tracy.end(); |
| 10089 | 10089 | |
| 10090 | 10090 | 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); | |
| 10092 | 10092 | |
| 10093 | 10093 | const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 10094 | 10094 | const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; |
| ... | ... | @@ -11309,7 +11309,7 @@ fn zirAsm( |
| 11309 | 11309 | defer tracy.end(); |
| 11310 | 11310 | |
| 11311 | 11311 | 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); | |
| 11313 | 11313 | const ret_ty_src: LazySrcLoc = .{ .node_offset_asm_ret_ty = extra.data.src_node }; |
| 11314 | 11314 | const outputs_len = @truncate(u5, extended.small); |
| 11315 | 11315 | const inputs_len = @truncate(u5, extended.small >> 5); |
| ... | ... | @@ -11761,7 +11761,7 @@ fn zirThis( |
| 11761 | 11761 | extended: Zir.Inst.Extended.InstData, |
| 11762 | 11762 | ) CompileError!Air.Inst.Ref { |
| 11763 | 11763 | 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)); | |
| 11765 | 11765 | return sema.analyzeDeclVal(block, src, this_decl_index); |
| 11766 | 11766 | } |
| 11767 | 11767 | |
| ... | ... | @@ -11815,7 +11815,7 @@ fn zirRetAddr( |
| 11815 | 11815 | block: *Block, |
| 11816 | 11816 | extended: Zir.Inst.Extended.InstData, |
| 11817 | 11817 | ) CompileError!Air.Inst.Ref { |
| 11818 | const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; | |
| 11818 | const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand)); | |
| 11819 | 11819 | try sema.requireRuntimeBlock(block, src); |
| 11820 | 11820 | return try block.addNoOp(.ret_addr); |
| 11821 | 11821 | } |
| ... | ... | @@ -11825,7 +11825,7 @@ fn zirFrameAddress( |
| 11825 | 11825 | block: *Block, |
| 11826 | 11826 | extended: Zir.Inst.Extended.InstData, |
| 11827 | 11827 | ) CompileError!Air.Inst.Ref { |
| 11828 | const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; | |
| 11828 | const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand)); | |
| 11829 | 11829 | try sema.requireRuntimeBlock(block, src); |
| 11830 | 11830 | return try block.addNoOp(.frame_addr); |
| 11831 | 11831 | } |
| ... | ... | @@ -11838,7 +11838,7 @@ fn zirBuiltinSrc( |
| 11838 | 11838 | const tracy = trace(@src()); |
| 11839 | 11839 | defer tracy.end(); |
| 11840 | 11840 | |
| 11841 | const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; | |
| 11841 | const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand)); | |
| 11842 | 11842 | const extra = sema.code.extraData(Zir.Inst.LineColumn, extended.operand).data; |
| 11843 | 11843 | const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{}); |
| 11844 | 11844 | const fn_owner_decl = sema.mod.declPtr(func.owner_decl); |
| ... | ... | @@ -12842,7 +12842,7 @@ fn zirTypeofPeer( |
| 12842 | 12842 | defer tracy.end(); |
| 12843 | 12843 | |
| 12844 | 12844 | 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); | |
| 12846 | 12846 | const body = sema.code.extra[extra.data.body_index..][0..extra.data.body_len]; |
| 12847 | 12847 | |
| 12848 | 12848 | var child_block: Block = .{ |
| ... | ... | @@ -14157,7 +14157,7 @@ fn zirErrorReturnTrace( |
| 14157 | 14157 | block: *Block, |
| 14158 | 14158 | extended: Zir.Inst.Extended.InstData, |
| 14159 | 14159 | ) CompileError!Air.Inst.Ref { |
| 14160 | const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; | |
| 14160 | const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand)); | |
| 14161 | 14161 | return sema.getErrorReturnTrace(block, src); |
| 14162 | 14162 | } |
| 14163 | 14163 | |
| ... | ... | @@ -14185,7 +14185,7 @@ fn zirFrame( |
| 14185 | 14185 | block: *Block, |
| 14186 | 14186 | extended: Zir.Inst.Extended.InstData, |
| 14187 | 14187 | ) CompileError!Air.Inst.Ref { |
| 14188 | const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; | |
| 14188 | const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand)); | |
| 14189 | 14189 | return sema.fail(block, src, "TODO: Sema.zirFrame", .{}); |
| 14190 | 14190 | } |
| 14191 | 14191 | |
| ... | ... | @@ -14629,7 +14629,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 14629 | 14629 | .tag_ty_inferred = false, |
| 14630 | 14630 | .fields = .{}, |
| 14631 | 14631 | .values = .{}, |
| 14632 | .node_offset = src.node_offset, | |
| 14632 | .node_offset = src.node_offset.x, | |
| 14633 | 14633 | .namespace = .{ |
| 14634 | 14634 | .parent = block.namespace, |
| 14635 | 14635 | .ty = enum_ty, |
| ... | ... | @@ -14711,7 +14711,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 14711 | 14711 | |
| 14712 | 14712 | opaque_obj.* = .{ |
| 14713 | 14713 | .owner_decl = new_decl_index, |
| 14714 | .node_offset = src.node_offset, | |
| 14714 | .node_offset = src.node_offset.x, | |
| 14715 | 14715 | .namespace = .{ |
| 14716 | 14716 | .parent = block.namespace, |
| 14717 | 14717 | .ty = opaque_ty, |
| ... | ... | @@ -14763,7 +14763,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 14763 | 14763 | .owner_decl = new_decl_index, |
| 14764 | 14764 | .tag_ty = Type.initTag(.@"null"), |
| 14765 | 14765 | .fields = .{}, |
| 14766 | .node_offset = src.node_offset, | |
| 14766 | .node_offset = src.node_offset.x, | |
| 14767 | 14767 | .zir_index = inst, |
| 14768 | 14768 | .layout = layout_val.toEnum(std.builtin.Type.ContainerLayout), |
| 14769 | 14769 | .status = .have_field_types, |
| ... | ... | @@ -14930,7 +14930,7 @@ fn reifyStruct( |
| 14930 | 14930 | struct_obj.* = .{ |
| 14931 | 14931 | .owner_decl = new_decl_index, |
| 14932 | 14932 | .fields = .{}, |
| 14933 | .node_offset = src.node_offset, | |
| 14933 | .node_offset = src.node_offset.x, | |
| 14934 | 14934 | .zir_index = inst, |
| 14935 | 14935 | .layout = layout_val.toEnum(std.builtin.Type.ContainerLayout), |
| 14936 | 14936 | .status = .have_field_types, |
| ... | ... | @@ -15130,7 +15130,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15130 | 15130 | |
| 15131 | 15131 | fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 15132 | 15132 | 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); | |
| 15134 | 15134 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 15135 | 15135 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; |
| 15136 | 15136 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| ... | ... | @@ -17114,7 +17114,7 @@ fn zirAwaitNosuspend( |
| 17114 | 17114 | extended: Zir.Inst.Extended.InstData, |
| 17115 | 17115 | ) CompileError!Air.Inst.Ref { |
| 17116 | 17116 | 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); | |
| 17118 | 17118 | |
| 17119 | 17119 | return sema.fail(block, src, "TODO: Sema.zirAwaitNosuspend", .{}); |
| 17120 | 17120 | } |
| ... | ... | @@ -17443,7 +17443,7 @@ fn zirWasmMemorySize( |
| 17443 | 17443 | ) CompileError!Air.Inst.Ref { |
| 17444 | 17444 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 17445 | 17445 | 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); | |
| 17447 | 17447 | const target = sema.mod.getTarget(); |
| 17448 | 17448 | if (!target.isWasm()) { |
| 17449 | 17449 | 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( |
| 17466 | 17466 | extended: Zir.Inst.Extended.InstData, |
| 17467 | 17467 | ) CompileError!Air.Inst.Ref { |
| 17468 | 17468 | 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); | |
| 17470 | 17470 | const index_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 17471 | 17471 | const delta_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; |
| 17472 | 17472 | const target = sema.mod.getTarget(); |
| ... | ... | @@ -17534,7 +17534,7 @@ fn zirBuiltinExtern( |
| 17534 | 17534 | extended: Zir.Inst.Extended.InstData, |
| 17535 | 17535 | ) CompileError!Air.Inst.Ref { |
| 17536 | 17536 | 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); | |
| 17538 | 17538 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 17539 | 17539 | const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; |
| 17540 | 17540 | |
| ... | ... | @@ -18061,7 +18061,6 @@ fn safetyPanic( |
| 18061 | 18061 | fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void { |
| 18062 | 18062 | sema.branch_count += 1; |
| 18063 | 18063 | if (sema.branch_count > sema.branch_quota) { |
| 18064 | // TODO show the "called from here" stack | |
| 18065 | 18064 | return sema.fail(block, src, "evaluation exceeded {d} backwards branches", .{sema.branch_quota}); |
| 18066 | 18065 | } |
| 18067 | 18066 | } |
| ... | ... | @@ -23586,7 +23585,7 @@ fn semaStructFields( |
| 23586 | 23585 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); |
| 23587 | 23586 | var extra_index: usize = extended.operand; |
| 23588 | 23587 | |
| 23589 | const src: LazySrcLoc = .{ .node_offset = struct_obj.node_offset }; | |
| 23588 | const src = LazySrcLoc.nodeOffset(struct_obj.node_offset); | |
| 23590 | 23589 | extra_index += @boolToInt(small.has_src_node); |
| 23591 | 23590 | |
| 23592 | 23591 | const body_len = if (small.has_body_len) blk: { |
| ... | ... | @@ -23773,7 +23772,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 23773 | 23772 | const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small); |
| 23774 | 23773 | var extra_index: usize = extended.operand; |
| 23775 | 23774 | |
| 23776 | const src: LazySrcLoc = .{ .node_offset = union_obj.node_offset }; | |
| 23775 | const src = LazySrcLoc.nodeOffset(union_obj.node_offset); | |
| 23777 | 23776 | extra_index += @boolToInt(small.has_src_node); |
| 23778 | 23777 | |
| 23779 | 23778 | const tag_type_ref: Zir.Inst.Ref = if (small.has_tag_type) blk: { |
| ... | ... | @@ -24459,7 +24458,7 @@ fn enumFieldSrcLoc( |
| 24459 | 24458 | .container_field, |
| 24460 | 24459 | => { |
| 24461 | 24460 | if (it_index == field_index) { |
| 24462 | return .{ .node_offset = decl.nodeIndexToRelative(member_node) }; | |
| 24461 | return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(member_node)); | |
| 24463 | 24462 | } |
| 24464 | 24463 | it_index += 1; |
| 24465 | 24464 | }, |
src/Zir.zig+5-5| ... | ... | @@ -2427,7 +2427,7 @@ pub const Inst = struct { |
| 2427 | 2427 | operand: Ref, |
| 2428 | 2428 | |
| 2429 | 2429 | pub fn src(self: @This()) LazySrcLoc { |
| 2430 | return .{ .node_offset = self.src_node }; | |
| 2430 | return LazySrcLoc.nodeOffset(self.src_node); | |
| 2431 | 2431 | } |
| 2432 | 2432 | }, |
| 2433 | 2433 | /// Used for unary operators, with a token source location. |
| ... | ... | @@ -2450,7 +2450,7 @@ pub const Inst = struct { |
| 2450 | 2450 | payload_index: u32, |
| 2451 | 2451 | |
| 2452 | 2452 | pub fn src(self: @This()) LazySrcLoc { |
| 2453 | return .{ .node_offset = self.src_node }; | |
| 2453 | return LazySrcLoc.nodeOffset(self.src_node); | |
| 2454 | 2454 | } |
| 2455 | 2455 | }, |
| 2456 | 2456 | pl_tok: struct { |
| ... | ... | @@ -2526,7 +2526,7 @@ pub const Inst = struct { |
| 2526 | 2526 | bit_count: u16, |
| 2527 | 2527 | |
| 2528 | 2528 | pub fn src(self: @This()) LazySrcLoc { |
| 2529 | return .{ .node_offset = self.src_node }; | |
| 2529 | return LazySrcLoc.nodeOffset(self.src_node); | |
| 2530 | 2530 | } |
| 2531 | 2531 | }, |
| 2532 | 2532 | bool_br: struct { |
| ... | ... | @@ -2545,7 +2545,7 @@ pub const Inst = struct { |
| 2545 | 2545 | force_comptime: bool, |
| 2546 | 2546 | |
| 2547 | 2547 | pub fn src(self: @This()) LazySrcLoc { |
| 2548 | return .{ .node_offset = self.src_node }; | |
| 2548 | return LazySrcLoc.nodeOffset(self.src_node); | |
| 2549 | 2549 | } |
| 2550 | 2550 | }, |
| 2551 | 2551 | @"break": struct { |
| ... | ... | @@ -2566,7 +2566,7 @@ pub const Inst = struct { |
| 2566 | 2566 | inst: Index, |
| 2567 | 2567 | |
| 2568 | 2568 | pub fn src(self: @This()) LazySrcLoc { |
| 2569 | return .{ .node_offset = self.src_node }; | |
| 2569 | return LazySrcLoc.nodeOffset(self.src_node); | |
| 2570 | 2570 | } |
| 2571 | 2571 | }, |
| 2572 | 2572 | str_op: struct { |
src/arch/wasm/CodeGen.zig+1-1| ... | ... | @@ -622,7 +622,7 @@ pub fn deinit(self: *Self) void { |
| 622 | 622 | |
| 623 | 623 | /// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig |
| 624 | 624 | fn fail(self: *Self, comptime fmt: []const u8, args: anytype) InnerError { |
| 625 | const src: LazySrcLoc = .{ .node_offset = 0 }; | |
| 625 | const src = LazySrcLoc.nodeOffset(0); | |
| 626 | 626 | const src_loc = src.toSrcLoc(self.decl); |
| 627 | 627 | self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, fmt, args); |
| 628 | 628 | return error.CodegenFail; |
src/codegen/c.zig+1-1| ... | ... | @@ -363,7 +363,7 @@ pub const DeclGen = struct { |
| 363 | 363 | |
| 364 | 364 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { |
| 365 | 365 | @setCold(true); |
| 366 | const src: LazySrcLoc = .{ .node_offset = 0 }; | |
| 366 | const src = LazySrcLoc.nodeOffset(0); | |
| 367 | 367 | const src_loc = src.toSrcLoc(dg.decl); |
| 368 | 368 | dg.error_msg = try Module.ErrorMsg.create(dg.module.gpa, src_loc, format, args); |
| 369 | 369 | return error.AnalysisFail; |
src/codegen/llvm.zig+1-1| ... | ... | @@ -2163,7 +2163,7 @@ pub const DeclGen = struct { |
| 2163 | 2163 | fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) Error { |
| 2164 | 2164 | @setCold(true); |
| 2165 | 2165 | 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); | |
| 2167 | 2167 | self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, "TODO (LLVM): " ++ format, args); |
| 2168 | 2168 | return error.CodegenFail; |
| 2169 | 2169 | } |
src/codegen/spirv.zig+2-2| ... | ... | @@ -184,7 +184,7 @@ pub const DeclGen = struct { |
| 184 | 184 | |
| 185 | 185 | fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error { |
| 186 | 186 | @setCold(true); |
| 187 | const src: LazySrcLoc = .{ .node_offset = 0 }; | |
| 187 | const src = LazySrcLoc.nodeOffset(0); | |
| 188 | 188 | const src_loc = src.toSrcLoc(self.decl); |
| 189 | 189 | assert(self.error_msg == null); |
| 190 | 190 | self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args); |
| ... | ... | @@ -193,7 +193,7 @@ pub const DeclGen = struct { |
| 193 | 193 | |
| 194 | 194 | fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) Error { |
| 195 | 195 | @setCold(true); |
| 196 | const src: LazySrcLoc = .{ .node_offset = 0 }; | |
| 196 | const src = LazySrcLoc.nodeOffset(0); | |
| 197 | 197 | const src_loc = src.toSrcLoc(self.decl); |
| 198 | 198 | assert(self.error_msg == null); |
| 199 | 199 | 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 |
| 8 | 8 | pub const enable_logging: bool = @ZIG_ENABLE_LOGGING_BOOL@; |
| 9 | 9 | pub const enable_link_snapshots: bool = false; |
| 10 | 10 | pub const enable_tracy = false; |
| 11 | pub const value_tracing = false; | |
| 11 | 12 | pub const is_stage1 = true; |
| 12 | 13 | pub const skip_non_native = false; |
| 13 | 14 | pub const omit_stage2: bool = @ZIG_OMIT_STAGE2_BOOL@; |
src/print_zir.zig+10-10| ... | ... | @@ -497,7 +497,7 @@ const Writer = struct { |
| 497 | 497 | .wasm_memory_size, |
| 498 | 498 | => { |
| 499 | 499 | 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); | |
| 501 | 501 | try self.writeInstRef(stream, inst_data.operand); |
| 502 | 502 | try stream.writeAll(")) "); |
| 503 | 503 | try self.writeSrc(stream, src); |
| ... | ... | @@ -510,7 +510,7 @@ const Writer = struct { |
| 510 | 510 | .prefetch, |
| 511 | 511 | => { |
| 512 | 512 | 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); | |
| 514 | 514 | try self.writeInstRef(stream, inst_data.lhs); |
| 515 | 515 | try stream.writeAll(", "); |
| 516 | 516 | try self.writeInstRef(stream, inst_data.rhs); |
| ... | ... | @@ -520,7 +520,7 @@ const Writer = struct { |
| 520 | 520 | |
| 521 | 521 | .field_call_bind_named => { |
| 522 | 522 | 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); | |
| 524 | 524 | try self.writeInstRef(stream, extra.lhs); |
| 525 | 525 | try stream.writeAll(", "); |
| 526 | 526 | try self.writeInstRef(stream, extra.field_name); |
| ... | ... | @@ -531,7 +531,7 @@ const Writer = struct { |
| 531 | 531 | } |
| 532 | 532 | |
| 533 | 533 | 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)); | |
| 535 | 535 | try stream.writeAll(")) "); |
| 536 | 536 | try self.writeSrc(stream, src); |
| 537 | 537 | } |
| ... | ... | @@ -1050,7 +1050,7 @@ const Writer = struct { |
| 1050 | 1050 | |
| 1051 | 1051 | fn writeNodeMultiOp(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 1052 | 1052 | 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); | |
| 1054 | 1054 | const operands = self.code.refSlice(extra.end, extended.small); |
| 1055 | 1055 | |
| 1056 | 1056 | for (operands) |operand, i| { |
| ... | ... | @@ -1074,7 +1074,7 @@ const Writer = struct { |
| 1074 | 1074 | |
| 1075 | 1075 | fn writeAsm(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 1076 | 1076 | 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); | |
| 1078 | 1078 | const outputs_len = @truncate(u5, extended.small); |
| 1079 | 1079 | const inputs_len = @truncate(u5, extended.small >> 5); |
| 1080 | 1080 | const clobbers_len = @truncate(u5, extended.small >> 10); |
| ... | ... | @@ -1145,7 +1145,7 @@ const Writer = struct { |
| 1145 | 1145 | |
| 1146 | 1146 | fn writeOverflowArithmetic(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 1147 | 1147 | 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); | |
| 1149 | 1149 | |
| 1150 | 1150 | try self.writeInstRef(stream, extra.lhs); |
| 1151 | 1151 | try stream.writeAll(", "); |
| ... | ... | @@ -1898,7 +1898,7 @@ const Writer = struct { |
| 1898 | 1898 | inst: Zir.Inst.Index, |
| 1899 | 1899 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { |
| 1900 | 1900 | 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); | |
| 1902 | 1902 | try stream.writeAll(") "); |
| 1903 | 1903 | try self.writeSrc(stream, src); |
| 1904 | 1904 | } |
| ... | ... | @@ -2117,7 +2117,7 @@ const Writer = struct { |
| 2117 | 2117 | fn writeAllocExtended(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 2118 | 2118 | const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand); |
| 2119 | 2119 | 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); | |
| 2121 | 2121 | |
| 2122 | 2122 | var extra_index: usize = extra.end; |
| 2123 | 2123 | const type_inst: Zir.Inst.Ref = if (!small.has_type) .none else blk: { |
| ... | ... | @@ -2351,7 +2351,7 @@ const Writer = struct { |
| 2351 | 2351 | |
| 2352 | 2352 | fn writeSrcNode(self: *Writer, stream: anytype, src_node: ?i32) !void { |
| 2353 | 2353 | const node_offset = src_node orelse return; |
| 2354 | const src: LazySrcLoc = .{ .node_offset = node_offset }; | |
| 2354 | const src = LazySrcLoc.nodeOffset(node_offset); | |
| 2355 | 2355 | try stream.writeAll(" "); |
| 2356 | 2356 | return self.writeSrc(stream, src); |
| 2357 | 2357 | } |
src/test.zig+36-7| ... | ... | @@ -61,10 +61,12 @@ const ErrorMsg = union(enum) { |
| 61 | 61 | // this is a workaround for stage1 compiler bug I ran into when making it ?u32 |
| 62 | 62 | column: u32, |
| 63 | 63 | kind: Kind, |
| 64 | count: u32, | |
| 64 | 65 | }, |
| 65 | 66 | plain: struct { |
| 66 | 67 | msg: []const u8, |
| 67 | 68 | kind: Kind, |
| 69 | count: u32, | |
| 68 | 70 | }, |
| 69 | 71 | |
| 70 | 72 | const Kind = enum { |
| ... | ... | @@ -81,12 +83,14 @@ const ErrorMsg = union(enum) { |
| 81 | 83 | .line = @intCast(u32, src.line), |
| 82 | 84 | .column = @intCast(u32, src.column), |
| 83 | 85 | .kind = kind, |
| 86 | .count = src.count, | |
| 84 | 87 | }, |
| 85 | 88 | }, |
| 86 | 89 | .plain => |plain| return .{ |
| 87 | 90 | .plain = .{ |
| 88 | 91 | .msg = plain.msg, |
| 89 | 92 | .kind = kind, |
| 93 | .count = plain.count, | |
| 90 | 94 | }, |
| 91 | 95 | }, |
| 92 | 96 | } |
| ... | ... | @@ -118,10 +122,16 @@ const ErrorMsg = union(enum) { |
| 118 | 122 | try writer.writeAll("?: "); |
| 119 | 123 | } |
| 120 | 124 | } |
| 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 | } | |
| 122 | 129 | }, |
| 123 | 130 | .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 | } | |
| 125 | 135 | }, |
| 126 | 136 | } |
| 127 | 137 | } |
| ... | ... | @@ -647,12 +657,20 @@ pub const TestContext = struct { |
| 647 | 657 | for (errors) |err_msg_line, i| { |
| 648 | 658 | if (std.mem.startsWith(u8, err_msg_line, "error: ")) { |
| 649 | 659 | 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 | }, | |
| 651 | 665 | }; |
| 652 | 666 | continue; |
| 653 | 667 | } else if (std.mem.startsWith(u8, err_msg_line, "note: ")) { |
| 654 | 668 | 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 | }, | |
| 656 | 674 | }; |
| 657 | 675 | continue; |
| 658 | 676 | } |
| ... | ... | @@ -662,7 +680,7 @@ pub const TestContext = struct { |
| 662 | 680 | const line_text = it.next() orelse @panic("missing line"); |
| 663 | 681 | const col_text = it.next() orelse @panic("missing column"); |
| 664 | 682 | 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: " | |
| 666 | 684 | |
| 667 | 685 | const line: ?u32 = if (std.mem.eql(u8, line_text, "?")) |
| 668 | 686 | null |
| ... | ... | @@ -695,6 +713,14 @@ pub const TestContext = struct { |
| 695 | 713 | break :blk n - 1; |
| 696 | 714 | } else std.math.maxInt(u32); |
| 697 | 715 | |
| 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 | ||
| 698 | 724 | array[i] = .{ |
| 699 | 725 | .src = .{ |
| 700 | 726 | .src_path = src_path, |
| ... | ... | @@ -702,6 +728,7 @@ pub const TestContext = struct { |
| 702 | 728 | .line = line_0based, |
| 703 | 729 | .column = column_0based, |
| 704 | 730 | .kind = kind, |
| 731 | .count = count, | |
| 705 | 732 | }, |
| 706 | 733 | }; |
| 707 | 734 | } |
| ... | ... | @@ -1606,7 +1633,8 @@ pub const TestContext = struct { |
| 1606 | 1633 | (case_msg.src.column == std.math.maxInt(u32) or |
| 1607 | 1634 | actual_msg.column == case_msg.src.column) and |
| 1608 | 1635 | 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) | |
| 1610 | 1638 | { |
| 1611 | 1639 | handled_errors[i] = true; |
| 1612 | 1640 | break; |
| ... | ... | @@ -1616,7 +1644,8 @@ pub const TestContext = struct { |
| 1616 | 1644 | if (ex_tag != .plain) continue; |
| 1617 | 1645 | |
| 1618 | 1646 | 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) | |
| 1620 | 1649 | { |
| 1621 | 1650 | handled_errors[i] = true; |
| 1622 | 1651 | break; |
test/behavior/bugs/920.zig+17-3| ... | ... | @@ -1,14 +1,24 @@ |
| 1 | const builtin = @import("builtin"); | |
| 1 | 2 | const std = @import("std"); |
| 2 | 3 | const Random = std.rand.Random; |
| 3 | 4 | |
| 5 | const zeroCaseFn = switch (builtin.zig_backend) { | |
| 6 | .stage1 => fn (*Random, f64) f64, | |
| 7 | else => *const fn (*Random, f64) f64, | |
| 8 | }; | |
| 9 | const pdfFn = switch (builtin.zig_backend) { | |
| 10 | .stage1 => fn (f64) f64, | |
| 11 | else => *const fn (f64) f64, | |
| 12 | }; | |
| 13 | ||
| 4 | 14 | const ZigTable = struct { |
| 5 | 15 | r: f64, |
| 6 | 16 | x: [257]f64, |
| 7 | 17 | f: [257]f64, |
| 8 | 18 | |
| 9 | pdf: fn (f64) f64, | |
| 19 | pdf: pdfFn, | |
| 10 | 20 | is_symmetric: bool, |
| 11 | zero_case: fn (*Random, f64) f64, | |
| 21 | zero_case: zeroCaseFn, | |
| 12 | 22 | }; |
| 13 | 23 | |
| 14 | 24 | fn 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: { |
| 56 | 66 | }; |
| 57 | 67 | |
| 58 | 68 | test "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 | |
| 60 | 74 | |
| 61 | 75 | const NormalDist1 = blk: { |
| 62 | 76 | 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 { |
| 14 | 14 | // error |
| 15 | 15 | // |
| 16 | 16 | // :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 { |
| 233 | 233 | \\} |
| 234 | 234 | , ""); |
| 235 | 235 | } |
| 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 | } | |
| 260 | 236 | { |
| 261 | 237 | var case = ctx.exeFromCompiledC("control flow", .{}); |
| 262 | 238 |