Commit d70853ba39
Changed files (2)
src/main.zig
@@ -122,6 +122,7 @@ const debug_usage = normal_usage ++
\\Debug Commands:
\\
\\ changelist Compute mappings from old ZIR to new ZIR
+ \\ dump-zir Dump a file containing cached ZIR
\\
;
@@ -326,6 +327,8 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
return cmdAstCheck(gpa, arena, cmd_args);
} else if (debug_extensions_enabled and mem.eql(u8, cmd, "changelist")) {
return cmdChangelist(gpa, arena, cmd_args);
+ } else if (debug_extensions_enabled and mem.eql(u8, cmd, "dump-zir")) {
+ return cmdDumpZir(gpa, arena, cmd_args);
} else {
std.log.info("{s}", .{usage});
fatal("unknown command: {s}", .{args[1]});
@@ -5579,6 +5582,65 @@ pub fn cmdAstCheck(
return @import("print_zir.zig").renderAsTextToFile(gpa, &file, io.getStdOut());
}
+/// This is only enabled for debug builds.
+pub fn cmdDumpZir(
+ gpa: Allocator,
+ arena: Allocator,
+ args: []const []const u8,
+) !void {
+ _ = arena;
+ const Zir = @import("Zir.zig");
+
+ const cache_file = args[0];
+
+ var f = fs.cwd().openFile(cache_file, .{}) catch |err| {
+ fatal("unable to open zir cache file for dumping '{s}': {s}", .{ cache_file, @errorName(err) });
+ };
+ defer f.close();
+
+ var file: Module.File = .{
+ .status = .never_loaded,
+ .source_loaded = false,
+ .tree_loaded = false,
+ .zir_loaded = true,
+ .sub_file_path = undefined,
+ .source = undefined,
+ .stat = undefined,
+ .tree = undefined,
+ .zir = try Module.loadZirCache(gpa, f),
+ .pkg = undefined,
+ .root_decl = .none,
+ };
+
+ {
+ const instruction_bytes = file.zir.instructions.len *
+ // Here we don't use @sizeOf(Zir.Inst.Data) because it would include
+ // the debug safety tag but we want to measure release size.
+ (@sizeOf(Zir.Inst.Tag) + 8);
+ const extra_bytes = file.zir.extra.len * @sizeOf(u32);
+ const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +
+ file.zir.string_bytes.len * @sizeOf(u8);
+ const stdout = io.getStdOut();
+ const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
+ // zig fmt: off
+ try stdout.writer().print(
+ \\# Total ZIR bytes: {}
+ \\# Instructions: {d} ({})
+ \\# String Table Bytes: {}
+ \\# Extra Data Items: {d} ({})
+ \\
+ , .{
+ fmtIntSizeBin(total_bytes),
+ file.zir.instructions.len, fmtIntSizeBin(instruction_bytes),
+ fmtIntSizeBin(file.zir.string_bytes.len),
+ file.zir.extra.len, fmtIntSizeBin(extra_bytes),
+ });
+ // zig fmt: on
+ }
+
+ return @import("print_zir.zig").renderAsTextToFile(gpa, &file, io.getStdOut());
+}
+
/// This is only enabled for debug builds.
pub fn cmdChangelist(
gpa: Allocator,
src/Module.zig
@@ -3671,74 +3671,13 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
file.sub_file_path, header.instructions_len,
});
- var instructions: std.MultiArrayList(Zir.Inst) = .{};
- defer instructions.deinit(gpa);
-
- try instructions.setCapacity(gpa, header.instructions_len);
- instructions.len = header.instructions_len;
-
- var zir: Zir = .{
- .instructions = instructions.toOwnedSlice(),
- .string_bytes = &.{},
- .extra = &.{},
- };
- var keep_zir = false;
- defer if (!keep_zir) zir.deinit(gpa);
-
- zir.string_bytes = try gpa.alloc(u8, header.string_bytes_len);
- zir.extra = try gpa.alloc(u32, header.extra_len);
-
- const safety_buffer = if (data_has_safety_tag)
- try gpa.alloc([8]u8, header.instructions_len)
- else
- undefined;
- defer if (data_has_safety_tag) gpa.free(safety_buffer);
-
- const data_ptr = if (data_has_safety_tag)
- @ptrCast([*]u8, safety_buffer.ptr)
- else
- @ptrCast([*]u8, zir.instructions.items(.data).ptr);
-
- var iovecs = [_]std.os.iovec{
- .{
- .iov_base = @ptrCast([*]u8, zir.instructions.items(.tag).ptr),
- .iov_len = header.instructions_len,
- },
- .{
- .iov_base = data_ptr,
- .iov_len = header.instructions_len * 8,
- },
- .{
- .iov_base = zir.string_bytes.ptr,
- .iov_len = header.string_bytes_len,
- },
- .{
- .iov_base = @ptrCast([*]u8, zir.extra.ptr),
- .iov_len = header.extra_len * 4,
+ file.zir = loadZirCacheBody(gpa, header, cache_file) catch |err| switch (err) {
+ error.UnexpectedFileSize => {
+ log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path});
+ break :update;
},
+ else => |e| return e,
};
- const amt_read = try cache_file.readvAll(&iovecs);
- const amt_expected = zir.instructions.len * 9 +
- zir.string_bytes.len +
- zir.extra.len * 4;
- if (amt_read != amt_expected) {
- log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path});
- break :update;
- }
- if (data_has_safety_tag) {
- const tags = zir.instructions.items(.tag);
- for (zir.instructions.items(.data), 0..) |*data, i| {
- const union_tag = Zir.Inst.Tag.data_tags[@enumToInt(tags[i])];
- const as_struct = @ptrCast(*HackDataLayout, data);
- as_struct.* = .{
- .safety_tag = @enumToInt(union_tag),
- .data = safety_buffer[i],
- };
- }
- }
-
- keep_zir = true;
- file.zir = zir;
file.zir_loaded = true;
file.stat = .{
.size = header.stat_size,
@@ -3916,6 +3855,76 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
}
}
+pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {
+ return loadZirCacheBody(gpa, try cache_file.reader().readStruct(Zir.Header), cache_file);
+}
+
+fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) !Zir {
+ var instructions: std.MultiArrayList(Zir.Inst) = .{};
+ errdefer instructions.deinit(gpa);
+
+ try instructions.setCapacity(gpa, header.instructions_len);
+ instructions.len = header.instructions_len;
+
+ var zir: Zir = .{
+ .instructions = instructions.toOwnedSlice(),
+ .string_bytes = &.{},
+ .extra = &.{},
+ };
+ errdefer zir.deinit(gpa);
+
+ zir.string_bytes = try gpa.alloc(u8, header.string_bytes_len);
+ zir.extra = try gpa.alloc(u32, header.extra_len);
+
+ const safety_buffer = if (data_has_safety_tag)
+ try gpa.alloc([8]u8, header.instructions_len)
+ else
+ undefined;
+ defer if (data_has_safety_tag) gpa.free(safety_buffer);
+
+ const data_ptr = if (data_has_safety_tag)
+ @ptrCast([*]u8, safety_buffer.ptr)
+ else
+ @ptrCast([*]u8, zir.instructions.items(.data).ptr);
+
+ var iovecs = [_]std.os.iovec{
+ .{
+ .iov_base = @ptrCast([*]u8, zir.instructions.items(.tag).ptr),
+ .iov_len = header.instructions_len,
+ },
+ .{
+ .iov_base = data_ptr,
+ .iov_len = header.instructions_len * 8,
+ },
+ .{
+ .iov_base = zir.string_bytes.ptr,
+ .iov_len = header.string_bytes_len,
+ },
+ .{
+ .iov_base = @ptrCast([*]u8, zir.extra.ptr),
+ .iov_len = header.extra_len * 4,
+ },
+ };
+ const amt_read = try cache_file.readvAll(&iovecs);
+ const amt_expected = zir.instructions.len * 9 +
+ zir.string_bytes.len +
+ zir.extra.len * 4;
+ if (amt_read != amt_expected) return error.UnexpectedFileSize;
+ if (data_has_safety_tag) {
+ const tags = zir.instructions.items(.tag);
+ for (zir.instructions.items(.data), 0..) |*data, i| {
+ const union_tag = Zir.Inst.Tag.data_tags[@enumToInt(tags[i])];
+ const as_struct = @ptrCast(*HackDataLayout, data);
+ as_struct.* = .{
+ .safety_tag = @enumToInt(union_tag),
+ .data = safety_buffer[i],
+ };
+ }
+ }
+
+ return zir;
+}
+
/// Patch ups:
/// * Struct.zir_index
/// * Decl.zir_index