mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 05:48:31 +00:00
stage2: improve debugging tools
llvm: dump failed module when -femit-llvm-ir set print_air: * print fully qualified name * use Type.fmt and Value.fmtValue, fmtDebug is useless TypedValue * handle anon structs and tuples * fix bugs
This commit is contained in:
parent
002df65b6e
commit
0f820d0bdf
@ -3790,9 +3790,12 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
|
||||
defer liveness.deinit(gpa);
|
||||
|
||||
if (builtin.mode == .Debug and mod.comp.verbose_air) {
|
||||
std.debug.print("# Begin Function AIR: {s}:\n", .{decl.name});
|
||||
const fqn = try decl.getFullyQualifiedName(mod);
|
||||
defer mod.gpa.free(fqn);
|
||||
|
||||
std.debug.print("# Begin Function AIR: {s}:\n", .{fqn});
|
||||
@import("print_air.zig").dump(mod, air, liveness);
|
||||
std.debug.print("# End Function AIR: {s}\n\n", .{decl.name});
|
||||
std.debug.print("# End Function AIR: {s}\n\n", .{fqn});
|
||||
}
|
||||
|
||||
mod.comp.bin_file.updateFunc(mod, func, air, liveness) catch |err| switch (err) {
|
||||
|
||||
@ -144,7 +144,41 @@ pub fn print(
|
||||
return writer.writeAll(".{ ... }");
|
||||
}
|
||||
const vals = val.castTag(.aggregate).?.data;
|
||||
if (ty.zigTypeTag() == .Struct) {
|
||||
if (ty.castTag(.anon_struct)) |anon_struct| {
|
||||
const field_names = anon_struct.data.names;
|
||||
const types = anon_struct.data.types;
|
||||
const max_len = std.math.min(types.len, max_aggregate_items);
|
||||
|
||||
var i: u32 = 0;
|
||||
while (i < max_len) : (i += 1) {
|
||||
if (i != 0) try writer.writeAll(", ");
|
||||
try writer.print(".{s} = ", .{field_names[i]});
|
||||
try print(.{
|
||||
.ty = types[i],
|
||||
.val = vals[i],
|
||||
}, writer, level - 1, mod);
|
||||
}
|
||||
if (types.len > max_aggregate_items) {
|
||||
try writer.writeAll(", ...");
|
||||
}
|
||||
return writer.writeAll(" }");
|
||||
} else if (ty.isTuple()) {
|
||||
const fields = ty.tupleFields();
|
||||
const max_len = std.math.min(fields.types.len, max_aggregate_items);
|
||||
|
||||
var i: u32 = 0;
|
||||
while (i < max_len) : (i += 1) {
|
||||
if (i != 0) try writer.writeAll(", ");
|
||||
try print(.{
|
||||
.ty = fields.types[i],
|
||||
.val = vals[i],
|
||||
}, writer, level - 1, mod);
|
||||
}
|
||||
if (fields.types.len > max_aggregate_items) {
|
||||
try writer.writeAll(", ...");
|
||||
}
|
||||
return writer.writeAll(" }");
|
||||
} else if (ty.zigTypeTag() == .Struct) {
|
||||
try writer.writeAll(".{ ");
|
||||
const struct_fields = ty.structFields();
|
||||
const len = struct_fields.count();
|
||||
@ -194,7 +228,7 @@ pub fn print(
|
||||
try writer.writeAll(".{ ");
|
||||
|
||||
try print(.{
|
||||
.ty = ty.unionTagType().?,
|
||||
.ty = ty.cast(Type.Payload.Union).?.data.tag_ty,
|
||||
.val = union_val.tag,
|
||||
}, writer, level - 1, mod);
|
||||
try writer.writeAll(" = ");
|
||||
@ -278,19 +312,27 @@ pub fn print(
|
||||
.elem_ptr => {
|
||||
const elem_ptr = val.castTag(.elem_ptr).?.data;
|
||||
try writer.writeAll("&");
|
||||
try print(.{
|
||||
.ty = elem_ptr.elem_ty,
|
||||
.val = elem_ptr.array_ptr,
|
||||
}, writer, level - 1, mod);
|
||||
if (level == 0) {
|
||||
try writer.writeAll("(ptr)");
|
||||
} else {
|
||||
try print(.{
|
||||
.ty = elem_ptr.elem_ty,
|
||||
.val = elem_ptr.array_ptr,
|
||||
}, writer, level - 1, mod);
|
||||
}
|
||||
return writer.print("[{}]", .{elem_ptr.index});
|
||||
},
|
||||
.field_ptr => {
|
||||
const field_ptr = val.castTag(.field_ptr).?.data;
|
||||
try writer.writeAll("&");
|
||||
try print(.{
|
||||
.ty = field_ptr.container_ty,
|
||||
.val = field_ptr.container_ptr,
|
||||
}, writer, level - 1, mod);
|
||||
if (level == 0) {
|
||||
try writer.writeAll("(ptr)");
|
||||
} else {
|
||||
try print(.{
|
||||
.ty = field_ptr.container_ty,
|
||||
.val = field_ptr.container_ptr,
|
||||
}, writer, level - 1, mod);
|
||||
}
|
||||
|
||||
if (field_ptr.container_ty.zigTypeTag() == .Struct) {
|
||||
const field_name = field_ptr.container_ty.structFields().keys()[field_ptr.field_index];
|
||||
@ -344,6 +386,9 @@ pub fn print(
|
||||
return writer.writeAll(" }");
|
||||
},
|
||||
.slice => {
|
||||
if (level == 0) {
|
||||
return writer.writeAll(".{ ... }");
|
||||
}
|
||||
const payload = val.castTag(.slice).?.data;
|
||||
try writer.writeAll(".{ ");
|
||||
const elem_ty = ty.elemType2();
|
||||
@ -372,17 +417,25 @@ pub fn print(
|
||||
.@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
|
||||
.eu_payload => {
|
||||
val = val.castTag(.eu_payload).?.data;
|
||||
ty = ty.errorUnionPayload();
|
||||
},
|
||||
.opt_payload => {
|
||||
val = val.castTag(.opt_payload).?.data;
|
||||
var buf: Type.Payload.ElemType = undefined;
|
||||
ty = ty.optionalChild(&buf);
|
||||
return print(.{ .ty = ty, .val = val }, writer, level, mod);
|
||||
},
|
||||
.eu_payload_ptr => {
|
||||
try writer.writeAll("&");
|
||||
val = val.castTag(.eu_payload_ptr).?.data.container_ptr;
|
||||
ty = ty.elemType2().errorUnionPayload();
|
||||
},
|
||||
.opt_payload_ptr => {
|
||||
try writer.writeAll("&");
|
||||
val = val.castTag(.opt_payload_ptr).?.data.container_ptr;
|
||||
val = val.castTag(.opt_payload).?.data;
|
||||
var buf: Type.Payload.ElemType = undefined;
|
||||
ty = ty.elemType2().optionalChild(&buf);
|
||||
return print(.{ .ty = ty, .val = val }, writer, level, mod);
|
||||
},
|
||||
|
||||
// TODO these should not appear in this function
|
||||
|
||||
@ -599,6 +599,13 @@ pub const Object = struct {
|
||||
self.llvm_module.dump();
|
||||
}
|
||||
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
const mod = comp.bin_file.options.module.?;
|
||||
const cache_dir = mod.zig_cache_artifact_directory;
|
||||
|
||||
if (std.debug.runtime_safety) {
|
||||
var error_message: [*:0]const u8 = undefined;
|
||||
// verifyModule always allocs the error_message even if there is no error
|
||||
@ -606,17 +613,15 @@ pub const Object = struct {
|
||||
|
||||
if (self.llvm_module.verify(.ReturnStatus, &error_message).toBool()) {
|
||||
std.debug.print("\n{s}\n", .{error_message});
|
||||
|
||||
if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path| {
|
||||
_ = self.llvm_module.printModuleToFile(emit_llvm_ir_path, &error_message);
|
||||
}
|
||||
|
||||
@panic("LLVM module verification failed");
|
||||
}
|
||||
}
|
||||
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
const mod = comp.bin_file.options.module.?;
|
||||
const cache_dir = mod.zig_cache_artifact_directory;
|
||||
|
||||
var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit|
|
||||
try emit.basenamePath(arena, try arena.dupeZ(u8, comp.bin_file.intermediary_basename.?))
|
||||
else
|
||||
|
||||
@ -390,6 +390,9 @@ pub const Module = opaque {
|
||||
|
||||
pub const setModuleInlineAsm2 = LLVMSetModuleInlineAsm2;
|
||||
extern fn LLVMSetModuleInlineAsm2(M: *const Module, Asm: [*]const u8, Len: usize) void;
|
||||
|
||||
pub const printModuleToFile = LLVMPrintModuleToFile;
|
||||
extern fn LLVMPrintModuleToFile(M: *const Module, Filename: [*:0]const u8, ErrorMessage: *[*:0]const u8) Bool;
|
||||
};
|
||||
|
||||
pub const lookupIntrinsicID = LLVMLookupIntrinsicID;
|
||||
|
||||
@ -4,6 +4,7 @@ const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
|
||||
|
||||
const Module = @import("Module.zig");
|
||||
const Value = @import("value.zig").Value;
|
||||
const Type = @import("type.zig").Type;
|
||||
const Air = @import("Air.zig");
|
||||
const Liveness = @import("Liveness.zig");
|
||||
|
||||
@ -304,14 +305,27 @@ const Writer = struct {
|
||||
// no-op, no argument to write
|
||||
}
|
||||
|
||||
fn writeType(w: *Writer, s: anytype, ty: Type) !void {
|
||||
const t = ty.tag();
|
||||
switch (t) {
|
||||
.inferred_alloc_const => try s.writeAll("(inferred_alloc_const)"),
|
||||
.inferred_alloc_mut => try s.writeAll("(inferred_alloc_mut)"),
|
||||
.generic_poison => try s.writeAll("(generic_poison)"),
|
||||
.var_args_param => try s.writeAll("(var_args_param)"),
|
||||
.bound_fn => try s.writeAll("(bound_fn)"),
|
||||
else => try ty.print(s, w.module),
|
||||
}
|
||||
}
|
||||
|
||||
fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
const ty = w.air.instructions.items(.data)[inst].ty;
|
||||
try s.print("{}", .{ty.fmtDebug()});
|
||||
try w.writeType(s, ty);
|
||||
}
|
||||
|
||||
fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
const ty_op = w.air.instructions.items(.data)[inst].ty_op;
|
||||
try s.print("{}, ", .{w.air.getRefType(ty_op.ty).fmtDebug()});
|
||||
try w.writeType(s, w.air.getRefType(ty_op.ty));
|
||||
try s.writeAll(", ");
|
||||
try w.writeOperand(s, inst, 0, ty_op.operand);
|
||||
}
|
||||
|
||||
@ -320,7 +334,8 @@ const Writer = struct {
|
||||
const extra = w.air.extraData(Air.Block, ty_pl.payload);
|
||||
const body = w.air.extra[extra.end..][0..extra.data.body_len];
|
||||
|
||||
try s.print("{}, {{\n", .{w.air.getRefType(ty_pl.ty).fmtDebug()});
|
||||
try w.writeType(s, w.air.getRefType(ty_pl.ty));
|
||||
try s.writeAll(", {\n");
|
||||
const old_indent = w.indent;
|
||||
w.indent += 2;
|
||||
try w.writeBody(s, body);
|
||||
@ -335,7 +350,8 @@ const Writer = struct {
|
||||
const len = @intCast(usize, vector_ty.arrayLen());
|
||||
const elements = @ptrCast([]const Air.Inst.Ref, w.air.extra[ty_pl.payload..][0..len]);
|
||||
|
||||
try s.print("{}, [", .{vector_ty.fmtDebug()});
|
||||
try w.writeType(s, vector_ty);
|
||||
try s.writeAll(", [");
|
||||
for (elements) |elem, i| {
|
||||
if (i != 0) try s.writeAll(", ");
|
||||
try w.writeOperand(s, inst, i, elem);
|
||||
@ -408,7 +424,8 @@ const Writer = struct {
|
||||
const extra = w.air.extraData(Air.Bin, pl_op.payload).data;
|
||||
|
||||
const elem_ty = w.air.typeOfIndex(inst).childType();
|
||||
try s.print("{}, ", .{elem_ty.fmtDebug()});
|
||||
try w.writeType(s, elem_ty);
|
||||
try s.writeAll(", ");
|
||||
try w.writeOperand(s, inst, 0, pl_op.operand);
|
||||
try s.writeAll(", ");
|
||||
try w.writeOperand(s, inst, 1, extra.lhs);
|
||||
@ -511,7 +528,9 @@ const Writer = struct {
|
||||
fn writeConstant(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
|
||||
const val = w.air.values[ty_pl.payload];
|
||||
try s.print("{}, {}", .{ w.air.getRefType(ty_pl.ty).fmtDebug(), val.fmtDebug() });
|
||||
const ty = w.air.getRefType(ty_pl.ty);
|
||||
try w.writeType(s, ty);
|
||||
try s.print(", {}", .{val.fmtValue(ty, w.module)});
|
||||
}
|
||||
|
||||
fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
@ -523,7 +542,7 @@ const Writer = struct {
|
||||
var op_index: usize = 0;
|
||||
|
||||
const ret_ty = w.air.typeOfIndex(inst);
|
||||
try s.print("{}", .{ret_ty.fmtDebug()});
|
||||
try w.writeType(s, ret_ty);
|
||||
|
||||
if (is_volatile) {
|
||||
try s.writeAll(", volatile");
|
||||
@ -647,7 +666,10 @@ const Writer = struct {
|
||||
const body = w.air.extra[extra.end..][0..extra.data.body_len];
|
||||
|
||||
try w.writeOperand(s, inst, 0, extra.data.ptr);
|
||||
try s.print(", {}, {{\n", .{w.air.getRefType(ty_pl.ty).fmtDebug()});
|
||||
|
||||
try s.writeAll(", ");
|
||||
try w.writeType(s, w.air.getRefType(ty_pl.ty));
|
||||
try s.writeAll(", {\n");
|
||||
const old_indent = w.indent;
|
||||
w.indent += 2;
|
||||
try w.writeBody(s, body);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user