| ... | @@ -130,6 +130,63 @@ const Writer = struct { | ... | @@ -130,6 +130,63 @@ const Writer = struct { |
| 130 | recurse_decls: bool, | 130 | recurse_decls: bool, |
| 131 | recurse_blocks: bool, | 131 | recurse_blocks: bool, |
| 132 | | 132 | |
| | 133 | /// Using `std.zig.findLineColumn` whenever we need to resolve a source location makes ZIR |
| | 134 | /// printing O(N^2), which can have drastic effects - taking a ZIR dump from a few seconds to |
| | 135 | /// many minutes. Since we're usually resolving source locations close to one another, |
| | 136 | /// preserving state across source location resolutions speeds things up a lot. |
| | 137 | line_col_cursor: struct { |
| | 138 | line: usize = 0, |
| | 139 | column: usize = 0, |
| | 140 | line_start: usize = 0, |
| | 141 | off: usize = 0, |
| | 142 | |
| | 143 | fn find(cur: *@This(), source: []const u8, want_offset: usize) std.zig.Loc { |
| | 144 | if (want_offset < cur.off) { |
| | 145 | // Go back to the start of this line |
| | 146 | cur.off = cur.line_start; |
| | 147 | cur.column = 0; |
| | 148 | |
| | 149 | while (want_offset < cur.off) { |
| | 150 | // Go back to the newline |
| | 151 | cur.off -= 1; |
| | 152 | |
| | 153 | // Seek to the start of the previous line |
| | 154 | while (cur.off > 0 and source[cur.off - 1] != '\n') { |
| | 155 | cur.off -= 1; |
| | 156 | } |
| | 157 | cur.line_start = cur.off; |
| | 158 | cur.line -= 1; |
| | 159 | } |
| | 160 | } |
| | 161 | |
| | 162 | // The cursor is now positioned before `want_offset`. |
| | 163 | // Seek forward as in `std.zig.findLineColumn`. |
| | 164 | |
| | 165 | while (cur.off < want_offset) : (cur.off += 1) { |
| | 166 | switch (source[cur.off]) { |
| | 167 | '\n' => { |
| | 168 | cur.line += 1; |
| | 169 | cur.column = 0; |
| | 170 | cur.line_start = cur.off + 1; |
| | 171 | }, |
| | 172 | else => { |
| | 173 | cur.column += 1; |
| | 174 | }, |
| | 175 | } |
| | 176 | } |
| | 177 | |
| | 178 | while (cur.off < source.len and source[cur.off] != '\n') { |
| | 179 | cur.off += 1; |
| | 180 | } |
| | 181 | |
| | 182 | return .{ |
| | 183 | .line = cur.line, |
| | 184 | .column = cur.column, |
| | 185 | .source_line = source[cur.line_start..cur.off], |
| | 186 | }; |
| | 187 | } |
| | 188 | } = .{}, |
| | 189 | |
| 133 | fn relativeToNodeIndex(self: *Writer, offset: i32) Ast.Node.Index { | 190 | fn relativeToNodeIndex(self: *Writer, offset: i32) Ast.Node.Index { |
| 134 | return @as(Ast.Node.Index, @bitCast(offset + @as(i32, @bitCast(self.parent_decl_node)))); | 191 | return @as(Ast.Node.Index, @bitCast(offset + @as(i32, @bitCast(self.parent_decl_node)))); |
| 135 | } | 192 | } |
| ... | @@ -2590,8 +2647,8 @@ const Writer = struct { | ... | @@ -2590,8 +2647,8 @@ const Writer = struct { |
| 2590 | .lazy = src, | 2647 | .lazy = src, |
| 2591 | }; | 2648 | }; |
| 2592 | const src_span = src_loc.span(self.gpa) catch unreachable; | 2649 | const src_span = src_loc.span(self.gpa) catch unreachable; |
| 2593 | const start = std.zig.findLineColumn(tree.source, src_span.start); | 2650 | const start = self.line_col_cursor.find(tree.source, src_span.start); |
| 2594 | const end = std.zig.findLineColumn(tree.source, src_span.end); | 2651 | const end = self.line_col_cursor.find(tree.source, src_span.end); |
| 2595 | try stream.print("{s}:{d}:{d} to :{d}:{d}", .{ | 2652 | try stream.print("{s}:{d}:{d} to :{d}:{d}", .{ |
| 2596 | @tagName(src), start.line + 1, start.column + 1, | 2653 | @tagName(src), start.line + 1, start.column + 1, |
| 2597 | end.line + 1, end.column + 1, | 2654 | end.line + 1, end.column + 1, |