| author | |
| committer | |
| log | 0f820d0bdf98b3f8429a9cf2f1b405c2c0a4d958 |
| tree | d8793ad6cd0258eb704d35fc536636aac3fa45fc |
| parent | 002df65b6ec55684d6bc6790ae7b0c0f4abb1375 |
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 bugs5 files changed, 114 insertions(+), 28 deletions(-)
src/Module.zig+5-2| ... | @@ -3790,9 +3790,12 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void { | ... | @@ -3790,9 +3790,12 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void { |
| 3790 | defer liveness.deinit(gpa); | 3790 | defer liveness.deinit(gpa); |
| 3791 | 3791 | ||
| 3792 | if (builtin.mode == .Debug and mod.comp.verbose_air) { | 3792 | if (builtin.mode == .Debug and mod.comp.verbose_air) { |
| 3793 | std.debug.print("# Begin Function AIR: {s}:\n", .{decl.name}); | 3793 | const fqn = try decl.getFullyQualifiedName(mod); |
| 3794 | defer mod.gpa.free(fqn); | ||
| 3795 | |||
| 3796 | std.debug.print("# Begin Function AIR: {s}:\n", .{fqn}); | ||
| 3794 | @import("print_air.zig").dump(mod, air, liveness); | 3797 | @import("print_air.zig").dump(mod, air, liveness); |
| 3795 | std.debug.print("# End Function AIR: {s}\n\n", .{decl.name}); | 3798 | std.debug.print("# End Function AIR: {s}\n\n", .{fqn}); |
| 3796 | } | 3799 | } |
| 3797 | 3800 | ||
| 3798 | mod.comp.bin_file.updateFunc(mod, func, air, liveness) catch |err| switch (err) { | 3801 | mod.comp.bin_file.updateFunc(mod, func, air, liveness) catch |err| switch (err) { |
src/TypedValue.zig+64-11| ... | @@ -144,7 +144,41 @@ pub fn print( | ... | @@ -144,7 +144,41 @@ pub fn print( |
| 144 | return writer.writeAll(".{ ... }"); | 144 | return writer.writeAll(".{ ... }"); |
| 145 | } | 145 | } |
| 146 | const vals = val.castTag(.aggregate).?.data; | 146 | const vals = val.castTag(.aggregate).?.data; |
| 147 | if (ty.zigTypeTag() == .Struct) { | 147 | if (ty.castTag(.anon_struct)) |anon_struct| { |
| 148 | const field_names = anon_struct.data.names; | ||
| 149 | const types = anon_struct.data.types; | ||
| 150 | const max_len = std.math.min(types.len, max_aggregate_items); | ||
| 151 | |||
| 152 | var i: u32 = 0; | ||
| 153 | while (i < max_len) : (i += 1) { | ||
| 154 | if (i != 0) try writer.writeAll(", "); | ||
| 155 | try writer.print(".{s} = ", .{field_names[i]}); | ||
| 156 | try print(.{ | ||
| 157 | .ty = types[i], | ||
| 158 | .val = vals[i], | ||
| 159 | }, writer, level - 1, mod); | ||
| 160 | } | ||
| 161 | if (types.len > max_aggregate_items) { | ||
| 162 | try writer.writeAll(", ..."); | ||
| 163 | } | ||
| 164 | return writer.writeAll(" }"); | ||
| 165 | } else if (ty.isTuple()) { | ||
| 166 | const fields = ty.tupleFields(); | ||
| 167 | const max_len = std.math.min(fields.types.len, max_aggregate_items); | ||
| 168 | |||
| 169 | var i: u32 = 0; | ||
| 170 | while (i < max_len) : (i += 1) { | ||
| 171 | if (i != 0) try writer.writeAll(", "); | ||
| 172 | try print(.{ | ||
| 173 | .ty = fields.types[i], | ||
| 174 | .val = vals[i], | ||
| 175 | }, writer, level - 1, mod); | ||
| 176 | } | ||
| 177 | if (fields.types.len > max_aggregate_items) { | ||
| 178 | try writer.writeAll(", ..."); | ||
| 179 | } | ||
| 180 | return writer.writeAll(" }"); | ||
| 181 | } else if (ty.zigTypeTag() == .Struct) { | ||
| 148 | try writer.writeAll(".{ "); | 182 | try writer.writeAll(".{ "); |
| 149 | const struct_fields = ty.structFields(); | 183 | const struct_fields = ty.structFields(); |
| 150 | const len = struct_fields.count(); | 184 | const len = struct_fields.count(); |
| ... | @@ -194,7 +228,7 @@ pub fn print( | ... | @@ -194,7 +228,7 @@ pub fn print( |
| 194 | try writer.writeAll(".{ "); | 228 | try writer.writeAll(".{ "); |
| 195 | 229 | ||
| 196 | try print(.{ | 230 | try print(.{ |
| 197 | .ty = ty.unionTagType().?, | 231 | .ty = ty.cast(Type.Payload.Union).?.data.tag_ty, |
| 198 | .val = union_val.tag, | 232 | .val = union_val.tag, |
| 199 | }, writer, level - 1, mod); | 233 | }, writer, level - 1, mod); |
| 200 | try writer.writeAll(" = "); | 234 | try writer.writeAll(" = "); |
| ... | @@ -278,19 +312,27 @@ pub fn print( | ... | @@ -278,19 +312,27 @@ pub fn print( |
| 278 | .elem_ptr => { | 312 | .elem_ptr => { |
| 279 | const elem_ptr = val.castTag(.elem_ptr).?.data; | 313 | const elem_ptr = val.castTag(.elem_ptr).?.data; |
| 280 | try writer.writeAll("&"); | 314 | try writer.writeAll("&"); |
| 281 | try print(.{ | 315 | if (level == 0) { |
| 282 | .ty = elem_ptr.elem_ty, | 316 | try writer.writeAll("(ptr)"); |
| 283 | .val = elem_ptr.array_ptr, | 317 | } else { |
| 284 | }, writer, level - 1, mod); | 318 | try print(.{ |
| 319 | .ty = elem_ptr.elem_ty, | ||
| 320 | .val = elem_ptr.array_ptr, | ||
| 321 | }, writer, level - 1, mod); | ||
| 322 | } | ||
| 285 | return writer.print("[{}]", .{elem_ptr.index}); | 323 | return writer.print("[{}]", .{elem_ptr.index}); |
| 286 | }, | 324 | }, |
| 287 | .field_ptr => { | 325 | .field_ptr => { |
| 288 | const field_ptr = val.castTag(.field_ptr).?.data; | 326 | const field_ptr = val.castTag(.field_ptr).?.data; |
| 289 | try writer.writeAll("&"); | 327 | try writer.writeAll("&"); |
| 290 | try print(.{ | 328 | if (level == 0) { |
| 291 | .ty = field_ptr.container_ty, | 329 | try writer.writeAll("(ptr)"); |
| 292 | .val = field_ptr.container_ptr, | 330 | } else { |
| 293 | }, writer, level - 1, mod); | 331 | try print(.{ |
| 332 | .ty = field_ptr.container_ty, | ||
| 333 | .val = field_ptr.container_ptr, | ||
| 334 | }, writer, level - 1, mod); | ||
| 335 | } | ||
| 294 | 336 | ||
| 295 | if (field_ptr.container_ty.zigTypeTag() == .Struct) { | 337 | if (field_ptr.container_ty.zigTypeTag() == .Struct) { |
| 296 | const field_name = field_ptr.container_ty.structFields().keys()[field_ptr.field_index]; | 338 | const field_name = field_ptr.container_ty.structFields().keys()[field_ptr.field_index]; |
| ... | @@ -344,6 +386,9 @@ pub fn print( | ... | @@ -344,6 +386,9 @@ pub fn print( |
| 344 | return writer.writeAll(" }"); | 386 | return writer.writeAll(" }"); |
| 345 | }, | 387 | }, |
| 346 | .slice => { | 388 | .slice => { |
| 389 | if (level == 0) { | ||
| 390 | return writer.writeAll(".{ ... }"); | ||
| 391 | } | ||
| 347 | const payload = val.castTag(.slice).?.data; | 392 | const payload = val.castTag(.slice).?.data; |
| 348 | try writer.writeAll(".{ "); | 393 | try writer.writeAll(".{ "); |
| 349 | const elem_ty = ty.elemType2(); | 394 | const elem_ty = ty.elemType2(); |
| ... | @@ -372,17 +417,25 @@ pub fn print( | ... | @@ -372,17 +417,25 @@ pub fn print( |
| 372 | .@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}), | 417 | .@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}), |
| 373 | .eu_payload => { | 418 | .eu_payload => { |
| 374 | val = val.castTag(.eu_payload).?.data; | 419 | val = val.castTag(.eu_payload).?.data; |
| 420 | ty = ty.errorUnionPayload(); | ||
| 375 | }, | 421 | }, |
| 376 | .opt_payload => { | 422 | .opt_payload => { |
| 377 | val = val.castTag(.opt_payload).?.data; | 423 | val = val.castTag(.opt_payload).?.data; |
| 424 | var buf: Type.Payload.ElemType = undefined; | ||
| 425 | ty = ty.optionalChild(&buf); | ||
| 426 | return print(.{ .ty = ty, .val = val }, writer, level, mod); | ||
| 378 | }, | 427 | }, |
| 379 | .eu_payload_ptr => { | 428 | .eu_payload_ptr => { |
| 380 | try writer.writeAll("&"); | 429 | try writer.writeAll("&"); |
| 381 | val = val.castTag(.eu_payload_ptr).?.data.container_ptr; | 430 | val = val.castTag(.eu_payload_ptr).?.data.container_ptr; |
| 431 | ty = ty.elemType2().errorUnionPayload(); | ||
| 382 | }, | 432 | }, |
| 383 | .opt_payload_ptr => { | 433 | .opt_payload_ptr => { |
| 384 | try writer.writeAll("&"); | 434 | try writer.writeAll("&"); |
| 385 | val = val.castTag(.opt_payload_ptr).?.data.container_ptr; | 435 | val = val.castTag(.opt_payload).?.data; |
| 436 | var buf: Type.Payload.ElemType = undefined; | ||
| 437 | ty = ty.elemType2().optionalChild(&buf); | ||
| 438 | return print(.{ .ty = ty, .val = val }, writer, level, mod); | ||
| 386 | }, | 439 | }, |
| 387 | 440 | ||
| 388 | // TODO these should not appear in this function | 441 | // TODO these should not appear in this function |
src/codegen/llvm.zig+12-7| ... | @@ -599,6 +599,13 @@ pub const Object = struct { | ... | @@ -599,6 +599,13 @@ pub const Object = struct { |
| 599 | self.llvm_module.dump(); | 599 | self.llvm_module.dump(); |
| 600 | } | 600 | } |
| 601 | 601 | ||
| 602 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); | ||
| 603 | defer arena_allocator.deinit(); | ||
| 604 | const arena = arena_allocator.allocator(); | ||
| 605 | |||
| 606 | const mod = comp.bin_file.options.module.?; | ||
| 607 | const cache_dir = mod.zig_cache_artifact_directory; | ||
| 608 | |||
| 602 | if (std.debug.runtime_safety) { | 609 | if (std.debug.runtime_safety) { |
| 603 | var error_message: [*:0]const u8 = undefined; | 610 | var error_message: [*:0]const u8 = undefined; |
| 604 | // verifyModule always allocs the error_message even if there is no error | 611 | // verifyModule always allocs the error_message even if there is no error |
| ... | @@ -606,17 +613,15 @@ pub const Object = struct { | ... | @@ -606,17 +613,15 @@ pub const Object = struct { |
| 606 | 613 | ||
| 607 | if (self.llvm_module.verify(.ReturnStatus, &error_message).toBool()) { | 614 | if (self.llvm_module.verify(.ReturnStatus, &error_message).toBool()) { |
| 608 | std.debug.print("\n{s}\n", .{error_message}); | 615 | std.debug.print("\n{s}\n", .{error_message}); |
| 616 | |||
| 617 | if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path| { | ||
| 618 | _ = self.llvm_module.printModuleToFile(emit_llvm_ir_path, &error_message); | ||
| 619 | } | ||
| 620 | |||
| 609 | @panic("LLVM module verification failed"); | 621 | @panic("LLVM module verification failed"); |
| 610 | } | 622 | } |
| 611 | } | 623 | } |
| 612 | 624 | ||
| 613 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); | ||
| 614 | defer arena_allocator.deinit(); | ||
| 615 | const arena = arena_allocator.allocator(); | ||
| 616 | |||
| 617 | const mod = comp.bin_file.options.module.?; | ||
| 618 | const cache_dir = mod.zig_cache_artifact_directory; | ||
| 619 | |||
| 620 | var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit| | 625 | var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit| |
| 621 | try emit.basenamePath(arena, try arena.dupeZ(u8, comp.bin_file.intermediary_basename.?)) | 626 | try emit.basenamePath(arena, try arena.dupeZ(u8, comp.bin_file.intermediary_basename.?)) |
| 622 | else | 627 | else |
src/codegen/llvm/bindings.zig+3| ... | @@ -390,6 +390,9 @@ pub const Module = opaque { | ... | @@ -390,6 +390,9 @@ pub const Module = opaque { |
| 390 | 390 | ||
| 391 | pub const setModuleInlineAsm2 = LLVMSetModuleInlineAsm2; | 391 | pub const setModuleInlineAsm2 = LLVMSetModuleInlineAsm2; |
| 392 | extern fn LLVMSetModuleInlineAsm2(M: *const Module, Asm: [*]const u8, Len: usize) void; | 392 | extern fn LLVMSetModuleInlineAsm2(M: *const Module, Asm: [*]const u8, Len: usize) void; |
| 393 | |||
| 394 | pub const printModuleToFile = LLVMPrintModuleToFile; | ||
| 395 | extern fn LLVMPrintModuleToFile(M: *const Module, Filename: [*:0]const u8, ErrorMessage: *[*:0]const u8) Bool; | ||
| 393 | }; | 396 | }; |
| 394 | 397 | ||
| 395 | pub const lookupIntrinsicID = LLVMLookupIntrinsicID; | 398 | pub const lookupIntrinsicID = LLVMLookupIntrinsicID; |
src/print_air.zig+30-8| ... | @@ -4,6 +4,7 @@ const fmtIntSizeBin = std.fmt.fmtIntSizeBin; | ... | @@ -4,6 +4,7 @@ const fmtIntSizeBin = std.fmt.fmtIntSizeBin; |
| 4 | 4 | ||
| 5 | const Module = @import("Module.zig"); | 5 | const Module = @import("Module.zig"); |
| 6 | const Value = @import("value.zig").Value; | 6 | const Value = @import("value.zig").Value; |
| 7 | const Type = @import("type.zig").Type; | ||
| 7 | const Air = @import("Air.zig"); | 8 | const Air = @import("Air.zig"); |
| 8 | const Liveness = @import("Liveness.zig"); | 9 | const Liveness = @import("Liveness.zig"); |
| 9 | 10 | ||
| ... | @@ -304,14 +305,27 @@ const Writer = struct { | ... | @@ -304,14 +305,27 @@ const Writer = struct { |
| 304 | // no-op, no argument to write | 305 | // no-op, no argument to write |
| 305 | } | 306 | } |
| 306 | 307 | ||
| 308 | fn writeType(w: *Writer, s: anytype, ty: Type) !void { | ||
| 309 | const t = ty.tag(); | ||
| 310 | switch (t) { | ||
| 311 | .inferred_alloc_const => try s.writeAll("(inferred_alloc_const)"), | ||
| 312 | .inferred_alloc_mut => try s.writeAll("(inferred_alloc_mut)"), | ||
| 313 | .generic_poison => try s.writeAll("(generic_poison)"), | ||
| 314 | .var_args_param => try s.writeAll("(var_args_param)"), | ||
| 315 | .bound_fn => try s.writeAll("(bound_fn)"), | ||
| 316 | else => try ty.print(s, w.module), | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 307 | fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 320 | fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 308 | const ty = w.air.instructions.items(.data)[inst].ty; | 321 | const ty = w.air.instructions.items(.data)[inst].ty; |
| 309 | try s.print("{}", .{ty.fmtDebug()}); | 322 | try w.writeType(s, ty); |
| 310 | } | 323 | } |
| 311 | 324 | ||
| 312 | fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 325 | fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 313 | const ty_op = w.air.instructions.items(.data)[inst].ty_op; | 326 | const ty_op = w.air.instructions.items(.data)[inst].ty_op; |
| 314 | try s.print("{}, ", .{w.air.getRefType(ty_op.ty).fmtDebug()}); | 327 | try w.writeType(s, w.air.getRefType(ty_op.ty)); |
| 328 | try s.writeAll(", "); | ||
| 315 | try w.writeOperand(s, inst, 0, ty_op.operand); | 329 | try w.writeOperand(s, inst, 0, ty_op.operand); |
| 316 | } | 330 | } |
| 317 | 331 | ||
| ... | @@ -320,7 +334,8 @@ const Writer = struct { | ... | @@ -320,7 +334,8 @@ const Writer = struct { |
| 320 | const extra = w.air.extraData(Air.Block, ty_pl.payload); | 334 | const extra = w.air.extraData(Air.Block, ty_pl.payload); |
| 321 | const body = w.air.extra[extra.end..][0..extra.data.body_len]; | 335 | const body = w.air.extra[extra.end..][0..extra.data.body_len]; |
| 322 | 336 | ||
| 323 | try s.print("{}, {{\n", .{w.air.getRefType(ty_pl.ty).fmtDebug()}); | 337 | try w.writeType(s, w.air.getRefType(ty_pl.ty)); |
| 338 | try s.writeAll(", {\n"); | ||
| 324 | const old_indent = w.indent; | 339 | const old_indent = w.indent; |
| 325 | w.indent += 2; | 340 | w.indent += 2; |
| 326 | try w.writeBody(s, body); | 341 | try w.writeBody(s, body); |
| ... | @@ -335,7 +350,8 @@ const Writer = struct { | ... | @@ -335,7 +350,8 @@ const Writer = struct { |
| 335 | const len = @intCast(usize, vector_ty.arrayLen()); | 350 | const len = @intCast(usize, vector_ty.arrayLen()); |
| 336 | const elements = @ptrCast([]const Air.Inst.Ref, w.air.extra[ty_pl.payload..][0..len]); | 351 | const elements = @ptrCast([]const Air.Inst.Ref, w.air.extra[ty_pl.payload..][0..len]); |
| 337 | 352 | ||
| 338 | try s.print("{}, [", .{vector_ty.fmtDebug()}); | 353 | try w.writeType(s, vector_ty); |
| 354 | try s.writeAll(", ["); | ||
| 339 | for (elements) |elem, i| { | 355 | for (elements) |elem, i| { |
| 340 | if (i != 0) try s.writeAll(", "); | 356 | if (i != 0) try s.writeAll(", "); |
| 341 | try w.writeOperand(s, inst, i, elem); | 357 | try w.writeOperand(s, inst, i, elem); |
| ... | @@ -408,7 +424,8 @@ const Writer = struct { | ... | @@ -408,7 +424,8 @@ const Writer = struct { |
| 408 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; | 424 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; |
| 409 | 425 | ||
| 410 | const elem_ty = w.air.typeOfIndex(inst).childType(); | 426 | const elem_ty = w.air.typeOfIndex(inst).childType(); |
| 411 | try s.print("{}, ", .{elem_ty.fmtDebug()}); | 427 | try w.writeType(s, elem_ty); |
| 428 | try s.writeAll(", "); | ||
| 412 | try w.writeOperand(s, inst, 0, pl_op.operand); | 429 | try w.writeOperand(s, inst, 0, pl_op.operand); |
| 413 | try s.writeAll(", "); | 430 | try s.writeAll(", "); |
| 414 | try w.writeOperand(s, inst, 1, extra.lhs); | 431 | try w.writeOperand(s, inst, 1, extra.lhs); |
| ... | @@ -511,7 +528,9 @@ const Writer = struct { | ... | @@ -511,7 +528,9 @@ const Writer = struct { |
| 511 | fn writeConstant(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 528 | fn writeConstant(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 512 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; | 529 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; |
| 513 | const val = w.air.values[ty_pl.payload]; | 530 | const val = w.air.values[ty_pl.payload]; |
| 514 | try s.print("{}, {}", .{ w.air.getRefType(ty_pl.ty).fmtDebug(), val.fmtDebug() }); | 531 | const ty = w.air.getRefType(ty_pl.ty); |
| 532 | try w.writeType(s, ty); | ||
| 533 | try s.print(", {}", .{val.fmtValue(ty, w.module)}); | ||
| 515 | } | 534 | } |
| 516 | 535 | ||
| 517 | fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 536 | fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| ... | @@ -523,7 +542,7 @@ const Writer = struct { | ... | @@ -523,7 +542,7 @@ const Writer = struct { |
| 523 | var op_index: usize = 0; | 542 | var op_index: usize = 0; |
| 524 | 543 | ||
| 525 | const ret_ty = w.air.typeOfIndex(inst); | 544 | const ret_ty = w.air.typeOfIndex(inst); |
| 526 | try s.print("{}", .{ret_ty.fmtDebug()}); | 545 | try w.writeType(s, ret_ty); |
| 527 | 546 | ||
| 528 | if (is_volatile) { | 547 | if (is_volatile) { |
| 529 | try s.writeAll(", volatile"); | 548 | try s.writeAll(", volatile"); |
| ... | @@ -647,7 +666,10 @@ const Writer = struct { | ... | @@ -647,7 +666,10 @@ const Writer = struct { |
| 647 | const body = w.air.extra[extra.end..][0..extra.data.body_len]; | 666 | const body = w.air.extra[extra.end..][0..extra.data.body_len]; |
| 648 | 667 | ||
| 649 | try w.writeOperand(s, inst, 0, extra.data.ptr); | 668 | try w.writeOperand(s, inst, 0, extra.data.ptr); |
| 650 | try s.print(", {}, {{\n", .{w.air.getRefType(ty_pl.ty).fmtDebug()}); | 669 | |
| 670 | try s.writeAll(", "); | ||
| 671 | try w.writeType(s, w.air.getRefType(ty_pl.ty)); | ||
| 672 | try s.writeAll(", {\n"); | ||
| 651 | const old_indent = w.indent; | 673 | const old_indent = w.indent; |
| 652 | w.indent += 2; | 674 | w.indent += 2; |
| 653 | try w.writeBody(s, body); | 675 | try w.writeBody(s, body); |