mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 13:58:27 +00:00
main: add debug dump-zir command
This commit is contained in:
parent
a111130977
commit
d70853ba39
143
src/Module.zig
143
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 = &.{},
|
||||
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,
|
||||
};
|
||||
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,
|
||||
},
|
||||
};
|
||||
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
|
||||
|
||||
62
src/main.zig
62
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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user