| author | |
| committer | |
| log | f08a8f0fc217914690a58035291da8bcc7a86e47 |
| tree | 64f17ff2fcdef605d510f8370fde1b41a4eb4b51 |
| parent | 77576c960388f0ad6712f1e15b97ca689892d708 |
* Add `.llvmbc`/`.llvmir` to `ObjectFormat` for emitting unoptimized IR
* Replace `--verbose-air`, `--verbose-intern-pool`,
`--verbose-generic-instances`, `--verbose-llvm-ir`, and
`--verbose-llvm-bc` with various `--debug-log` scopes
* `--debug-log illegal-air`: pre-legalized Air
* `--debug-log legal-air`: post-legalized Air
* `--debug-log air`: final Air with liveness
* `--debug-log ip-stats`: InternPool statistics
* `--debug-log ip-values`: InternPool values
* `--debug-log ip-generic-instances`: InternPool generic instances
* `--debug-log llvm-ir`: pre-optimized LLVM IR
* `--debug-log opt-llvm-ir`: post-optimized LLVM IR
* Delete `--verbose-cimport` which does nothing
* Delete `--verbose-llvm-cpu-features` which is equivalent to looking at
the outputs of `--show-builtin` and `--debug-log llvm-ir`49 files changed, 1392 insertions(+), 1464 deletions(-)
CMakeLists.txt+1-1| ... | ... | @@ -330,7 +330,7 @@ set(ZIG_STAGE2_SOURCES |
| 330 | 330 | src/Air/Legalize.zig |
| 331 | 331 | src/Air/Liveness.zig |
| 332 | 332 | src/Air/Liveness/Verify.zig |
| 333 | src/Air/print.zig | |
| 333 | src/Air/Print.zig | |
| 334 | 334 | src/Builtin.zig |
| 335 | 335 | src/Compilation.zig |
| 336 | 336 | src/Compilation/Config.zig |
bootstrap.c+1-1| ... | ... | @@ -179,7 +179,7 @@ int main(int argc, char **argv) { |
| 179 | 179 | "pub const version: [:0]const u8 = \"%s\";\n" |
| 180 | 180 | "pub const semver = @import(\"std\").SemanticVersion.parse(version) catch unreachable;\n" |
| 181 | 181 | "pub const enable_debug_extensions = false;\n" |
| 182 | "pub const enable_logging = false;\n" | |
| 182 | "pub const log_level: @import(\"std\").log.Level = .err;\n" | |
| 183 | 183 | "pub const enable_link_snapshots = false;\n" |
| 184 | 184 | "pub const enable_tracy = false;\n" |
| 185 | 185 | "pub const value_tracing = false;\n" |
build.zig+17-7| ... | ... | @@ -25,6 +25,10 @@ pub fn build(b: *std.Build) !void { |
| 25 | 25 | }, |
| 26 | 26 | }); |
| 27 | 27 | const optimize = b.standardOptimizeOption(.{}); |
| 28 | const is_debug = switch (optimize) { | |
| 29 | .debug => true, | |
| 30 | .safe, .fast, .small => false, | |
| 31 | }; | |
| 28 | 32 | |
| 29 | 33 | const flat = b.option(bool, "flat", "Put files into the installation prefix in a manner suited for upstream distribution rather than a posix file system hierarchy standard") orelse false; |
| 30 | 34 | const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode"); |
| ... | ... | @@ -205,9 +209,9 @@ pub fn build(b: *std.Build) !void { |
| 205 | 209 | const value_tracing = b.option(bool, "value-tracing", "Enable extra state tracking to help troubleshoot bugs in the compiler (using the std.debug.Trace API)") orelse false; |
| 206 | 210 | |
| 207 | 211 | const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse blk: { |
| 208 | if (strip == true) break :blk @as(u32, 0); | |
| 209 | if (optimize != .debug) break :blk 0; | |
| 210 | break :blk 4; | |
| 212 | if (strip == true) break :blk 0; | |
| 213 | if (is_debug) break :blk 4; | |
| 214 | break :blk 0; | |
| 211 | 215 | }; |
| 212 | 216 | |
| 213 | 217 | const exe = addCompilerStep(b, .{ |
| ... | ... | @@ -255,9 +259,15 @@ pub fn build(b: *std.Build) !void { |
| 255 | 259 | exe.root_module.link_libc = true; |
| 256 | 260 | } |
| 257 | 261 | |
| 258 | const is_debug = optimize == .debug; | |
| 259 | 262 | const enable_debug_extensions = b.option(bool, "debug-extensions", "Enable commands and options useful for debugging the compiler") orelse is_debug; |
| 260 | const enable_logging = b.option(bool, "log", "Enable debug logging with --debug-log") orelse is_debug; | |
| 263 | const log_level: std.log.Level = b.option(std.log.Level, "log", "Enable logs of the given or higher severity. Passing 'debug' still requires passing '--debug-log' to actually see any debug logs.") orelse switch (enable_debug_extensions) { | |
| 264 | true => .debug, | |
| 265 | false => switch (optimize) { | |
| 266 | .debug => .debug, | |
| 267 | .safe, .fast => .info, | |
| 268 | .small => .err, | |
| 269 | }, | |
| 270 | }; | |
| 261 | 271 | |
| 262 | 272 | const opt_version_string = b.option([]const u8, "version-string", "Override Zig version string. Default is to find out with git."); |
| 263 | 273 | const version_slice = if (opt_version_string) |version| version else v: { |
| ... | ... | @@ -398,7 +408,7 @@ pub fn build(b: *std.Build) !void { |
| 398 | 408 | exe_options.addOption(std.SemanticVersion, "semver", semver); |
| 399 | 409 | |
| 400 | 410 | exe_options.addOption(bool, "enable_debug_extensions", enable_debug_extensions); |
| 401 | exe_options.addOption(bool, "enable_logging", enable_logging); | |
| 411 | exe_options.addOption(std.log.Level, "log_level", log_level); | |
| 402 | 412 | exe_options.addOption(bool, "enable_tracy", tracy != null); |
| 403 | 413 | exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack); |
| 404 | 414 | exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation); |
| ... | ... | @@ -837,7 +847,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { |
| 837 | 847 | exe_options.addOption([:0]const u8, "version", version); |
| 838 | 848 | exe_options.addOption(std.SemanticVersion, "semver", semver); |
| 839 | 849 | exe_options.addOption(bool, "enable_debug_extensions", false); |
| 840 | exe_options.addOption(bool, "enable_logging", false); | |
| 850 | exe_options.addOption(std.log.Level, "log_level", .err); | |
| 841 | 851 | exe_options.addOption(bool, "enable_tracy", false); |
| 842 | 852 | exe_options.addOption(bool, "enable_tracy_callstack", false); |
| 843 | 853 | exe_options.addOption(bool, "enable_tracy_allocation", false); |
lib/compiler/Maker.zig-4| ... | ... | @@ -509,14 +509,10 @@ pub fn main(init: process.Init.Minimal) !void { |
| 509 | 509 | } else if (mem.eql(u8, arg, "--libc-runtimes") or mem.eql(u8, arg, "--glibc-runtimes")) { |
| 510 | 510 | // --glibc-runtimes was the old name of the flag; kept for compatibility for now. |
| 511 | 511 | graph.libc_runtimes_dir = nextArgOrFatal(args, &arg_i); |
| 512 | } else if (mem.eql(u8, arg, "--verbose-air")) { | |
| 513 | graph.verbose_air = true; | |
| 514 | 512 | } else if (mem.eql(u8, arg, "--verbose-cc")) { |
| 515 | 513 | graph.verbose_cc = true; |
| 516 | 514 | } else if (mem.eql(u8, arg, "--verbose-link")) { |
| 517 | 515 | graph.verbose_link = true; |
| 518 | } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { | |
| 519 | graph.verbose_llvm_ir = true; | |
| 520 | 516 | } else if (mem.eql(u8, arg, "--watch")) { |
| 521 | 517 | watch_flag = true; |
| 522 | 518 | } else if (mem.eql(u8, arg, "--time-report")) { |
lib/compiler/Maker/Graph.zig-3| ... | ... | @@ -32,11 +32,8 @@ debug_compile_errors: bool = false, |
| 32 | 32 | debug_incremental: bool = false, |
| 33 | 33 | fuzzing: bool = false, |
| 34 | 34 | verbose: bool = false, |
| 35 | verbose_air: bool = false, | |
| 36 | 35 | verbose_cc: bool = false, |
| 37 | 36 | verbose_link: bool = false, |
| 38 | verbose_llvm_cpu_features: bool = false, | |
| 39 | verbose_llvm_ir: bool = false, | |
| 40 | 37 | libc_file: ?[]const u8 = null, |
| 41 | 38 | /// What does this do? Nobody bothered to document it, and I think it's a |
| 42 | 39 | /// smelly option. So unless somebody deletes these passive aggressive comments |
lib/compiler/Maker/ScannedConfig.zig+2-6| ... | ... | @@ -351,6 +351,8 @@ const general_usage = |
| 351 | 351 | \\ preferred optimization mode: fast, safe, small |
| 352 | 352 | \\ |
| 353 | 353 | \\ --verbose Print commands before executing them |
| 354 | \\ --verbose-cc Print C compiler commands before executing them | |
| 355 | \\ --verbose-link Print linker commands before executing them | |
| 354 | 356 | \\ --color [auto|off|on] Enable or disable colored error messages |
| 355 | 357 | \\ --error-style [style] Control how build errors are printed |
| 356 | 358 | \\ verbose (Default) Report errors with full context |
| ... | ... | @@ -417,11 +419,5 @@ const general_usage = |
| 417 | 419 | \\ none (default) No build ID |
| 418 | 420 | \\ --debug-log [scope] Enable debugging the compiler |
| 419 | 421 | \\ --debug-pkg-config Fail if unknown pkg-config flags encountered |
| 420 | \\ --verbose-link Enable compiler debug output for linking | |
| 421 | \\ --verbose-air Enable compiler debug output for Zig AIR | |
| 422 | \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR | |
| 423 | \\ --verbose-cimport Enable compiler debug output for C imports | |
| 424 | \\ --verbose-cc Enable compiler debug output for C compilation | |
| 425 | \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features | |
| 426 | 422 | \\ |
| 427 | 423 | ; |
lib/compiler/Maker/Step/Compile.zig+1-4| ... | ... | @@ -608,11 +608,8 @@ fn lowerZigArgs( |
| 608 | 608 | |
| 609 | 609 | try addBool(gpa, zig_args, "--debug-compile-errors", graph.debug_compile_errors); |
| 610 | 610 | try addBool(gpa, zig_args, "--debug-incremental", graph.debug_incremental); |
| 611 | try addBool(gpa, zig_args, "--verbose-air", graph.verbose_air); | |
| 612 | try addBool(gpa, zig_args, "--verbose-llvm-ir", graph.verbose_llvm_ir); | |
| 613 | try addBool(gpa, zig_args, "--verbose-link", graph.verbose_link or conf_comp.flags.verbose_link); | |
| 614 | 611 | try addBool(gpa, zig_args, "--verbose-cc", graph.verbose_cc or conf_comp.flags.verbose_cc); |
| 615 | try addBool(gpa, zig_args, "--verbose-llvm-cpu-features", graph.verbose_llvm_cpu_features); | |
| 612 | try addBool(gpa, zig_args, "--verbose-link", graph.verbose_link or conf_comp.flags.verbose_link); | |
| 616 | 613 | try addBool(gpa, zig_args, "--time-report", graph.time_report); |
| 617 | 614 | |
| 618 | 615 | if (conf_comp.generated_bin.value == null) try zig_args.append(gpa, "-fno-emit-bin"); |
lib/compiler/aro/aro/Driver.zig+1-1| ... | ... | @@ -927,7 +927,7 @@ pub fn parseArgs( |
| 927 | 927 | break :debug switch (d.comp.target.ofmt) { |
| 928 | 928 | .elf, .macho, .wasm => .{ .dwarf = .@"32" }, |
| 929 | 929 | .coff => .code_view, |
| 930 | .c => switch (d.comp.target.os.tag) { | |
| 930 | .c, .llvmbc, .llvmir => switch (d.comp.target.os.tag) { | |
| 931 | 931 | .windows, .uefi => .code_view, |
| 932 | 932 | else => .{ .dwarf = .@"32" }, |
| 933 | 933 | }, |
lib/std/Build/Configuration.zig+2| ... | ... | @@ -2519,6 +2519,8 @@ pub const TargetQuery = struct { |
| 2519 | 2519 | coff, |
| 2520 | 2520 | elf, |
| 2521 | 2521 | hex, |
| 2522 | llvmbc, | |
| 2523 | llvmir, | |
| 2522 | 2524 | macho, |
| 2523 | 2525 | plan9, |
| 2524 | 2526 | raw, |
lib/std/Target.zig+6| ... | ... | @@ -1043,6 +1043,10 @@ pub const ObjectFormat = enum { |
| 1043 | 1043 | elf, |
| 1044 | 1044 | /// The Intel HEX format for storing binary code in ASCII text. |
| 1045 | 1045 | hex, |
| 1046 | /// LLVM binary intermediate representation. | |
| 1047 | llvmbc, | |
| 1048 | /// LLVM text intermediate representation. | |
| 1049 | llvmir, | |
| 1046 | 1050 | /// The Mach object format used by macOS and other Apple platforms. |
| 1047 | 1051 | macho, |
| 1048 | 1052 | /// The a.out format used by Plan 9 from Bell Labs. |
| ... | ... | @@ -1060,6 +1064,8 @@ pub const ObjectFormat = enum { |
| 1060 | 1064 | .coff => ".obj", |
| 1061 | 1065 | .elf, .macho, .wasm => ".o", |
| 1062 | 1066 | .hex => ".ihex", |
| 1067 | .llvmbc => ".bc", | |
| 1068 | .llvmir => ".ll", | |
| 1063 | 1069 | .plan9 => arch.plan9Ext(), |
| 1064 | 1070 | .raw => ".bin", |
| 1065 | 1071 | .spirv => ".spv", |
lib/std/debug.zig+1-1| ... | ... | @@ -76,7 +76,7 @@ pub fn TargetInfo(os: std.Target.Os.Tag, arch: std.Target.Cpu.Arch) type { |
| 76 | 76 | }, |
| 77 | 77 | .macho => @import("debug/SelfInfo/MachO.zig"), |
| 78 | 78 | .plan9, .spirv, .wasm, .raw, .hex => void, |
| 79 | .c => unreachable, | |
| 79 | .c, .llvmbc, .llvmir => unreachable, | |
| 80 | 80 | }; |
| 81 | 81 | } |
| 82 | 82 |
lib/std/fmt.zig+7-1| ... | ... | @@ -285,7 +285,13 @@ pub fn Alt( |
| 285 | 285 | pub fn alt( |
| 286 | 286 | context: anytype, |
| 287 | 287 | comptime func_name: @EnumLiteral(), |
| 288 | ) Alt(@TypeOf(context), @field(@TypeOf(context), @tagName(func_name))) { | |
| 288 | ) Alt(@TypeOf(context), @field(switch (@typeInfo(@TypeOf(context))) { | |
| 289 | else => @TypeOf(context), | |
| 290 | .pointer => |pointer| switch (pointer.size) { | |
| 291 | else => @TypeOf(context), | |
| 292 | .one => pointer.child, | |
| 293 | }, | |
| 294 | }, @tagName(func_name))) { | |
| 289 | 295 | return .{ .data = context }; |
| 290 | 296 | } |
| 291 | 297 |
lib/std/zig.zig+2| ... | ... | @@ -218,6 +218,8 @@ pub fn binNameAlloc(allocator: Allocator, options: BinNameOptions) error{OutOfMe |
| 218 | 218 | }, |
| 219 | 219 | .Obj => return std.fmt.allocPrint(allocator, "{s}.o", .{root_name}), |
| 220 | 220 | }, |
| 221 | .llvmbc => return std.fmt.allocPrint(allocator, "{s}.bc", .{root_name}), | |
| 222 | .llvmir => return std.fmt.allocPrint(allocator, "{s}.ll", .{root_name}), | |
| 221 | 223 | .macho => switch (options.output_mode) { |
| 222 | 224 | .Exe => return allocator.dupe(u8, root_name), |
| 223 | 225 | .Lib => { |
lib/std/zig/llvm/Builder.zig+16-5| ... | ... | @@ -10855,11 +10855,22 @@ pub fn resolveAlignmentForwardReference(b: *Builder, fwd_ref: Alignment.Lazy, va |
| 10855 | 10855 | b.alignment_forward_references.items[index] = value; |
| 10856 | 10856 | } |
| 10857 | 10857 | |
| 10858 | pub fn dump(b: *Builder, io: Io) void { | |
| 10859 | var buffer: [4000]u8 = undefined; | |
| 10860 | const stderr: Io.File = .stderr(); | |
| 10861 | b.printToFile(io, stderr, &buffer) catch {}; | |
| 10862 | } | |
| 10858 | pub const Print = struct { | |
| 10859 | name: []const u8, | |
| 10860 | builder: *Builder, | |
| 10861 | err: ?Allocator.Error, | |
| 10862 | ||
| 10863 | pub fn format(p: *Print, w: *Writer) Writer.Error!void { | |
| 10864 | try w.print("{q}", .{p.name}); | |
| 10865 | p.builder.print(w) catch |err| switch (err) { | |
| 10866 | error.WriteFailed => |e| return e, | |
| 10867 | error.OutOfMemory => |e| { | |
| 10868 | p.err = e; | |
| 10869 | return error.WriteFailed; | |
| 10870 | }, | |
| 10871 | }; | |
| 10872 | } | |
| 10873 | }; | |
| 10863 | 10874 | |
| 10864 | 10875 | pub fn printToFilePath(b: *Builder, io: Io, dir: Io.Dir, path: []const u8) !void { |
| 10865 | 10876 | var buffer: [4000]u8 = undefined; |
src/Air.zig+5-5| ... | ... | @@ -13,10 +13,10 @@ const InternPool = @import("InternPool.zig"); |
| 13 | 13 | const Type = @import("Type.zig"); |
| 14 | 14 | const Value = @import("Value.zig"); |
| 15 | 15 | const Zcu = @import("Zcu.zig"); |
| 16 | const print = @import("Air/print.zig"); | |
| 17 | 16 | |
| 18 | 17 | pub const Legalize = @import("Air/Legalize.zig"); |
| 19 | 18 | pub const Liveness = @import("Air/Liveness.zig"); |
| 19 | pub const Print = @import("Air/Print.zig"); | |
| 20 | 20 | pub const Verify = @import("Air/Verify.zig"); |
| 21 | 21 | |
| 22 | 22 | instructions: std.MultiArrayList(Inst).Slice, |
| ... | ... | @@ -2517,10 +2517,10 @@ pub fn unwrapShuffleTwo(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index |
| 2517 | 2517 | } |
| 2518 | 2518 | |
| 2519 | 2519 | pub const legalize = Legalize.legalize; |
| 2520 | pub const write = print.write; | |
| 2521 | pub const writeInst = print.writeInst; | |
| 2522 | pub const dump = print.dump; | |
| 2523 | pub const dumpInst = print.dumpInst; | |
| 2520 | pub const write = Print.write; | |
| 2521 | pub const writeInst = Print.writeInst; | |
| 2522 | pub const dump = Print.dump; | |
| 2523 | pub const dumpInst = Print.dumpInst; | |
| 2524 | 2524 | |
| 2525 | 2525 | pub const CoveragePoint = enum(u1) { |
| 2526 | 2526 | /// Indicates the block is not a place of interest corresponding to |
src/Air/Print.zig created+1059| ... | ... | @@ -0,0 +1,1059 @@ |
| 1 | const std = @import("std"); | |
| 2 | const Allocator = std.mem.Allocator; | |
| 3 | const assert = std.debug.assert; | |
| 4 | ||
| 5 | const build_options = @import("build_options"); | |
| 6 | const Zcu = @import("../Zcu.zig"); | |
| 7 | const Value = @import("../Value.zig"); | |
| 8 | const Type = @import("../Type.zig"); | |
| 9 | const Air = @import("../Air.zig"); | |
| 10 | const InternPool = @import("../InternPool.zig"); | |
| 11 | const Printer = @This(); | |
| 12 | ||
| 13 | zcu: *Zcu, | |
| 14 | fqn: InternPool.NullTerminatedString, | |
| 15 | air: *const Air, | |
| 16 | liveness: *const ?Air.Liveness, | |
| 17 | ||
| 18 | pub fn format(p: *const Printer, w: *std.Io.Writer) std.Io.Writer.Error!void { | |
| 19 | try w.print("{qf}:\n", .{p.fqn.fmt(&p.zcu.intern_pool)}); | |
| 20 | try p.air.write(w, p.zcu, p.liveness.*); | |
| 21 | } | |
| 22 | ||
| 23 | pub fn write(air: Air, stream: *std.Io.Writer, zcu: *Zcu, liveness: ?Air.Liveness) !void { | |
| 24 | comptime assert(build_options.log_level == .debug); | |
| 25 | const instruction_bytes = air.instructions.len * | |
| 26 | // Here we don't use @sizeOf(Air.Inst.Data) because it would include | |
| 27 | // the debug safety tag but we want to measure release size. | |
| 28 | (@sizeOf(Air.Inst.Tag) + 8); | |
| 29 | const extra_bytes = air.extra.items.len * @sizeOf(u32); | |
| 30 | const tomb_bytes = if (liveness) |l| l.tomb_bits.len * @sizeOf(usize) else 0; | |
| 31 | const liveness_extra_bytes = if (liveness) |l| l.extra.len * @sizeOf(u32) else 0; | |
| 32 | const liveness_special_bytes = if (liveness) |l| l.special.count() * 8 else 0; | |
| 33 | const total_bytes = @sizeOf(Air) + instruction_bytes + extra_bytes + | |
| 34 | @sizeOf(Air.Liveness) + liveness_extra_bytes + | |
| 35 | liveness_special_bytes + tomb_bytes; | |
| 36 | ||
| 37 | // zig fmt: off | |
| 38 | try stream.print( | |
| 39 | \\# Total AIR+Liveness bytes: {Bi} | |
| 40 | \\# AIR Instructions: {d} ({Bi}) | |
| 41 | \\# AIR Extra Data: {d} ({Bi}) | |
| 42 | \\# Liveness tomb_bits: {Bi} | |
| 43 | \\# Liveness Extra Data: {d} ({Bi}) | |
| 44 | \\# Liveness special table: {d} ({Bi}) | |
| 45 | \\ | |
| 46 | , .{ | |
| 47 | total_bytes, | |
| 48 | air.instructions.len, instruction_bytes, | |
| 49 | air.extra.items.len, extra_bytes, | |
| 50 | tomb_bytes, | |
| 51 | if (liveness) |l| l.extra.len else 0, liveness_extra_bytes, | |
| 52 | if (liveness) |l| l.special.count() else 0, liveness_special_bytes, | |
| 53 | }); | |
| 54 | // zig fmt: on | |
| 55 | ||
| 56 | var writer: Writer = .{ | |
| 57 | .zcu = zcu, | |
| 58 | .gpa = zcu.comp.gpa, | |
| 59 | .air = air, | |
| 60 | .liveness = liveness, | |
| 61 | .indent = 2, | |
| 62 | .skip_body = false, | |
| 63 | }; | |
| 64 | try writer.writeBody(stream, air.getMainBody()); | |
| 65 | } | |
| 66 | ||
| 67 | pub fn writeInst( | |
| 68 | air: Air, | |
| 69 | stream: *std.Io.Writer, | |
| 70 | inst: Air.Inst.Index, | |
| 71 | zcu: *Zcu, | |
| 72 | liveness: ?Air.Liveness, | |
| 73 | ) void { | |
| 74 | comptime assert(build_options.log_level == .debug); | |
| 75 | var writer: Writer = .{ | |
| 76 | .zcu = zcu, | |
| 77 | .gpa = zcu.comp.gpa, | |
| 78 | .air = air, | |
| 79 | .liveness = liveness, | |
| 80 | .indent = 2, | |
| 81 | .skip_body = true, | |
| 82 | }; | |
| 83 | writer.writeInst(stream, inst) catch return; | |
| 84 | } | |
| 85 | ||
| 86 | pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { | |
| 87 | var buffer: [4096]u8 = undefined; | |
| 88 | const stderr = std.debug.lockStderr(&buffer); | |
| 89 | defer std.debug.unlockStderr(); | |
| 90 | const w = &stderr.file_writer.interface; | |
| 91 | air.write(w, pt, liveness) catch return; | |
| 92 | } | |
| 93 | ||
| 94 | pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { | |
| 95 | var buffer: [4096]u8 = undefined; | |
| 96 | const stderr = std.debug.lockStderr(&buffer); | |
| 97 | defer std.debug.unlockStderr(); | |
| 98 | const w = &stderr.file_writer.interface; | |
| 99 | air.writeInst(w, inst, pt, liveness) catch return; | |
| 100 | } | |
| 101 | ||
| 102 | const Writer = struct { | |
| 103 | zcu: *Zcu, | |
| 104 | gpa: Allocator, | |
| 105 | air: Air, | |
| 106 | liveness: ?Air.Liveness, | |
| 107 | indent: usize, | |
| 108 | skip_body: bool, | |
| 109 | ||
| 110 | const Error = std.Io.Writer.Error; | |
| 111 | ||
| 112 | fn writeBody(w: *Writer, s: *std.Io.Writer, body: []const Air.Inst.Index) Error!void { | |
| 113 | for (body) |inst| { | |
| 114 | try w.writeInst(s, inst); | |
| 115 | try s.writeByte('\n'); | |
| 116 | } | |
| 117 | } | |
| 118 | ||
| 119 | fn writeInst(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 120 | const tag = w.air.instructions.items(.tag)[@backingInt(inst)]; | |
| 121 | try s.splatByteAll(' ', w.indent); | |
| 122 | try s.print("{f}{c}= {s}(", .{ | |
| 123 | inst, | |
| 124 | @as(u8, if (if (w.liveness) |liveness| liveness.isUnused(inst) else false) '!' else ' '), | |
| 125 | @tagName(tag), | |
| 126 | }); | |
| 127 | switch (tag) { | |
| 128 | .add, | |
| 129 | .add_optimized, | |
| 130 | .add_safe, | |
| 131 | .add_wrap, | |
| 132 | .add_sat, | |
| 133 | .sub, | |
| 134 | .sub_optimized, | |
| 135 | .sub_safe, | |
| 136 | .sub_wrap, | |
| 137 | .sub_sat, | |
| 138 | .mul, | |
| 139 | .mul_optimized, | |
| 140 | .mul_safe, | |
| 141 | .mul_wrap, | |
| 142 | .mul_sat, | |
| 143 | .div_float, | |
| 144 | .div_trunc, | |
| 145 | .div_floor, | |
| 146 | .div_ceil, | |
| 147 | .div_exact, | |
| 148 | .rem, | |
| 149 | .mod, | |
| 150 | .bit_and, | |
| 151 | .bit_or, | |
| 152 | .xor, | |
| 153 | .cmp_lt, | |
| 154 | .cmp_lte, | |
| 155 | .cmp_eq, | |
| 156 | .cmp_gte, | |
| 157 | .cmp_gt, | |
| 158 | .cmp_neq, | |
| 159 | .store, | |
| 160 | .store_safe, | |
| 161 | .array_elem_val, | |
| 162 | .slice_elem_val, | |
| 163 | .ptr_elem_val, | |
| 164 | .shl, | |
| 165 | .shl_exact, | |
| 166 | .shl_sat, | |
| 167 | .shr, | |
| 168 | .shr_exact, | |
| 169 | .set_union_tag, | |
| 170 | .min, | |
| 171 | .max, | |
| 172 | .div_float_optimized, | |
| 173 | .div_trunc_optimized, | |
| 174 | .div_floor_optimized, | |
| 175 | .div_ceil_optimized, | |
| 176 | .div_exact_optimized, | |
| 177 | .rem_optimized, | |
| 178 | .mod_optimized, | |
| 179 | .cmp_lt_optimized, | |
| 180 | .cmp_lte_optimized, | |
| 181 | .cmp_eq_optimized, | |
| 182 | .cmp_gte_optimized, | |
| 183 | .cmp_gt_optimized, | |
| 184 | .cmp_neq_optimized, | |
| 185 | .memcpy, | |
| 186 | .memmove, | |
| 187 | .memset, | |
| 188 | .memset_safe, | |
| 189 | .legalize_vec_elem_val, | |
| 190 | => try w.writeBinOp(s, inst), | |
| 191 | ||
| 192 | .is_null, | |
| 193 | .is_non_null, | |
| 194 | .is_null_ptr, | |
| 195 | .is_non_null_ptr, | |
| 196 | .is_err, | |
| 197 | .is_non_err, | |
| 198 | .is_err_ptr, | |
| 199 | .is_non_err_ptr, | |
| 200 | .ret, | |
| 201 | .ret_safe, | |
| 202 | .ret_load, | |
| 203 | .is_named_enum_value, | |
| 204 | .tag_name, | |
| 205 | .error_name, | |
| 206 | .sqrt, | |
| 207 | .sin, | |
| 208 | .cos, | |
| 209 | .tan, | |
| 210 | .exp, | |
| 211 | .exp2, | |
| 212 | .log, | |
| 213 | .log2, | |
| 214 | .log10, | |
| 215 | .floor, | |
| 216 | .ceil, | |
| 217 | .round, | |
| 218 | .trunc_float, | |
| 219 | .neg, | |
| 220 | .neg_optimized, | |
| 221 | .cmp_lte_errors_len, | |
| 222 | .set_err_return_trace, | |
| 223 | .c_va_end, | |
| 224 | => try w.writeUnOp(s, inst), | |
| 225 | ||
| 226 | .trap, | |
| 227 | .breakpoint, | |
| 228 | .dbg_empty_stmt, | |
| 229 | .unreach, | |
| 230 | .ret_addr, | |
| 231 | .frame_addr, | |
| 232 | .save_err_return_trace_index, | |
| 233 | => try w.writeNoOp(s, inst), | |
| 234 | ||
| 235 | .alloc, | |
| 236 | .ret_ptr, | |
| 237 | .err_return_trace, | |
| 238 | .c_va_start, | |
| 239 | => try w.writeTy(s, inst), | |
| 240 | ||
| 241 | .arg => try w.writeArg(s, inst), | |
| 242 | ||
| 243 | .not, | |
| 244 | .bit_cast, | |
| 245 | .bit_cast_safe, | |
| 246 | .ptr_cast, | |
| 247 | .ptr_from_int, | |
| 248 | .int_from_ptr, | |
| 249 | .error_cast, | |
| 250 | .error_from_int, | |
| 251 | .int_from_error, | |
| 252 | .union_from_enum, | |
| 253 | .load, | |
| 254 | .fptrunc, | |
| 255 | .fpext, | |
| 256 | .int_cast, | |
| 257 | .int_cast_safe, | |
| 258 | .trunc, | |
| 259 | .optional_payload, | |
| 260 | .optional_payload_ptr, | |
| 261 | .optional_payload_ptr_set, | |
| 262 | .errunion_payload_ptr_set, | |
| 263 | .wrap_optional, | |
| 264 | .unwrap_errunion_payload, | |
| 265 | .unwrap_errunion_err, | |
| 266 | .unwrap_errunion_payload_ptr, | |
| 267 | .unwrap_errunion_err_ptr, | |
| 268 | .wrap_errunion_payload, | |
| 269 | .wrap_errunion_err, | |
| 270 | .slice_ptr, | |
| 271 | .slice_len, | |
| 272 | .ptr_slice_len_ptr, | |
| 273 | .ptr_slice_ptr_ptr, | |
| 274 | .struct_field_ptr_index_0, | |
| 275 | .struct_field_ptr_index_1, | |
| 276 | .struct_field_ptr_index_2, | |
| 277 | .struct_field_ptr_index_3, | |
| 278 | .array_to_slice, | |
| 279 | .array_to_vector, | |
| 280 | .float_from_int, | |
| 281 | .splat, | |
| 282 | .int_from_float, | |
| 283 | .int_from_float_optimized, | |
| 284 | .int_from_float_safe, | |
| 285 | .int_from_float_optimized_safe, | |
| 286 | .get_union_tag, | |
| 287 | .clz, | |
| 288 | .ctz, | |
| 289 | .popcount, | |
| 290 | .byte_swap, | |
| 291 | .bit_reverse, | |
| 292 | .abs, | |
| 293 | .error_set_has_value, | |
| 294 | .addrspace_cast, | |
| 295 | .c_va_arg, | |
| 296 | .c_va_copy, | |
| 297 | => try w.writeTyOp(s, inst), | |
| 298 | ||
| 299 | .block, .dbg_inline_block => try w.writeBlock(s, tag, inst), | |
| 300 | ||
| 301 | .loop => try w.writeLoop(s, inst), | |
| 302 | ||
| 303 | .slice, | |
| 304 | .slice_elem_ptr, | |
| 305 | .ptr_elem_ptr, | |
| 306 | .ptr_add, | |
| 307 | .ptr_sub, | |
| 308 | .add_with_overflow, | |
| 309 | .sub_with_overflow, | |
| 310 | .mul_with_overflow, | |
| 311 | .shl_with_overflow, | |
| 312 | => try w.writeTyPlBin(s, inst), | |
| 313 | ||
| 314 | .call, | |
| 315 | .call_always_tail, | |
| 316 | .call_never_tail, | |
| 317 | .call_never_inline, | |
| 318 | => try w.writeCall(s, inst), | |
| 319 | ||
| 320 | .dbg_var_ptr, | |
| 321 | .dbg_var_val, | |
| 322 | .dbg_arg_inline, | |
| 323 | => try w.writeDbgVar(s, inst), | |
| 324 | ||
| 325 | .struct_field_ptr => try w.writeStructField(s, inst), | |
| 326 | .agg_field_val => try w.writeStructField(s, inst), | |
| 327 | .spirv_runtime_array_len => try w.writeStructField(s, inst), | |
| 328 | .inferred_alloc => @panic("TODO"), | |
| 329 | .inferred_alloc_comptime => @panic("TODO"), | |
| 330 | .assembly => try w.writeAssembly(s, inst), | |
| 331 | .dbg_stmt => try w.writeDbgStmt(s, inst), | |
| 332 | ||
| 333 | .aggregate_init => try w.writeAggregateInit(s, inst), | |
| 334 | .union_init => try w.writeUnionInit(s, inst), | |
| 335 | .br => try w.writeBr(s, inst), | |
| 336 | .switch_dispatch => try w.writeBr(s, inst), | |
| 337 | .repeat => try w.writeRepeat(s, inst), | |
| 338 | .cond_br => try w.writeCondBr(s, inst), | |
| 339 | .@"try", .try_cold => try w.writeTry(s, inst), | |
| 340 | .try_ptr, .try_ptr_cold => try w.writeTryPtr(s, inst), | |
| 341 | .loop_switch_br, .switch_br => try w.writeSwitchBr(s, inst), | |
| 342 | .cmpxchg_weak, .cmpxchg_strong => try w.writeCmpxchg(s, inst), | |
| 343 | .atomic_load => try w.writeAtomicLoad(s, inst), | |
| 344 | .prefetch => try w.writePrefetch(s, inst), | |
| 345 | .atomic_store_unordered => try w.writeAtomicStore(s, inst, .unordered), | |
| 346 | .atomic_store_monotonic => try w.writeAtomicStore(s, inst, .monotonic), | |
| 347 | .atomic_store_release => try w.writeAtomicStore(s, inst, .release), | |
| 348 | .atomic_store_seq_cst => try w.writeAtomicStore(s, inst, .seq_cst), | |
| 349 | .atomic_rmw => try w.writeAtomicRmw(s, inst), | |
| 350 | .field_parent_ptr => try w.writeFieldParentPtr(s, inst), | |
| 351 | .wasm_memory_size => try w.writeWasmMemorySize(s, inst), | |
| 352 | .wasm_memory_grow => try w.writeWasmMemoryGrow(s, inst), | |
| 353 | .mul_add => try w.writeMulAdd(s, inst), | |
| 354 | .select => try w.writeSelect(s, inst), | |
| 355 | .shuffle_one => try w.writeShuffleOne(s, inst), | |
| 356 | .shuffle_two => try w.writeShuffleTwo(s, inst), | |
| 357 | .reduce, .reduce_optimized => try w.writeReduce(s, inst), | |
| 358 | .cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst), | |
| 359 | .runtime_nav_ptr => try w.writeRuntimeNavPtr(s, inst), | |
| 360 | .legalize_vec_store_elem => try w.writeLegalizeVecStoreElem(s, inst), | |
| 361 | .legalize_compiler_rt_call => try w.writeLegalizeCompilerRtCall(s, inst), | |
| 362 | ||
| 363 | .work_item_id, | |
| 364 | .work_group_size, | |
| 365 | .work_group_id, | |
| 366 | => try w.writeWorkDimension(s, inst), | |
| 367 | } | |
| 368 | try s.writeByte(')'); | |
| 369 | } | |
| 370 | ||
| 371 | fn writeBinOp(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 372 | const bin_op = w.air.instructions.items(.data)[@backingInt(inst)].bin_op; | |
| 373 | try w.writeOperand(s, inst, 0, bin_op.lhs); | |
| 374 | try s.writeAll(", "); | |
| 375 | try w.writeOperand(s, inst, 1, bin_op.rhs); | |
| 376 | } | |
| 377 | ||
| 378 | fn writeUnOp(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 379 | const un_op = w.air.instructions.items(.data)[@backingInt(inst)].un_op; | |
| 380 | try w.writeOperand(s, inst, 0, un_op); | |
| 381 | } | |
| 382 | ||
| 383 | fn writeNoOp(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 384 | _ = w; | |
| 385 | _ = s; | |
| 386 | _ = inst; | |
| 387 | // no-op, no argument to write | |
| 388 | } | |
| 389 | ||
| 390 | fn writeType(w: *Writer, s: *std.Io.Writer, ty: Type) !void { | |
| 391 | return ty.print(s, w.zcu, null); | |
| 392 | } | |
| 393 | ||
| 394 | fn writeTy(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 395 | const ty = w.air.instructions.items(.data)[@backingInt(inst)].ty; | |
| 396 | try w.writeType(s, ty); | |
| 397 | } | |
| 398 | ||
| 399 | fn writeArg(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 400 | const arg = w.air.instructions.items(.data)[@backingInt(inst)].arg; | |
| 401 | try w.writeType(s, arg.ty); | |
| 402 | try s.print(", {d}", .{arg.zir_param_index}); | |
| 403 | } | |
| 404 | ||
| 405 | fn writeTyOp(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 406 | const ty_op = w.air.instructions.items(.data)[@backingInt(inst)].ty_op; | |
| 407 | try w.writeType(s, ty_op.ty); | |
| 408 | try s.writeAll(", "); | |
| 409 | try w.writeOperand(s, inst, 0, ty_op.operand); | |
| 410 | } | |
| 411 | ||
| 412 | fn writeBlock(w: *Writer, s: *std.Io.Writer, tag: Air.Inst.Tag, inst: Air.Inst.Index) Error!void { | |
| 413 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 414 | try w.writeType(s, ty_pl.ty); | |
| 415 | ||
| 416 | const body = switch (tag) { | |
| 417 | .block => w.air.unwrapBlock(inst).body, | |
| 418 | .dbg_inline_block => body: { | |
| 419 | const dbg_block = w.air.unwrapDbgBlock(inst); | |
| 420 | try s.writeAll(", "); | |
| 421 | try w.writeInstRef(s, Air.internedToRef(dbg_block.func), false); | |
| 422 | break :body dbg_block.body; | |
| 423 | }, | |
| 424 | else => unreachable, | |
| 425 | }; | |
| 426 | if (w.skip_body) return s.writeAll(", ..."); | |
| 427 | const liveness_block: Air.Liveness.BlockSlices = if (w.liveness) |liveness| | |
| 428 | liveness.getBlock(inst) | |
| 429 | else | |
| 430 | .{ .deaths = &.{} }; | |
| 431 | ||
| 432 | try s.writeAll(", {\n"); | |
| 433 | const old_indent = w.indent; | |
| 434 | w.indent += 2; | |
| 435 | try w.writeBody(s, body); | |
| 436 | w.indent = old_indent; | |
| 437 | try s.splatByteAll(' ', w.indent); | |
| 438 | try s.writeAll("}"); | |
| 439 | ||
| 440 | for (liveness_block.deaths) |operand| { | |
| 441 | try s.print(" {f}!", .{operand}); | |
| 442 | } | |
| 443 | } | |
| 444 | ||
| 445 | fn writeLoop(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 446 | const block = w.air.unwrapBlock(inst); | |
| 447 | ||
| 448 | try w.writeType(s, block.ty); | |
| 449 | if (w.skip_body) return s.writeAll(", ..."); | |
| 450 | try s.writeAll(", {\n"); | |
| 451 | const old_indent = w.indent; | |
| 452 | w.indent += 2; | |
| 453 | try w.writeBody(s, block.body); | |
| 454 | w.indent = old_indent; | |
| 455 | try s.splatByteAll(' ', w.indent); | |
| 456 | try s.writeAll("}"); | |
| 457 | } | |
| 458 | ||
| 459 | fn writeAggregateInit(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 460 | const zcu = w.zcu; | |
| 461 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 462 | const vector_ty = ty_pl.ty; | |
| 463 | const len = @as(usize, @intCast(vector_ty.arrayLen(zcu))); | |
| 464 | const elements = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[ty_pl.payload..][0..len])); | |
| 465 | ||
| 466 | try w.writeType(s, vector_ty); | |
| 467 | try s.writeAll(", ["); | |
| 468 | for (elements, 0..) |elem, i| { | |
| 469 | if (i != 0) try s.writeAll(", "); | |
| 470 | try w.writeOperand(s, inst, i, elem); | |
| 471 | } | |
| 472 | try s.writeAll("]"); | |
| 473 | } | |
| 474 | ||
| 475 | fn writeUnionInit(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 476 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 477 | const extra = w.air.extraData(Air.UnionInit, ty_pl.payload).data; | |
| 478 | ||
| 479 | try s.print("{d}, ", .{extra.field_index}); | |
| 480 | try w.writeOperand(s, inst, 0, extra.init); | |
| 481 | } | |
| 482 | ||
| 483 | fn writeStructField(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 484 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 485 | const extra = w.air.extraData(Air.StructField, ty_pl.payload).data; | |
| 486 | ||
| 487 | try w.writeOperand(s, inst, 0, extra.struct_operand); | |
| 488 | try s.print(", {d}", .{extra.field_index}); | |
| 489 | } | |
| 490 | ||
| 491 | fn writeTyPlBin(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 492 | const data = w.air.instructions.items(.data); | |
| 493 | const ty_pl = data[@backingInt(inst)].ty_pl; | |
| 494 | const extra = w.air.extraData(Air.Bin, ty_pl.payload).data; | |
| 495 | ||
| 496 | const inst_ty = data[@backingInt(inst)].ty_pl.ty; | |
| 497 | try w.writeType(s, inst_ty); | |
| 498 | try s.writeAll(", "); | |
| 499 | try w.writeOperand(s, inst, 0, extra.lhs); | |
| 500 | try s.writeAll(", "); | |
| 501 | try w.writeOperand(s, inst, 1, extra.rhs); | |
| 502 | } | |
| 503 | ||
| 504 | fn writeCmpxchg(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 505 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 506 | const extra = w.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | |
| 507 | ||
| 508 | try w.writeOperand(s, inst, 0, extra.ptr); | |
| 509 | try s.writeAll(", "); | |
| 510 | try w.writeOperand(s, inst, 1, extra.expected_value); | |
| 511 | try s.writeAll(", "); | |
| 512 | try w.writeOperand(s, inst, 2, extra.new_value); | |
| 513 | try s.print(", {s}, {s}", .{ | |
| 514 | @tagName(extra.successOrder()), @tagName(extra.failureOrder()), | |
| 515 | }); | |
| 516 | } | |
| 517 | ||
| 518 | fn writeMulAdd(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 519 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 520 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; | |
| 521 | ||
| 522 | try w.writeOperand(s, inst, 0, extra.lhs); | |
| 523 | try s.writeAll(", "); | |
| 524 | try w.writeOperand(s, inst, 1, extra.rhs); | |
| 525 | try s.writeAll(", "); | |
| 526 | try w.writeOperand(s, inst, 2, pl_op.operand); | |
| 527 | } | |
| 528 | ||
| 529 | fn writeLegalizeVecStoreElem(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 530 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 531 | const bin = w.air.extraData(Air.Bin, pl_op.payload).data; | |
| 532 | ||
| 533 | try w.writeOperand(s, inst, 0, pl_op.operand); | |
| 534 | try s.writeAll(", "); | |
| 535 | try w.writeOperand(s, inst, 1, bin.lhs); | |
| 536 | try s.writeAll(", "); | |
| 537 | try w.writeOperand(s, inst, 2, bin.rhs); | |
| 538 | } | |
| 539 | ||
| 540 | fn writeLegalizeCompilerRtCall(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 541 | const rt_call = w.air.unwrapCompilerRtCall(inst); | |
| 542 | const args = rt_call.args; | |
| 543 | ||
| 544 | try s.print("{t}, [", .{rt_call.func}); | |
| 545 | for (args, 0..) |arg, i| { | |
| 546 | if (i != 0) try s.writeAll(", "); | |
| 547 | try w.writeOperand(s, inst, i, arg); | |
| 548 | } | |
| 549 | try s.writeByte(']'); | |
| 550 | } | |
| 551 | ||
| 552 | fn writeShuffleOne(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 553 | const unwrapped = w.air.unwrapShuffleOne(w.zcu, inst); | |
| 554 | try w.writeType(s, unwrapped.result_ty); | |
| 555 | try s.writeAll(", "); | |
| 556 | try w.writeOperand(s, inst, 0, unwrapped.operand); | |
| 557 | try s.writeAll(", ["); | |
| 558 | for (unwrapped.mask, 0..) |mask_elem, mask_idx| { | |
| 559 | if (mask_idx > 0) try s.writeAll(", "); | |
| 560 | switch (mask_elem.unwrap()) { | |
| 561 | .elem => |idx| try s.print("elem {d}", .{idx}), | |
| 562 | .value => |val| try s.print("val {f}", .{Value.fromInterned(val).fmtValue(w.zcu)}), | |
| 563 | } | |
| 564 | } | |
| 565 | try s.writeByte(']'); | |
| 566 | } | |
| 567 | ||
| 568 | fn writeShuffleTwo(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 569 | const unwrapped = w.air.unwrapShuffleTwo(w.zcu, inst); | |
| 570 | try w.writeType(s, unwrapped.result_ty); | |
| 571 | try s.writeAll(", "); | |
| 572 | try w.writeOperand(s, inst, 0, unwrapped.operand_a); | |
| 573 | try s.writeAll(", "); | |
| 574 | try w.writeOperand(s, inst, 1, unwrapped.operand_b); | |
| 575 | try s.writeAll(", ["); | |
| 576 | for (unwrapped.mask, 0..) |mask_elem, mask_idx| { | |
| 577 | if (mask_idx > 0) try s.writeAll(", "); | |
| 578 | switch (mask_elem.unwrap()) { | |
| 579 | .a_elem => |idx| try s.print("a_elem {d}", .{idx}), | |
| 580 | .b_elem => |idx| try s.print("b_elem {d}", .{idx}), | |
| 581 | .undef => try s.writeAll("undef"), | |
| 582 | } | |
| 583 | } | |
| 584 | try s.writeByte(']'); | |
| 585 | } | |
| 586 | ||
| 587 | fn writeSelect(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 588 | const zcu = w.zcu; | |
| 589 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 590 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; | |
| 591 | ||
| 592 | const elem_ty = w.typeOfIndex(inst).childType(zcu); | |
| 593 | try w.writeType(s, elem_ty); | |
| 594 | try s.writeAll(", "); | |
| 595 | try w.writeOperand(s, inst, 0, pl_op.operand); | |
| 596 | try s.writeAll(", "); | |
| 597 | try w.writeOperand(s, inst, 1, extra.lhs); | |
| 598 | try s.writeAll(", "); | |
| 599 | try w.writeOperand(s, inst, 2, extra.rhs); | |
| 600 | } | |
| 601 | ||
| 602 | fn writeReduce(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 603 | const reduce = w.air.instructions.items(.data)[@backingInt(inst)].reduce; | |
| 604 | ||
| 605 | try w.writeOperand(s, inst, 0, reduce.operand); | |
| 606 | try s.print(", {s}", .{@tagName(reduce.operation)}); | |
| 607 | } | |
| 608 | ||
| 609 | fn writeCmpVector(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 610 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 611 | const extra = w.air.extraData(Air.VectorCmp, ty_pl.payload).data; | |
| 612 | ||
| 613 | try s.print("{s}, ", .{@tagName(extra.compareOperator())}); | |
| 614 | try w.writeOperand(s, inst, 0, extra.lhs); | |
| 615 | try s.writeAll(", "); | |
| 616 | try w.writeOperand(s, inst, 1, extra.rhs); | |
| 617 | } | |
| 618 | ||
| 619 | fn writeRuntimeNavPtr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 620 | const ip = &w.zcu.intern_pool; | |
| 621 | const ty_nav = w.air.instructions.items(.data)[@backingInt(inst)].ty_nav; | |
| 622 | try w.writeType(s, ty_nav.ty); | |
| 623 | try s.print(", '{f}'", .{ip.getNav(ty_nav.nav).fqn.fmt(ip)}); | |
| 624 | } | |
| 625 | ||
| 626 | fn writeAtomicLoad(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 627 | const atomic_load = w.air.instructions.items(.data)[@backingInt(inst)].atomic_load; | |
| 628 | ||
| 629 | try w.writeOperand(s, inst, 0, atomic_load.ptr); | |
| 630 | try s.print(", {s}", .{@tagName(atomic_load.order)}); | |
| 631 | } | |
| 632 | ||
| 633 | fn writePrefetch(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 634 | const prefetch = w.air.instructions.items(.data)[@backingInt(inst)].prefetch; | |
| 635 | ||
| 636 | try w.writeOperand(s, inst, 0, prefetch.ptr); | |
| 637 | try s.print(", {s}, {d}, {s}", .{ | |
| 638 | @tagName(prefetch.rw), prefetch.locality, @tagName(prefetch.cache), | |
| 639 | }); | |
| 640 | } | |
| 641 | ||
| 642 | fn writeAtomicStore( | |
| 643 | w: *Writer, | |
| 644 | s: *std.Io.Writer, | |
| 645 | inst: Air.Inst.Index, | |
| 646 | order: std.lang.AtomicOrder, | |
| 647 | ) Error!void { | |
| 648 | const bin_op = w.air.instructions.items(.data)[@backingInt(inst)].bin_op; | |
| 649 | try w.writeOperand(s, inst, 0, bin_op.lhs); | |
| 650 | try s.writeAll(", "); | |
| 651 | try w.writeOperand(s, inst, 1, bin_op.rhs); | |
| 652 | try s.print(", {s}", .{@tagName(order)}); | |
| 653 | } | |
| 654 | ||
| 655 | fn writeAtomicRmw(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 656 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 657 | const extra = w.air.extraData(Air.AtomicRmw, pl_op.payload).data; | |
| 658 | ||
| 659 | try w.writeOperand(s, inst, 0, pl_op.operand); | |
| 660 | try s.writeAll(", "); | |
| 661 | try w.writeOperand(s, inst, 1, extra.operand); | |
| 662 | try s.print(", {s}, {s}", .{ @tagName(extra.op()), @tagName(extra.ordering()) }); | |
| 663 | } | |
| 664 | ||
| 665 | fn writeFieldParentPtr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 666 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 667 | const extra = w.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | |
| 668 | ||
| 669 | try w.writeOperand(s, inst, 0, extra.field_ptr); | |
| 670 | try s.print(", {d}", .{extra.field_index}); | |
| 671 | } | |
| 672 | ||
| 673 | fn writeAssembly(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 674 | const unwrapped_asm = w.air.unwrapAsm(inst); | |
| 675 | const is_volatile = unwrapped_asm.is_volatile; | |
| 676 | var op_index: usize = 0; | |
| 677 | ||
| 678 | const ret_ty = w.typeOfIndex(inst); | |
| 679 | try w.writeType(s, ret_ty); | |
| 680 | ||
| 681 | if (is_volatile) { | |
| 682 | try s.writeAll(", volatile"); | |
| 683 | } | |
| 684 | ||
| 685 | var it = unwrapped_asm.iterateOutputs(); | |
| 686 | while (it.next()) |out| { | |
| 687 | const name = out.name; | |
| 688 | const constraint = out.constraint; | |
| 689 | if (out.operand == .none) { | |
| 690 | try s.print(", [{s}] -> {s}", .{ name, constraint }); | |
| 691 | } else { | |
| 692 | try s.print(", [{s}] out {s} = (", .{ name, constraint }); | |
| 693 | try w.writeOperand(s, inst, op_index, out.operand); | |
| 694 | op_index += 1; | |
| 695 | try s.writeByte(')'); | |
| 696 | } | |
| 697 | } | |
| 698 | ||
| 699 | it = unwrapped_asm.iterateInputs(); | |
| 700 | while (it.next()) |in| { | |
| 701 | const name = in.name; | |
| 702 | const constraint = in.constraint; | |
| 703 | try s.print(", [{s}] in {s} = (", .{ name, constraint }); | |
| 704 | try w.writeOperand(s, inst, op_index, in.operand); | |
| 705 | op_index += 1; | |
| 706 | try s.writeByte(')'); | |
| 707 | } | |
| 708 | ||
| 709 | const zcu = w.zcu; | |
| 710 | const ip = &zcu.intern_pool; | |
| 711 | const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); | |
| 712 | const clobbers_ty = clobbers_val.typeOf(zcu); | |
| 713 | var clobbers_bigint_buf: Value.BigIntSpace = undefined; | |
| 714 | const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); | |
| 715 | for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { | |
| 716 | assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); | |
| 717 | const limb_bits = @bitSizeOf(std.math.big.Limb); | |
| 718 | if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false | |
| 719 | switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { | |
| 720 | 0 => continue, // field is false | |
| 721 | 1 => {}, // field is true | |
| 722 | } | |
| 723 | const clobber = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; | |
| 724 | assert(clobber.len != 0); | |
| 725 | try s.writeAll(", ~{"); | |
| 726 | try s.writeAll(clobber); | |
| 727 | try s.writeAll("}"); | |
| 728 | } | |
| 729 | const asm_source = unwrapped_asm.source; | |
| 730 | try s.print(", \"{f}\"", .{std.zig.fmtString(asm_source)}); | |
| 731 | } | |
| 732 | ||
| 733 | fn writeDbgStmt(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 734 | const dbg_stmt = w.air.instructions.items(.data)[@backingInt(inst)].dbg_stmt; | |
| 735 | try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); | |
| 736 | } | |
| 737 | ||
| 738 | fn writeDbgVar(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 739 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 740 | try w.writeOperand(s, inst, 0, pl_op.operand); | |
| 741 | const name: Air.NullTerminatedString = @fromBackingInt(@intCast(pl_op.payload)); | |
| 742 | try s.print(", \"{f}\"", .{std.zig.fmtString(name.toSlice(w.air))}); | |
| 743 | } | |
| 744 | ||
| 745 | fn writeCall(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 746 | const call = w.air.unwrapCall(inst); | |
| 747 | const args = call.args; | |
| 748 | try w.writeOperand(s, inst, 0, call.callee); | |
| 749 | try s.writeAll(", ["); | |
| 750 | for (args, 0..) |arg, i| { | |
| 751 | if (i != 0) try s.writeAll(", "); | |
| 752 | try w.writeOperand(s, inst, 1 + i, arg); | |
| 753 | } | |
| 754 | try s.writeAll("]"); | |
| 755 | } | |
| 756 | ||
| 757 | fn writeBr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 758 | const br = w.air.instructions.items(.data)[@backingInt(inst)].br; | |
| 759 | try w.writeInstIndex(s, br.block_inst, false); | |
| 760 | try s.writeAll(", "); | |
| 761 | try w.writeOperand(s, inst, 0, br.operand); | |
| 762 | } | |
| 763 | ||
| 764 | fn writeRepeat(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 765 | const repeat = w.air.instructions.items(.data)[@backingInt(inst)].repeat; | |
| 766 | try w.writeInstIndex(s, repeat.loop_inst, false); | |
| 767 | } | |
| 768 | ||
| 769 | fn writeTry(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 770 | const unwrapped_try = w.air.unwrapTry(inst); | |
| 771 | const body = unwrapped_try.else_body; | |
| 772 | const liveness_condbr: Air.Liveness.CondBrSlices = if (w.liveness) |liveness| | |
| 773 | liveness.getCondBr(inst) | |
| 774 | else | |
| 775 | .{ .then_deaths = &.{}, .else_deaths = &.{} }; | |
| 776 | ||
| 777 | try w.writeOperand(s, inst, 0, unwrapped_try.error_union); | |
| 778 | if (w.skip_body) return s.writeAll(", ..."); | |
| 779 | try s.writeAll(", {\n"); | |
| 780 | const old_indent = w.indent; | |
| 781 | w.indent += 2; | |
| 782 | ||
| 783 | if (liveness_condbr.else_deaths.len != 0) { | |
| 784 | try s.splatByteAll(' ', w.indent); | |
| 785 | for (liveness_condbr.else_deaths, 0..) |operand, i| { | |
| 786 | if (i != 0) try s.writeAll(" "); | |
| 787 | try s.print("{f}!", .{operand}); | |
| 788 | } | |
| 789 | try s.writeAll("\n"); | |
| 790 | } | |
| 791 | try w.writeBody(s, body); | |
| 792 | ||
| 793 | w.indent = old_indent; | |
| 794 | try s.splatByteAll(' ', w.indent); | |
| 795 | try s.writeAll("}"); | |
| 796 | ||
| 797 | for (liveness_condbr.then_deaths) |operand| { | |
| 798 | try s.print(" {f}!", .{operand}); | |
| 799 | } | |
| 800 | } | |
| 801 | ||
| 802 | fn writeTryPtr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 803 | const unwrapped_try = w.air.unwrapTryPtr(inst); | |
| 804 | const body = unwrapped_try.else_body; | |
| 805 | const liveness_condbr: Air.Liveness.CondBrSlices = if (w.liveness) |liveness| | |
| 806 | liveness.getCondBr(inst) | |
| 807 | else | |
| 808 | .{ .then_deaths = &.{}, .else_deaths = &.{} }; | |
| 809 | ||
| 810 | try w.writeOperand(s, inst, 0, unwrapped_try.error_union_ptr); | |
| 811 | ||
| 812 | try s.writeAll(", "); | |
| 813 | try w.writeType(s, unwrapped_try.error_union_payload_ptr_ty); | |
| 814 | if (w.skip_body) return s.writeAll(", ..."); | |
| 815 | try s.writeAll(", {\n"); | |
| 816 | const old_indent = w.indent; | |
| 817 | w.indent += 2; | |
| 818 | ||
| 819 | if (liveness_condbr.else_deaths.len != 0) { | |
| 820 | try s.splatByteAll(' ', w.indent); | |
| 821 | for (liveness_condbr.else_deaths, 0..) |operand, i| { | |
| 822 | if (i != 0) try s.writeAll(" "); | |
| 823 | try s.print("{f}!", .{operand}); | |
| 824 | } | |
| 825 | try s.writeAll("\n"); | |
| 826 | } | |
| 827 | try w.writeBody(s, body); | |
| 828 | ||
| 829 | w.indent = old_indent; | |
| 830 | try s.splatByteAll(' ', w.indent); | |
| 831 | try s.writeAll("}"); | |
| 832 | ||
| 833 | for (liveness_condbr.then_deaths) |operand| { | |
| 834 | try s.print(" {f}!", .{operand}); | |
| 835 | } | |
| 836 | } | |
| 837 | ||
| 838 | fn writeCondBr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 839 | const cond_br = w.air.unwrapCondBr(inst); | |
| 840 | const then_body = cond_br.then_body; | |
| 841 | const else_body = cond_br.else_body; | |
| 842 | const liveness_condbr: Air.Liveness.CondBrSlices = if (w.liveness) |liveness| | |
| 843 | liveness.getCondBr(inst) | |
| 844 | else | |
| 845 | .{ .then_deaths = &.{}, .else_deaths = &.{} }; | |
| 846 | ||
| 847 | try w.writeOperand(s, inst, 0, cond_br.condition); | |
| 848 | if (w.skip_body) return s.writeAll(", ..."); | |
| 849 | try s.writeAll(","); | |
| 850 | if (cond_br.branch_hints.true != .none) { | |
| 851 | try s.print(" {s}", .{@tagName(cond_br.branch_hints.true)}); | |
| 852 | } | |
| 853 | if (cond_br.branch_hints.then_cov != .none) { | |
| 854 | try s.print(" {s}", .{@tagName(cond_br.branch_hints.then_cov)}); | |
| 855 | } | |
| 856 | try s.writeAll(" {\n"); | |
| 857 | const old_indent = w.indent; | |
| 858 | w.indent += 2; | |
| 859 | ||
| 860 | if (liveness_condbr.then_deaths.len != 0) { | |
| 861 | try s.splatByteAll(' ', w.indent); | |
| 862 | for (liveness_condbr.then_deaths, 0..) |operand, i| { | |
| 863 | if (i != 0) try s.writeAll(" "); | |
| 864 | try s.print("{f}!", .{operand}); | |
| 865 | } | |
| 866 | try s.writeAll("\n"); | |
| 867 | } | |
| 868 | ||
| 869 | try w.writeBody(s, then_body); | |
| 870 | try s.splatByteAll(' ', old_indent); | |
| 871 | try s.writeAll("},"); | |
| 872 | if (cond_br.branch_hints.false != .none) { | |
| 873 | try s.print(" {s}", .{@tagName(cond_br.branch_hints.false)}); | |
| 874 | } | |
| 875 | if (cond_br.branch_hints.else_cov != .none) { | |
| 876 | try s.print(" {s}", .{@tagName(cond_br.branch_hints.else_cov)}); | |
| 877 | } | |
| 878 | try s.writeAll(" {\n"); | |
| 879 | ||
| 880 | if (liveness_condbr.else_deaths.len != 0) { | |
| 881 | try s.splatByteAll(' ', w.indent); | |
| 882 | for (liveness_condbr.else_deaths, 0..) |operand, i| { | |
| 883 | if (i != 0) try s.writeAll(" "); | |
| 884 | try s.print("{f}!", .{operand}); | |
| 885 | } | |
| 886 | try s.writeAll("\n"); | |
| 887 | } | |
| 888 | ||
| 889 | try w.writeBody(s, else_body); | |
| 890 | w.indent = old_indent; | |
| 891 | ||
| 892 | try s.splatByteAll(' ', old_indent); | |
| 893 | try s.writeAll("}"); | |
| 894 | } | |
| 895 | ||
| 896 | fn writeSwitchBr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 897 | const switch_br = w.air.unwrapSwitch(inst); | |
| 898 | ||
| 899 | const liveness: Air.Liveness.SwitchBrTable = if (w.liveness) |liveness| | |
| 900 | liveness.getSwitchBr(w.gpa, inst, switch_br.cases_len + 1) catch | |
| 901 | @panic("out of memory") | |
| 902 | else blk: { | |
| 903 | const slice = w.gpa.alloc([]const Air.Inst.Index, switch_br.cases_len + 1) catch | |
| 904 | @panic("out of memory"); | |
| 905 | @memset(slice, &.{}); | |
| 906 | break :blk .{ .deaths = slice }; | |
| 907 | }; | |
| 908 | defer w.gpa.free(liveness.deaths); | |
| 909 | ||
| 910 | try w.writeOperand(s, inst, 0, switch_br.operand); | |
| 911 | if (w.skip_body) return s.writeAll(", ..."); | |
| 912 | const old_indent = w.indent; | |
| 913 | w.indent += 2; | |
| 914 | ||
| 915 | var it = switch_br.iterateCases(); | |
| 916 | while (it.next()) |case| { | |
| 917 | try s.writeAll(", ["); | |
| 918 | for (case.items, 0..) |item, item_i| { | |
| 919 | if (item_i != 0) try s.writeAll(", "); | |
| 920 | try w.writeInstRef(s, item, false); | |
| 921 | } | |
| 922 | for (case.ranges, 0..) |range, range_i| { | |
| 923 | if (range_i != 0 or case.items.len != 0) try s.writeAll(", "); | |
| 924 | try w.writeInstRef(s, range[0], false); | |
| 925 | try s.writeAll("..."); | |
| 926 | try w.writeInstRef(s, range[1], false); | |
| 927 | } | |
| 928 | try s.writeAll("] "); | |
| 929 | const hint = switch_br.getHint(case.idx); | |
| 930 | if (hint != .none) { | |
| 931 | try s.print(".{s} ", .{@tagName(hint)}); | |
| 932 | } | |
| 933 | try s.writeAll("=> {\n"); | |
| 934 | w.indent += 2; | |
| 935 | ||
| 936 | const deaths = liveness.deaths[case.idx]; | |
| 937 | if (deaths.len != 0) { | |
| 938 | try s.splatByteAll(' ', w.indent); | |
| 939 | for (deaths, 0..) |operand, i| { | |
| 940 | if (i != 0) try s.writeAll(" "); | |
| 941 | try s.print("{f}!", .{operand}); | |
| 942 | } | |
| 943 | try s.writeAll("\n"); | |
| 944 | } | |
| 945 | ||
| 946 | try w.writeBody(s, case.body); | |
| 947 | w.indent -= 2; | |
| 948 | try s.splatByteAll(' ', w.indent); | |
| 949 | try s.writeAll("}"); | |
| 950 | } | |
| 951 | ||
| 952 | const else_body = it.elseBody(); | |
| 953 | if (else_body.len != 0) { | |
| 954 | try s.writeAll(", else "); | |
| 955 | const hint = switch_br.getElseHint(); | |
| 956 | if (hint != .none) { | |
| 957 | try s.print(".{s} ", .{@tagName(hint)}); | |
| 958 | } | |
| 959 | try s.writeAll("=> {\n"); | |
| 960 | w.indent += 2; | |
| 961 | ||
| 962 | const deaths = liveness.deaths[liveness.deaths.len - 1]; | |
| 963 | if (deaths.len != 0) { | |
| 964 | try s.splatByteAll(' ', w.indent); | |
| 965 | for (deaths, 0..) |operand, i| { | |
| 966 | if (i != 0) try s.writeAll(" "); | |
| 967 | try s.print("{f}!", .{operand}); | |
| 968 | } | |
| 969 | try s.writeAll("\n"); | |
| 970 | } | |
| 971 | ||
| 972 | try w.writeBody(s, else_body); | |
| 973 | w.indent -= 2; | |
| 974 | try s.splatByteAll(' ', w.indent); | |
| 975 | try s.writeAll("}"); | |
| 976 | } | |
| 977 | ||
| 978 | try s.writeAll("\n"); | |
| 979 | try s.splatByteAll(' ', old_indent); | |
| 980 | } | |
| 981 | ||
| 982 | fn writeWasmMemorySize(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 983 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 984 | try s.print("{d}", .{pl_op.payload}); | |
| 985 | } | |
| 986 | ||
| 987 | fn writeWasmMemoryGrow(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 988 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 989 | try s.print("{d}, ", .{pl_op.payload}); | |
| 990 | try w.writeOperand(s, inst, 0, pl_op.operand); | |
| 991 | } | |
| 992 | ||
| 993 | fn writeWorkDimension(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 994 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 995 | try s.print("{d}", .{pl_op.payload}); | |
| 996 | } | |
| 997 | ||
| 998 | fn writeOperand( | |
| 999 | w: *Writer, | |
| 1000 | s: *std.Io.Writer, | |
| 1001 | inst: Air.Inst.Index, | |
| 1002 | op_index: usize, | |
| 1003 | operand: Air.Inst.Ref, | |
| 1004 | ) Error!void { | |
| 1005 | const small_tomb_bits = Air.Liveness.bpi - 1; | |
| 1006 | const dies = if (w.liveness) |liveness| blk: { | |
| 1007 | if (op_index < small_tomb_bits) | |
| 1008 | break :blk liveness.operandDies(inst, @intCast(op_index)); | |
| 1009 | var extra_index = liveness.special.get(inst).?; | |
| 1010 | var tomb_op_index: usize = small_tomb_bits; | |
| 1011 | while (true) { | |
| 1012 | const bits = liveness.extra[extra_index]; | |
| 1013 | if (op_index < tomb_op_index + 31) { | |
| 1014 | break :blk @as(u1, @truncate(bits >> @as(u5, @intCast(op_index - tomb_op_index)))) != 0; | |
| 1015 | } | |
| 1016 | if ((bits >> 31) != 0) break :blk false; | |
| 1017 | extra_index += 1; | |
| 1018 | tomb_op_index += 31; | |
| 1019 | } | |
| 1020 | } else false; | |
| 1021 | return w.writeInstRef(s, operand, dies); | |
| 1022 | } | |
| 1023 | ||
| 1024 | fn writeInstRef( | |
| 1025 | w: *Writer, | |
| 1026 | s: *std.Io.Writer, | |
| 1027 | operand: Air.Inst.Ref, | |
| 1028 | dies: bool, | |
| 1029 | ) Error!void { | |
| 1030 | if (@backingInt(operand) < InternPool.static_len) { | |
| 1031 | return s.print("@{}", .{operand}); | |
| 1032 | } else if (operand.toInterned()) |ip_index| { | |
| 1033 | const zcu = w.zcu; | |
| 1034 | const ty = Type.fromInterned(zcu.intern_pool.indexToKey(ip_index).typeOf()); | |
| 1035 | try s.print("<{f}, {f}>", .{ | |
| 1036 | ty.fmt(zcu), | |
| 1037 | Value.fromInterned(ip_index).fmtValue(w.zcu), | |
| 1038 | }); | |
| 1039 | } else { | |
| 1040 | return w.writeInstIndex(s, operand.toIndex().?, dies); | |
| 1041 | } | |
| 1042 | } | |
| 1043 | ||
| 1044 | fn writeInstIndex( | |
| 1045 | w: *Writer, | |
| 1046 | s: *std.Io.Writer, | |
| 1047 | inst: Air.Inst.Index, | |
| 1048 | dies: bool, | |
| 1049 | ) Error!void { | |
| 1050 | _ = w; | |
| 1051 | try s.print("{f}", .{inst}); | |
| 1052 | if (dies) try s.writeByte('!'); | |
| 1053 | } | |
| 1054 | ||
| 1055 | fn typeOfIndex(w: *Writer, inst: Air.Inst.Index) Type { | |
| 1056 | const zcu = w.zcu; | |
| 1057 | return w.air.typeOfIndex(inst, &zcu.intern_pool); | |
| 1058 | } | |
| 1059 | }; |
src/Air/print.zig deleted-1048| ... | ... | @@ -1,1048 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const Allocator = std.mem.Allocator; | |
| 3 | const assert = std.debug.assert; | |
| 4 | ||
| 5 | const build_options = @import("build_options"); | |
| 6 | const Zcu = @import("../Zcu.zig"); | |
| 7 | const Value = @import("../Value.zig"); | |
| 8 | const Type = @import("../Type.zig"); | |
| 9 | const Air = @import("../Air.zig"); | |
| 10 | const InternPool = @import("../InternPool.zig"); | |
| 11 | ||
| 12 | pub fn write(air: Air, stream: *std.Io.Writer, zcu: *Zcu, liveness: ?Air.Liveness) !void { | |
| 13 | comptime assert(build_options.enable_debug_extensions); | |
| 14 | const instruction_bytes = air.instructions.len * | |
| 15 | // Here we don't use @sizeOf(Air.Inst.Data) because it would include | |
| 16 | // the debug safety tag but we want to measure release size. | |
| 17 | (@sizeOf(Air.Inst.Tag) + 8); | |
| 18 | const extra_bytes = air.extra.items.len * @sizeOf(u32); | |
| 19 | const tomb_bytes = if (liveness) |l| l.tomb_bits.len * @sizeOf(usize) else 0; | |
| 20 | const liveness_extra_bytes = if (liveness) |l| l.extra.len * @sizeOf(u32) else 0; | |
| 21 | const liveness_special_bytes = if (liveness) |l| l.special.count() * 8 else 0; | |
| 22 | const total_bytes = @sizeOf(Air) + instruction_bytes + extra_bytes + | |
| 23 | @sizeOf(Air.Liveness) + liveness_extra_bytes + | |
| 24 | liveness_special_bytes + tomb_bytes; | |
| 25 | ||
| 26 | // zig fmt: off | |
| 27 | try stream.print( | |
| 28 | \\# Total AIR+Liveness bytes: {Bi} | |
| 29 | \\# AIR Instructions: {d} ({Bi}) | |
| 30 | \\# AIR Extra Data: {d} ({Bi}) | |
| 31 | \\# Liveness tomb_bits: {Bi} | |
| 32 | \\# Liveness Extra Data: {d} ({Bi}) | |
| 33 | \\# Liveness special table: {d} ({Bi}) | |
| 34 | \\ | |
| 35 | , .{ | |
| 36 | total_bytes, | |
| 37 | air.instructions.len, instruction_bytes, | |
| 38 | air.extra.items.len, extra_bytes, | |
| 39 | tomb_bytes, | |
| 40 | if (liveness) |l| l.extra.len else 0, liveness_extra_bytes, | |
| 41 | if (liveness) |l| l.special.count() else 0, liveness_special_bytes, | |
| 42 | }); | |
| 43 | // zig fmt: on | |
| 44 | ||
| 45 | var writer: Writer = .{ | |
| 46 | .zcu = zcu, | |
| 47 | .gpa = zcu.comp.gpa, | |
| 48 | .air = air, | |
| 49 | .liveness = liveness, | |
| 50 | .indent = 2, | |
| 51 | .skip_body = false, | |
| 52 | }; | |
| 53 | try writer.writeBody(stream, air.getMainBody()); | |
| 54 | } | |
| 55 | ||
| 56 | pub fn writeInst( | |
| 57 | air: Air, | |
| 58 | stream: *std.Io.Writer, | |
| 59 | inst: Air.Inst.Index, | |
| 60 | zcu: *Zcu, | |
| 61 | liveness: ?Air.Liveness, | |
| 62 | ) void { | |
| 63 | comptime assert(build_options.enable_debug_extensions); | |
| 64 | var writer: Writer = .{ | |
| 65 | .zcu = zcu, | |
| 66 | .gpa = zcu.comp.gpa, | |
| 67 | .air = air, | |
| 68 | .liveness = liveness, | |
| 69 | .indent = 2, | |
| 70 | .skip_body = true, | |
| 71 | }; | |
| 72 | writer.writeInst(stream, inst) catch return; | |
| 73 | } | |
| 74 | ||
| 75 | pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { | |
| 76 | var buffer: [4096]u8 = undefined; | |
| 77 | const stderr = std.debug.lockStderr(&buffer); | |
| 78 | defer std.debug.unlockStderr(); | |
| 79 | const w = &stderr.file_writer.interface; | |
| 80 | air.write(w, pt, liveness) catch return; | |
| 81 | } | |
| 82 | ||
| 83 | pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { | |
| 84 | var buffer: [4096]u8 = undefined; | |
| 85 | const stderr = std.debug.lockStderr(&buffer); | |
| 86 | defer std.debug.unlockStderr(); | |
| 87 | const w = &stderr.file_writer.interface; | |
| 88 | air.writeInst(w, inst, pt, liveness) catch return; | |
| 89 | } | |
| 90 | ||
| 91 | const Writer = struct { | |
| 92 | zcu: *Zcu, | |
| 93 | gpa: Allocator, | |
| 94 | air: Air, | |
| 95 | liveness: ?Air.Liveness, | |
| 96 | indent: usize, | |
| 97 | skip_body: bool, | |
| 98 | ||
| 99 | const Error = std.Io.Writer.Error; | |
| 100 | ||
| 101 | fn writeBody(w: *Writer, s: *std.Io.Writer, body: []const Air.Inst.Index) Error!void { | |
| 102 | for (body) |inst| { | |
| 103 | try w.writeInst(s, inst); | |
| 104 | try s.writeByte('\n'); | |
| 105 | } | |
| 106 | } | |
| 107 | ||
| 108 | fn writeInst(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 109 | const tag = w.air.instructions.items(.tag)[@backingInt(inst)]; | |
| 110 | try s.splatByteAll(' ', w.indent); | |
| 111 | try s.print("{f}{c}= {s}(", .{ | |
| 112 | inst, | |
| 113 | @as(u8, if (if (w.liveness) |liveness| liveness.isUnused(inst) else false) '!' else ' '), | |
| 114 | @tagName(tag), | |
| 115 | }); | |
| 116 | switch (tag) { | |
| 117 | .add, | |
| 118 | .add_optimized, | |
| 119 | .add_safe, | |
| 120 | .add_wrap, | |
| 121 | .add_sat, | |
| 122 | .sub, | |
| 123 | .sub_optimized, | |
| 124 | .sub_safe, | |
| 125 | .sub_wrap, | |
| 126 | .sub_sat, | |
| 127 | .mul, | |
| 128 | .mul_optimized, | |
| 129 | .mul_safe, | |
| 130 | .mul_wrap, | |
| 131 | .mul_sat, | |
| 132 | .div_float, | |
| 133 | .div_trunc, | |
| 134 | .div_floor, | |
| 135 | .div_ceil, | |
| 136 | .div_exact, | |
| 137 | .rem, | |
| 138 | .mod, | |
| 139 | .bit_and, | |
| 140 | .bit_or, | |
| 141 | .xor, | |
| 142 | .cmp_lt, | |
| 143 | .cmp_lte, | |
| 144 | .cmp_eq, | |
| 145 | .cmp_gte, | |
| 146 | .cmp_gt, | |
| 147 | .cmp_neq, | |
| 148 | .store, | |
| 149 | .store_safe, | |
| 150 | .array_elem_val, | |
| 151 | .slice_elem_val, | |
| 152 | .ptr_elem_val, | |
| 153 | .shl, | |
| 154 | .shl_exact, | |
| 155 | .shl_sat, | |
| 156 | .shr, | |
| 157 | .shr_exact, | |
| 158 | .set_union_tag, | |
| 159 | .min, | |
| 160 | .max, | |
| 161 | .div_float_optimized, | |
| 162 | .div_trunc_optimized, | |
| 163 | .div_floor_optimized, | |
| 164 | .div_ceil_optimized, | |
| 165 | .div_exact_optimized, | |
| 166 | .rem_optimized, | |
| 167 | .mod_optimized, | |
| 168 | .cmp_lt_optimized, | |
| 169 | .cmp_lte_optimized, | |
| 170 | .cmp_eq_optimized, | |
| 171 | .cmp_gte_optimized, | |
| 172 | .cmp_gt_optimized, | |
| 173 | .cmp_neq_optimized, | |
| 174 | .memcpy, | |
| 175 | .memmove, | |
| 176 | .memset, | |
| 177 | .memset_safe, | |
| 178 | .legalize_vec_elem_val, | |
| 179 | => try w.writeBinOp(s, inst), | |
| 180 | ||
| 181 | .is_null, | |
| 182 | .is_non_null, | |
| 183 | .is_null_ptr, | |
| 184 | .is_non_null_ptr, | |
| 185 | .is_err, | |
| 186 | .is_non_err, | |
| 187 | .is_err_ptr, | |
| 188 | .is_non_err_ptr, | |
| 189 | .ret, | |
| 190 | .ret_safe, | |
| 191 | .ret_load, | |
| 192 | .is_named_enum_value, | |
| 193 | .tag_name, | |
| 194 | .error_name, | |
| 195 | .sqrt, | |
| 196 | .sin, | |
| 197 | .cos, | |
| 198 | .tan, | |
| 199 | .exp, | |
| 200 | .exp2, | |
| 201 | .log, | |
| 202 | .log2, | |
| 203 | .log10, | |
| 204 | .floor, | |
| 205 | .ceil, | |
| 206 | .round, | |
| 207 | .trunc_float, | |
| 208 | .neg, | |
| 209 | .neg_optimized, | |
| 210 | .cmp_lte_errors_len, | |
| 211 | .set_err_return_trace, | |
| 212 | .c_va_end, | |
| 213 | => try w.writeUnOp(s, inst), | |
| 214 | ||
| 215 | .trap, | |
| 216 | .breakpoint, | |
| 217 | .dbg_empty_stmt, | |
| 218 | .unreach, | |
| 219 | .ret_addr, | |
| 220 | .frame_addr, | |
| 221 | .save_err_return_trace_index, | |
| 222 | => try w.writeNoOp(s, inst), | |
| 223 | ||
| 224 | .alloc, | |
| 225 | .ret_ptr, | |
| 226 | .err_return_trace, | |
| 227 | .c_va_start, | |
| 228 | => try w.writeTy(s, inst), | |
| 229 | ||
| 230 | .arg => try w.writeArg(s, inst), | |
| 231 | ||
| 232 | .not, | |
| 233 | .bit_cast, | |
| 234 | .bit_cast_safe, | |
| 235 | .ptr_cast, | |
| 236 | .ptr_from_int, | |
| 237 | .int_from_ptr, | |
| 238 | .error_cast, | |
| 239 | .error_from_int, | |
| 240 | .int_from_error, | |
| 241 | .union_from_enum, | |
| 242 | .load, | |
| 243 | .fptrunc, | |
| 244 | .fpext, | |
| 245 | .int_cast, | |
| 246 | .int_cast_safe, | |
| 247 | .trunc, | |
| 248 | .optional_payload, | |
| 249 | .optional_payload_ptr, | |
| 250 | .optional_payload_ptr_set, | |
| 251 | .errunion_payload_ptr_set, | |
| 252 | .wrap_optional, | |
| 253 | .unwrap_errunion_payload, | |
| 254 | .unwrap_errunion_err, | |
| 255 | .unwrap_errunion_payload_ptr, | |
| 256 | .unwrap_errunion_err_ptr, | |
| 257 | .wrap_errunion_payload, | |
| 258 | .wrap_errunion_err, | |
| 259 | .slice_ptr, | |
| 260 | .slice_len, | |
| 261 | .ptr_slice_len_ptr, | |
| 262 | .ptr_slice_ptr_ptr, | |
| 263 | .struct_field_ptr_index_0, | |
| 264 | .struct_field_ptr_index_1, | |
| 265 | .struct_field_ptr_index_2, | |
| 266 | .struct_field_ptr_index_3, | |
| 267 | .array_to_slice, | |
| 268 | .array_to_vector, | |
| 269 | .float_from_int, | |
| 270 | .splat, | |
| 271 | .int_from_float, | |
| 272 | .int_from_float_optimized, | |
| 273 | .int_from_float_safe, | |
| 274 | .int_from_float_optimized_safe, | |
| 275 | .get_union_tag, | |
| 276 | .clz, | |
| 277 | .ctz, | |
| 278 | .popcount, | |
| 279 | .byte_swap, | |
| 280 | .bit_reverse, | |
| 281 | .abs, | |
| 282 | .error_set_has_value, | |
| 283 | .addrspace_cast, | |
| 284 | .c_va_arg, | |
| 285 | .c_va_copy, | |
| 286 | => try w.writeTyOp(s, inst), | |
| 287 | ||
| 288 | .block, .dbg_inline_block => try w.writeBlock(s, tag, inst), | |
| 289 | ||
| 290 | .loop => try w.writeLoop(s, inst), | |
| 291 | ||
| 292 | .slice, | |
| 293 | .slice_elem_ptr, | |
| 294 | .ptr_elem_ptr, | |
| 295 | .ptr_add, | |
| 296 | .ptr_sub, | |
| 297 | .add_with_overflow, | |
| 298 | .sub_with_overflow, | |
| 299 | .mul_with_overflow, | |
| 300 | .shl_with_overflow, | |
| 301 | => try w.writeTyPlBin(s, inst), | |
| 302 | ||
| 303 | .call, | |
| 304 | .call_always_tail, | |
| 305 | .call_never_tail, | |
| 306 | .call_never_inline, | |
| 307 | => try w.writeCall(s, inst), | |
| 308 | ||
| 309 | .dbg_var_ptr, | |
| 310 | .dbg_var_val, | |
| 311 | .dbg_arg_inline, | |
| 312 | => try w.writeDbgVar(s, inst), | |
| 313 | ||
| 314 | .struct_field_ptr => try w.writeStructField(s, inst), | |
| 315 | .agg_field_val => try w.writeStructField(s, inst), | |
| 316 | .spirv_runtime_array_len => try w.writeStructField(s, inst), | |
| 317 | .inferred_alloc => @panic("TODO"), | |
| 318 | .inferred_alloc_comptime => @panic("TODO"), | |
| 319 | .assembly => try w.writeAssembly(s, inst), | |
| 320 | .dbg_stmt => try w.writeDbgStmt(s, inst), | |
| 321 | ||
| 322 | .aggregate_init => try w.writeAggregateInit(s, inst), | |
| 323 | .union_init => try w.writeUnionInit(s, inst), | |
| 324 | .br => try w.writeBr(s, inst), | |
| 325 | .switch_dispatch => try w.writeBr(s, inst), | |
| 326 | .repeat => try w.writeRepeat(s, inst), | |
| 327 | .cond_br => try w.writeCondBr(s, inst), | |
| 328 | .@"try", .try_cold => try w.writeTry(s, inst), | |
| 329 | .try_ptr, .try_ptr_cold => try w.writeTryPtr(s, inst), | |
| 330 | .loop_switch_br, .switch_br => try w.writeSwitchBr(s, inst), | |
| 331 | .cmpxchg_weak, .cmpxchg_strong => try w.writeCmpxchg(s, inst), | |
| 332 | .atomic_load => try w.writeAtomicLoad(s, inst), | |
| 333 | .prefetch => try w.writePrefetch(s, inst), | |
| 334 | .atomic_store_unordered => try w.writeAtomicStore(s, inst, .unordered), | |
| 335 | .atomic_store_monotonic => try w.writeAtomicStore(s, inst, .monotonic), | |
| 336 | .atomic_store_release => try w.writeAtomicStore(s, inst, .release), | |
| 337 | .atomic_store_seq_cst => try w.writeAtomicStore(s, inst, .seq_cst), | |
| 338 | .atomic_rmw => try w.writeAtomicRmw(s, inst), | |
| 339 | .field_parent_ptr => try w.writeFieldParentPtr(s, inst), | |
| 340 | .wasm_memory_size => try w.writeWasmMemorySize(s, inst), | |
| 341 | .wasm_memory_grow => try w.writeWasmMemoryGrow(s, inst), | |
| 342 | .mul_add => try w.writeMulAdd(s, inst), | |
| 343 | .select => try w.writeSelect(s, inst), | |
| 344 | .shuffle_one => try w.writeShuffleOne(s, inst), | |
| 345 | .shuffle_two => try w.writeShuffleTwo(s, inst), | |
| 346 | .reduce, .reduce_optimized => try w.writeReduce(s, inst), | |
| 347 | .cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst), | |
| 348 | .runtime_nav_ptr => try w.writeRuntimeNavPtr(s, inst), | |
| 349 | .legalize_vec_store_elem => try w.writeLegalizeVecStoreElem(s, inst), | |
| 350 | .legalize_compiler_rt_call => try w.writeLegalizeCompilerRtCall(s, inst), | |
| 351 | ||
| 352 | .work_item_id, | |
| 353 | .work_group_size, | |
| 354 | .work_group_id, | |
| 355 | => try w.writeWorkDimension(s, inst), | |
| 356 | } | |
| 357 | try s.writeByte(')'); | |
| 358 | } | |
| 359 | ||
| 360 | fn writeBinOp(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 361 | const bin_op = w.air.instructions.items(.data)[@backingInt(inst)].bin_op; | |
| 362 | try w.writeOperand(s, inst, 0, bin_op.lhs); | |
| 363 | try s.writeAll(", "); | |
| 364 | try w.writeOperand(s, inst, 1, bin_op.rhs); | |
| 365 | } | |
| 366 | ||
| 367 | fn writeUnOp(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 368 | const un_op = w.air.instructions.items(.data)[@backingInt(inst)].un_op; | |
| 369 | try w.writeOperand(s, inst, 0, un_op); | |
| 370 | } | |
| 371 | ||
| 372 | fn writeNoOp(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 373 | _ = w; | |
| 374 | _ = s; | |
| 375 | _ = inst; | |
| 376 | // no-op, no argument to write | |
| 377 | } | |
| 378 | ||
| 379 | fn writeType(w: *Writer, s: *std.Io.Writer, ty: Type) !void { | |
| 380 | return ty.print(s, w.zcu, null); | |
| 381 | } | |
| 382 | ||
| 383 | fn writeTy(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 384 | const ty = w.air.instructions.items(.data)[@backingInt(inst)].ty; | |
| 385 | try w.writeType(s, ty); | |
| 386 | } | |
| 387 | ||
| 388 | fn writeArg(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 389 | const arg = w.air.instructions.items(.data)[@backingInt(inst)].arg; | |
| 390 | try w.writeType(s, arg.ty); | |
| 391 | try s.print(", {d}", .{arg.zir_param_index}); | |
| 392 | } | |
| 393 | ||
| 394 | fn writeTyOp(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 395 | const ty_op = w.air.instructions.items(.data)[@backingInt(inst)].ty_op; | |
| 396 | try w.writeType(s, ty_op.ty); | |
| 397 | try s.writeAll(", "); | |
| 398 | try w.writeOperand(s, inst, 0, ty_op.operand); | |
| 399 | } | |
| 400 | ||
| 401 | fn writeBlock(w: *Writer, s: *std.Io.Writer, tag: Air.Inst.Tag, inst: Air.Inst.Index) Error!void { | |
| 402 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 403 | try w.writeType(s, ty_pl.ty); | |
| 404 | ||
| 405 | const body = switch (tag) { | |
| 406 | .block => w.air.unwrapBlock(inst).body, | |
| 407 | .dbg_inline_block => body: { | |
| 408 | const dbg_block = w.air.unwrapDbgBlock(inst); | |
| 409 | try s.writeAll(", "); | |
| 410 | try w.writeInstRef(s, Air.internedToRef(dbg_block.func), false); | |
| 411 | break :body dbg_block.body; | |
| 412 | }, | |
| 413 | else => unreachable, | |
| 414 | }; | |
| 415 | if (w.skip_body) return s.writeAll(", ..."); | |
| 416 | const liveness_block: Air.Liveness.BlockSlices = if (w.liveness) |liveness| | |
| 417 | liveness.getBlock(inst) | |
| 418 | else | |
| 419 | .{ .deaths = &.{} }; | |
| 420 | ||
| 421 | try s.writeAll(", {\n"); | |
| 422 | const old_indent = w.indent; | |
| 423 | w.indent += 2; | |
| 424 | try w.writeBody(s, body); | |
| 425 | w.indent = old_indent; | |
| 426 | try s.splatByteAll(' ', w.indent); | |
| 427 | try s.writeAll("}"); | |
| 428 | ||
| 429 | for (liveness_block.deaths) |operand| { | |
| 430 | try s.print(" {f}!", .{operand}); | |
| 431 | } | |
| 432 | } | |
| 433 | ||
| 434 | fn writeLoop(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 435 | const block = w.air.unwrapBlock(inst); | |
| 436 | ||
| 437 | try w.writeType(s, block.ty); | |
| 438 | if (w.skip_body) return s.writeAll(", ..."); | |
| 439 | try s.writeAll(", {\n"); | |
| 440 | const old_indent = w.indent; | |
| 441 | w.indent += 2; | |
| 442 | try w.writeBody(s, block.body); | |
| 443 | w.indent = old_indent; | |
| 444 | try s.splatByteAll(' ', w.indent); | |
| 445 | try s.writeAll("}"); | |
| 446 | } | |
| 447 | ||
| 448 | fn writeAggregateInit(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 449 | const zcu = w.zcu; | |
| 450 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 451 | const vector_ty = ty_pl.ty; | |
| 452 | const len = @as(usize, @intCast(vector_ty.arrayLen(zcu))); | |
| 453 | const elements = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[ty_pl.payload..][0..len])); | |
| 454 | ||
| 455 | try w.writeType(s, vector_ty); | |
| 456 | try s.writeAll(", ["); | |
| 457 | for (elements, 0..) |elem, i| { | |
| 458 | if (i != 0) try s.writeAll(", "); | |
| 459 | try w.writeOperand(s, inst, i, elem); | |
| 460 | } | |
| 461 | try s.writeAll("]"); | |
| 462 | } | |
| 463 | ||
| 464 | fn writeUnionInit(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 465 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 466 | const extra = w.air.extraData(Air.UnionInit, ty_pl.payload).data; | |
| 467 | ||
| 468 | try s.print("{d}, ", .{extra.field_index}); | |
| 469 | try w.writeOperand(s, inst, 0, extra.init); | |
| 470 | } | |
| 471 | ||
| 472 | fn writeStructField(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 473 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 474 | const extra = w.air.extraData(Air.StructField, ty_pl.payload).data; | |
| 475 | ||
| 476 | try w.writeOperand(s, inst, 0, extra.struct_operand); | |
| 477 | try s.print(", {d}", .{extra.field_index}); | |
| 478 | } | |
| 479 | ||
| 480 | fn writeTyPlBin(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 481 | const data = w.air.instructions.items(.data); | |
| 482 | const ty_pl = data[@backingInt(inst)].ty_pl; | |
| 483 | const extra = w.air.extraData(Air.Bin, ty_pl.payload).data; | |
| 484 | ||
| 485 | const inst_ty = data[@backingInt(inst)].ty_pl.ty; | |
| 486 | try w.writeType(s, inst_ty); | |
| 487 | try s.writeAll(", "); | |
| 488 | try w.writeOperand(s, inst, 0, extra.lhs); | |
| 489 | try s.writeAll(", "); | |
| 490 | try w.writeOperand(s, inst, 1, extra.rhs); | |
| 491 | } | |
| 492 | ||
| 493 | fn writeCmpxchg(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 494 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 495 | const extra = w.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | |
| 496 | ||
| 497 | try w.writeOperand(s, inst, 0, extra.ptr); | |
| 498 | try s.writeAll(", "); | |
| 499 | try w.writeOperand(s, inst, 1, extra.expected_value); | |
| 500 | try s.writeAll(", "); | |
| 501 | try w.writeOperand(s, inst, 2, extra.new_value); | |
| 502 | try s.print(", {s}, {s}", .{ | |
| 503 | @tagName(extra.successOrder()), @tagName(extra.failureOrder()), | |
| 504 | }); | |
| 505 | } | |
| 506 | ||
| 507 | fn writeMulAdd(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 508 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 509 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; | |
| 510 | ||
| 511 | try w.writeOperand(s, inst, 0, extra.lhs); | |
| 512 | try s.writeAll(", "); | |
| 513 | try w.writeOperand(s, inst, 1, extra.rhs); | |
| 514 | try s.writeAll(", "); | |
| 515 | try w.writeOperand(s, inst, 2, pl_op.operand); | |
| 516 | } | |
| 517 | ||
| 518 | fn writeLegalizeVecStoreElem(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 519 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 520 | const bin = w.air.extraData(Air.Bin, pl_op.payload).data; | |
| 521 | ||
| 522 | try w.writeOperand(s, inst, 0, pl_op.operand); | |
| 523 | try s.writeAll(", "); | |
| 524 | try w.writeOperand(s, inst, 1, bin.lhs); | |
| 525 | try s.writeAll(", "); | |
| 526 | try w.writeOperand(s, inst, 2, bin.rhs); | |
| 527 | } | |
| 528 | ||
| 529 | fn writeLegalizeCompilerRtCall(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 530 | const rt_call = w.air.unwrapCompilerRtCall(inst); | |
| 531 | const args = rt_call.args; | |
| 532 | ||
| 533 | try s.print("{t}, [", .{rt_call.func}); | |
| 534 | for (args, 0..) |arg, i| { | |
| 535 | if (i != 0) try s.writeAll(", "); | |
| 536 | try w.writeOperand(s, inst, i, arg); | |
| 537 | } | |
| 538 | try s.writeByte(']'); | |
| 539 | } | |
| 540 | ||
| 541 | fn writeShuffleOne(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 542 | const unwrapped = w.air.unwrapShuffleOne(w.zcu, inst); | |
| 543 | try w.writeType(s, unwrapped.result_ty); | |
| 544 | try s.writeAll(", "); | |
| 545 | try w.writeOperand(s, inst, 0, unwrapped.operand); | |
| 546 | try s.writeAll(", ["); | |
| 547 | for (unwrapped.mask, 0..) |mask_elem, mask_idx| { | |
| 548 | if (mask_idx > 0) try s.writeAll(", "); | |
| 549 | switch (mask_elem.unwrap()) { | |
| 550 | .elem => |idx| try s.print("elem {d}", .{idx}), | |
| 551 | .value => |val| try s.print("val {f}", .{Value.fromInterned(val).fmtValue(w.zcu)}), | |
| 552 | } | |
| 553 | } | |
| 554 | try s.writeByte(']'); | |
| 555 | } | |
| 556 | ||
| 557 | fn writeShuffleTwo(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 558 | const unwrapped = w.air.unwrapShuffleTwo(w.zcu, inst); | |
| 559 | try w.writeType(s, unwrapped.result_ty); | |
| 560 | try s.writeAll(", "); | |
| 561 | try w.writeOperand(s, inst, 0, unwrapped.operand_a); | |
| 562 | try s.writeAll(", "); | |
| 563 | try w.writeOperand(s, inst, 1, unwrapped.operand_b); | |
| 564 | try s.writeAll(", ["); | |
| 565 | for (unwrapped.mask, 0..) |mask_elem, mask_idx| { | |
| 566 | if (mask_idx > 0) try s.writeAll(", "); | |
| 567 | switch (mask_elem.unwrap()) { | |
| 568 | .a_elem => |idx| try s.print("a_elem {d}", .{idx}), | |
| 569 | .b_elem => |idx| try s.print("b_elem {d}", .{idx}), | |
| 570 | .undef => try s.writeAll("undef"), | |
| 571 | } | |
| 572 | } | |
| 573 | try s.writeByte(']'); | |
| 574 | } | |
| 575 | ||
| 576 | fn writeSelect(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 577 | const zcu = w.zcu; | |
| 578 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 579 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; | |
| 580 | ||
| 581 | const elem_ty = w.typeOfIndex(inst).childType(zcu); | |
| 582 | try w.writeType(s, elem_ty); | |
| 583 | try s.writeAll(", "); | |
| 584 | try w.writeOperand(s, inst, 0, pl_op.operand); | |
| 585 | try s.writeAll(", "); | |
| 586 | try w.writeOperand(s, inst, 1, extra.lhs); | |
| 587 | try s.writeAll(", "); | |
| 588 | try w.writeOperand(s, inst, 2, extra.rhs); | |
| 589 | } | |
| 590 | ||
| 591 | fn writeReduce(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 592 | const reduce = w.air.instructions.items(.data)[@backingInt(inst)].reduce; | |
| 593 | ||
| 594 | try w.writeOperand(s, inst, 0, reduce.operand); | |
| 595 | try s.print(", {s}", .{@tagName(reduce.operation)}); | |
| 596 | } | |
| 597 | ||
| 598 | fn writeCmpVector(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 599 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 600 | const extra = w.air.extraData(Air.VectorCmp, ty_pl.payload).data; | |
| 601 | ||
| 602 | try s.print("{s}, ", .{@tagName(extra.compareOperator())}); | |
| 603 | try w.writeOperand(s, inst, 0, extra.lhs); | |
| 604 | try s.writeAll(", "); | |
| 605 | try w.writeOperand(s, inst, 1, extra.rhs); | |
| 606 | } | |
| 607 | ||
| 608 | fn writeRuntimeNavPtr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 609 | const ip = &w.zcu.intern_pool; | |
| 610 | const ty_nav = w.air.instructions.items(.data)[@backingInt(inst)].ty_nav; | |
| 611 | try w.writeType(s, ty_nav.ty); | |
| 612 | try s.print(", '{f}'", .{ip.getNav(ty_nav.nav).fqn.fmt(ip)}); | |
| 613 | } | |
| 614 | ||
| 615 | fn writeAtomicLoad(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 616 | const atomic_load = w.air.instructions.items(.data)[@backingInt(inst)].atomic_load; | |
| 617 | ||
| 618 | try w.writeOperand(s, inst, 0, atomic_load.ptr); | |
| 619 | try s.print(", {s}", .{@tagName(atomic_load.order)}); | |
| 620 | } | |
| 621 | ||
| 622 | fn writePrefetch(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 623 | const prefetch = w.air.instructions.items(.data)[@backingInt(inst)].prefetch; | |
| 624 | ||
| 625 | try w.writeOperand(s, inst, 0, prefetch.ptr); | |
| 626 | try s.print(", {s}, {d}, {s}", .{ | |
| 627 | @tagName(prefetch.rw), prefetch.locality, @tagName(prefetch.cache), | |
| 628 | }); | |
| 629 | } | |
| 630 | ||
| 631 | fn writeAtomicStore( | |
| 632 | w: *Writer, | |
| 633 | s: *std.Io.Writer, | |
| 634 | inst: Air.Inst.Index, | |
| 635 | order: std.lang.AtomicOrder, | |
| 636 | ) Error!void { | |
| 637 | const bin_op = w.air.instructions.items(.data)[@backingInt(inst)].bin_op; | |
| 638 | try w.writeOperand(s, inst, 0, bin_op.lhs); | |
| 639 | try s.writeAll(", "); | |
| 640 | try w.writeOperand(s, inst, 1, bin_op.rhs); | |
| 641 | try s.print(", {s}", .{@tagName(order)}); | |
| 642 | } | |
| 643 | ||
| 644 | fn writeAtomicRmw(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 645 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 646 | const extra = w.air.extraData(Air.AtomicRmw, pl_op.payload).data; | |
| 647 | ||
| 648 | try w.writeOperand(s, inst, 0, pl_op.operand); | |
| 649 | try s.writeAll(", "); | |
| 650 | try w.writeOperand(s, inst, 1, extra.operand); | |
| 651 | try s.print(", {s}, {s}", .{ @tagName(extra.op()), @tagName(extra.ordering()) }); | |
| 652 | } | |
| 653 | ||
| 654 | fn writeFieldParentPtr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 655 | const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 656 | const extra = w.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | |
| 657 | ||
| 658 | try w.writeOperand(s, inst, 0, extra.field_ptr); | |
| 659 | try s.print(", {d}", .{extra.field_index}); | |
| 660 | } | |
| 661 | ||
| 662 | fn writeAssembly(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 663 | const unwrapped_asm = w.air.unwrapAsm(inst); | |
| 664 | const is_volatile = unwrapped_asm.is_volatile; | |
| 665 | var op_index: usize = 0; | |
| 666 | ||
| 667 | const ret_ty = w.typeOfIndex(inst); | |
| 668 | try w.writeType(s, ret_ty); | |
| 669 | ||
| 670 | if (is_volatile) { | |
| 671 | try s.writeAll(", volatile"); | |
| 672 | } | |
| 673 | ||
| 674 | var it = unwrapped_asm.iterateOutputs(); | |
| 675 | while (it.next()) |out| { | |
| 676 | const name = out.name; | |
| 677 | const constraint = out.constraint; | |
| 678 | if (out.operand == .none) { | |
| 679 | try s.print(", [{s}] -> {s}", .{ name, constraint }); | |
| 680 | } else { | |
| 681 | try s.print(", [{s}] out {s} = (", .{ name, constraint }); | |
| 682 | try w.writeOperand(s, inst, op_index, out.operand); | |
| 683 | op_index += 1; | |
| 684 | try s.writeByte(')'); | |
| 685 | } | |
| 686 | } | |
| 687 | ||
| 688 | it = unwrapped_asm.iterateInputs(); | |
| 689 | while (it.next()) |in| { | |
| 690 | const name = in.name; | |
| 691 | const constraint = in.constraint; | |
| 692 | try s.print(", [{s}] in {s} = (", .{ name, constraint }); | |
| 693 | try w.writeOperand(s, inst, op_index, in.operand); | |
| 694 | op_index += 1; | |
| 695 | try s.writeByte(')'); | |
| 696 | } | |
| 697 | ||
| 698 | const zcu = w.zcu; | |
| 699 | const ip = &zcu.intern_pool; | |
| 700 | const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); | |
| 701 | const clobbers_ty = clobbers_val.typeOf(zcu); | |
| 702 | var clobbers_bigint_buf: Value.BigIntSpace = undefined; | |
| 703 | const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); | |
| 704 | for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { | |
| 705 | assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); | |
| 706 | const limb_bits = @bitSizeOf(std.math.big.Limb); | |
| 707 | if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false | |
| 708 | switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { | |
| 709 | 0 => continue, // field is false | |
| 710 | 1 => {}, // field is true | |
| 711 | } | |
| 712 | const clobber = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; | |
| 713 | assert(clobber.len != 0); | |
| 714 | try s.writeAll(", ~{"); | |
| 715 | try s.writeAll(clobber); | |
| 716 | try s.writeAll("}"); | |
| 717 | } | |
| 718 | const asm_source = unwrapped_asm.source; | |
| 719 | try s.print(", \"{f}\"", .{std.zig.fmtString(asm_source)}); | |
| 720 | } | |
| 721 | ||
| 722 | fn writeDbgStmt(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 723 | const dbg_stmt = w.air.instructions.items(.data)[@backingInt(inst)].dbg_stmt; | |
| 724 | try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); | |
| 725 | } | |
| 726 | ||
| 727 | fn writeDbgVar(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 728 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 729 | try w.writeOperand(s, inst, 0, pl_op.operand); | |
| 730 | const name: Air.NullTerminatedString = @fromBackingInt(@intCast(pl_op.payload)); | |
| 731 | try s.print(", \"{f}\"", .{std.zig.fmtString(name.toSlice(w.air))}); | |
| 732 | } | |
| 733 | ||
| 734 | fn writeCall(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 735 | const call = w.air.unwrapCall(inst); | |
| 736 | const args = call.args; | |
| 737 | try w.writeOperand(s, inst, 0, call.callee); | |
| 738 | try s.writeAll(", ["); | |
| 739 | for (args, 0..) |arg, i| { | |
| 740 | if (i != 0) try s.writeAll(", "); | |
| 741 | try w.writeOperand(s, inst, 1 + i, arg); | |
| 742 | } | |
| 743 | try s.writeAll("]"); | |
| 744 | } | |
| 745 | ||
| 746 | fn writeBr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 747 | const br = w.air.instructions.items(.data)[@backingInt(inst)].br; | |
| 748 | try w.writeInstIndex(s, br.block_inst, false); | |
| 749 | try s.writeAll(", "); | |
| 750 | try w.writeOperand(s, inst, 0, br.operand); | |
| 751 | } | |
| 752 | ||
| 753 | fn writeRepeat(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 754 | const repeat = w.air.instructions.items(.data)[@backingInt(inst)].repeat; | |
| 755 | try w.writeInstIndex(s, repeat.loop_inst, false); | |
| 756 | } | |
| 757 | ||
| 758 | fn writeTry(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 759 | const unwrapped_try = w.air.unwrapTry(inst); | |
| 760 | const body = unwrapped_try.else_body; | |
| 761 | const liveness_condbr: Air.Liveness.CondBrSlices = if (w.liveness) |liveness| | |
| 762 | liveness.getCondBr(inst) | |
| 763 | else | |
| 764 | .{ .then_deaths = &.{}, .else_deaths = &.{} }; | |
| 765 | ||
| 766 | try w.writeOperand(s, inst, 0, unwrapped_try.error_union); | |
| 767 | if (w.skip_body) return s.writeAll(", ..."); | |
| 768 | try s.writeAll(", {\n"); | |
| 769 | const old_indent = w.indent; | |
| 770 | w.indent += 2; | |
| 771 | ||
| 772 | if (liveness_condbr.else_deaths.len != 0) { | |
| 773 | try s.splatByteAll(' ', w.indent); | |
| 774 | for (liveness_condbr.else_deaths, 0..) |operand, i| { | |
| 775 | if (i != 0) try s.writeAll(" "); | |
| 776 | try s.print("{f}!", .{operand}); | |
| 777 | } | |
| 778 | try s.writeAll("\n"); | |
| 779 | } | |
| 780 | try w.writeBody(s, body); | |
| 781 | ||
| 782 | w.indent = old_indent; | |
| 783 | try s.splatByteAll(' ', w.indent); | |
| 784 | try s.writeAll("}"); | |
| 785 | ||
| 786 | for (liveness_condbr.then_deaths) |operand| { | |
| 787 | try s.print(" {f}!", .{operand}); | |
| 788 | } | |
| 789 | } | |
| 790 | ||
| 791 | fn writeTryPtr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 792 | const unwrapped_try = w.air.unwrapTryPtr(inst); | |
| 793 | const body = unwrapped_try.else_body; | |
| 794 | const liveness_condbr: Air.Liveness.CondBrSlices = if (w.liveness) |liveness| | |
| 795 | liveness.getCondBr(inst) | |
| 796 | else | |
| 797 | .{ .then_deaths = &.{}, .else_deaths = &.{} }; | |
| 798 | ||
| 799 | try w.writeOperand(s, inst, 0, unwrapped_try.error_union_ptr); | |
| 800 | ||
| 801 | try s.writeAll(", "); | |
| 802 | try w.writeType(s, unwrapped_try.error_union_payload_ptr_ty); | |
| 803 | if (w.skip_body) return s.writeAll(", ..."); | |
| 804 | try s.writeAll(", {\n"); | |
| 805 | const old_indent = w.indent; | |
| 806 | w.indent += 2; | |
| 807 | ||
| 808 | if (liveness_condbr.else_deaths.len != 0) { | |
| 809 | try s.splatByteAll(' ', w.indent); | |
| 810 | for (liveness_condbr.else_deaths, 0..) |operand, i| { | |
| 811 | if (i != 0) try s.writeAll(" "); | |
| 812 | try s.print("{f}!", .{operand}); | |
| 813 | } | |
| 814 | try s.writeAll("\n"); | |
| 815 | } | |
| 816 | try w.writeBody(s, body); | |
| 817 | ||
| 818 | w.indent = old_indent; | |
| 819 | try s.splatByteAll(' ', w.indent); | |
| 820 | try s.writeAll("}"); | |
| 821 | ||
| 822 | for (liveness_condbr.then_deaths) |operand| { | |
| 823 | try s.print(" {f}!", .{operand}); | |
| 824 | } | |
| 825 | } | |
| 826 | ||
| 827 | fn writeCondBr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 828 | const cond_br = w.air.unwrapCondBr(inst); | |
| 829 | const then_body = cond_br.then_body; | |
| 830 | const else_body = cond_br.else_body; | |
| 831 | const liveness_condbr: Air.Liveness.CondBrSlices = if (w.liveness) |liveness| | |
| 832 | liveness.getCondBr(inst) | |
| 833 | else | |
| 834 | .{ .then_deaths = &.{}, .else_deaths = &.{} }; | |
| 835 | ||
| 836 | try w.writeOperand(s, inst, 0, cond_br.condition); | |
| 837 | if (w.skip_body) return s.writeAll(", ..."); | |
| 838 | try s.writeAll(","); | |
| 839 | if (cond_br.branch_hints.true != .none) { | |
| 840 | try s.print(" {s}", .{@tagName(cond_br.branch_hints.true)}); | |
| 841 | } | |
| 842 | if (cond_br.branch_hints.then_cov != .none) { | |
| 843 | try s.print(" {s}", .{@tagName(cond_br.branch_hints.then_cov)}); | |
| 844 | } | |
| 845 | try s.writeAll(" {\n"); | |
| 846 | const old_indent = w.indent; | |
| 847 | w.indent += 2; | |
| 848 | ||
| 849 | if (liveness_condbr.then_deaths.len != 0) { | |
| 850 | try s.splatByteAll(' ', w.indent); | |
| 851 | for (liveness_condbr.then_deaths, 0..) |operand, i| { | |
| 852 | if (i != 0) try s.writeAll(" "); | |
| 853 | try s.print("{f}!", .{operand}); | |
| 854 | } | |
| 855 | try s.writeAll("\n"); | |
| 856 | } | |
| 857 | ||
| 858 | try w.writeBody(s, then_body); | |
| 859 | try s.splatByteAll(' ', old_indent); | |
| 860 | try s.writeAll("},"); | |
| 861 | if (cond_br.branch_hints.false != .none) { | |
| 862 | try s.print(" {s}", .{@tagName(cond_br.branch_hints.false)}); | |
| 863 | } | |
| 864 | if (cond_br.branch_hints.else_cov != .none) { | |
| 865 | try s.print(" {s}", .{@tagName(cond_br.branch_hints.else_cov)}); | |
| 866 | } | |
| 867 | try s.writeAll(" {\n"); | |
| 868 | ||
| 869 | if (liveness_condbr.else_deaths.len != 0) { | |
| 870 | try s.splatByteAll(' ', w.indent); | |
| 871 | for (liveness_condbr.else_deaths, 0..) |operand, i| { | |
| 872 | if (i != 0) try s.writeAll(" "); | |
| 873 | try s.print("{f}!", .{operand}); | |
| 874 | } | |
| 875 | try s.writeAll("\n"); | |
| 876 | } | |
| 877 | ||
| 878 | try w.writeBody(s, else_body); | |
| 879 | w.indent = old_indent; | |
| 880 | ||
| 881 | try s.splatByteAll(' ', old_indent); | |
| 882 | try s.writeAll("}"); | |
| 883 | } | |
| 884 | ||
| 885 | fn writeSwitchBr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 886 | const switch_br = w.air.unwrapSwitch(inst); | |
| 887 | ||
| 888 | const liveness: Air.Liveness.SwitchBrTable = if (w.liveness) |liveness| | |
| 889 | liveness.getSwitchBr(w.gpa, inst, switch_br.cases_len + 1) catch | |
| 890 | @panic("out of memory") | |
| 891 | else blk: { | |
| 892 | const slice = w.gpa.alloc([]const Air.Inst.Index, switch_br.cases_len + 1) catch | |
| 893 | @panic("out of memory"); | |
| 894 | @memset(slice, &.{}); | |
| 895 | break :blk .{ .deaths = slice }; | |
| 896 | }; | |
| 897 | defer w.gpa.free(liveness.deaths); | |
| 898 | ||
| 899 | try w.writeOperand(s, inst, 0, switch_br.operand); | |
| 900 | if (w.skip_body) return s.writeAll(", ..."); | |
| 901 | const old_indent = w.indent; | |
| 902 | w.indent += 2; | |
| 903 | ||
| 904 | var it = switch_br.iterateCases(); | |
| 905 | while (it.next()) |case| { | |
| 906 | try s.writeAll(", ["); | |
| 907 | for (case.items, 0..) |item, item_i| { | |
| 908 | if (item_i != 0) try s.writeAll(", "); | |
| 909 | try w.writeInstRef(s, item, false); | |
| 910 | } | |
| 911 | for (case.ranges, 0..) |range, range_i| { | |
| 912 | if (range_i != 0 or case.items.len != 0) try s.writeAll(", "); | |
| 913 | try w.writeInstRef(s, range[0], false); | |
| 914 | try s.writeAll("..."); | |
| 915 | try w.writeInstRef(s, range[1], false); | |
| 916 | } | |
| 917 | try s.writeAll("] "); | |
| 918 | const hint = switch_br.getHint(case.idx); | |
| 919 | if (hint != .none) { | |
| 920 | try s.print(".{s} ", .{@tagName(hint)}); | |
| 921 | } | |
| 922 | try s.writeAll("=> {\n"); | |
| 923 | w.indent += 2; | |
| 924 | ||
| 925 | const deaths = liveness.deaths[case.idx]; | |
| 926 | if (deaths.len != 0) { | |
| 927 | try s.splatByteAll(' ', w.indent); | |
| 928 | for (deaths, 0..) |operand, i| { | |
| 929 | if (i != 0) try s.writeAll(" "); | |
| 930 | try s.print("{f}!", .{operand}); | |
| 931 | } | |
| 932 | try s.writeAll("\n"); | |
| 933 | } | |
| 934 | ||
| 935 | try w.writeBody(s, case.body); | |
| 936 | w.indent -= 2; | |
| 937 | try s.splatByteAll(' ', w.indent); | |
| 938 | try s.writeAll("}"); | |
| 939 | } | |
| 940 | ||
| 941 | const else_body = it.elseBody(); | |
| 942 | if (else_body.len != 0) { | |
| 943 | try s.writeAll(", else "); | |
| 944 | const hint = switch_br.getElseHint(); | |
| 945 | if (hint != .none) { | |
| 946 | try s.print(".{s} ", .{@tagName(hint)}); | |
| 947 | } | |
| 948 | try s.writeAll("=> {\n"); | |
| 949 | w.indent += 2; | |
| 950 | ||
| 951 | const deaths = liveness.deaths[liveness.deaths.len - 1]; | |
| 952 | if (deaths.len != 0) { | |
| 953 | try s.splatByteAll(' ', w.indent); | |
| 954 | for (deaths, 0..) |operand, i| { | |
| 955 | if (i != 0) try s.writeAll(" "); | |
| 956 | try s.print("{f}!", .{operand}); | |
| 957 | } | |
| 958 | try s.writeAll("\n"); | |
| 959 | } | |
| 960 | ||
| 961 | try w.writeBody(s, else_body); | |
| 962 | w.indent -= 2; | |
| 963 | try s.splatByteAll(' ', w.indent); | |
| 964 | try s.writeAll("}"); | |
| 965 | } | |
| 966 | ||
| 967 | try s.writeAll("\n"); | |
| 968 | try s.splatByteAll(' ', old_indent); | |
| 969 | } | |
| 970 | ||
| 971 | fn writeWasmMemorySize(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 972 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 973 | try s.print("{d}", .{pl_op.payload}); | |
| 974 | } | |
| 975 | ||
| 976 | fn writeWasmMemoryGrow(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 977 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 978 | try s.print("{d}, ", .{pl_op.payload}); | |
| 979 | try w.writeOperand(s, inst, 0, pl_op.operand); | |
| 980 | } | |
| 981 | ||
| 982 | fn writeWorkDimension(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void { | |
| 983 | const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op; | |
| 984 | try s.print("{d}", .{pl_op.payload}); | |
| 985 | } | |
| 986 | ||
| 987 | fn writeOperand( | |
| 988 | w: *Writer, | |
| 989 | s: *std.Io.Writer, | |
| 990 | inst: Air.Inst.Index, | |
| 991 | op_index: usize, | |
| 992 | operand: Air.Inst.Ref, | |
| 993 | ) Error!void { | |
| 994 | const small_tomb_bits = Air.Liveness.bpi - 1; | |
| 995 | const dies = if (w.liveness) |liveness| blk: { | |
| 996 | if (op_index < small_tomb_bits) | |
| 997 | break :blk liveness.operandDies(inst, @intCast(op_index)); | |
| 998 | var extra_index = liveness.special.get(inst).?; | |
| 999 | var tomb_op_index: usize = small_tomb_bits; | |
| 1000 | while (true) { | |
| 1001 | const bits = liveness.extra[extra_index]; | |
| 1002 | if (op_index < tomb_op_index + 31) { | |
| 1003 | break :blk @as(u1, @truncate(bits >> @as(u5, @intCast(op_index - tomb_op_index)))) != 0; | |
| 1004 | } | |
| 1005 | if ((bits >> 31) != 0) break :blk false; | |
| 1006 | extra_index += 1; | |
| 1007 | tomb_op_index += 31; | |
| 1008 | } | |
| 1009 | } else false; | |
| 1010 | return w.writeInstRef(s, operand, dies); | |
| 1011 | } | |
| 1012 | ||
| 1013 | fn writeInstRef( | |
| 1014 | w: *Writer, | |
| 1015 | s: *std.Io.Writer, | |
| 1016 | operand: Air.Inst.Ref, | |
| 1017 | dies: bool, | |
| 1018 | ) Error!void { | |
| 1019 | if (@backingInt(operand) < InternPool.static_len) { | |
| 1020 | return s.print("@{}", .{operand}); | |
| 1021 | } else if (operand.toInterned()) |ip_index| { | |
| 1022 | const zcu = w.zcu; | |
| 1023 | const ty = Type.fromInterned(zcu.intern_pool.indexToKey(ip_index).typeOf()); | |
| 1024 | try s.print("<{f}, {f}>", .{ | |
| 1025 | ty.fmt(zcu), | |
| 1026 | Value.fromInterned(ip_index).fmtValue(w.zcu), | |
| 1027 | }); | |
| 1028 | } else { | |
| 1029 | return w.writeInstIndex(s, operand.toIndex().?, dies); | |
| 1030 | } | |
| 1031 | } | |
| 1032 | ||
| 1033 | fn writeInstIndex( | |
| 1034 | w: *Writer, | |
| 1035 | s: *std.Io.Writer, | |
| 1036 | inst: Air.Inst.Index, | |
| 1037 | dies: bool, | |
| 1038 | ) Error!void { | |
| 1039 | _ = w; | |
| 1040 | try s.print("{f}", .{inst}); | |
| 1041 | if (dies) try s.writeByte('!'); | |
| 1042 | } | |
| 1043 | ||
| 1044 | fn typeOfIndex(w: *Writer, inst: Air.Inst.Index) Type { | |
| 1045 | const zcu = w.zcu; | |
| 1046 | return w.air.typeOfIndex(inst, &zcu.intern_pool); | |
| 1047 | } | |
| 1048 | }; |
src/Compilation.zig+28-84| ... | ... | @@ -20,6 +20,7 @@ const link = @import("link.zig"); |
| 20 | 20 | const tracy = @import("tracy.zig"); |
| 21 | 21 | const trace = tracy.trace; |
| 22 | 22 | const build_options = @import("build_options"); |
| 23 | const debugLogScopeEnabled = @import("main.zig").debugLogScopeEnabled; | |
| 23 | 24 | const LibCInstallation = std.zig.LibCInstallation; |
| 24 | 25 | const glibc = @import("libs/glibc.zig"); |
| 25 | 26 | const musl = @import("libs/musl.zig"); |
| ... | ... | @@ -161,12 +162,6 @@ clang_passthrough_mode: bool, |
| 161 | 162 | clang_preprocessor_mode: ClangPreprocessorMode, |
| 162 | 163 | /// Whether to print clang argvs to stdout. |
| 163 | 164 | verbose_cc: bool, |
| 164 | verbose_air: bool, | |
| 165 | verbose_intern_pool: bool, | |
| 166 | verbose_generic_instances: bool, | |
| 167 | verbose_llvm_ir: ?[]const u8, | |
| 168 | verbose_llvm_bc: ?[]const u8, | |
| 169 | verbose_llvm_cpu_features: bool, | |
| 170 | 165 | verbose_link: bool, |
| 171 | 166 | link_depfile: ?[]const u8, |
| 172 | 167 | disable_c_depfile: bool, |
| ... | ... | @@ -1544,13 +1539,7 @@ pub const CreateOptions = struct { |
| 1544 | 1539 | clang_passthrough_mode: bool = false, |
| 1545 | 1540 | verbose_cc: bool = false, |
| 1546 | 1541 | verbose_link: bool = false, |
| 1547 | verbose_air: bool = false, | |
| 1548 | verbose_intern_pool: bool = false, | |
| 1549 | verbose_generic_instances: bool = false, | |
| 1550 | verbose_llvm_ir: ?[]const u8 = null, | |
| 1551 | verbose_llvm_bc: ?[]const u8 = null, | |
| 1552 | 1542 | link_depfile: ?[]const u8 = null, |
| 1553 | verbose_llvm_cpu_features: bool = false, | |
| 1554 | 1543 | debug_compiler_runtime_libs: ?std.lang.Optimize = null, |
| 1555 | 1544 | debug_compile_errors: bool = false, |
| 1556 | 1545 | debug_incremental: bool = false, |
| ... | ... | @@ -1932,21 +1921,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 1932 | 1921 | try options.root_mod.deps.putNoClobber(arena, "zigc", zigc_mod); |
| 1933 | 1922 | } |
| 1934 | 1923 | |
| 1935 | if (options.verbose_llvm_cpu_features) { | |
| 1936 | if (options.root_mod.resolved_target.llvm_cpu_features) |cf| { | |
| 1937 | const stderr = try io.lockStderr(&.{}, null); | |
| 1938 | defer io.unlockStderr(); | |
| 1939 | const w = &stderr.file_writer.interface; | |
| 1940 | printVerboseLlvmCpuFeatures(w, arena, options.root_name, target, cf) catch |err| switch (err) { | |
| 1941 | error.WriteFailed => switch (stderr.file_writer.err.?) { | |
| 1942 | error.Canceled => |e| return e, | |
| 1943 | else => {}, | |
| 1944 | }, | |
| 1945 | error.OutOfMemory => |e| return e, | |
| 1946 | }; | |
| 1947 | } | |
| 1948 | } | |
| 1949 | ||
| 1950 | 1924 | const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1); |
| 1951 | 1925 | const main_mod = options.main_mod orelse options.root_mod; |
| 1952 | 1926 | |
| ... | ... | @@ -2111,14 +2085,8 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2111 | 2085 | .clang_passthrough_mode = options.clang_passthrough_mode, |
| 2112 | 2086 | .clang_preprocessor_mode = options.clang_preprocessor_mode, |
| 2113 | 2087 | .verbose_cc = options.verbose_cc, |
| 2114 | .verbose_air = options.verbose_air, | |
| 2115 | .verbose_intern_pool = options.verbose_intern_pool, | |
| 2116 | .verbose_generic_instances = options.verbose_generic_instances, | |
| 2117 | .verbose_llvm_ir = options.verbose_llvm_ir, | |
| 2118 | .verbose_llvm_bc = options.verbose_llvm_bc, | |
| 2119 | .link_depfile = options.link_depfile, | |
| 2120 | .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features, | |
| 2121 | 2088 | .verbose_link = options.verbose_link, |
| 2089 | .link_depfile = options.link_depfile, | |
| 2122 | 2090 | .disable_c_depfile = options.disable_c_depfile, |
| 2123 | 2091 | .reference_trace = options.reference_trace, |
| 2124 | 2092 | .time_report = if (options.time_report) .init else null, |
| ... | ... | @@ -2353,8 +2321,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2353 | 2321 | comp.emit_asm != null or |
| 2354 | 2322 | comp.emit_llvm_ir != null or |
| 2355 | 2323 | comp.emit_llvm_bc != null or |
| 2356 | comp.verbose_llvm_ir != null or | |
| 2357 | comp.verbose_llvm_bc != null)) | |
| 2324 | log_llvm_ir: { | |
| 2325 | break :log_llvm_ir debugLogScopeEnabled("llvm-ir") or debugLogScopeEnabled("opt-llvm-ir"); | |
| 2326 | })) | |
| 2358 | 2327 | { |
| 2359 | 2328 | if (opt_zcu) |zcu| { |
| 2360 | 2329 | dev.check(.llvm_backend); |
| ... | ... | @@ -2566,19 +2535,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2566 | 2535 | return comp; |
| 2567 | 2536 | } |
| 2568 | 2537 | |
| 2569 | fn printVerboseLlvmCpuFeatures( | |
| 2570 | w: *Writer, | |
| 2571 | arena: Allocator, | |
| 2572 | root_name: []const u8, | |
| 2573 | target: *const std.Target, | |
| 2574 | cf: [*:0]const u8, | |
| 2575 | ) (Writer.Error || Allocator.Error)!void { | |
| 2576 | try w.print("compilation: {s}\n", .{root_name}); | |
| 2577 | try w.print(" target: {s}\n", .{try target.zigTriple(arena)}); | |
| 2578 | try w.print(" cpu: {s}\n", .{target.cpu.model.name}); | |
| 2579 | try w.print(" features: {s}\n", .{cf}); | |
| 2580 | } | |
| 2581 | ||
| 2582 | 2538 | pub fn destroy(comp: *Compilation) void { |
| 2583 | 2539 | const gpa = comp.gpa; |
| 2584 | 2540 | const io = comp.io; |
| ... | ... | @@ -2991,14 +2947,19 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 2991 | 2947 | try pt.processExports(); |
| 2992 | 2948 | } |
| 2993 | 2949 | |
| 2994 | if (build_options.enable_debug_extensions and comp.verbose_intern_pool) { | |
| 2995 | std.debug.print("intern pool stats for {q}:\n", .{comp.root_name}); | |
| 2996 | zcu.intern_pool.dump(); | |
| 2997 | } | |
| 2998 | ||
| 2999 | if (build_options.enable_debug_extensions and comp.verbose_generic_instances) { | |
| 3000 | std.debug.print("generic instances for '{s}:0x{x}':\n", .{ comp.root_name, @intFromPtr(zcu) }); | |
| 3001 | zcu.intern_pool.dumpGenericInstances(gpa); | |
| 2950 | { | |
| 2951 | var d: InternPool.Dump = .{ | |
| 2952 | .name = comp.root_name, | |
| 2953 | .arena = arena, | |
| 2954 | .ip = &zcu.intern_pool, | |
| 2955 | .err = null, | |
| 2956 | }; | |
| 2957 | std.log.scoped(.@"ip-stats").debug("{f}", .{&d}); | |
| 2958 | if (d.err) |err| return err; | |
| 2959 | std.log.scoped(.@"ip-values").debug("{f}", .{std.fmt.alt(&d, .formatAll)}); | |
| 2960 | if (d.err) |err| return err; | |
| 2961 | std.log.scoped(.@"ip-generic-instances").debug("{f}", .{std.fmt.alt(&d, .formatGenericInstances)}); | |
| 2962 | if (d.err) |err| return err; | |
| 3002 | 2963 | } |
| 3003 | 2964 | } |
| 3004 | 2965 | |
| ... | ... | @@ -3220,28 +3181,29 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error |
| 3220 | 3181 | comp.time_report.?.stats.real_ns_llvm_emit = ns; |
| 3221 | 3182 | }; |
| 3222 | 3183 | |
| 3223 | const zcu_obj_path: ?Cache.Path = if (comp.bin_file != null) p: { | |
| 3224 | break :p try comp.resolveEmitPathFlush(arena, .temp, llvm_object.out_bin_basename); | |
| 3225 | } else null; | |
| 3184 | const zcu_obj_path: ?Cache.Path = switch (comp.getTarget().ofmt) { | |
| 3185 | .llvmbc, .llvmir => null, | |
| 3186 | else => if (comp.bin_file != null) | |
| 3187 | try comp.resolveEmitPathFlush(arena, .temp, llvm_object.out_bin_basename) | |
| 3188 | else | |
| 3189 | null, | |
| 3190 | }; | |
| 3226 | 3191 | |
| 3227 | 3192 | const active = zcu.activate(tid); |
| 3228 | 3193 | defer active.deactivate(); |
| 3229 | 3194 | llvm_object.emit(active.pt, .{ |
| 3230 | .pre_ir_path = comp.verbose_llvm_ir, | |
| 3231 | .pre_bc_path = comp.verbose_llvm_bc, | |
| 3232 | ||
| 3233 | 3195 | .bin_path = if (zcu_obj_path) |p| try p.toStringZ(arena) else null, |
| 3234 | 3196 | .asm_path = p: { |
| 3235 | 3197 | const raw = comp.emit_asm orelse break :p null; |
| 3236 | 3198 | const p = try comp.resolveEmitPathFlush(arena, .artifact, raw); |
| 3237 | 3199 | break :p try p.toStringZ(arena); |
| 3238 | 3200 | }, |
| 3239 | .post_ir_path = p: { | |
| 3201 | .opt_ir_path = p: { | |
| 3240 | 3202 | const raw = comp.emit_llvm_ir orelse break :p null; |
| 3241 | 3203 | const p = try comp.resolveEmitPathFlush(arena, .artifact, raw); |
| 3242 | 3204 | break :p try p.toStringZ(arena); |
| 3243 | 3205 | }, |
| 3244 | .post_bc_path = p: { | |
| 3206 | .opt_bc_path = p: { | |
| 3245 | 3207 | const raw = comp.emit_llvm_bc orelse break :p null; |
| 3246 | 3208 | const p = try comp.resolveEmitPathFlush(arena, .artifact, raw); |
| 3247 | 3209 | break :p try p.toStringZ(arena); |
| ... | ... | @@ -3267,7 +3229,7 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error |
| 3267 | 3229 | error.Canceled, error.OutOfMemory => |e| return e, |
| 3268 | 3230 | error.AlreadyReported => return, |
| 3269 | 3231 | }; |
| 3270 | } | |
| 3232 | } else return; | |
| 3271 | 3233 | } |
| 3272 | 3234 | } |
| 3273 | 3235 | if (comp.bin_file) |lf| { |
| ... | ... | @@ -4903,12 +4865,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU |
| 4903 | 4865 | .emit_bin = .yes_cache, |
| 4904 | 4866 | .verbose_cc = comp.verbose_cc, |
| 4905 | 4867 | .verbose_link = comp.verbose_link, |
| 4906 | .verbose_air = comp.verbose_air, | |
| 4907 | .verbose_intern_pool = comp.verbose_intern_pool, | |
| 4908 | .verbose_generic_instances = comp.verbose_intern_pool, | |
| 4909 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 4910 | .verbose_llvm_bc = comp.verbose_llvm_bc, | |
| 4911 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 4912 | 4868 | .environ_map = comp.environ_map, |
| 4913 | 4869 | }) catch |err| switch (err) { |
| 4914 | 4870 | error.CreateFail => { |
| ... | ... | @@ -7415,12 +7371,6 @@ fn buildOutputFromZig( |
| 7415 | 7371 | .data_sections = true, |
| 7416 | 7372 | .verbose_cc = comp.verbose_cc, |
| 7417 | 7373 | .verbose_link = comp.verbose_link, |
| 7418 | .verbose_air = comp.verbose_air, | |
| 7419 | .verbose_intern_pool = comp.verbose_intern_pool, | |
| 7420 | .verbose_generic_instances = comp.verbose_intern_pool, | |
| 7421 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 7422 | .verbose_llvm_bc = comp.verbose_llvm_bc, | |
| 7423 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 7424 | 7374 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 7425 | 7375 | .skip_linker_dependencies = true, |
| 7426 | 7376 | .environ_map = comp.environ_map, |
| ... | ... | @@ -7552,12 +7502,6 @@ pub fn build_crt_file( |
| 7552 | 7502 | .c_source_files = c_source_files, |
| 7553 | 7503 | .verbose_cc = comp.verbose_cc, |
| 7554 | 7504 | .verbose_link = comp.verbose_link, |
| 7555 | .verbose_air = comp.verbose_air, | |
| 7556 | .verbose_intern_pool = comp.verbose_intern_pool, | |
| 7557 | .verbose_generic_instances = comp.verbose_generic_instances, | |
| 7558 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 7559 | .verbose_llvm_bc = comp.verbose_llvm_bc, | |
| 7560 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 7561 | 7505 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 7562 | 7506 | .skip_linker_dependencies = true, |
| 7563 | 7507 | .environ_map = comp.environ_map, |
src/Compilation/Config.zig+4-4| ... | ... | @@ -190,7 +190,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 190 | 190 | // *If* the LLVM backend were to be selected, should Zig use the LLVM |
| 191 | 191 | // library to build the LLVM module? |
| 192 | 192 | const use_lib_llvm = b: { |
| 193 | if (!build_options.have_llvm) { | |
| 193 | if (!build_options.have_llvm or target.ofmt == .llvmbc or target.ofmt == .llvmir) { | |
| 194 | 194 | if (options.use_lib_llvm == true) return error.LlvmLibraryUnavailable; |
| 195 | 195 | break :b false; |
| 196 | 196 | } |
| ... | ... | @@ -324,7 +324,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 324 | 324 | if (!options.have_zcu) break :b false; |
| 325 | 325 | |
| 326 | 326 | // If emitting to LLVM bitcode object format, must use LLVM backend. |
| 327 | if (options.emit_llvm_ir or options.emit_llvm_bc) { | |
| 327 | if (target.ofmt == .llvmbc or target.ofmt == .llvmir or options.emit_llvm_bc or options.emit_llvm_ir) { | |
| 328 | 328 | if (options.use_llvm == false) |
| 329 | 329 | return error.EmittingLlvmModuleRequiresLlvmBackend; |
| 330 | 330 | if (!target_util.hasLlvmSupport(target, target.ofmt)) |
| ... | ... | @@ -379,7 +379,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 379 | 379 | const backend = target_util.zigBackend(target, use_llvm); |
| 380 | 380 | |
| 381 | 381 | if (options.emit_bin and options.have_zcu) { |
| 382 | if (!use_lib_llvm and use_llvm) { | |
| 382 | if (target.ofmt != .llvmbc and target.ofmt != .llvmir and !use_lib_llvm and use_llvm) { | |
| 383 | 383 | // Explicit request to use LLVM to produce an object file, but without |
| 384 | 384 | // using LLVM libraries. Impossible. |
| 385 | 385 | return error.EmittingBinaryRequiresLlvmLibrary; |
| ... | ... | @@ -513,7 +513,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 513 | 513 | break :b switch (target.ofmt) { |
| 514 | 514 | .elf, .macho, .wasm => .{ .dwarf = .@"32" }, |
| 515 | 515 | .coff => .code_view, |
| 516 | .c => switch (target.os.tag) { | |
| 516 | .c, .llvmbc, .llvmir => switch (target.os.tag) { | |
| 517 | 517 | .windows, .uefi => .code_view, |
| 518 | 518 | else => .{ .dwarf = .@"32" }, |
| 519 | 519 | }, |
src/InternPool.zig+33-25| ... | ... | @@ -10591,17 +10591,36 @@ pub fn errorUnionPayload(ip: *const InternPool, ty: Index) Index { |
| 10591 | 10591 | return ip.indexToKey(ty).error_union_type.payload_type; |
| 10592 | 10592 | } |
| 10593 | 10593 | |
| 10594 | pub fn dump(ip: *const InternPool) void { | |
| 10595 | var buffer: [4096]u8 = undefined; | |
| 10596 | const stderr = std.debug.lockStderr(&buffer); | |
| 10597 | defer std.debug.unlockStderr(); | |
| 10598 | const w = &stderr.file_writer.interface; | |
| 10599 | dumpDependencyStatsFallible(ip, w) catch return; | |
| 10600 | dumpStatsFallible(ip, w, std.heap.page_allocator) catch return; | |
| 10601 | dumpAllFallible(ip, w) catch return; | |
| 10602 | } | |
| 10594 | pub const Dump = struct { | |
| 10595 | name: []const u8, | |
| 10596 | arena: std.mem.Allocator, | |
| 10597 | ip: *const InternPool, | |
| 10598 | err: ?Allocator.Error, | |
| 10599 | ||
| 10600 | pub fn format(d: *Dump, w: *Io.Writer) Io.Writer.Error!void { | |
| 10601 | try w.print("{q}:\n", .{d.name}); | |
| 10602 | try d.ip.dumpDependencyStatsFallible(w); | |
| 10603 | d.ip.dumpStatsFallible(d.arena, w) catch |err| switch (err) { | |
| 10604 | error.WriteFailed => |e| return e, | |
| 10605 | error.OutOfMemory => |e| { | |
| 10606 | d.err = e; | |
| 10607 | return error.WriteFailed; | |
| 10608 | }, | |
| 10609 | }; | |
| 10610 | } | |
| 10611 | ||
| 10612 | pub fn formatAll(d: *Dump, w: *Io.Writer) Io.Writer.Error!void { | |
| 10613 | try w.print("{q}:\n", .{d.name}); | |
| 10614 | try d.ip.dumpAllFallible(w); | |
| 10615 | } | |
| 10603 | 10616 | |
| 10604 | fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { | |
| 10617 | pub fn formatGenericInstances(d: *Dump, w: *Io.Writer) Io.Writer.Error!void { | |
| 10618 | try w.print("{q}:\n", .{d.name}); | |
| 10619 | d.ip.dumpGenericInstancesFallible(d.arena, w) catch return; | |
| 10620 | } | |
| 10621 | }; | |
| 10622 | ||
| 10623 | fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) Io.Writer.Error!void { | |
| 10605 | 10624 | const dep_entries_len = ip.dep_entries.items.len - ip.free_dep_entries.items.len; |
| 10606 | 10625 | const src_hash_deps_len = ip.src_hash_deps.count(); |
| 10607 | 10626 | const nav_val_deps_len = ip.nav_val_deps.count(); |
| ... | ... | @@ -10668,7 +10687,7 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { |
| 10668 | 10687 | }); |
| 10669 | 10688 | } |
| 10670 | 10689 | |
| 10671 | fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !void { | |
| 10690 | fn dumpStatsFallible(ip: *const InternPool, arena: Allocator, w: *Io.Writer) (Allocator.Error || Io.Writer.Error)!void { | |
| 10672 | 10691 | var items_len: usize = 0; |
| 10673 | 10692 | var extra_len: usize = 0; |
| 10674 | 10693 | var limbs_len: usize = 0; |
| ... | ... | @@ -10968,7 +10987,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo |
| 10968 | 10987 | } |
| 10969 | 10988 | } |
| 10970 | 10989 | |
| 10971 | fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { | |
| 10990 | fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) Io.Writer.Error!void { | |
| 10972 | 10991 | for (ip.locals, 0..) |*local, tid| { |
| 10973 | 10992 | // Early check for length 0, because `view()` is invalid if capacity is 0 |
| 10974 | 10993 | if (local.mutate.items.len == 0) continue; |
| ... | ... | @@ -11071,21 +11090,10 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { |
| 11071 | 11090 | } |
| 11072 | 11091 | } |
| 11073 | 11092 | |
| 11074 | pub fn dumpGenericInstances(ip: *const InternPool, allocator: Allocator) void { | |
| 11075 | var buffer: [4096]u8 = undefined; | |
| 11076 | const stderr = std.debug.lockStderr(&buffer); | |
| 11077 | defer std.debug.unlockStderr(); | |
| 11078 | const w = &stderr.file_writer.interface; | |
| 11079 | ip.dumpGenericInstancesFallible(allocator, w) catch return; | |
| 11080 | } | |
| 11081 | ||
| 11082 | pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator, w: *Io.Writer) !void { | |
| 11083 | var arena_allocator = std.heap.ArenaAllocator.init(allocator); | |
| 11084 | defer arena_allocator.deinit(); | |
| 11085 | const arena = arena_allocator.allocator(); | |
| 11086 | ||
| 11093 | pub fn dumpGenericInstancesFallible(ip: *const InternPool, arena: Allocator, w: *Io.Writer) !void { | |
| 11087 | 11094 | var instances: std.array_hash_map.Auto(Index, std.ArrayList(Index)) = .empty; |
| 11088 | 11095 | for (ip.locals, 0..) |*local, tid| { |
| 11096 | if (local.mutate.items.len == 0) continue; | |
| 11089 | 11097 | const items = local.shared.items.view().slice(); |
| 11090 | 11098 | const extra_list = local.shared.extra; |
| 11091 | 11099 | for ( |
src/Module.zig+8-11| ... | ... | @@ -26,6 +26,7 @@ fully_qualified_name: []const u8, |
| 26 | 26 | deps: Deps = .{}, |
| 27 | 27 | |
| 28 | 28 | resolved_target: ResolvedTarget, |
| 29 | llvm_cpu_features: ?[:0]const u8, | |
| 29 | 30 | optimize_mode: std.lang.Optimize, |
| 30 | 31 | code_model: std.lang.CodeModel, |
| 31 | 32 | single_threaded: bool, |
| ... | ... | @@ -94,7 +95,6 @@ pub const ResolvedTarget = struct { |
| 94 | 95 | is_native_os: bool, |
| 95 | 96 | is_native_abi: bool, |
| 96 | 97 | is_explicit_dynamic_linker: bool, |
| 97 | llvm_cpu_features: ?[*:0]const u8 = null, | |
| 98 | 98 | }; |
| 99 | 99 | |
| 100 | 100 | pub const CreateError = error{ |
| ... | ... | @@ -362,15 +362,13 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { |
| 362 | 362 | break :b 0; |
| 363 | 363 | }; |
| 364 | 364 | |
| 365 | const llvm_cpu_features: ?[*:0]const u8 = b: { | |
| 366 | if (resolved_target.llvm_cpu_features) |x| break :b x; | |
| 365 | const llvm_cpu_features: ?[:0]const u8 = b: { | |
| 367 | 366 | if (!options.global.use_llvm) break :b null; |
| 367 | if (options.inherited.resolved_target == null) break :b options.parent.?.llvm_cpu_features; | |
| 368 | 368 | |
| 369 | // Append disabled features after enabled ones, so that their effects aren't overwritten. | |
| 369 | 370 | var buf = std.array_list.Managed(u8).init(arena); |
| 370 | 371 | var disabled_features = std.array_list.Managed(u8).init(arena); |
| 371 | defer disabled_features.deinit(); | |
| 372 | ||
| 373 | // Append disabled features after enabled ones, so that their effects aren't overwritten. | |
| 374 | 372 | for (target.cpu.arch.allFeaturesList()) |feature| { |
| 375 | 373 | if (feature.llvm_name) |llvm_name| { |
| 376 | 374 | // Ignore these until we figure out how to handle the concept of omitting features. |
| ... | ... | @@ -401,10 +399,9 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { |
| 401 | 399 | |
| 402 | 400 | try buf.appendSlice(disabled_features.items); |
| 403 | 401 | if (buf.items.len == 0) break :b ""; |
| 404 | assert(std.mem.endsWith(u8, buf.items, ",")); | |
| 402 | assert(buf.items[buf.items.len - 1] == ','); | |
| 405 | 403 | buf.items[buf.items.len - 1] = 0; |
| 406 | buf.shrinkAndFree(buf.items.len); | |
| 407 | break :b buf.items[0 .. buf.items.len - 1 :0].ptr; | |
| 404 | break :b buf.items[0 .. buf.items.len - 1 :0]; | |
| 408 | 405 | }; |
| 409 | 406 | |
| 410 | 407 | const mod = try arena.create(Module); |
| ... | ... | @@ -417,8 +414,8 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { |
| 417 | 414 | .is_native_os = resolved_target.is_native_os, |
| 418 | 415 | .is_native_abi = resolved_target.is_native_abi, |
| 419 | 416 | .is_explicit_dynamic_linker = resolved_target.is_explicit_dynamic_linker, |
| 420 | .llvm_cpu_features = llvm_cpu_features, | |
| 421 | 417 | }, |
| 418 | .llvm_cpu_features = llvm_cpu_features, | |
| 422 | 419 | .optimize_mode = optimize_mode, |
| 423 | 420 | .single_threaded = single_threaded, |
| 424 | 421 | .error_tracing = error_tracing, |
| ... | ... | @@ -494,8 +491,8 @@ pub fn createBuiltin(arena: Allocator, opts: Builtin, dirs: std.zig.Directories) |
| 494 | 491 | .is_native_os = false, |
| 495 | 492 | .is_native_abi = false, |
| 496 | 493 | .is_explicit_dynamic_linker = false, |
| 497 | .llvm_cpu_features = null, | |
| 498 | 494 | }, |
| 495 | .llvm_cpu_features = null, | |
| 499 | 496 | .optimize_mode = opts.optimize_mode, |
| 500 | 497 | .single_threaded = opts.single_threaded, |
| 501 | 498 | .error_tracing = opts.error_tracing, |
src/Sema.zig+3-5| ... | ... | @@ -1126,6 +1126,8 @@ fn analyzeBodyInner( |
| 1126 | 1126 | crash_info.push(sema, block, body); |
| 1127 | 1127 | defer crash_info.pop(); |
| 1128 | 1128 | |
| 1129 | const path = zcu.namespacePtr(block.namespace).fileScope(zcu).path; | |
| 1130 | ||
| 1129 | 1131 | // We use a while (true) loop here to avoid a redundant way of breaking out of |
| 1130 | 1132 | // the loop. The only way to break out of the loop is with a `noreturn` |
| 1131 | 1133 | // instruction. |
| ... | ... | @@ -1134,11 +1136,7 @@ fn analyzeBodyInner( |
| 1134 | 1136 | crash_info.setBodyIndex(i); |
| 1135 | 1137 | const inst = body[i]; |
| 1136 | 1138 | |
| 1137 | // This log is a bit expensive, and LLVM fails to optimize it away. | |
| 1138 | if (build_options.enable_logging) { | |
| 1139 | const path = zcu.namespacePtr(block.namespace).fileScope(zcu).path; | |
| 1140 | std.log.scoped(.sema_zir).debug("sema ZIR {f} %{d}", .{ path.fmt(comp), inst }); | |
| 1141 | } | |
| 1139 | std.log.scoped(.sema_zir).debug("sema ZIR {f} %{d}", .{ path.fmt(comp), inst }); | |
| 1142 | 1140 | |
| 1143 | 1141 | const air_ref: Air.Inst.Ref = inst: switch (tags[@backingInt(inst)]) { |
| 1144 | 1142 | // zig fmt: off |
src/Zcu/PerThread.zig+20-38| ... | ... | @@ -25,6 +25,7 @@ const InternPool = @import("../InternPool.zig"); |
| 25 | 25 | const AnalUnit = InternPool.AnalUnit; |
| 26 | 26 | const Module = @import("../Module.zig"); |
| 27 | 27 | const Sema = @import("../Sema.zig"); |
| 28 | const debugLogScopeEnabled = @import("../main.zig").debugLogScopeEnabled; | |
| 28 | 29 | const target_util = @import("../target.zig"); |
| 29 | 30 | const tracy = @import("../tracy.zig"); |
| 30 | 31 | const trace = tracy.trace; |
| ... | ... | @@ -2303,10 +2304,9 @@ fn analyzeFuncBody( |
| 2303 | 2304 | |
| 2304 | 2305 | const comp = zcu.comp; |
| 2305 | 2306 | |
| 2306 | const dump_air = build_options.enable_debug_extensions and comp.verbose_air; | |
| 2307 | const dump_llvm_ir = build_options.enable_debug_extensions and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null); | |
| 2308 | ||
| 2309 | if (comp.bin_file != null or zcu.llvm_object != null or dump_air or dump_llvm_ir) { | |
| 2307 | if (comp.bin_file != null or zcu.llvm_object != null or log_air: { | |
| 2308 | break :log_air debugLogScopeEnabled("illegal-air") or debugLogScopeEnabled("legal-air") or debugLogScopeEnabled("air"); | |
| 2309 | }) { | |
| 2310 | 2310 | zcu.codegen_prog_node.increaseEstimatedTotalItems(1); |
| 2311 | 2311 | comp.link_prog_node.increaseEstimatedTotalItems(1); |
| 2312 | 2312 | |
| ... | ... | @@ -4522,32 +4522,28 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e |
| 4522 | 4522 | tracy_trace.addText(fqn.toSlice(ip)); |
| 4523 | 4523 | tracy_trace.addTextFmt("func_ip_index={d}", .{func_index}); |
| 4524 | 4524 | |
| 4525 | Air.Verify.run(pt, func_index, air); | |
| 4525 | var liveness: ?Air.Liveness = null; | |
| 4526 | defer if (liveness) |*l| l.deinit(gpa); | |
| 4527 | ||
| 4528 | const ap: Air.Print = .{ | |
| 4529 | .zcu = zcu, | |
| 4530 | .fqn = fqn, | |
| 4531 | .air = air, | |
| 4532 | .liveness = &liveness, | |
| 4533 | }; | |
| 4534 | std.log.scoped(.@"illegal-air").debug("{f}", .{&ap}); | |
| 4526 | 4535 | |
| 4527 | 4536 | if (codegen.legalizeFeatures(pt, nav)) |features| { |
| 4528 | try air.legalize(pt, features); | |
| 4529 | // Verify the AIR again post-legalization. | |
| 4537 | // Verify the AIR again pre-legalization. | |
| 4530 | 4538 | Air.Verify.run(pt, func_index, air); |
| 4539 | try air.legalize(pt, features); | |
| 4531 | 4540 | } |
| 4532 | 4541 | |
| 4533 | var liveness: ?Air.Liveness = if (codegen.wantsLiveness(pt, nav)) | |
| 4534 | try .analyze(zcu, air.*, ip) | |
| 4535 | else | |
| 4536 | null; | |
| 4537 | defer if (liveness) |*l| l.deinit(gpa); | |
| 4538 | ||
| 4539 | if (build_options.enable_debug_extensions and comp.verbose_air) p: { | |
| 4540 | const io = comp.io; | |
| 4541 | const stderr = try io.lockStderr(&.{}, null); | |
| 4542 | defer io.unlockStderr(); | |
| 4543 | printVerboseAir(pt, liveness, fqn, air, &stderr.file_writer.interface) catch |err| switch (err) { | |
| 4544 | error.WriteFailed => switch (stderr.file_writer.err.?) { | |
| 4545 | error.Canceled => |e| return e, | |
| 4546 | else => break :p, | |
| 4547 | }, | |
| 4548 | }; | |
| 4549 | } | |
| 4542 | std.log.scoped(.@"legal-air").debug("{f}", .{&ap}); | |
| 4543 | Air.Verify.run(pt, func_index, air); | |
| 4550 | 4544 | |
| 4545 | if (codegen.wantsLiveness(pt, nav)) liveness = try .analyze(zcu, air.*, ip); | |
| 4546 | std.log.scoped(.air).debug("{f}", .{&ap}); | |
| 4551 | 4547 | if (std.debug.runtime_safety) verify_liveness: { |
| 4552 | 4548 | var verify: Air.Liveness.Verify = .{ |
| 4553 | 4549 | .gpa = gpa, |
| ... | ... | @@ -4577,17 +4573,3 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e |
| 4577 | 4573 | |
| 4578 | 4574 | return codegen.generateFunction(lf, pt, func_index, air, &liveness); |
| 4579 | 4575 | } |
| 4580 | ||
| 4581 | fn printVerboseAir( | |
| 4582 | pt: Zcu.PerThread, | |
| 4583 | liveness: ?Air.Liveness, | |
| 4584 | fqn: InternPool.NullTerminatedString, | |
| 4585 | air: *const Air, | |
| 4586 | w: *Io.Writer, | |
| 4587 | ) Io.Writer.Error!void { | |
| 4588 | const zcu = pt.zcu; | |
| 4589 | const ip = &zcu.intern_pool; | |
| 4590 | try w.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)}); | |
| 4591 | try air.write(w, zcu, liveness); | |
| 4592 | try w.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)}); | |
| 4593 | } |
src/codegen/llvm.zig+66-59| ... | ... | @@ -10,6 +10,7 @@ const build_options = @import("build_options"); |
| 10 | 10 | const Air = @import("../Air.zig"); |
| 11 | 11 | const codegen = @import("../codegen.zig"); |
| 12 | 12 | const Compilation = @import("../Compilation.zig"); |
| 13 | const debugLogScopeEnabled = @import("../main.zig").debugLogScopeEnabled; | |
| 13 | 14 | const InternPool = @import("../InternPool.zig"); |
| 14 | 15 | const link = @import("../link.zig"); |
| 15 | 16 | const Module = @import("../Module.zig"); |
| ... | ... | @@ -331,12 +332,10 @@ pub const Object = struct { |
| 331 | 332 | } |
| 332 | 333 | |
| 333 | 334 | pub const EmitOptions = struct { |
| 334 | pre_ir_path: ?[]const u8, | |
| 335 | pre_bc_path: ?[]const u8, | |
| 336 | 335 | bin_path: ?[:0]const u8, |
| 337 | 336 | asm_path: ?[:0]const u8, |
| 338 | post_ir_path: ?[:0]const u8, | |
| 339 | post_bc_path: ?[:0]const u8, | |
| 337 | opt_ir_path: ?[:0]const u8, | |
| 338 | opt_bc_path: ?[:0]const u8, | |
| 340 | 339 | |
| 341 | 340 | is_debug: bool, |
| 342 | 341 | is_small: bool, |
| ... | ... | @@ -351,6 +350,7 @@ pub const Object = struct { |
| 351 | 350 | const comp = zcu.comp; |
| 352 | 351 | const io = comp.io; |
| 353 | 352 | const diags = &comp.link_diags; |
| 353 | const target = &comp.root_mod.resolved_target.result; | |
| 354 | 354 | |
| 355 | 355 | { |
| 356 | 356 | if (o.errors_len_variable != .none) { |
| ... | ... | @@ -403,7 +403,7 @@ pub const Object = struct { |
| 403 | 403 | const behavior_max = try o.builder.metadataConstant(try o.builder.intConst(.i32, 7)); |
| 404 | 404 | const behavior_min = try o.builder.metadataConstant(try o.builder.intConst(.i32, 8)); |
| 405 | 405 | |
| 406 | if (target_util.llvmMachineAbi(&comp.root_mod.resolved_target.result)) |abi| { | |
| 406 | if (target_util.llvmMachineAbi(target)) |abi| { | |
| 407 | 407 | module_flags.appendAssumeCapacity(try o.builder.metadataTuple(&.{ |
| 408 | 408 | behavior_error, |
| 409 | 409 | (try o.builder.metadataString("target-abi")).toMetadata(), |
| ... | ... | @@ -411,7 +411,7 @@ pub const Object = struct { |
| 411 | 411 | })); |
| 412 | 412 | } |
| 413 | 413 | |
| 414 | const pic_level = target_util.picLevel(&comp.root_mod.resolved_target.result); | |
| 414 | const pic_level = target_util.picLevel(target); | |
| 415 | 415 | if (comp.root_mod.pic) { |
| 416 | 416 | module_flags.appendAssumeCapacity(try o.builder.metadataTuple(&.{ |
| 417 | 417 | behavior_min, |
| ... | ... | @@ -434,7 +434,7 @@ pub const Object = struct { |
| 434 | 434 | (try o.builder.metadataString("Code Model")).toMetadata(), |
| 435 | 435 | try o.builder.metadataConstant(try o.builder.intConst(.i32, @as( |
| 436 | 436 | i32, |
| 437 | switch (codeModel(comp.root_mod.code_model, &comp.root_mod.resolved_target.result)) { | |
| 437 | switch (codeModel(comp.root_mod.code_model, target)) { | |
| 438 | 438 | .default => unreachable, |
| 439 | 439 | .tiny => 0, |
| 440 | 440 | .small => 1, |
| ... | ... | @@ -480,7 +480,6 @@ pub const Object = struct { |
| 480 | 480 | } |
| 481 | 481 | } |
| 482 | 482 | |
| 483 | const target = &comp.root_mod.resolved_target.result; | |
| 484 | 483 | if (target.os.tag == .windows and (target.cpu.arch == .x86_64 or target.cpu.arch == .x86)) { |
| 485 | 484 | // Add the "RegCallv4" flag so that any functions using `x86_regcallcc` use regcall |
| 486 | 485 | // v4, which is essentially a requirement on Windows. See corresponding logic in |
| ... | ... | @@ -515,21 +514,26 @@ pub const Object = struct { |
| 515 | 514 | |
| 516 | 515 | const emit_asm_msg = options.asm_path orelse "(none)"; |
| 517 | 516 | const emit_bin_msg = options.bin_path orelse "(none)"; |
| 518 | const post_llvm_ir_msg = options.post_ir_path orelse "(none)"; | |
| 519 | const post_llvm_bc_msg = options.post_bc_path orelse "(none)"; | |
| 517 | const opt_llvm_ir_msg = options.opt_ir_path orelse "(none)"; | |
| 518 | const opt_llvm_bc_msg = options.opt_bc_path orelse "(none)"; | |
| 520 | 519 | log.debug("emit LLVM object asm={s} bin={s} ir={s} bc={s}", .{ |
| 521 | emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg, | |
| 520 | emit_asm_msg, emit_bin_msg, opt_llvm_ir_msg, opt_llvm_bc_msg, | |
| 522 | 521 | }); |
| 522 | const log_opt_llvm_ir = debugLogScopeEnabled("opt-llvm-ir"); | |
| 523 | 523 | |
| 524 | 524 | const context, const module = emit: { |
| 525 | if (options.pre_ir_path) |path| { | |
| 526 | if (std.mem.eql(u8, path, "-")) { | |
| 527 | o.builder.dump(io); | |
| 528 | } else { | |
| 529 | o.builder.printToFilePath(io, Io.Dir.cwd(), path) catch |err| { | |
| 530 | log.err("failed printing LLVM module to \"{s}\": {t}", .{ path, err }); | |
| 531 | }; | |
| 532 | } | |
| 525 | { | |
| 526 | var p: Builder.Print = .{ .name = comp.root_name, .builder = &o.builder, .err = null }; | |
| 527 | std.log.scoped(.@"llvm-ir").debug("{f}", .{&p}); | |
| 528 | if (p.err) |err| return err; | |
| 529 | } | |
| 530 | ||
| 531 | if (target.ofmt == .llvmir) { | |
| 532 | const path = comp.bin_file.?.emit; | |
| 533 | o.builder.printToFilePath(io, path.root_dir.handle, path.sub_path) catch |err| { | |
| 534 | return diags.fail("failed emitting LLVM module to {qf}: {t}", .{ path, err }); | |
| 535 | }; | |
| 536 | return; | |
| 533 | 537 | } |
| 534 | 538 | |
| 535 | 539 | const bitcode = try o.builder.toBitcode(o.gpa, .{ |
| ... | ... | @@ -538,23 +542,26 @@ pub const Object = struct { |
| 538 | 542 | }); |
| 539 | 543 | defer o.gpa.free(bitcode); |
| 540 | 544 | |
| 541 | if (options.pre_bc_path) |path| { | |
| 542 | var file = Io.Dir.cwd().createFile(io, path, .{}) catch |err| | |
| 543 | return diags.fail("failed to create '{s}': {t}", .{ path, err }); | |
| 545 | if (target.ofmt == .llvmbc) { | |
| 546 | const path = comp.bin_file.?.emit; | |
| 547 | var file = path.root_dir.handle.createFile(io, path.sub_path, .{}) catch |err| | |
| 548 | return diags.fail("failed to create {qf}: {t}", .{ path, err }); | |
| 544 | 549 | defer file.close(io); |
| 545 | 550 | |
| 546 | 551 | file.writeStreamingAll(io, @ptrCast(bitcode)) catch |err| |
| 547 | return diags.fail("failed to write to '{s}': {t}", .{ path, err }); | |
| 552 | return diags.fail("failed to write to {qf}: {t}", .{ path, err }); | |
| 553 | return; | |
| 548 | 554 | } |
| 549 | 555 | |
| 550 | 556 | if (options.asm_path == null and options.bin_path == null and |
| 551 | options.post_ir_path == null and options.post_bc_path == null) return; | |
| 557 | options.opt_ir_path == null and options.opt_bc_path == null and | |
| 558 | !log_opt_llvm_ir) return; | |
| 552 | 559 | |
| 553 | 560 | if (!build_options.have_llvm or !comp.config.use_lib_llvm) { |
| 554 | 561 | return diags.fail("emitting without libllvm not implemented", .{}); |
| 555 | 562 | } |
| 556 | 563 | |
| 557 | initializeLLVMTarget(io, comp.root_mod.resolved_target.result.cpu.arch); | |
| 564 | initializeLLVMTarget(io, target.cpu.arch); | |
| 558 | 565 | |
| 559 | 566 | const context: *bindings.Context = .create(); |
| 560 | 567 | errdefer context.dispose(); |
| ... | ... | @@ -577,9 +584,9 @@ pub const Object = struct { |
| 577 | 584 | }; |
| 578 | 585 | defer context.dispose(); |
| 579 | 586 | |
| 580 | var target: *bindings.Target = undefined; | |
| 587 | var llvm_target: *bindings.Target = undefined; | |
| 581 | 588 | var error_message: [*:0]const u8 = undefined; |
| 582 | if (bindings.Target.getFromTriple(target_triple_sentinel, &target, &error_message).toBool()) { | |
| 589 | if (bindings.Target.getFromTriple(target_triple_sentinel, &llvm_target, &error_message).toBool()) { | |
| 583 | 590 | defer bindings.disposeMessage(error_message); |
| 584 | 591 | return diags.fail("LLVM failed to parse '{s}': {s}", .{ target_triple_sentinel, error_message }); |
| 585 | 592 | } |
| ... | ... | @@ -598,7 +605,7 @@ pub const Object = struct { |
| 598 | 605 | else |
| 599 | 606 | .Static; |
| 600 | 607 | |
| 601 | const code_model: bindings.CodeModel = switch (codeModel(comp.root_mod.code_model, &comp.root_mod.resolved_target.result)) { | |
| 608 | const code_model: bindings.CodeModel = switch (codeModel(comp.root_mod.code_model, target)) { | |
| 602 | 609 | .default => .Default, |
| 603 | 610 | .tiny => .Tiny, |
| 604 | 611 | .small => .Small, |
| ... | ... | @@ -607,24 +614,22 @@ pub const Object = struct { |
| 607 | 614 | .large => .Large, |
| 608 | 615 | }; |
| 609 | 616 | |
| 610 | const float_abi: bindings.TargetMachine.FloatABI = if (comp.root_mod.resolved_target.result.abi.float() == .hard) | |
| 611 | .Hard | |
| 612 | else | |
| 613 | .Soft; | |
| 614 | ||
| 615 | 617 | var target_machine = bindings.TargetMachine.create( |
| 616 | target, | |
| 618 | llvm_target, | |
| 617 | 619 | target_triple_sentinel, |
| 618 | if (comp.root_mod.resolved_target.result.cpu.model.llvm_name) |s| s.ptr else null, | |
| 619 | comp.root_mod.resolved_target.llvm_cpu_features.?, | |
| 620 | if (target.cpu.model.llvm_name) |s| s.ptr else null, | |
| 621 | comp.root_mod.llvm_cpu_features.?, | |
| 620 | 622 | opt_level, |
| 621 | 623 | reloc_mode, |
| 622 | 624 | code_model, |
| 623 | 625 | comp.function_sections, |
| 624 | 626 | comp.data_sections, |
| 625 | float_abi, | |
| 626 | if (target_util.llvmMachineAbi(&comp.root_mod.resolved_target.result)) |s| s.ptr else null, | |
| 627 | target_util.useEmulatedTls(&comp.root_mod.resolved_target.result), | |
| 627 | switch (target.abi.float()) { | |
| 628 | .hard => .Hard, | |
| 629 | .soft => .Soft, | |
| 630 | }, | |
| 631 | if (target_util.llvmMachineAbi(target)) |s| s.ptr else null, | |
| 632 | target_util.useEmulatedTls(target), | |
| 628 | 633 | ); |
| 629 | 634 | errdefer target_machine.dispose(); |
| 630 | 635 | |
| ... | ... | @@ -634,7 +639,10 @@ pub const Object = struct { |
| 634 | 639 | |
| 635 | 640 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. |
| 636 | 641 | // So we call the entire pipeline multiple times if this is requested. |
| 637 | // var error_message: [*:0]const u8 = undefined; | |
| 642 | var time_report_c_str: ?[*:0]u8 = null; | |
| 643 | defer if (time_report_c_str) |time_report| bindings.disposeMessage(time_report); | |
| 644 | var llvm_ir_c_str: ?[*:0]u8 = null; | |
| 645 | defer if (llvm_ir_c_str) |llvm_ir| bindings.disposeMessage(llvm_ir); | |
| 638 | 646 | var lowered_options: bindings.TargetMachine.EmitOptions = .{ |
| 639 | 647 | .is_debug = options.is_debug, |
| 640 | 648 | .is_small = options.is_small, |
| ... | ... | @@ -648,11 +656,12 @@ pub const Object = struct { |
| 648 | 656 | .allow_fast_isel = true, |
| 649 | 657 | // LLVM's RISC-V backend for some reason enables the machine outliner by default even |
| 650 | 658 | // though it's clearly not ready and produces multiple miscompilations in our std tests. |
| 651 | .allow_machine_outliner = !comp.root_mod.resolved_target.result.cpu.arch.isRISCV(), | |
| 659 | .allow_machine_outliner = !target.cpu.arch.isRISCV(), | |
| 652 | 660 | .asm_filename = null, |
| 653 | 661 | .bin_filename = if (options.bin_path) |x| x.ptr else null, |
| 654 | .llvm_ir_filename = if (options.post_ir_path) |x| x.ptr else null, | |
| 655 | .bitcode_filename = if (options.post_bc_path) |x| x.ptr else null, | |
| 662 | .llvm_ir_filename = if (options.opt_ir_path) |x| x.ptr else null, | |
| 663 | .bitcode_filename = if (options.opt_bc_path) |x| x.ptr else null, | |
| 664 | .llvm_ir_out = if (log_opt_llvm_ir) &llvm_ir_c_str else null, | |
| 656 | 665 | |
| 657 | 666 | // `.coverage` value is only used when `.sancov` is enabled. |
| 658 | 667 | .sancov = options.fuzz or comp.config.san_cov_trace_pc_guard, |
| ... | ... | @@ -684,33 +693,31 @@ pub const Object = struct { |
| 684 | 693 | }; |
| 685 | 694 | if (options.asm_path != null and options.bin_path != null) { |
| 686 | 695 | if (target_machine.emitToFile(module, &error_message, &lowered_options)) { |
| 687 | defer bindings.disposeMessage(error_message); | |
| 688 | 696 | return diags.fail("LLVM failed to emit bin={s} ir={s}: {s}", .{ |
| 689 | emit_bin_msg, post_llvm_ir_msg, error_message, | |
| 697 | emit_bin_msg, opt_llvm_ir_msg, error_message, | |
| 690 | 698 | }); |
| 691 | 699 | } |
| 692 | 700 | lowered_options.bin_filename = null; |
| 693 | 701 | lowered_options.llvm_ir_filename = null; |
| 694 | 702 | lowered_options.bitcode_filename = null; |
| 703 | lowered_options.llvm_ir_out = null; | |
| 695 | 704 | } |
| 696 | ||
| 697 | var time_report_c_str: [*:0]u8 = undefined; | |
| 698 | if (options.time_report != null) { | |
| 699 | lowered_options.time_report_out = &time_report_c_str; | |
| 700 | } | |
| 701 | ||
| 705 | if (options.time_report) |_| lowered_options.time_report_out = &time_report_c_str; | |
| 702 | 706 | lowered_options.asm_filename = if (options.asm_path) |x| x.ptr else null; |
| 703 | 707 | if (target_machine.emitToFile(module, &error_message, &lowered_options)) { |
| 704 | 708 | defer bindings.disposeMessage(error_message); |
| 705 | 709 | return diags.fail("LLVM failed to emit asm={s} bin={s} ir={s} bc={s}: {s}", .{ |
| 706 | emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg, error_message, | |
| 710 | emit_asm_msg, emit_bin_msg, opt_llvm_ir_msg, opt_llvm_bc_msg, error_message, | |
| 707 | 711 | }); |
| 708 | 712 | } |
| 709 | if (options.time_report) |tr| { | |
| 710 | defer std.c.free(time_report_c_str); | |
| 711 | const time_report_data = std.mem.span(time_report_c_str); | |
| 712 | assert(tr.llvm_pass_timings.len == 0); | |
| 713 | tr.llvm_pass_timings = try comp.gpa.dupe(u8, time_report_data); | |
| 713 | if (log_opt_llvm_ir) std.log.scoped(.@"opt-llvm-ir").debug("{s}", .{ | |
| 714 | llvm_ir_c_str orelse return error.OutOfMemory, | |
| 715 | }); | |
| 716 | if (options.time_report) |time_report| { | |
| 717 | assert(time_report.llvm_pass_timings.len == 0); | |
| 718 | time_report.llvm_pass_timings = try comp.gpa.dupe(u8, std.mem.span( | |
| 719 | time_report_c_str orelse return error.OutOfMemory, | |
| 720 | )); | |
| 714 | 721 | } |
| 715 | 722 | } |
| 716 | 723 | |
| ... | ... | @@ -2184,10 +2191,10 @@ pub const Object = struct { |
| 2184 | 2191 | .value = try o.builder.string(s), |
| 2185 | 2192 | } }, &o.builder); |
| 2186 | 2193 | } |
| 2187 | if (owner_mod.resolved_target.llvm_cpu_features) |s| { | |
| 2194 | if (owner_mod.llvm_cpu_features) |s| { | |
| 2188 | 2195 | try attributes.addFnAttr(.{ .string = .{ |
| 2189 | 2196 | .kind = try o.builder.string("target-features"), |
| 2190 | .value = try o.builder.string(std.mem.span(s)), | |
| 2197 | .value = try o.builder.string(s), | |
| 2191 | 2198 | } }, &o.builder); |
| 2192 | 2199 | } |
| 2193 | 2200 |
src/codegen/llvm/bindings.zig+3-2| ... | ... | @@ -51,7 +51,7 @@ pub const Module = opaque { |
| 51 | 51 | }; |
| 52 | 52 | |
| 53 | 53 | pub const disposeMessage = LLVMDisposeMessage; |
| 54 | extern fn LLVMDisposeMessage(Message: [*:0]const u8) void; | |
| 54 | extern fn LLVMDisposeMessage(Message: ?[*:0]const u8) void; | |
| 55 | 55 | |
| 56 | 56 | pub const TargetMachine = opaque { |
| 57 | 57 | pub const FloatABI = enum(c_int) { |
| ... | ... | @@ -85,7 +85,7 @@ pub const TargetMachine = opaque { |
| 85 | 85 | pub const EmitOptions = extern struct { |
| 86 | 86 | is_debug: bool, |
| 87 | 87 | is_small: bool, |
| 88 | time_report_out: ?*[*:0]u8, | |
| 88 | time_report_out: ?*?[*:0]u8, | |
| 89 | 89 | tsan: bool, |
| 90 | 90 | sancov: bool, |
| 91 | 91 | lto: LtoPhase, |
| ... | ... | @@ -95,6 +95,7 @@ pub const TargetMachine = opaque { |
| 95 | 95 | bin_filename: ?[*:0]const u8, |
| 96 | 96 | llvm_ir_filename: ?[*:0]const u8, |
| 97 | 97 | bitcode_filename: ?[*:0]const u8, |
| 98 | llvm_ir_out: ?*?[*:0]u8, | |
| 98 | 99 | coverage: Coverage, |
| 99 | 100 | |
| 100 | 101 | pub const LtoPhase = enum(c_int) { |
src/codegen/riscv64/CodeGen.zig+1-1| ... | ... | @@ -27,7 +27,7 @@ const Target = std.Target; |
| 27 | 27 | const log = std.log.scoped(.riscv_codegen); |
| 28 | 28 | const tracking_log = std.log.scoped(.tracking); |
| 29 | 29 | const verbose_tracking_log = std.log.scoped(.verbose_tracking); |
| 30 | const wip_mir_log = std.log.scoped(.wip_mir); | |
| 30 | const wip_mir_log = std.log.scoped(.@"wip-mir"); | |
| 31 | 31 | const Alignment = InternPool.Alignment; |
| 32 | 32 | |
| 33 | 33 | const bits = @import("bits.zig"); |
src/codegen/x86_64/CodeGen.zig+1-1| ... | ... | @@ -5,7 +5,7 @@ const link = @import("../../link.zig"); |
| 5 | 5 | const log = std.log.scoped(.codegen); |
| 6 | 6 | const tracking_log = std.log.scoped(.tracking); |
| 7 | 7 | const verbose_tracking_log = std.log.scoped(.verbose_tracking); |
| 8 | const wip_mir_log = std.log.scoped(.wip_mir); | |
| 8 | const wip_mir_log = std.log.scoped(.@"wip-mir"); | |
| 9 | 9 | const Writer = std.Io.Writer; |
| 10 | 10 | |
| 11 | 11 | const Air = @import("../../Air.zig"); |
src/dev.zig+2| ... | ... | @@ -112,6 +112,7 @@ pub const Env = enum { |
| 112 | 112 | .loongarch_backend, |
| 113 | 113 | .spork8_backend, |
| 114 | 114 | .lld_linker, |
| 115 | .llvm_linker, | |
| 115 | 116 | .coff_linker, |
| 116 | 117 | .elf_linker, |
| 117 | 118 | .elf2_linker, |
| ... | ... | @@ -333,6 +334,7 @@ pub const Feature = enum { |
| 333 | 334 | spork8_backend, |
| 334 | 335 | |
| 335 | 336 | lld_linker, |
| 337 | llvm_linker, | |
| 336 | 338 | coff_linker, |
| 337 | 339 | elf_linker, |
| 338 | 340 | elf2_linker, |
src/libs/freebsd.zig-4| ... | ... | @@ -1120,10 +1120,6 @@ fn buildSharedLib( |
| 1120 | 1120 | .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, |
| 1121 | 1121 | .verbose_cc = comp.verbose_cc, |
| 1122 | 1122 | .verbose_link = comp.verbose_link, |
| 1123 | .verbose_air = comp.verbose_air, | |
| 1124 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 1125 | .verbose_llvm_bc = comp.verbose_llvm_bc, | |
| 1126 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 1127 | 1123 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 1128 | 1124 | .version = version, |
| 1129 | 1125 | .version_script = .{ |
src/libs/glibc.zig-4| ... | ... | @@ -1268,10 +1268,6 @@ fn buildSharedLib( |
| 1268 | 1268 | .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, |
| 1269 | 1269 | .verbose_cc = comp.verbose_cc, |
| 1270 | 1270 | .verbose_link = comp.verbose_link, |
| 1271 | .verbose_air = comp.verbose_air, | |
| 1272 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 1273 | .verbose_llvm_bc = comp.verbose_llvm_bc, | |
| 1274 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 1275 | 1271 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 1276 | 1272 | .version = version, |
| 1277 | 1273 | .version_script = .{ |
src/libs/libcxx.zig-8| ... | ... | @@ -260,10 +260,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError! |
| 260 | 260 | .c_source_files = c_source_files.items, |
| 261 | 261 | .verbose_cc = comp.verbose_cc, |
| 262 | 262 | .verbose_link = comp.verbose_link, |
| 263 | .verbose_air = comp.verbose_air, | |
| 264 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 265 | .verbose_llvm_bc = comp.verbose_llvm_bc, | |
| 266 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 267 | 263 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 268 | 264 | .skip_linker_dependencies = true, |
| 269 | 265 | .environ_map = comp.environ_map, |
| ... | ... | @@ -445,10 +441,6 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 445 | 441 | .c_source_files = c_source_files.items, |
| 446 | 442 | .verbose_cc = comp.verbose_cc, |
| 447 | 443 | .verbose_link = comp.verbose_link, |
| 448 | .verbose_air = comp.verbose_air, | |
| 449 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 450 | .verbose_llvm_bc = comp.verbose_llvm_bc, | |
| 451 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 452 | 444 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 453 | 445 | .skip_linker_dependencies = true, |
| 454 | 446 | .environ_map = comp.environ_map, |
src/libs/libtsan.zig-4| ... | ... | @@ -295,10 +295,6 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo |
| 295 | 295 | .c_source_files = c_source_files.items, |
| 296 | 296 | .verbose_cc = comp.verbose_cc, |
| 297 | 297 | .verbose_link = comp.verbose_link, |
| 298 | .verbose_air = comp.verbose_air, | |
| 299 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 300 | .verbose_llvm_bc = comp.verbose_llvm_bc, | |
| 301 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 302 | 298 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 303 | 299 | .skip_linker_dependencies = skip_linker_dependencies, |
| 304 | 300 | .linker_allow_shlib_undefined = linker_allow_shlib_undefined, |
src/libs/libunwind.zig-4| ... | ... | @@ -157,10 +157,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 157 | 157 | .c_source_files = &c_source_files, |
| 158 | 158 | .verbose_cc = comp.verbose_cc, |
| 159 | 159 | .verbose_link = comp.verbose_link, |
| 160 | .verbose_air = comp.verbose_air, | |
| 161 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 162 | .verbose_llvm_bc = comp.verbose_llvm_bc, | |
| 163 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 164 | 160 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 165 | 161 | .skip_linker_dependencies = true, |
| 166 | 162 | .environ_map = comp.environ_map, |
src/libs/musl.zig-3| ... | ... | @@ -246,9 +246,6 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro |
| 246 | 246 | .emit_bin = .yes_cache, |
| 247 | 247 | .verbose_cc = comp.verbose_cc, |
| 248 | 248 | .verbose_link = comp.verbose_link, |
| 249 | .verbose_air = comp.verbose_air, | |
| 250 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 251 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 252 | 249 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 253 | 250 | .c_source_files = &.{ |
| 254 | 251 | .{ |
src/libs/netbsd.zig-4| ... | ... | @@ -771,10 +771,6 @@ fn buildSharedLib( |
| 771 | 771 | .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, |
| 772 | 772 | .verbose_cc = comp.verbose_cc, |
| 773 | 773 | .verbose_link = comp.verbose_link, |
| 774 | .verbose_air = comp.verbose_air, | |
| 775 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 776 | .verbose_llvm_bc = comp.verbose_llvm_bc, | |
| 777 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 778 | 774 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 779 | 775 | .version = version, |
| 780 | 776 | .soname = soname, |
src/libs/openbsd.zig-4| ... | ... | @@ -691,10 +691,6 @@ fn buildSharedLib( |
| 691 | 691 | .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, |
| 692 | 692 | .verbose_cc = comp.verbose_cc, |
| 693 | 693 | .verbose_link = comp.verbose_link, |
| 694 | .verbose_air = comp.verbose_air, | |
| 695 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 696 | .verbose_llvm_bc = comp.verbose_llvm_bc, | |
| 697 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 698 | 694 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 699 | 695 | .soname = soname, |
| 700 | 696 | .c_source_files = &c_source_files, |
src/link.zig+35-4| ... | ... | @@ -550,6 +550,7 @@ pub const File = struct { |
| 550 | 550 | return &ptr.base; |
| 551 | 551 | }, |
| 552 | 552 | .lld => unreachable, // not known from ofmt |
| 553 | .llvm => |tag| return createDummy(arena, tag, comp, emit), | |
| 553 | 554 | } |
| 554 | 555 | } |
| 555 | 556 | |
| ... | ... | @@ -573,9 +574,26 @@ pub const File = struct { |
| 573 | 574 | return &ptr.base; |
| 574 | 575 | }, |
| 575 | 576 | .lld => unreachable, // not known from ofmt |
| 577 | .llvm => |tag| return createDummy(arena, tag, comp, emit), | |
| 576 | 578 | } |
| 577 | 579 | } |
| 578 | 580 | |
| 581 | fn createDummy(arena: Allocator, tag: Tag, comp: *Compilation, path: Path) Allocator.Error!*File { | |
| 582 | const base = try arena.create(File); | |
| 583 | base.* = .{ | |
| 584 | .tag = tag, | |
| 585 | .comp = comp, | |
| 586 | .emit = path, | |
| 587 | .file = null, | |
| 588 | .gc_sections = false, | |
| 589 | .print_gc_sections = false, | |
| 590 | .build_id = .none, | |
| 591 | .allow_shlib_undefined = false, | |
| 592 | .stack_size = 0, | |
| 593 | }; | |
| 594 | return base; | |
| 595 | } | |
| 596 | ||
| 579 | 597 | pub fn cast(base: *File, comptime tag: Tag) if (dev.env.supports(tag.devFeature())) ?*tag.Type() else ?noreturn { |
| 580 | 598 | return if (dev.env.supports(tag.devFeature()) and base.tag == tag) @fieldParentPtr("base", base) else null; |
| 581 | 599 | } |
| ... | ... | @@ -606,7 +624,7 @@ pub const File = struct { |
| 606 | 624 | const gpa = comp.gpa; |
| 607 | 625 | const io = comp.io; |
| 608 | 626 | switch (base.tag) { |
| 609 | .lld => assert(base.file == null), | |
| 627 | .lld, .llvm => assert(base.file == null), | |
| 610 | 628 | .elf, .macho, .wasm => { |
| 611 | 629 | dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker }); |
| 612 | 630 | if (base.file != null) return; |
| ... | ... | @@ -706,7 +724,7 @@ pub const File = struct { |
| 706 | 724 | if (!base.canMakeExecutable()) |
| 707 | 725 | return; |
| 708 | 726 | switch (base.tag) { |
| 709 | .lld => assert(base.file == null), | |
| 727 | .lld, .llvm => assert(base.file == null), | |
| 710 | 728 | .elf => if (base.file) |f| { |
| 711 | 729 | dev.check(.elf_linker); |
| 712 | 730 | f.close(io); |
| ... | ... | @@ -827,6 +845,7 @@ pub const File = struct { |
| 827 | 845 | |
| 828 | 846 | switch (base.tag) { |
| 829 | 847 | .lld => unreachable, |
| 848 | .llvm => unreachable, | |
| 830 | 849 | .plan9 => unreachable, |
| 831 | 850 | inline else => |tag| { |
| 832 | 851 | dev.check(tag.devFeature()); |
| ... | ... | @@ -862,6 +881,7 @@ pub const File = struct { |
| 862 | 881 | assert(pt.zcu.llvm_object == null); |
| 863 | 882 | switch (base.tag) { |
| 864 | 883 | .lld => unreachable, |
| 884 | .llvm => unreachable, | |
| 865 | 885 | .plan9 => unreachable, |
| 866 | 886 | inline else => |tag| { |
| 867 | 887 | dev.check(tag.devFeature()); |
| ... | ... | @@ -897,6 +917,7 @@ pub const File = struct { |
| 897 | 917 | } |
| 898 | 918 | switch (base.tag) { |
| 899 | 919 | .lld => unreachable, |
| 920 | .llvm => unreachable, | |
| 900 | 921 | .plan9 => unreachable, |
| 901 | 922 | .spirv => {}, |
| 902 | 923 | .coff => {}, |
| ... | ... | @@ -941,6 +962,7 @@ pub const File = struct { |
| 941 | 962 | base.releaseLock(); |
| 942 | 963 | if (base.file) |f| f.close(io); |
| 943 | 964 | switch (base.tag) { |
| 965 | .llvm => {}, | |
| 944 | 966 | .plan9 => unreachable, |
| 945 | 967 | inline else => |tag| { |
| 946 | 968 | dev.check(tag.devFeature()); |
| ... | ... | @@ -1003,6 +1025,7 @@ pub const File = struct { |
| 1003 | 1025 | } |
| 1004 | 1026 | assert(base.post_prelink); |
| 1005 | 1027 | switch (base.tag) { |
| 1028 | .llvm => {}, | |
| 1006 | 1029 | .plan9 => unreachable, |
| 1007 | 1030 | inline else => |tag| { |
| 1008 | 1031 | dev.check(tag.devFeature()); |
| ... | ... | @@ -1030,6 +1053,7 @@ pub const File = struct { |
| 1030 | 1053 | |
| 1031 | 1054 | switch (base.tag) { |
| 1032 | 1055 | .lld => unreachable, |
| 1056 | .llvm => unreachable, | |
| 1033 | 1057 | .plan9 => unreachable, |
| 1034 | 1058 | inline else => |tag| { |
| 1035 | 1059 | dev.check(tag.devFeature()); |
| ... | ... | @@ -1056,6 +1080,7 @@ pub const File = struct { |
| 1056 | 1080 | assert(base.comp.zcu.?.llvm_object == null); |
| 1057 | 1081 | switch (base.tag) { |
| 1058 | 1082 | .lld => unreachable, |
| 1083 | .llvm => unreachable, | |
| 1059 | 1084 | .c => unreachable, |
| 1060 | 1085 | .spirv => unreachable, |
| 1061 | 1086 | .wasm => unreachable, |
| ... | ... | @@ -1078,6 +1103,7 @@ pub const File = struct { |
| 1078 | 1103 | assert(pt.zcu.llvm_object == null); |
| 1079 | 1104 | switch (base.tag) { |
| 1080 | 1105 | .lld => unreachable, |
| 1106 | .llvm => unreachable, | |
| 1081 | 1107 | .c => unreachable, |
| 1082 | 1108 | .spirv => unreachable, |
| 1083 | 1109 | .wasm => unreachable, |
| ... | ... | @@ -1095,6 +1121,7 @@ pub const File = struct { |
| 1095 | 1121 | assert(base.comp.zcu.?.llvm_object == null); |
| 1096 | 1122 | switch (base.tag) { |
| 1097 | 1123 | .lld => unreachable, |
| 1124 | .llvm => unreachable, | |
| 1098 | 1125 | .c => unreachable, |
| 1099 | 1126 | .spirv => unreachable, |
| 1100 | 1127 | .wasm => unreachable, |
| ... | ... | @@ -1124,6 +1151,7 @@ pub const File = struct { |
| 1124 | 1151 | .spirv, |
| 1125 | 1152 | .plan9, |
| 1126 | 1153 | .lld, |
| 1154 | .llvm, | |
| 1127 | 1155 | .spork8, |
| 1128 | 1156 | => return .unimplemented, |
| 1129 | 1157 | inline else => |tag| { |
| ... | ... | @@ -1240,7 +1268,7 @@ pub const File = struct { |
| 1240 | 1268 | dev.check(tag.devFeature()); |
| 1241 | 1269 | return @as(*tag.Type(), @fieldParentPtr("base", base)).loadInput(input); |
| 1242 | 1270 | }, |
| 1243 | .c, .spork8, .plan9, .lld => {}, | |
| 1271 | .c, .spork8, .plan9, .lld, .llvm => {}, | |
| 1244 | 1272 | } |
| 1245 | 1273 | } |
| 1246 | 1274 | |
| ... | ... | @@ -1352,6 +1380,7 @@ pub const File = struct { |
| 1352 | 1380 | coff, |
| 1353 | 1381 | elf, |
| 1354 | 1382 | elf2, |
| 1383 | llvm, | |
| 1355 | 1384 | macho, |
| 1356 | 1385 | macho2, |
| 1357 | 1386 | c, |
| ... | ... | @@ -1366,13 +1395,14 @@ pub const File = struct { |
| 1366 | 1395 | .coff => Coff, |
| 1367 | 1396 | .elf => Elf, |
| 1368 | 1397 | .elf2 => Elf2, |
| 1398 | .llvm => File, | |
| 1369 | 1399 | .macho => MachO, |
| 1370 | 1400 | .macho2 => MachO2, |
| 1371 | 1401 | .c => C, |
| 1372 | 1402 | .wasm => Wasm, |
| 1373 | 1403 | .spirv => Spirv, |
| 1374 | 1404 | .lld => Lld, |
| 1375 | .plan9 => comptime unreachable, | |
| 1405 | .plan9 => unreachable, | |
| 1376 | 1406 | .spork8 => Spork8, |
| 1377 | 1407 | }; |
| 1378 | 1408 | } |
| ... | ... | @@ -1381,6 +1411,7 @@ pub const File = struct { |
| 1381 | 1411 | return switch (ofmt) { |
| 1382 | 1412 | .coff => .coff, |
| 1383 | 1413 | .elf => if (use_new_linker) .elf2 else .elf, |
| 1414 | .llvmbc, .llvmir => .llvm, | |
| 1384 | 1415 | .macho => if (use_new_linker) .macho2 else .macho, |
| 1385 | 1416 | .wasm => .wasm, |
| 1386 | 1417 | .plan9 => .plan9, |
src/link/Elf.zig+1-3| ... | ... | @@ -860,9 +860,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void { |
| 860 | 860 | |
| 861 | 861 | // Dump the state for easy debugging. |
| 862 | 862 | // State can be dumped via `--debug-log link_state`. |
| 863 | if (build_options.enable_logging) { | |
| 864 | state_log.debug("{f}", .{self.dumpState()}); | |
| 865 | } | |
| 863 | state_log.debug("{f}", .{self.dumpState()}); | |
| 866 | 864 | |
| 867 | 865 | // Beyond this point, everything has been allocated a virtual address and we can resolve |
| 868 | 866 | // the relocations, and commit objects to file. |
src/link/Elf/ZigObject.zig+1-1| ... | ... | @@ -291,7 +291,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void { |
| 291 | 291 | if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed; |
| 292 | 292 | } |
| 293 | 293 | |
| 294 | if (build_options.enable_logging) { | |
| 294 | if (build_options.enable_debug_extensions) { | |
| 295 | 295 | const active = elf_file.base.comp.zcu.?.activate(tid); |
| 296 | 296 | defer active.deactivate(); |
| 297 | 297 | for (self.navs.keys(), self.navs.values()) |nav_index, meta| { |
src/link/Elf/gc.zig+1-1| ... | ... | @@ -98,7 +98,7 @@ fn markAtom(atom: *Atom) bool { |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | 100 | fn markLive(atom: *Atom, elf_file: *Elf) void { |
| 101 | if (@import("build_options").enable_logging) track_live_level.incr(); | |
| 101 | if (@import("build_options").enable_debug_extensions) track_live_level.incr(); | |
| 102 | 102 | |
| 103 | 103 | assert(atom.visited); |
| 104 | 104 | const file = atom.file(elf_file).?; |
src/link/Elf/relocatable.zig+4-10| ... | ... | @@ -51,9 +51,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { |
| 51 | 51 | try allocateAllocSections(elf_file); |
| 52 | 52 | try elf_file.allocateNonAllocSections(); |
| 53 | 53 | |
| 54 | if (build_options.enable_logging) { | |
| 55 | state_log.debug("{f}", .{elf_file.dumpState()}); | |
| 56 | } | |
| 54 | state_log.debug("{f}", .{elf_file.dumpState()}); | |
| 57 | 55 | |
| 58 | 56 | try elf_file.writeMergeSections(); |
| 59 | 57 | try writeSyntheticSections(elf_file); |
| ... | ... | @@ -117,10 +115,8 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { |
| 117 | 115 | break :blk pos; |
| 118 | 116 | }; |
| 119 | 117 | |
| 120 | if (build_options.enable_logging) { | |
| 121 | state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(elf_file)}); | |
| 122 | state_log.debug("ar_strtab\n{f}\n", .{ar_strtab}); | |
| 123 | } | |
| 118 | state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(elf_file)}); | |
| 119 | state_log.debug("ar_strtab\n{f}\n", .{ar_strtab}); | |
| 124 | 120 | |
| 125 | 121 | const buffer = try gpa.alloc(u8, total_size); |
| 126 | 122 | defer gpa.free(buffer); |
| ... | ... | @@ -193,9 +189,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void { |
| 193 | 189 | try allocateAllocSections(elf_file); |
| 194 | 190 | try elf_file.allocateNonAllocSections(); |
| 195 | 191 | |
| 196 | if (build_options.enable_logging) { | |
| 197 | state_log.debug("{f}", .{elf_file.dumpState()}); | |
| 198 | } | |
| 192 | state_log.debug("{f}", .{elf_file.dumpState()}); | |
| 199 | 193 | |
| 200 | 194 | try writeAtoms(elf_file); |
| 201 | 195 | try elf_file.writeMergeSections(); |
src/link/MachO.zig+1-3| ... | ... | @@ -456,9 +456,7 @@ pub fn flush( |
| 456 | 456 | self.allocateSegments(); |
| 457 | 457 | self.allocateSyntheticSymbols(); |
| 458 | 458 | |
| 459 | if (build_options.enable_logging) { | |
| 460 | state_log.debug("{f}", .{self.dumpState()}); | |
| 461 | } | |
| 459 | state_log.debug("{f}", .{self.dumpState()}); | |
| 462 | 460 | |
| 463 | 461 | // Beyond this point, everything has been allocated a virtual address and we can resolve |
| 464 | 462 | // the relocations, and commit objects to file. |
src/link/MachO/dead_strip.zig+2-1| ... | ... | @@ -123,8 +123,9 @@ fn markLive(atom: *Atom, macho_file: *MachO) void { |
| 123 | 123 | atom.getName(macho_file), |
| 124 | 124 | }); |
| 125 | 125 | |
| 126 | if (build_options.enable_logging) | |
| 126 | if (build_options.enable_debug_extensions) { | |
| 127 | 127 | track_live_level.incr(); |
| 128 | } | |
| 128 | 129 | |
| 129 | 130 | for (atom.getRelocs(macho_file)) |rel| { |
| 130 | 131 | const target_atom = switch (rel.tag) { |
src/link/MachO/relocatable.zig+3-9| ... | ... | @@ -61,9 +61,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation) link.Error!void { |
| 61 | 61 | }; |
| 62 | 62 | allocateSegment(macho_file); |
| 63 | 63 | |
| 64 | if (build_options.enable_logging) { | |
| 65 | state_log.debug("{f}", .{macho_file.dumpState()}); | |
| 66 | } | |
| 64 | state_log.debug("{f}", .{macho_file.dumpState()}); | |
| 67 | 65 | |
| 68 | 66 | try writeSections(macho_file); |
| 69 | 67 | sortRelocs(macho_file); |
| ... | ... | @@ -107,9 +105,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation) link.Error!void { |
| 107 | 105 | return diags.fail("failed to allocate sections: {s}", .{@errorName(err)}); |
| 108 | 106 | allocateSegment(macho_file); |
| 109 | 107 | |
| 110 | if (build_options.enable_logging) { | |
| 111 | state_log.debug("{f}", .{macho_file.dumpState()}); | |
| 112 | } | |
| 108 | state_log.debug("{f}", .{macho_file.dumpState()}); | |
| 113 | 109 | |
| 114 | 110 | try writeSections(macho_file); |
| 115 | 111 | sortRelocs(macho_file); |
| ... | ... | @@ -185,9 +181,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation) link.Error!void { |
| 185 | 181 | break :blk pos; |
| 186 | 182 | }; |
| 187 | 183 | |
| 188 | if (build_options.enable_logging) { | |
| 189 | state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)}); | |
| 190 | } | |
| 184 | state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)}); | |
| 191 | 185 | |
| 192 | 186 | const buffer = try gpa.alloc(u8, total_size); |
| 193 | 187 | defer gpa.free(buffer); |
src/main.zig+40-74| ... | ... | @@ -42,11 +42,8 @@ const thread_stack_size = 60 << 20; |
| 42 | 42 | |
| 43 | 43 | pub const std_options: std.Options = .{ |
| 44 | 44 | .logFn = log, |
| 45 | ||
| 46 | .log_level = switch (builtin.mode) { | |
| 47 | .debug => .debug, | |
| 48 | .safe, .fast => .info, | |
| 49 | .small => .err, | |
| 45 | .log_level = switch (build_options.log_level) { | |
| 46 | inline else => |log_level| @field(std.log.Level, @tagName(log_level)), | |
| 50 | 47 | }, |
| 51 | 48 | }; |
| 52 | 49 | pub const std_options_cwd = if (native_os == .wasi) wasi_cwd else null; |
| ... | ... | @@ -104,7 +101,7 @@ const normal_usage = |
| 104 | 101 | \\ help Print this help and exit |
| 105 | 102 | \\ cache-cat Print a zig-cache manifest file as zon |
| 106 | 103 | \\ std View standard library documentation in a browser |
| 107 | \\ libc Display native libc paths file or validate one | |
| 104 | \\ libc Print native libc paths file or validate one | |
| 108 | 105 | \\ targets List available compilation targets |
| 109 | 106 | \\ version Print version number and exit |
| 110 | 107 | \\ zen Print Zen of Zig and exit |
| ... | ... | @@ -126,7 +123,15 @@ const debug_usage = normal_usage ++ |
| 126 | 123 | |
| 127 | 124 | const usage = if (build_options.enable_debug_extensions) debug_usage else normal_usage; |
| 128 | 125 | |
| 129 | var log_scopes: std.ArrayList([]const u8) = .empty; | |
| 126 | var log_scopes: std.array_hash_map.String(void) = .empty; | |
| 127 | ||
| 128 | pub fn debugLogScopeEnabled(scope: []const u8) bool { | |
| 129 | switch (build_options.log_level) { | |
| 130 | else => {}, | |
| 131 | .debug => if (log_scopes.contains(scope)) return true, | |
| 132 | } | |
| 133 | return false; | |
| 134 | } | |
| 130 | 135 | |
| 131 | 136 | pub fn log( |
| 132 | 137 | comptime level: std.log.Level, |
| ... | ... | @@ -135,18 +140,11 @@ pub fn log( |
| 135 | 140 | args: anytype, |
| 136 | 141 | ) void { |
| 137 | 142 | // Hide debug messages unless: |
| 138 | // * logging enabled with `-Dlog`. | |
| 143 | // * logging enabled with `-Ddebug-extensions` or `-Dlog=debug`. | |
| 139 | 144 | // * the --debug-log arg for the scope has been provided |
| 140 | if (@backingInt(level) > @backingInt(std.options.log_level) or | |
| 141 | @backingInt(level) > @backingInt(std.log.Level.info)) | |
| 142 | { | |
| 143 | if (!build_options.enable_logging) return; | |
| 144 | ||
| 145 | const scope_name = @tagName(scope); | |
| 146 | for (log_scopes.items) |log_scope| { | |
| 147 | if (mem.eql(u8, log_scope, scope_name)) | |
| 148 | break; | |
| 149 | } else return; | |
| 145 | switch (level) { | |
| 146 | else => {}, | |
| 147 | .debug => if (!debugLogScopeEnabled(@tagName(scope))) return, | |
| 150 | 148 | } |
| 151 | 149 | |
| 152 | 150 | // Otherwise, use the default implementation. |
| ... | ... | @@ -557,11 +555,14 @@ const compile_usage = |
| 557 | 555 | \\ -fno-emit-docs (default) Do not produce docs/ dir with html documentation |
| 558 | 556 | \\ -femit-implib[=path] (default) Produce an import .lib when building a Windows DLL |
| 559 | 557 | \\ -fno-emit-implib Do not produce an import .lib when building a Windows DLL |
| 560 | \\ --show-builtin Output the source of @import("builtin") then exit | |
| 561 | 558 | \\ --cache-dir [path] Override the local cache directory |
| 562 | 559 | \\ --global-cache-dir [path] Override the global cache directory |
| 563 | 560 | \\ --zig-lib-dir [path] Override path to Zig installation lib directory |
| 564 | 561 | \\ --build-root [path] Override path to project source files |
| 562 | \\ --show-builtin Output the source of @import("builtin") then exit | |
| 563 | \\ --time-report Send timing diagnostics to '--listen' clients | |
| 564 | \\ --verbose-cc Print C compiler commands before executing them | |
| 565 | \\ --verbose-link Print linker commands before executing them | |
| 565 | 566 | \\ |
| 566 | 567 | \\Global Compile Options: |
| 567 | 568 | \\ --name [name] Compilation unit name (not a file path) |
| ... | ... | @@ -593,7 +594,6 @@ const compile_usage = |
| 593 | 594 | \\ -fpatchable-function-entry=[num] Add num NOPs of padding in function prologues |
| 594 | 595 | \\ -mexec-model=[value] (WASI) Execution model |
| 595 | 596 | \\ -municode (Windows) Use wmain/wWinMain as entry point |
| 596 | \\ --time-report Send timing diagnostics to '--listen' clients | |
| 597 | 597 | \\ |
| 598 | 598 | \\Per-Module Compile Options: |
| 599 | 599 | \\ --dep [[import=]name] Add an entry to the next module's import table |
| ... | ... | @@ -604,13 +604,15 @@ const compile_usage = |
| 604 | 604 | \\ safe Enable both safety checks and machine code optimizations |
| 605 | 605 | \\ small Prioritize small binary size. Safety checks off. |
| 606 | 606 | \\ -ofmt=[fmt] Override target object format |
| 607 | \\ elf Executable and Linking Format | |
| 608 | 607 | \\ c C source code |
| 609 | \\ wasm WebAssembly | |
| 610 | 608 | \\ coff Common Object File Format (Windows) |
| 609 | \\ elf Executable and Linking Format | |
| 610 | \\ llvmir LLVM text intermediate representation | |
| 611 | \\ llvmbc LLVM binary intermediate representation | |
| 611 | 612 | \\ macho macOS relocatables |
| 612 | \\ spirv Standard, Portable Intermediate Representation V (SPIR-V) | |
| 613 | 613 | \\ plan9 Plan 9 from Bell Labs object format |
| 614 | \\ spirv Standard, Portable Intermediate Representation V (SPIR-V) | |
| 615 | \\ wasm WebAssembly | |
| 614 | 616 | \\ hex (planned feature) Intel IHEX |
| 615 | 617 | \\ raw (planned feature) Dump machine code directly |
| 616 | 618 | \\ -mcpu [cpu] Specify target CPU and feature set |
| ... | ... | @@ -791,15 +793,6 @@ const compile_usage = |
| 791 | 793 | \\Debug Options (Zig Compiler Development): |
| 792 | 794 | \\ -fopt-bisect-limit=[limit] Only run [limit] first LLVM optimization passes |
| 793 | 795 | \\ -fstack-report Print stack size diagnostics |
| 794 | \\ --verbose-link Display linker invocations | |
| 795 | \\ --verbose-cc Display C compiler invocations | |
| 796 | \\ --verbose-air Enable compiler debug output for Zig AIR | |
| 797 | \\ --verbose-intern-pool Enable compiler debug output for InternPool | |
| 798 | \\ --verbose-generic-instances Enable compiler debug output for generic instance generation | |
| 799 | \\ --verbose-llvm-ir[=path] Enable compiler debug output for unoptimized LLVM IR | |
| 800 | \\ --verbose-llvm-bc=[path] Enable compiler debug output for unoptimized LLVM BC | |
| 801 | \\ --verbose-cimport Enable compiler debug output for C imports | |
| 802 | \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features | |
| 803 | 796 | \\ --debug-log [scope] Enable printing debug/info log messages for scope |
| 804 | 797 | \\ --debug-compile-errors Crash with helpful diagnostics at the first compile error |
| 805 | 798 | \\ --debug-link-snapshot Dump linker state and output file information for troubleshooting |
| ... | ... | @@ -933,17 +926,11 @@ fn buildOutputType( |
| 933 | 926 | var listen: Listen = .none; |
| 934 | 927 | var debug_compile_errors = false; |
| 935 | 928 | var debug_incremental = false; |
| 936 | var verbose_link = (native_os != .wasi or builtin.link_libc) and | |
| 937 | EnvVar.ZIG_VERBOSE_LINK.isSet(environ_map); | |
| 938 | 929 | var verbose_cc = (native_os != .wasi or builtin.link_libc) and |
| 939 | 930 | EnvVar.ZIG_VERBOSE_CC.isSet(environ_map); |
| 940 | var verbose_air = false; | |
| 941 | var verbose_intern_pool = false; | |
| 942 | var verbose_generic_instances = false; | |
| 943 | var verbose_llvm_ir: ?[]const u8 = null; | |
| 944 | var verbose_llvm_bc: ?[]const u8 = null; | |
| 931 | var verbose_link = (native_os != .wasi or builtin.link_libc) and | |
| 932 | EnvVar.ZIG_VERBOSE_LINK.isSet(environ_map); | |
| 945 | 933 | var link_depfile: ?[]const u8 = null; |
| 946 | var verbose_llvm_cpu_features = false; | |
| 947 | 934 | var time_report = false; |
| 948 | 935 | var stack_report = false; |
| 949 | 936 | var show_builtin = false; |
| ... | ... | @@ -1809,24 +1796,10 @@ fn buildOutputType( |
| 1809 | 1796 | } else { |
| 1810 | 1797 | warn("Zig was compiled without debug extensions. --debug-compile-errors has no effect.", .{}); |
| 1811 | 1798 | } |
| 1812 | } else if (mem.eql(u8, arg, "--verbose-link")) { | |
| 1813 | verbose_link = true; | |
| 1814 | 1799 | } else if (mem.eql(u8, arg, "--verbose-cc")) { |
| 1815 | 1800 | verbose_cc = true; |
| 1816 | } else if (mem.eql(u8, arg, "--verbose-air")) { | |
| 1817 | verbose_air = true; | |
| 1818 | } else if (mem.eql(u8, arg, "--verbose-intern-pool")) { | |
| 1819 | verbose_intern_pool = true; | |
| 1820 | } else if (mem.eql(u8, arg, "--verbose-generic-instances")) { | |
| 1821 | verbose_generic_instances = true; | |
| 1822 | } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { | |
| 1823 | verbose_llvm_ir = "-"; | |
| 1824 | } else if (mem.cutPrefix(u8, arg, "--verbose-llvm-ir=")) |rest| { | |
| 1825 | verbose_llvm_ir = rest; | |
| 1826 | } else if (mem.cutPrefix(u8, arg, "--verbose-llvm-bc=")) |rest| { | |
| 1827 | verbose_llvm_bc = rest; | |
| 1828 | } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { | |
| 1829 | verbose_llvm_cpu_features = true; | |
| 1801 | } else if (mem.eql(u8, arg, "--verbose-link")) { | |
| 1802 | verbose_link = true; | |
| 1830 | 1803 | } else if (mem.cutPrefix(u8, arg, "-T")) |rest| { |
| 1831 | 1804 | linker_script = rest; |
| 1832 | 1805 | } else if (mem.cutPrefix(u8, arg, "-L")) |rest| { |
| ... | ... | @@ -3729,13 +3702,7 @@ fn buildOutputType( |
| 3729 | 3702 | .libc_installation = if (create_module.libc_installation) |*lci| lci else null, |
| 3730 | 3703 | .verbose_cc = verbose_cc, |
| 3731 | 3704 | .verbose_link = verbose_link, |
| 3732 | .verbose_air = verbose_air, | |
| 3733 | .verbose_intern_pool = verbose_intern_pool, | |
| 3734 | .verbose_generic_instances = verbose_generic_instances, | |
| 3735 | .verbose_llvm_ir = verbose_llvm_ir, | |
| 3736 | .verbose_llvm_bc = verbose_llvm_bc, | |
| 3737 | 3705 | .link_depfile = link_depfile, |
| 3738 | .verbose_llvm_cpu_features = verbose_llvm_cpu_features, | |
| 3739 | 3706 | .time_report = time_report, |
| 3740 | 3707 | .stack_report = stack_report, |
| 3741 | 3708 | .build_id = build_id, |
| ... | ... | @@ -3956,10 +3923,10 @@ fn buildOutputType( |
| 3956 | 3923 | }); |
| 3957 | 3924 | } |
| 3958 | 3925 | |
| 3959 | try test_exec_args.ensureUnusedCapacity(arena, 2 * log_scopes.items.len + @intFromBool(verbose_link) + @intFromBool(verbose_cc)); | |
| 3960 | for (log_scopes.items) |log_scope| test_exec_args.appendSliceAssumeCapacity(&.{ "--debug-log", log_scope }); | |
| 3961 | if (verbose_link) test_exec_args.appendAssumeCapacity("--verbose-link"); | |
| 3926 | try test_exec_args.ensureUnusedCapacity(arena, 2 * log_scopes.count() + @intFromBool(verbose_link) + @intFromBool(verbose_cc)); | |
| 3927 | for (log_scopes.keys()) |log_scope| test_exec_args.appendSliceAssumeCapacity(&.{ "--debug-log", log_scope }); | |
| 3962 | 3928 | if (verbose_cc) test_exec_args.appendAssumeCapacity("--verbose-cc"); |
| 3929 | if (verbose_link) test_exec_args.appendAssumeCapacity("--verbose-link"); | |
| 3963 | 3930 | } |
| 3964 | 3931 | |
| 3965 | 3932 | try runOrTest( |
| ... | ... | @@ -5627,17 +5594,17 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map: |
| 5627 | 5594 | } |
| 5628 | 5595 | } |
| 5629 | 5596 | |
| 5630 | const display_path = zig_source_path orelse "<stdin>"; | |
| 5597 | const print_path = zig_source_path orelse "<stdin>"; | |
| 5631 | 5598 | const source: [:0]const u8 = s: { |
| 5632 | 5599 | var f = if (zig_source_path) |p| file: { |
| 5633 | 5600 | break :file Io.Dir.cwd().openFile(io, p, .{}) catch |err| { |
| 5634 | fatal("unable to open file {q} for ast-check: {t}", .{ display_path, err }); | |
| 5601 | fatal("unable to open file {q} for ast-check: {t}", .{ print_path, err }); | |
| 5635 | 5602 | }; |
| 5636 | 5603 | } else Io.File.stdin(); |
| 5637 | 5604 | defer if (zig_source_path != null) f.close(io); |
| 5638 | 5605 | var file_reader: Io.File.Reader = f.reader(io, &stdin_buffer); |
| 5639 | 5606 | break :s std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| { |
| 5640 | fatal("unable to load file {q} for ast-check: {t}", .{ display_path, err }); | |
| 5607 | fatal("unable to load file {q} for ast-check: {t}", .{ print_path, err }); | |
| 5641 | 5608 | }; |
| 5642 | 5609 | }; |
| 5643 | 5610 | |
| ... | ... | @@ -5661,7 +5628,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map: |
| 5661 | 5628 | |
| 5662 | 5629 | if (zir.hasCompileErrors()) { |
| 5663 | 5630 | var wip_errors: std.zig.ErrorBundle.Wip = try .init(arena); |
| 5664 | try wip_errors.addZirErrorMessages(zir, tree, source, display_path); | |
| 5631 | try wip_errors.addZirErrorMessages(zir, tree, source, print_path); | |
| 5665 | 5632 | var error_bundle = try wip_errors.toOwnedBundle(""); |
| 5666 | 5633 | try error_bundle.renderToStderr(io, .{}, color); |
| 5667 | 5634 | if (zir.loweringFailed()) { |
| ... | ... | @@ -5731,7 +5698,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map: |
| 5731 | 5698 | const zoir = try ZonGen.generate(arena, tree, .{}); |
| 5732 | 5699 | if (zoir.hasCompileErrors()) { |
| 5733 | 5700 | var wip_errors: std.zig.ErrorBundle.Wip = try .init(arena); |
| 5734 | try wip_errors.addZoirErrorMessages(zoir, tree, source, display_path); | |
| 5701 | try wip_errors.addZoirErrorMessages(zoir, tree, source, print_path); | |
| 5735 | 5702 | var error_bundle = try wip_errors.toOwnedBundle(""); |
| 5736 | 5703 | error_bundle.renderToStderr(io, .{}, color) catch {}; |
| 5737 | 5704 | process.exit(1); |
| ... | ... | @@ -6254,9 +6221,8 @@ fn randInt(io: Io, comptime T: type) T { |
| 6254 | 6221 | } |
| 6255 | 6222 | |
| 6256 | 6223 | fn addDebugLog(arena: Allocator, scope_name: []const u8) error{OutOfMemory}!void { |
| 6257 | if (!build_options.enable_logging) { | |
| 6258 | warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); | |
| 6259 | } else { | |
| 6260 | try log_scopes.append(arena, scope_name); | |
| 6224 | switch (build_options.log_level) { | |
| 6225 | else => warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}), | |
| 6226 | .debug => try log_scopes.put(arena, try arena.dupe(u8, scope_name), {}), | |
| 6261 | 6227 | } |
| 6262 | 6228 | } |
src/target.zig+2| ... | ... | @@ -193,6 +193,8 @@ pub fn hasLlvmSupport(target: *const std.Target, ofmt: std.Target.ObjectFormat) |
| 193 | 193 | .coff, |
| 194 | 194 | .elf, |
| 195 | 195 | .hex, |
| 196 | .llvmbc, | |
| 197 | .llvmir, | |
| 196 | 198 | .macho, |
| 197 | 199 | .spirv, |
| 198 | 200 | .raw, |
src/zig_llvm.cpp+5-3| ... | ... | @@ -410,6 +410,10 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi |
| 410 | 410 | // Code generation phase |
| 411 | 411 | codegen_pm.run(llvm_module); |
| 412 | 412 | |
| 413 | if (options->llvm_ir_out != nullptr) { | |
| 414 | *options->llvm_ir_out = LLVMPrintModuleToString(module_ref); | |
| 415 | } | |
| 416 | ||
| 413 | 417 | if (options->llvm_ir_filename) { |
| 414 | 418 | if (LLVMPrintModuleToFile(module_ref, options->llvm_ir_filename, error_message)) { |
| 415 | 419 | return true; |
| ... | ... | @@ -430,9 +434,7 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi |
| 430 | 434 | auto os = raw_string_ostream(out_str); |
| 431 | 435 | TimerGroup::printAll(os); |
| 432 | 436 | TimerGroup::clearAll(); |
| 433 | auto c_str = (char *)malloc(out_str.length() + 1); | |
| 434 | strcpy(c_str, out_str.c_str()); | |
| 435 | *options->time_report_out = c_str; | |
| 437 | *options->time_report_out = LLVMCreateMessage(out_str.c_str()); | |
| 436 | 438 | } |
| 437 | 439 | return false; |
| 438 | 440 | } |
src/zig_llvm.h+6-2| ... | ... | @@ -67,8 +67,8 @@ struct ZigLLVMEmitOptions { |
| 67 | 67 | bool is_debug; |
| 68 | 68 | bool is_small; |
| 69 | 69 | // If not null, and `ZigLLVMTargetMachineEmitToFile` returns `false` indicating success, this |
| 70 | // `char *` will be populated with a `malloc`-allocated string containing the serialized (as | |
| 71 | // JSON) time report data. The caller is responsible for freeing that memory. | |
| 70 | // `char *` will be populated with the serialized (as JSON) time report data. The caller is | |
| 71 | // responsible for freeing that memory with `disposeMessage`. | |
| 72 | 72 | char **time_report_out; |
| 73 | 73 | bool tsan; |
| 74 | 74 | bool sancov; |
| ... | ... | @@ -79,6 +79,10 @@ struct ZigLLVMEmitOptions { |
| 79 | 79 | const char *bin_filename; |
| 80 | 80 | const char *llvm_ir_filename; |
| 81 | 81 | const char *bitcode_filename; |
| 82 | // If not null and `ZigLLVMTargetMachineEmitToFile` returns `false` indicating success, this | |
| 83 | // `char *` will be populated with the optimized LLVM IR. The caller is responsible for freeing | |
| 84 | // this memory with `disposeMessage`. | |
| 85 | char **llvm_ir_out; | |
| 82 | 86 | ZigLLVMCoverageOptions coverage; |
| 83 | 87 | }; |
| 84 | 88 |
stage1/config.zig.in+1-1| ... | ... | @@ -6,7 +6,7 @@ pub const llvm_has_xtensa = false; |
| 6 | 6 | pub const version: [:0]const u8 = "@RESOLVED_ZIG_VERSION@"; |
| 7 | 7 | pub const semver = @import("std").SemanticVersion.parse(version) catch unreachable; |
| 8 | 8 | pub const enable_debug_extensions = false; |
| 9 | pub const enable_logging = false; | |
| 9 | pub const log_level: @import("std").log.Level = .err; | |
| 10 | 10 | pub const enable_link_snapshots = false; |
| 11 | 11 | pub const enable_tracy = false; |
| 12 | 12 | pub const value_tracing = false; |