| 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,7 +330,7 @@ set(ZIG_STAGE2_SOURCES |
| 330 | src/Air/Legalize.zig | 330 | src/Air/Legalize.zig |
| 331 | src/Air/Liveness.zig | 331 | src/Air/Liveness.zig |
| 332 | src/Air/Liveness/Verify.zig | 332 | src/Air/Liveness/Verify.zig |
| 333 | src/Air/print.zig | 333 | src/Air/Print.zig |
| 334 | src/Builtin.zig | 334 | src/Builtin.zig |
| 335 | src/Compilation.zig | 335 | src/Compilation.zig |
| 336 | src/Compilation/Config.zig | 336 | src/Compilation/Config.zig |
bootstrap.c+1-1| ... | @@ -179,7 +179,7 @@ int main(int argc, char **argv) { | ... | @@ -179,7 +179,7 @@ int main(int argc, char **argv) { |
| 179 | "pub const version: [:0]const u8 = \"%s\";\n" | 179 | "pub const version: [:0]const u8 = \"%s\";\n" |
| 180 | "pub const semver = @import(\"std\").SemanticVersion.parse(version) catch unreachable;\n" | 180 | "pub const semver = @import(\"std\").SemanticVersion.parse(version) catch unreachable;\n" |
| 181 | "pub const enable_debug_extensions = false;\n" | 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 | "pub const enable_link_snapshots = false;\n" | 183 | "pub const enable_link_snapshots = false;\n" |
| 184 | "pub const enable_tracy = false;\n" | 184 | "pub const enable_tracy = false;\n" |
| 185 | "pub const value_tracing = false;\n" | 185 | "pub const value_tracing = false;\n" |
build.zig+17-7| ... | @@ -25,6 +25,10 @@ pub fn build(b: *std.Build) !void { | ... | @@ -25,6 +25,10 @@ pub fn build(b: *std.Build) !void { |
| 25 | }, | 25 | }, |
| 26 | }); | 26 | }); |
| 27 | const optimize = b.standardOptimizeOption(.{}); | 27 | const optimize = b.standardOptimizeOption(.{}); |
| 28 | const is_debug = switch (optimize) { | ||
| 29 | .debug => true, | ||
| 30 | .safe, .fast, .small => false, | ||
| 31 | }; | ||
| 28 | 32 | ||
| 29 | 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; | 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 | const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode"); | 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,9 +209,9 @@ pub fn build(b: *std.Build) !void { |
| 205 | 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; | 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 | 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: { | 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); | 212 | if (strip == true) break :blk 0; |
| 209 | if (optimize != .debug) break :blk 0; | 213 | if (is_debug) break :blk 4; |
| 210 | break :blk 4; | 214 | break :blk 0; |
| 211 | }; | 215 | }; |
| 212 | 216 | ||
| 213 | const exe = addCompilerStep(b, .{ | 217 | const exe = addCompilerStep(b, .{ |
| ... | @@ -255,9 +259,15 @@ pub fn build(b: *std.Build) !void { | ... | @@ -255,9 +259,15 @@ pub fn build(b: *std.Build) !void { |
| 255 | exe.root_module.link_libc = true; | 259 | exe.root_module.link_libc = true; |
| 256 | } | 260 | } |
| 257 | 261 | ||
| 258 | const is_debug = optimize == .debug; | ||
| 259 | const enable_debug_extensions = b.option(bool, "debug-extensions", "Enable commands and options useful for debugging the compiler") orelse is_debug; | 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 | const opt_version_string = b.option([]const u8, "version-string", "Override Zig version string. Default is to find out with git."); | 272 | const opt_version_string = b.option([]const u8, "version-string", "Override Zig version string. Default is to find out with git."); |
| 263 | const version_slice = if (opt_version_string) |version| version else v: { | 273 | const version_slice = if (opt_version_string) |version| version else v: { |
| ... | @@ -398,7 +408,7 @@ pub fn build(b: *std.Build) !void { | ... | @@ -398,7 +408,7 @@ pub fn build(b: *std.Build) !void { |
| 398 | exe_options.addOption(std.SemanticVersion, "semver", semver); | 408 | exe_options.addOption(std.SemanticVersion, "semver", semver); |
| 399 | 409 | ||
| 400 | exe_options.addOption(bool, "enable_debug_extensions", enable_debug_extensions); | 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 | exe_options.addOption(bool, "enable_tracy", tracy != null); | 412 | exe_options.addOption(bool, "enable_tracy", tracy != null); |
| 403 | exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack); | 413 | exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack); |
| 404 | exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation); | 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,7 +847,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { |
| 837 | exe_options.addOption([:0]const u8, "version", version); | 847 | exe_options.addOption([:0]const u8, "version", version); |
| 838 | exe_options.addOption(std.SemanticVersion, "semver", semver); | 848 | exe_options.addOption(std.SemanticVersion, "semver", semver); |
| 839 | exe_options.addOption(bool, "enable_debug_extensions", false); | 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 | exe_options.addOption(bool, "enable_tracy", false); | 851 | exe_options.addOption(bool, "enable_tracy", false); |
| 842 | exe_options.addOption(bool, "enable_tracy_callstack", false); | 852 | exe_options.addOption(bool, "enable_tracy_callstack", false); |
| 843 | exe_options.addOption(bool, "enable_tracy_allocation", false); | 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,14 +509,10 @@ pub fn main(init: process.Init.Minimal) !void { |
| 509 | } else if (mem.eql(u8, arg, "--libc-runtimes") or mem.eql(u8, arg, "--glibc-runtimes")) { | 509 | } else if (mem.eql(u8, arg, "--libc-runtimes") or mem.eql(u8, arg, "--glibc-runtimes")) { |
| 510 | // --glibc-runtimes was the old name of the flag; kept for compatibility for now. | 510 | // --glibc-runtimes was the old name of the flag; kept for compatibility for now. |
| 511 | graph.libc_runtimes_dir = nextArgOrFatal(args, &arg_i); | 511 | graph.libc_runtimes_dir = nextArgOrFatal(args, &arg_i); |
| 512 | } else if (mem.eql(u8, arg, "--verbose-air")) { | ||
| 513 | graph.verbose_air = true; | ||
| 514 | } else if (mem.eql(u8, arg, "--verbose-cc")) { | 512 | } else if (mem.eql(u8, arg, "--verbose-cc")) { |
| 515 | graph.verbose_cc = true; | 513 | graph.verbose_cc = true; |
| 516 | } else if (mem.eql(u8, arg, "--verbose-link")) { | 514 | } else if (mem.eql(u8, arg, "--verbose-link")) { |
| 517 | graph.verbose_link = true; | 515 | graph.verbose_link = true; |
| 518 | } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { | ||
| 519 | graph.verbose_llvm_ir = true; | ||
| 520 | } else if (mem.eql(u8, arg, "--watch")) { | 516 | } else if (mem.eql(u8, arg, "--watch")) { |
| 521 | watch_flag = true; | 517 | watch_flag = true; |
| 522 | } else if (mem.eql(u8, arg, "--time-report")) { | 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,11 +32,8 @@ debug_compile_errors: bool = false, |
| 32 | debug_incremental: bool = false, | 32 | debug_incremental: bool = false, |
| 33 | fuzzing: bool = false, | 33 | fuzzing: bool = false, |
| 34 | verbose: bool = false, | 34 | verbose: bool = false, |
| 35 | verbose_air: bool = false, | ||
| 36 | verbose_cc: bool = false, | 35 | verbose_cc: bool = false, |
| 37 | verbose_link: bool = false, | 36 | verbose_link: bool = false, |
| 38 | verbose_llvm_cpu_features: bool = false, | ||
| 39 | verbose_llvm_ir: bool = false, | ||
| 40 | libc_file: ?[]const u8 = null, | 37 | libc_file: ?[]const u8 = null, |
| 41 | /// What does this do? Nobody bothered to document it, and I think it's a | 38 | /// What does this do? Nobody bothered to document it, and I think it's a |
| 42 | /// smelly option. So unless somebody deletes these passive aggressive comments | 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,6 +351,8 @@ const general_usage = |
| 351 | \\ preferred optimization mode: fast, safe, small | 351 | \\ preferred optimization mode: fast, safe, small |
| 352 | \\ | 352 | \\ |
| 353 | \\ --verbose Print commands before executing them | 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 | \\ --color [auto|off|on] Enable or disable colored error messages | 356 | \\ --color [auto|off|on] Enable or disable colored error messages |
| 355 | \\ --error-style [style] Control how build errors are printed | 357 | \\ --error-style [style] Control how build errors are printed |
| 356 | \\ verbose (Default) Report errors with full context | 358 | \\ verbose (Default) Report errors with full context |
| ... | @@ -417,11 +419,5 @@ const general_usage = | ... | @@ -417,11 +419,5 @@ const general_usage = |
| 417 | \\ none (default) No build ID | 419 | \\ none (default) No build ID |
| 418 | \\ --debug-log [scope] Enable debugging the compiler | 420 | \\ --debug-log [scope] Enable debugging the compiler |
| 419 | \\ --debug-pkg-config Fail if unknown pkg-config flags encountered | 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,11 +608,8 @@ fn lowerZigArgs( |
| 608 | 608 | ||
| 609 | try addBool(gpa, zig_args, "--debug-compile-errors", graph.debug_compile_errors); | 609 | try addBool(gpa, zig_args, "--debug-compile-errors", graph.debug_compile_errors); |
| 610 | try addBool(gpa, zig_args, "--debug-incremental", graph.debug_incremental); | 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 | try addBool(gpa, zig_args, "--verbose-cc", graph.verbose_cc or conf_comp.flags.verbose_cc); | 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 | try addBool(gpa, zig_args, "--time-report", graph.time_report); | 613 | try addBool(gpa, zig_args, "--time-report", graph.time_report); |
| 617 | 614 | ||
| 618 | if (conf_comp.generated_bin.value == null) try zig_args.append(gpa, "-fno-emit-bin"); | 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,7 +927,7 @@ pub fn parseArgs( |
| 927 | break :debug switch (d.comp.target.ofmt) { | 927 | break :debug switch (d.comp.target.ofmt) { |
| 928 | .elf, .macho, .wasm => .{ .dwarf = .@"32" }, | 928 | .elf, .macho, .wasm => .{ .dwarf = .@"32" }, |
| 929 | .coff => .code_view, | 929 | .coff => .code_view, |
| 930 | .c => switch (d.comp.target.os.tag) { | 930 | .c, .llvmbc, .llvmir => switch (d.comp.target.os.tag) { |
| 931 | .windows, .uefi => .code_view, | 931 | .windows, .uefi => .code_view, |
| 932 | else => .{ .dwarf = .@"32" }, | 932 | else => .{ .dwarf = .@"32" }, |
| 933 | }, | 933 | }, |
lib/std/Build/Configuration.zig+2| ... | @@ -2519,6 +2519,8 @@ pub const TargetQuery = struct { | ... | @@ -2519,6 +2519,8 @@ pub const TargetQuery = struct { |
| 2519 | coff, | 2519 | coff, |
| 2520 | elf, | 2520 | elf, |
| 2521 | hex, | 2521 | hex, |
| 2522 | llvmbc, | ||
| 2523 | llvmir, | ||
| 2522 | macho, | 2524 | macho, |
| 2523 | plan9, | 2525 | plan9, |
| 2524 | raw, | 2526 | raw, |
lib/std/Target.zig+6| ... | @@ -1043,6 +1043,10 @@ pub const ObjectFormat = enum { | ... | @@ -1043,6 +1043,10 @@ pub const ObjectFormat = enum { |
| 1043 | elf, | 1043 | elf, |
| 1044 | /// The Intel HEX format for storing binary code in ASCII text. | 1044 | /// The Intel HEX format for storing binary code in ASCII text. |
| 1045 | hex, | 1045 | hex, |
| 1046 | /// LLVM binary intermediate representation. | ||
| 1047 | llvmbc, | ||
| 1048 | /// LLVM text intermediate representation. | ||
| 1049 | llvmir, | ||
| 1046 | /// The Mach object format used by macOS and other Apple platforms. | 1050 | /// The Mach object format used by macOS and other Apple platforms. |
| 1047 | macho, | 1051 | macho, |
| 1048 | /// The a.out format used by Plan 9 from Bell Labs. | 1052 | /// The a.out format used by Plan 9 from Bell Labs. |
| ... | @@ -1060,6 +1064,8 @@ pub const ObjectFormat = enum { | ... | @@ -1060,6 +1064,8 @@ pub const ObjectFormat = enum { |
| 1060 | .coff => ".obj", | 1064 | .coff => ".obj", |
| 1061 | .elf, .macho, .wasm => ".o", | 1065 | .elf, .macho, .wasm => ".o", |
| 1062 | .hex => ".ihex", | 1066 | .hex => ".ihex", |
| 1067 | .llvmbc => ".bc", | ||
| 1068 | .llvmir => ".ll", | ||
| 1063 | .plan9 => arch.plan9Ext(), | 1069 | .plan9 => arch.plan9Ext(), |
| 1064 | .raw => ".bin", | 1070 | .raw => ".bin", |
| 1065 | .spirv => ".spv", | 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,7 +76,7 @@ pub fn TargetInfo(os: std.Target.Os.Tag, arch: std.Target.Cpu.Arch) type { |
| 76 | }, | 76 | }, |
| 77 | .macho => @import("debug/SelfInfo/MachO.zig"), | 77 | .macho => @import("debug/SelfInfo/MachO.zig"), |
| 78 | .plan9, .spirv, .wasm, .raw, .hex => void, | 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,7 +285,13 @@ pub fn Alt( |
| 285 | pub fn alt( | 285 | pub fn alt( |
| 286 | context: anytype, | 286 | context: anytype, |
| 287 | comptime func_name: @EnumLiteral(), | 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 | return .{ .data = context }; | 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,6 +218,8 @@ pub fn binNameAlloc(allocator: Allocator, options: BinNameOptions) error{OutOfMe |
| 218 | }, | 218 | }, |
| 219 | .Obj => return std.fmt.allocPrint(allocator, "{s}.o", .{root_name}), | 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 | .macho => switch (options.output_mode) { | 223 | .macho => switch (options.output_mode) { |
| 222 | .Exe => return allocator.dupe(u8, root_name), | 224 | .Exe => return allocator.dupe(u8, root_name), |
| 223 | .Lib => { | 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,11 +10855,22 @@ pub fn resolveAlignmentForwardReference(b: *Builder, fwd_ref: Alignment.Lazy, va |
| 10855 | b.alignment_forward_references.items[index] = value; | 10855 | b.alignment_forward_references.items[index] = value; |
| 10856 | } | 10856 | } |
| 10857 | 10857 | ||
| 10858 | pub fn dump(b: *Builder, io: Io) void { | 10858 | pub const Print = struct { |
| 10859 | var buffer: [4000]u8 = undefined; | 10859 | name: []const u8, |
| 10860 | const stderr: Io.File = .stderr(); | 10860 | builder: *Builder, |
| 10861 | b.printToFile(io, stderr, &buffer) catch {}; | 10861 | err: ?Allocator.Error, |
| 10862 | } | 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 | pub fn printToFilePath(b: *Builder, io: Io, dir: Io.Dir, path: []const u8) !void { | 10875 | pub fn printToFilePath(b: *Builder, io: Io, dir: Io.Dir, path: []const u8) !void { |
| 10865 | var buffer: [4000]u8 = undefined; | 10876 | var buffer: [4000]u8 = undefined; |
src/Air.zig+5-5| ... | @@ -13,10 +13,10 @@ const InternPool = @import("InternPool.zig"); | ... | @@ -13,10 +13,10 @@ const InternPool = @import("InternPool.zig"); |
| 13 | const Type = @import("Type.zig"); | 13 | const Type = @import("Type.zig"); |
| 14 | const Value = @import("Value.zig"); | 14 | const Value = @import("Value.zig"); |
| 15 | const Zcu = @import("Zcu.zig"); | 15 | const Zcu = @import("Zcu.zig"); |
| 16 | const print = @import("Air/print.zig"); | ||
| 17 | 16 | ||
| 18 | pub const Legalize = @import("Air/Legalize.zig"); | 17 | pub const Legalize = @import("Air/Legalize.zig"); |
| 19 | pub const Liveness = @import("Air/Liveness.zig"); | 18 | pub const Liveness = @import("Air/Liveness.zig"); |
| 19 | pub const Print = @import("Air/Print.zig"); | ||
| 20 | pub const Verify = @import("Air/Verify.zig"); | 20 | pub const Verify = @import("Air/Verify.zig"); |
| 21 | 21 | ||
| 22 | instructions: std.MultiArrayList(Inst).Slice, | 22 | instructions: std.MultiArrayList(Inst).Slice, |
| ... | @@ -2517,10 +2517,10 @@ pub fn unwrapShuffleTwo(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index | ... | @@ -2517,10 +2517,10 @@ pub fn unwrapShuffleTwo(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index |
| 2517 | } | 2517 | } |
| 2518 | 2518 | ||
| 2519 | pub const legalize = Legalize.legalize; | 2519 | pub const legalize = Legalize.legalize; |
| 2520 | pub const write = print.write; | 2520 | pub const write = Print.write; |
| 2521 | pub const writeInst = print.writeInst; | 2521 | pub const writeInst = Print.writeInst; |
| 2522 | pub const dump = print.dump; | 2522 | pub const dump = Print.dump; |
| 2523 | pub const dumpInst = print.dumpInst; | 2523 | pub const dumpInst = Print.dumpInst; |
| 2524 | 2524 | ||
| 2525 | pub const CoveragePoint = enum(u1) { | 2525 | pub const CoveragePoint = enum(u1) { |
| 2526 | /// Indicates the block is not a place of interest corresponding to | 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,6 +20,7 @@ const link = @import("link.zig"); |
| 20 | const tracy = @import("tracy.zig"); | 20 | const tracy = @import("tracy.zig"); |
| 21 | const trace = tracy.trace; | 21 | const trace = tracy.trace; |
| 22 | const build_options = @import("build_options"); | 22 | const build_options = @import("build_options"); |
| 23 | const debugLogScopeEnabled = @import("main.zig").debugLogScopeEnabled; | ||
| 23 | const LibCInstallation = std.zig.LibCInstallation; | 24 | const LibCInstallation = std.zig.LibCInstallation; |
| 24 | const glibc = @import("libs/glibc.zig"); | 25 | const glibc = @import("libs/glibc.zig"); |
| 25 | const musl = @import("libs/musl.zig"); | 26 | const musl = @import("libs/musl.zig"); |
| ... | @@ -161,12 +162,6 @@ clang_passthrough_mode: bool, | ... | @@ -161,12 +162,6 @@ clang_passthrough_mode: bool, |
| 161 | clang_preprocessor_mode: ClangPreprocessorMode, | 162 | clang_preprocessor_mode: ClangPreprocessorMode, |
| 162 | /// Whether to print clang argvs to stdout. | 163 | /// Whether to print clang argvs to stdout. |
| 163 | verbose_cc: bool, | 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 | verbose_link: bool, | 165 | verbose_link: bool, |
| 171 | link_depfile: ?[]const u8, | 166 | link_depfile: ?[]const u8, |
| 172 | disable_c_depfile: bool, | 167 | disable_c_depfile: bool, |
| ... | @@ -1544,13 +1539,7 @@ pub const CreateOptions = struct { | ... | @@ -1544,13 +1539,7 @@ pub const CreateOptions = struct { |
| 1544 | clang_passthrough_mode: bool = false, | 1539 | clang_passthrough_mode: bool = false, |
| 1545 | verbose_cc: bool = false, | 1540 | verbose_cc: bool = false, |
| 1546 | verbose_link: bool = false, | 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 | link_depfile: ?[]const u8 = null, | 1542 | link_depfile: ?[]const u8 = null, |
| 1553 | verbose_llvm_cpu_features: bool = false, | ||
| 1554 | debug_compiler_runtime_libs: ?std.lang.Optimize = null, | 1543 | debug_compiler_runtime_libs: ?std.lang.Optimize = null, |
| 1555 | debug_compile_errors: bool = false, | 1544 | debug_compile_errors: bool = false, |
| 1556 | debug_incremental: bool = false, | 1545 | debug_incremental: bool = false, |
| ... | @@ -1932,21 +1921,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, | ... | @@ -1932,21 +1921,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 1932 | try options.root_mod.deps.putNoClobber(arena, "zigc", zigc_mod); | 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 | const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1); | 1924 | const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1); |
| 1951 | const main_mod = options.main_mod orelse options.root_mod; | 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,14 +2085,8 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2111 | .clang_passthrough_mode = options.clang_passthrough_mode, | 2085 | .clang_passthrough_mode = options.clang_passthrough_mode, |
| 2112 | .clang_preprocessor_mode = options.clang_preprocessor_mode, | 2086 | .clang_preprocessor_mode = options.clang_preprocessor_mode, |
| 2113 | .verbose_cc = options.verbose_cc, | 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 | .verbose_link = options.verbose_link, | 2088 | .verbose_link = options.verbose_link, |
| 2089 | .link_depfile = options.link_depfile, | ||
| 2122 | .disable_c_depfile = options.disable_c_depfile, | 2090 | .disable_c_depfile = options.disable_c_depfile, |
| 2123 | .reference_trace = options.reference_trace, | 2091 | .reference_trace = options.reference_trace, |
| 2124 | .time_report = if (options.time_report) .init else null, | 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,8 +2321,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2353 | comp.emit_asm != null or | 2321 | comp.emit_asm != null or |
| 2354 | comp.emit_llvm_ir != null or | 2322 | comp.emit_llvm_ir != null or |
| 2355 | comp.emit_llvm_bc != null or | 2323 | comp.emit_llvm_bc != null or |
| 2356 | comp.verbose_llvm_ir != null or | 2324 | log_llvm_ir: { |
| 2357 | comp.verbose_llvm_bc != null)) | 2325 | break :log_llvm_ir debugLogScopeEnabled("llvm-ir") or debugLogScopeEnabled("opt-llvm-ir"); |
| 2326 | })) | ||
| 2358 | { | 2327 | { |
| 2359 | if (opt_zcu) |zcu| { | 2328 | if (opt_zcu) |zcu| { |
| 2360 | dev.check(.llvm_backend); | 2329 | dev.check(.llvm_backend); |
| ... | @@ -2566,19 +2535,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, | ... | @@ -2566,19 +2535,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2566 | return comp; | 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 | pub fn destroy(comp: *Compilation) void { | 2538 | pub fn destroy(comp: *Compilation) void { |
| 2583 | const gpa = comp.gpa; | 2539 | const gpa = comp.gpa; |
| 2584 | const io = comp.io; | 2540 | const io = comp.io; |
| ... | @@ -2991,14 +2947,19 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE | ... | @@ -2991,14 +2947,19 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 2991 | try pt.processExports(); | 2947 | try pt.processExports(); |
| 2992 | } | 2948 | } |
| 2993 | 2949 | ||
| 2994 | if (build_options.enable_debug_extensions and comp.verbose_intern_pool) { | 2950 | { |
| 2995 | std.debug.print("intern pool stats for {q}:\n", .{comp.root_name}); | 2951 | var d: InternPool.Dump = .{ |
| 2996 | zcu.intern_pool.dump(); | 2952 | .name = comp.root_name, |
| 2997 | } | 2953 | .arena = arena, |
| 2998 | 2954 | .ip = &zcu.intern_pool, | |
| 2999 | if (build_options.enable_debug_extensions and comp.verbose_generic_instances) { | 2955 | .err = null, |
| 3000 | std.debug.print("generic instances for '{s}:0x{x}':\n", .{ comp.root_name, @intFromPtr(zcu) }); | 2956 | }; |
| 3001 | zcu.intern_pool.dumpGenericInstances(gpa); | 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,28 +3181,29 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error |
| 3220 | comp.time_report.?.stats.real_ns_llvm_emit = ns; | 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: { | 3184 | const zcu_obj_path: ?Cache.Path = switch (comp.getTarget().ofmt) { |
| 3224 | break :p try comp.resolveEmitPathFlush(arena, .temp, llvm_object.out_bin_basename); | 3185 | .llvmbc, .llvmir => null, |
| 3225 | } else 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 | const active = zcu.activate(tid); | 3192 | const active = zcu.activate(tid); |
| 3228 | defer active.deactivate(); | 3193 | defer active.deactivate(); |
| 3229 | llvm_object.emit(active.pt, .{ | 3194 | llvm_object.emit(active.pt, .{ |
| 3230 | .pre_ir_path = comp.verbose_llvm_ir, | ||
| 3231 | .pre_bc_path = comp.verbose_llvm_bc, | ||
| 3232 | |||
| 3233 | .bin_path = if (zcu_obj_path) |p| try p.toStringZ(arena) else null, | 3195 | .bin_path = if (zcu_obj_path) |p| try p.toStringZ(arena) else null, |
| 3234 | .asm_path = p: { | 3196 | .asm_path = p: { |
| 3235 | const raw = comp.emit_asm orelse break :p null; | 3197 | const raw = comp.emit_asm orelse break :p null; |
| 3236 | const p = try comp.resolveEmitPathFlush(arena, .artifact, raw); | 3198 | const p = try comp.resolveEmitPathFlush(arena, .artifact, raw); |
| 3237 | break :p try p.toStringZ(arena); | 3199 | break :p try p.toStringZ(arena); |
| 3238 | }, | 3200 | }, |
| 3239 | .post_ir_path = p: { | 3201 | .opt_ir_path = p: { |
| 3240 | const raw = comp.emit_llvm_ir orelse break :p null; | 3202 | const raw = comp.emit_llvm_ir orelse break :p null; |
| 3241 | const p = try comp.resolveEmitPathFlush(arena, .artifact, raw); | 3203 | const p = try comp.resolveEmitPathFlush(arena, .artifact, raw); |
| 3242 | break :p try p.toStringZ(arena); | 3204 | break :p try p.toStringZ(arena); |
| 3243 | }, | 3205 | }, |
| 3244 | .post_bc_path = p: { | 3206 | .opt_bc_path = p: { |
| 3245 | const raw = comp.emit_llvm_bc orelse break :p null; | 3207 | const raw = comp.emit_llvm_bc orelse break :p null; |
| 3246 | const p = try comp.resolveEmitPathFlush(arena, .artifact, raw); | 3208 | const p = try comp.resolveEmitPathFlush(arena, .artifact, raw); |
| 3247 | break :p try p.toStringZ(arena); | 3209 | break :p try p.toStringZ(arena); |
| ... | @@ -3267,7 +3229,7 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error | ... | @@ -3267,7 +3229,7 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error |
| 3267 | error.Canceled, error.OutOfMemory => |e| return e, | 3229 | error.Canceled, error.OutOfMemory => |e| return e, |
| 3268 | error.AlreadyReported => return, | 3230 | error.AlreadyReported => return, |
| 3269 | }; | 3231 | }; |
| 3270 | } | 3232 | } else return; |
| 3271 | } | 3233 | } |
| 3272 | } | 3234 | } |
| 3273 | if (comp.bin_file) |lf| { | 3235 | if (comp.bin_file) |lf| { |
| ... | @@ -4903,12 +4865,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU | ... | @@ -4903,12 +4865,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU |
| 4903 | .emit_bin = .yes_cache, | 4865 | .emit_bin = .yes_cache, |
| 4904 | .verbose_cc = comp.verbose_cc, | 4866 | .verbose_cc = comp.verbose_cc, |
| 4905 | .verbose_link = comp.verbose_link, | 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 | .environ_map = comp.environ_map, | 4868 | .environ_map = comp.environ_map, |
| 4913 | }) catch |err| switch (err) { | 4869 | }) catch |err| switch (err) { |
| 4914 | error.CreateFail => { | 4870 | error.CreateFail => { |
| ... | @@ -7415,12 +7371,6 @@ fn buildOutputFromZig( | ... | @@ -7415,12 +7371,6 @@ fn buildOutputFromZig( |
| 7415 | .data_sections = true, | 7371 | .data_sections = true, |
| 7416 | .verbose_cc = comp.verbose_cc, | 7372 | .verbose_cc = comp.verbose_cc, |
| 7417 | .verbose_link = comp.verbose_link, | 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 | .clang_passthrough_mode = comp.clang_passthrough_mode, | 7374 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 7425 | .skip_linker_dependencies = true, | 7375 | .skip_linker_dependencies = true, |
| 7426 | .environ_map = comp.environ_map, | 7376 | .environ_map = comp.environ_map, |
| ... | @@ -7552,12 +7502,6 @@ pub fn build_crt_file( | ... | @@ -7552,12 +7502,6 @@ pub fn build_crt_file( |
| 7552 | .c_source_files = c_source_files, | 7502 | .c_source_files = c_source_files, |
| 7553 | .verbose_cc = comp.verbose_cc, | 7503 | .verbose_cc = comp.verbose_cc, |
| 7554 | .verbose_link = comp.verbose_link, | 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 | .clang_passthrough_mode = comp.clang_passthrough_mode, | 7505 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 7562 | .skip_linker_dependencies = true, | 7506 | .skip_linker_dependencies = true, |
| 7563 | .environ_map = comp.environ_map, | 7507 | .environ_map = comp.environ_map, |
src/Compilation/Config.zig+4-4| ... | @@ -190,7 +190,7 @@ pub fn resolve(options: Options) ResolveError!Config { | ... | @@ -190,7 +190,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 190 | // *If* the LLVM backend were to be selected, should Zig use the LLVM | 190 | // *If* the LLVM backend were to be selected, should Zig use the LLVM |
| 191 | // library to build the LLVM module? | 191 | // library to build the LLVM module? |
| 192 | const use_lib_llvm = b: { | 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 | if (options.use_lib_llvm == true) return error.LlvmLibraryUnavailable; | 194 | if (options.use_lib_llvm == true) return error.LlvmLibraryUnavailable; |
| 195 | break :b false; | 195 | break :b false; |
| 196 | } | 196 | } |
| ... | @@ -324,7 +324,7 @@ pub fn resolve(options: Options) ResolveError!Config { | ... | @@ -324,7 +324,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 324 | if (!options.have_zcu) break :b false; | 324 | if (!options.have_zcu) break :b false; |
| 325 | 325 | ||
| 326 | // If emitting to LLVM bitcode object format, must use LLVM backend. | 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 | if (options.use_llvm == false) | 328 | if (options.use_llvm == false) |
| 329 | return error.EmittingLlvmModuleRequiresLlvmBackend; | 329 | return error.EmittingLlvmModuleRequiresLlvmBackend; |
| 330 | if (!target_util.hasLlvmSupport(target, target.ofmt)) | 330 | if (!target_util.hasLlvmSupport(target, target.ofmt)) |
| ... | @@ -379,7 +379,7 @@ pub fn resolve(options: Options) ResolveError!Config { | ... | @@ -379,7 +379,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 379 | const backend = target_util.zigBackend(target, use_llvm); | 379 | const backend = target_util.zigBackend(target, use_llvm); |
| 380 | 380 | ||
| 381 | if (options.emit_bin and options.have_zcu) { | 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 | // Explicit request to use LLVM to produce an object file, but without | 383 | // Explicit request to use LLVM to produce an object file, but without |
| 384 | // using LLVM libraries. Impossible. | 384 | // using LLVM libraries. Impossible. |
| 385 | return error.EmittingBinaryRequiresLlvmLibrary; | 385 | return error.EmittingBinaryRequiresLlvmLibrary; |
| ... | @@ -513,7 +513,7 @@ pub fn resolve(options: Options) ResolveError!Config { | ... | @@ -513,7 +513,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 513 | break :b switch (target.ofmt) { | 513 | break :b switch (target.ofmt) { |
| 514 | .elf, .macho, .wasm => .{ .dwarf = .@"32" }, | 514 | .elf, .macho, .wasm => .{ .dwarf = .@"32" }, |
| 515 | .coff => .code_view, | 515 | .coff => .code_view, |
| 516 | .c => switch (target.os.tag) { | 516 | .c, .llvmbc, .llvmir => switch (target.os.tag) { |
| 517 | .windows, .uefi => .code_view, | 517 | .windows, .uefi => .code_view, |
| 518 | else => .{ .dwarf = .@"32" }, | 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,17 +10591,36 @@ pub fn errorUnionPayload(ip: *const InternPool, ty: Index) Index { |
| 10591 | return ip.indexToKey(ty).error_union_type.payload_type; | 10591 | return ip.indexToKey(ty).error_union_type.payload_type; |
| 10592 | } | 10592 | } |
| 10593 | 10593 | ||
| 10594 | pub fn dump(ip: *const InternPool) void { | 10594 | pub const Dump = struct { |
| 10595 | var buffer: [4096]u8 = undefined; | 10595 | name: []const u8, |
| 10596 | const stderr = std.debug.lockStderr(&buffer); | 10596 | arena: std.mem.Allocator, |
| 10597 | defer std.debug.unlockStderr(); | 10597 | ip: *const InternPool, |
| 10598 | const w = &stderr.file_writer.interface; | 10598 | err: ?Allocator.Error, |
| 10599 | dumpDependencyStatsFallible(ip, w) catch return; | 10599 | |
| 10600 | dumpStatsFallible(ip, w, std.heap.page_allocator) catch return; | 10600 | pub fn format(d: *Dump, w: *Io.Writer) Io.Writer.Error!void { |
| 10601 | dumpAllFallible(ip, w) catch return; | 10601 | try w.print("{q}:\n", .{d.name}); |
| 10602 | } | 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 | const dep_entries_len = ip.dep_entries.items.len - ip.free_dep_entries.items.len; | 10624 | const dep_entries_len = ip.dep_entries.items.len - ip.free_dep_entries.items.len; |
| 10606 | const src_hash_deps_len = ip.src_hash_deps.count(); | 10625 | const src_hash_deps_len = ip.src_hash_deps.count(); |
| 10607 | const nav_val_deps_len = ip.nav_val_deps.count(); | 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,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 | var items_len: usize = 0; | 10691 | var items_len: usize = 0; |
| 10673 | var extra_len: usize = 0; | 10692 | var extra_len: usize = 0; |
| 10674 | var limbs_len: usize = 0; | 10693 | var limbs_len: usize = 0; |
| ... | @@ -10968,7 +10987,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo | ... | @@ -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 | for (ip.locals, 0..) |*local, tid| { | 10991 | for (ip.locals, 0..) |*local, tid| { |
| 10973 | // Early check for length 0, because `view()` is invalid if capacity is 0 | 10992 | // Early check for length 0, because `view()` is invalid if capacity is 0 |
| 10974 | if (local.mutate.items.len == 0) continue; | 10993 | if (local.mutate.items.len == 0) continue; |
| ... | @@ -11071,21 +11090,10 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { | ... | @@ -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 { | 11093 | pub fn dumpGenericInstancesFallible(ip: *const InternPool, arena: Allocator, w: *Io.Writer) !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 | |||
| 11087 | var instances: std.array_hash_map.Auto(Index, std.ArrayList(Index)) = .empty; | 11094 | var instances: std.array_hash_map.Auto(Index, std.ArrayList(Index)) = .empty; |
| 11088 | for (ip.locals, 0..) |*local, tid| { | 11095 | for (ip.locals, 0..) |*local, tid| { |
| 11096 | if (local.mutate.items.len == 0) continue; | ||
| 11089 | const items = local.shared.items.view().slice(); | 11097 | const items = local.shared.items.view().slice(); |
| 11090 | const extra_list = local.shared.extra; | 11098 | const extra_list = local.shared.extra; |
| 11091 | for ( | 11099 | for ( |
src/Module.zig+8-11| ... | @@ -26,6 +26,7 @@ fully_qualified_name: []const u8, | ... | @@ -26,6 +26,7 @@ fully_qualified_name: []const u8, |
| 26 | deps: Deps = .{}, | 26 | deps: Deps = .{}, |
| 27 | 27 | ||
| 28 | resolved_target: ResolvedTarget, | 28 | resolved_target: ResolvedTarget, |
| 29 | llvm_cpu_features: ?[:0]const u8, | ||
| 29 | optimize_mode: std.lang.Optimize, | 30 | optimize_mode: std.lang.Optimize, |
| 30 | code_model: std.lang.CodeModel, | 31 | code_model: std.lang.CodeModel, |
| 31 | single_threaded: bool, | 32 | single_threaded: bool, |
| ... | @@ -94,7 +95,6 @@ pub const ResolvedTarget = struct { | ... | @@ -94,7 +95,6 @@ pub const ResolvedTarget = struct { |
| 94 | is_native_os: bool, | 95 | is_native_os: bool, |
| 95 | is_native_abi: bool, | 96 | is_native_abi: bool, |
| 96 | is_explicit_dynamic_linker: bool, | 97 | is_explicit_dynamic_linker: bool, |
| 97 | llvm_cpu_features: ?[*:0]const u8 = null, | ||
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| 100 | pub const CreateError = error{ | 100 | pub const CreateError = error{ |
| ... | @@ -362,15 +362,13 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { | ... | @@ -362,15 +362,13 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { |
| 362 | break :b 0; | 362 | break :b 0; |
| 363 | }; | 363 | }; |
| 364 | 364 | ||
| 365 | const llvm_cpu_features: ?[*:0]const u8 = b: { | 365 | const llvm_cpu_features: ?[:0]const u8 = b: { |
| 366 | if (resolved_target.llvm_cpu_features) |x| break :b x; | ||
| 367 | if (!options.global.use_llvm) break :b null; | 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 | var buf = std.array_list.Managed(u8).init(arena); | 370 | var buf = std.array_list.Managed(u8).init(arena); |
| 370 | var disabled_features = std.array_list.Managed(u8).init(arena); | 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 | for (target.cpu.arch.allFeaturesList()) |feature| { | 372 | for (target.cpu.arch.allFeaturesList()) |feature| { |
| 375 | if (feature.llvm_name) |llvm_name| { | 373 | if (feature.llvm_name) |llvm_name| { |
| 376 | // Ignore these until we figure out how to handle the concept of omitting features. | 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,10 +399,9 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { |
| 401 | 399 | ||
| 402 | try buf.appendSlice(disabled_features.items); | 400 | try buf.appendSlice(disabled_features.items); |
| 403 | if (buf.items.len == 0) break :b ""; | 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 | buf.items[buf.items.len - 1] = 0; | 403 | buf.items[buf.items.len - 1] = 0; |
| 406 | buf.shrinkAndFree(buf.items.len); | 404 | break :b buf.items[0 .. buf.items.len - 1 :0]; |
| 407 | break :b buf.items[0 .. buf.items.len - 1 :0].ptr; | ||
| 408 | }; | 405 | }; |
| 409 | 406 | ||
| 410 | const mod = try arena.create(Module); | 407 | const mod = try arena.create(Module); |
| ... | @@ -417,8 +414,8 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { | ... | @@ -417,8 +414,8 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { |
| 417 | .is_native_os = resolved_target.is_native_os, | 414 | .is_native_os = resolved_target.is_native_os, |
| 418 | .is_native_abi = resolved_target.is_native_abi, | 415 | .is_native_abi = resolved_target.is_native_abi, |
| 419 | .is_explicit_dynamic_linker = resolved_target.is_explicit_dynamic_linker, | 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 | .optimize_mode = optimize_mode, | 419 | .optimize_mode = optimize_mode, |
| 423 | .single_threaded = single_threaded, | 420 | .single_threaded = single_threaded, |
| 424 | .error_tracing = error_tracing, | 421 | .error_tracing = error_tracing, |
| ... | @@ -494,8 +491,8 @@ pub fn createBuiltin(arena: Allocator, opts: Builtin, dirs: std.zig.Directories) | ... | @@ -494,8 +491,8 @@ pub fn createBuiltin(arena: Allocator, opts: Builtin, dirs: std.zig.Directories) |
| 494 | .is_native_os = false, | 491 | .is_native_os = false, |
| 495 | .is_native_abi = false, | 492 | .is_native_abi = false, |
| 496 | .is_explicit_dynamic_linker = false, | 493 | .is_explicit_dynamic_linker = false, |
| 497 | .llvm_cpu_features = null, | ||
| 498 | }, | 494 | }, |
| 495 | .llvm_cpu_features = null, | ||
| 499 | .optimize_mode = opts.optimize_mode, | 496 | .optimize_mode = opts.optimize_mode, |
| 500 | .single_threaded = opts.single_threaded, | 497 | .single_threaded = opts.single_threaded, |
| 501 | .error_tracing = opts.error_tracing, | 498 | .error_tracing = opts.error_tracing, |
src/Sema.zig+3-5| ... | @@ -1126,6 +1126,8 @@ fn analyzeBodyInner( | ... | @@ -1126,6 +1126,8 @@ fn analyzeBodyInner( |
| 1126 | crash_info.push(sema, block, body); | 1126 | crash_info.push(sema, block, body); |
| 1127 | defer crash_info.pop(); | 1127 | defer crash_info.pop(); |
| 1128 | 1128 | ||
| 1129 | const path = zcu.namespacePtr(block.namespace).fileScope(zcu).path; | ||
| 1130 | |||
| 1129 | // We use a while (true) loop here to avoid a redundant way of breaking out of | 1131 | // We use a while (true) loop here to avoid a redundant way of breaking out of |
| 1130 | // the loop. The only way to break out of the loop is with a `noreturn` | 1132 | // the loop. The only way to break out of the loop is with a `noreturn` |
| 1131 | // instruction. | 1133 | // instruction. |
| ... | @@ -1134,11 +1136,7 @@ fn analyzeBodyInner( | ... | @@ -1134,11 +1136,7 @@ fn analyzeBodyInner( |
| 1134 | crash_info.setBodyIndex(i); | 1136 | crash_info.setBodyIndex(i); |
| 1135 | const inst = body[i]; | 1137 | const inst = body[i]; |
| 1136 | 1138 | ||
| 1137 | // This log is a bit expensive, and LLVM fails to optimize it away. | 1139 | std.log.scoped(.sema_zir).debug("sema ZIR {f} %{d}", .{ path.fmt(comp), inst }); |
| 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 | } | ||
| 1142 | 1140 | ||
| 1143 | const air_ref: Air.Inst.Ref = inst: switch (tags[@backingInt(inst)]) { | 1141 | const air_ref: Air.Inst.Ref = inst: switch (tags[@backingInt(inst)]) { |
| 1144 | // zig fmt: off | 1142 | // zig fmt: off |
src/Zcu/PerThread.zig+20-38| ... | @@ -25,6 +25,7 @@ const InternPool = @import("../InternPool.zig"); | ... | @@ -25,6 +25,7 @@ const InternPool = @import("../InternPool.zig"); |
| 25 | const AnalUnit = InternPool.AnalUnit; | 25 | const AnalUnit = InternPool.AnalUnit; |
| 26 | const Module = @import("../Module.zig"); | 26 | const Module = @import("../Module.zig"); |
| 27 | const Sema = @import("../Sema.zig"); | 27 | const Sema = @import("../Sema.zig"); |
| 28 | const debugLogScopeEnabled = @import("../main.zig").debugLogScopeEnabled; | ||
| 28 | const target_util = @import("../target.zig"); | 29 | const target_util = @import("../target.zig"); |
| 29 | const tracy = @import("../tracy.zig"); | 30 | const tracy = @import("../tracy.zig"); |
| 30 | const trace = tracy.trace; | 31 | const trace = tracy.trace; |
| ... | @@ -2303,10 +2304,9 @@ fn analyzeFuncBody( | ... | @@ -2303,10 +2304,9 @@ fn analyzeFuncBody( |
| 2303 | 2304 | ||
| 2304 | const comp = zcu.comp; | 2305 | const comp = zcu.comp; |
| 2305 | 2306 | ||
| 2306 | const dump_air = build_options.enable_debug_extensions and comp.verbose_air; | 2307 | if (comp.bin_file != null or zcu.llvm_object != null or log_air: { |
| 2307 | const dump_llvm_ir = build_options.enable_debug_extensions and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null); | 2308 | break :log_air debugLogScopeEnabled("illegal-air") or debugLogScopeEnabled("legal-air") or debugLogScopeEnabled("air"); |
| 2308 | 2309 | }) { | |
| 2309 | if (comp.bin_file != null or zcu.llvm_object != null or dump_air or dump_llvm_ir) { | ||
| 2310 | zcu.codegen_prog_node.increaseEstimatedTotalItems(1); | 2310 | zcu.codegen_prog_node.increaseEstimatedTotalItems(1); |
| 2311 | comp.link_prog_node.increaseEstimatedTotalItems(1); | 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,32 +4522,28 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e |
| 4522 | tracy_trace.addText(fqn.toSlice(ip)); | 4522 | tracy_trace.addText(fqn.toSlice(ip)); |
| 4523 | tracy_trace.addTextFmt("func_ip_index={d}", .{func_index}); | 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 | if (codegen.legalizeFeatures(pt, nav)) |features| { | 4536 | if (codegen.legalizeFeatures(pt, nav)) |features| { |
| 4528 | try air.legalize(pt, features); | 4537 | // Verify the AIR again pre-legalization. |
| 4529 | // Verify the AIR again post-legalization. | ||
| 4530 | Air.Verify.run(pt, func_index, air); | 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)) | 4542 | std.log.scoped(.@"legal-air").debug("{f}", .{&ap}); |
| 4534 | try .analyze(zcu, air.*, ip) | 4543 | Air.Verify.run(pt, func_index, air); |
| 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 | } | ||
| 4550 | 4544 | ||
| 4545 | if (codegen.wantsLiveness(pt, nav)) liveness = try .analyze(zcu, air.*, ip); | ||
| 4546 | std.log.scoped(.air).debug("{f}", .{&ap}); | ||
| 4551 | if (std.debug.runtime_safety) verify_liveness: { | 4547 | if (std.debug.runtime_safety) verify_liveness: { |
| 4552 | var verify: Air.Liveness.Verify = .{ | 4548 | var verify: Air.Liveness.Verify = .{ |
| 4553 | .gpa = gpa, | 4549 | .gpa = gpa, |
| ... | @@ -4577,17 +4573,3 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e | ... | @@ -4577,17 +4573,3 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e |
| 4577 | 4573 | ||
| 4578 | return codegen.generateFunction(lf, pt, func_index, air, &liveness); | 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,6 +10,7 @@ const build_options = @import("build_options"); |
| 10 | const Air = @import("../Air.zig"); | 10 | const Air = @import("../Air.zig"); |
| 11 | const codegen = @import("../codegen.zig"); | 11 | const codegen = @import("../codegen.zig"); |
| 12 | const Compilation = @import("../Compilation.zig"); | 12 | const Compilation = @import("../Compilation.zig"); |
| 13 | const debugLogScopeEnabled = @import("../main.zig").debugLogScopeEnabled; | ||
| 13 | const InternPool = @import("../InternPool.zig"); | 14 | const InternPool = @import("../InternPool.zig"); |
| 14 | const link = @import("../link.zig"); | 15 | const link = @import("../link.zig"); |
| 15 | const Module = @import("../Module.zig"); | 16 | const Module = @import("../Module.zig"); |
| ... | @@ -331,12 +332,10 @@ pub const Object = struct { | ... | @@ -331,12 +332,10 @@ pub const Object = struct { |
| 331 | } | 332 | } |
| 332 | 333 | ||
| 333 | pub const EmitOptions = struct { | 334 | pub const EmitOptions = struct { |
| 334 | pre_ir_path: ?[]const u8, | ||
| 335 | pre_bc_path: ?[]const u8, | ||
| 336 | bin_path: ?[:0]const u8, | 335 | bin_path: ?[:0]const u8, |
| 337 | asm_path: ?[:0]const u8, | 336 | asm_path: ?[:0]const u8, |
| 338 | post_ir_path: ?[:0]const u8, | 337 | opt_ir_path: ?[:0]const u8, |
| 339 | post_bc_path: ?[:0]const u8, | 338 | opt_bc_path: ?[:0]const u8, |
| 340 | 339 | ||
| 341 | is_debug: bool, | 340 | is_debug: bool, |
| 342 | is_small: bool, | 341 | is_small: bool, |
| ... | @@ -351,6 +350,7 @@ pub const Object = struct { | ... | @@ -351,6 +350,7 @@ pub const Object = struct { |
| 351 | const comp = zcu.comp; | 350 | const comp = zcu.comp; |
| 352 | const io = comp.io; | 351 | const io = comp.io; |
| 353 | const diags = &comp.link_diags; | 352 | const diags = &comp.link_diags; |
| 353 | const target = &comp.root_mod.resolved_target.result; | ||
| 354 | 354 | ||
| 355 | { | 355 | { |
| 356 | if (o.errors_len_variable != .none) { | 356 | if (o.errors_len_variable != .none) { |
| ... | @@ -403,7 +403,7 @@ pub const Object = struct { | ... | @@ -403,7 +403,7 @@ pub const Object = struct { |
| 403 | const behavior_max = try o.builder.metadataConstant(try o.builder.intConst(.i32, 7)); | 403 | const behavior_max = try o.builder.metadataConstant(try o.builder.intConst(.i32, 7)); |
| 404 | const behavior_min = try o.builder.metadataConstant(try o.builder.intConst(.i32, 8)); | 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 | module_flags.appendAssumeCapacity(try o.builder.metadataTuple(&.{ | 407 | module_flags.appendAssumeCapacity(try o.builder.metadataTuple(&.{ |
| 408 | behavior_error, | 408 | behavior_error, |
| 409 | (try o.builder.metadataString("target-abi")).toMetadata(), | 409 | (try o.builder.metadataString("target-abi")).toMetadata(), |
| ... | @@ -411,7 +411,7 @@ pub const Object = struct { | ... | @@ -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 | if (comp.root_mod.pic) { | 415 | if (comp.root_mod.pic) { |
| 416 | module_flags.appendAssumeCapacity(try o.builder.metadataTuple(&.{ | 416 | module_flags.appendAssumeCapacity(try o.builder.metadataTuple(&.{ |
| 417 | behavior_min, | 417 | behavior_min, |
| ... | @@ -434,7 +434,7 @@ pub const Object = struct { | ... | @@ -434,7 +434,7 @@ pub const Object = struct { |
| 434 | (try o.builder.metadataString("Code Model")).toMetadata(), | 434 | (try o.builder.metadataString("Code Model")).toMetadata(), |
| 435 | try o.builder.metadataConstant(try o.builder.intConst(.i32, @as( | 435 | try o.builder.metadataConstant(try o.builder.intConst(.i32, @as( |
| 436 | i32, | 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 | .default => unreachable, | 438 | .default => unreachable, |
| 439 | .tiny => 0, | 439 | .tiny => 0, |
| 440 | .small => 1, | 440 | .small => 1, |
| ... | @@ -480,7 +480,6 @@ pub const Object = struct { | ... | @@ -480,7 +480,6 @@ pub const Object = struct { |
| 480 | } | 480 | } |
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | const target = &comp.root_mod.resolved_target.result; | ||
| 484 | if (target.os.tag == .windows and (target.cpu.arch == .x86_64 or target.cpu.arch == .x86)) { | 483 | if (target.os.tag == .windows and (target.cpu.arch == .x86_64 or target.cpu.arch == .x86)) { |
| 485 | // Add the "RegCallv4" flag so that any functions using `x86_regcallcc` use regcall | 484 | // Add the "RegCallv4" flag so that any functions using `x86_regcallcc` use regcall |
| 486 | // v4, which is essentially a requirement on Windows. See corresponding logic in | 485 | // v4, which is essentially a requirement on Windows. See corresponding logic in |
| ... | @@ -515,21 +514,26 @@ pub const Object = struct { | ... | @@ -515,21 +514,26 @@ pub const Object = struct { |
| 515 | 514 | ||
| 516 | const emit_asm_msg = options.asm_path orelse "(none)"; | 515 | const emit_asm_msg = options.asm_path orelse "(none)"; |
| 517 | const emit_bin_msg = options.bin_path orelse "(none)"; | 516 | const emit_bin_msg = options.bin_path orelse "(none)"; |
| 518 | const post_llvm_ir_msg = options.post_ir_path orelse "(none)"; | 517 | const opt_llvm_ir_msg = options.opt_ir_path orelse "(none)"; |
| 519 | const post_llvm_bc_msg = options.post_bc_path orelse "(none)"; | 518 | const opt_llvm_bc_msg = options.opt_bc_path orelse "(none)"; |
| 520 | log.debug("emit LLVM object asm={s} bin={s} ir={s} bc={s}", .{ | 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 | const context, const module = emit: { | 524 | const context, const module = emit: { |
| 525 | if (options.pre_ir_path) |path| { | 525 | { |
| 526 | if (std.mem.eql(u8, path, "-")) { | 526 | var p: Builder.Print = .{ .name = comp.root_name, .builder = &o.builder, .err = null }; |
| 527 | o.builder.dump(io); | 527 | std.log.scoped(.@"llvm-ir").debug("{f}", .{&p}); |
| 528 | } else { | 528 | if (p.err) |err| return err; |
| 529 | o.builder.printToFilePath(io, Io.Dir.cwd(), path) catch |err| { | 529 | } |
| 530 | log.err("failed printing LLVM module to \"{s}\": {t}", .{ path, err }); | 530 | |
| 531 | }; | 531 | if (target.ofmt == .llvmir) { |
| 532 | } | 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 | const bitcode = try o.builder.toBitcode(o.gpa, .{ | 539 | const bitcode = try o.builder.toBitcode(o.gpa, .{ |
| ... | @@ -538,23 +542,26 @@ pub const Object = struct { | ... | @@ -538,23 +542,26 @@ pub const Object = struct { |
| 538 | }); | 542 | }); |
| 539 | defer o.gpa.free(bitcode); | 543 | defer o.gpa.free(bitcode); |
| 540 | 544 | ||
| 541 | if (options.pre_bc_path) |path| { | 545 | if (target.ofmt == .llvmbc) { |
| 542 | var file = Io.Dir.cwd().createFile(io, path, .{}) catch |err| | 546 | const path = comp.bin_file.?.emit; |
| 543 | return diags.fail("failed to create '{s}': {t}", .{ path, err }); | 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 | defer file.close(io); | 549 | defer file.close(io); |
| 545 | 550 | ||
| 546 | file.writeStreamingAll(io, @ptrCast(bitcode)) catch |err| | 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 | if (options.asm_path == null and options.bin_path == null and | 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 | if (!build_options.have_llvm or !comp.config.use_lib_llvm) { | 560 | if (!build_options.have_llvm or !comp.config.use_lib_llvm) { |
| 554 | return diags.fail("emitting without libllvm not implemented", .{}); | 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 | const context: *bindings.Context = .create(); | 566 | const context: *bindings.Context = .create(); |
| 560 | errdefer context.dispose(); | 567 | errdefer context.dispose(); |
| ... | @@ -577,9 +584,9 @@ pub const Object = struct { | ... | @@ -577,9 +584,9 @@ pub const Object = struct { |
| 577 | }; | 584 | }; |
| 578 | defer context.dispose(); | 585 | defer context.dispose(); |
| 579 | 586 | ||
| 580 | var target: *bindings.Target = undefined; | 587 | var llvm_target: *bindings.Target = undefined; |
| 581 | var error_message: [*:0]const u8 = undefined; | 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 | defer bindings.disposeMessage(error_message); | 590 | defer bindings.disposeMessage(error_message); |
| 584 | return diags.fail("LLVM failed to parse '{s}': {s}", .{ target_triple_sentinel, error_message }); | 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,7 +605,7 @@ pub const Object = struct { |
| 598 | else | 605 | else |
| 599 | .Static; | 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 | .default => .Default, | 609 | .default => .Default, |
| 603 | .tiny => .Tiny, | 610 | .tiny => .Tiny, |
| 604 | .small => .Small, | 611 | .small => .Small, |
| ... | @@ -607,24 +614,22 @@ pub const Object = struct { | ... | @@ -607,24 +614,22 @@ pub const Object = struct { |
| 607 | .large => .Large, | 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 | var target_machine = bindings.TargetMachine.create( | 617 | var target_machine = bindings.TargetMachine.create( |
| 616 | target, | 618 | llvm_target, |
| 617 | target_triple_sentinel, | 619 | target_triple_sentinel, |
| 618 | if (comp.root_mod.resolved_target.result.cpu.model.llvm_name) |s| s.ptr else null, | 620 | if (target.cpu.model.llvm_name) |s| s.ptr else null, |
| 619 | comp.root_mod.resolved_target.llvm_cpu_features.?, | 621 | comp.root_mod.llvm_cpu_features.?, |
| 620 | opt_level, | 622 | opt_level, |
| 621 | reloc_mode, | 623 | reloc_mode, |
| 622 | code_model, | 624 | code_model, |
| 623 | comp.function_sections, | 625 | comp.function_sections, |
| 624 | comp.data_sections, | 626 | comp.data_sections, |
| 625 | float_abi, | 627 | switch (target.abi.float()) { |
| 626 | if (target_util.llvmMachineAbi(&comp.root_mod.resolved_target.result)) |s| s.ptr else null, | 628 | .hard => .Hard, |
| 627 | target_util.useEmulatedTls(&comp.root_mod.resolved_target.result), | 629 | .soft => .Soft, |
| 630 | }, | ||
| 631 | if (target_util.llvmMachineAbi(target)) |s| s.ptr else null, | ||
| 632 | target_util.useEmulatedTls(target), | ||
| 628 | ); | 633 | ); |
| 629 | errdefer target_machine.dispose(); | 634 | errdefer target_machine.dispose(); |
| 630 | 635 | ||
| ... | @@ -634,7 +639,10 @@ pub const Object = struct { | ... | @@ -634,7 +639,10 @@ pub const Object = struct { |
| 634 | 639 | ||
| 635 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. | 640 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. |
| 636 | // So we call the entire pipeline multiple times if this is requested. | 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 | var lowered_options: bindings.TargetMachine.EmitOptions = .{ | 646 | var lowered_options: bindings.TargetMachine.EmitOptions = .{ |
| 639 | .is_debug = options.is_debug, | 647 | .is_debug = options.is_debug, |
| 640 | .is_small = options.is_small, | 648 | .is_small = options.is_small, |
| ... | @@ -648,11 +656,12 @@ pub const Object = struct { | ... | @@ -648,11 +656,12 @@ pub const Object = struct { |
| 648 | .allow_fast_isel = true, | 656 | .allow_fast_isel = true, |
| 649 | // LLVM's RISC-V backend for some reason enables the machine outliner by default even | 657 | // LLVM's RISC-V backend for some reason enables the machine outliner by default even |
| 650 | // though it's clearly not ready and produces multiple miscompilations in our std tests. | 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 | .asm_filename = null, | 660 | .asm_filename = null, |
| 653 | .bin_filename = if (options.bin_path) |x| x.ptr else null, | 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, | 662 | .llvm_ir_filename = if (options.opt_ir_path) |x| x.ptr else null, |
| 655 | .bitcode_filename = if (options.post_bc_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 | // `.coverage` value is only used when `.sancov` is enabled. | 666 | // `.coverage` value is only used when `.sancov` is enabled. |
| 658 | .sancov = options.fuzz or comp.config.san_cov_trace_pc_guard, | 667 | .sancov = options.fuzz or comp.config.san_cov_trace_pc_guard, |
| ... | @@ -684,33 +693,31 @@ pub const Object = struct { | ... | @@ -684,33 +693,31 @@ pub const Object = struct { |
| 684 | }; | 693 | }; |
| 685 | if (options.asm_path != null and options.bin_path != null) { | 694 | if (options.asm_path != null and options.bin_path != null) { |
| 686 | if (target_machine.emitToFile(module, &error_message, &lowered_options)) { | 695 | if (target_machine.emitToFile(module, &error_message, &lowered_options)) { |
| 687 | defer bindings.disposeMessage(error_message); | ||
| 688 | return diags.fail("LLVM failed to emit bin={s} ir={s}: {s}", .{ | 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 | lowered_options.bin_filename = null; | 700 | lowered_options.bin_filename = null; |
| 693 | lowered_options.llvm_ir_filename = null; | 701 | lowered_options.llvm_ir_filename = null; |
| 694 | lowered_options.bitcode_filename = null; | 702 | lowered_options.bitcode_filename = null; |
| 703 | lowered_options.llvm_ir_out = null; | ||
| 695 | } | 704 | } |
| 696 | 705 | if (options.time_report) |_| lowered_options.time_report_out = &time_report_c_str; | |
| 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 | |||
| 702 | lowered_options.asm_filename = if (options.asm_path) |x| x.ptr else null; | 706 | lowered_options.asm_filename = if (options.asm_path) |x| x.ptr else null; |
| 703 | if (target_machine.emitToFile(module, &error_message, &lowered_options)) { | 707 | if (target_machine.emitToFile(module, &error_message, &lowered_options)) { |
| 704 | defer bindings.disposeMessage(error_message); | 708 | defer bindings.disposeMessage(error_message); |
| 705 | return diags.fail("LLVM failed to emit asm={s} bin={s} ir={s} bc={s}: {s}", .{ | 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| { | 713 | if (log_opt_llvm_ir) std.log.scoped(.@"opt-llvm-ir").debug("{s}", .{ |
| 710 | defer std.c.free(time_report_c_str); | 714 | llvm_ir_c_str orelse return error.OutOfMemory, |
| 711 | const time_report_data = std.mem.span(time_report_c_str); | 715 | }); |
| 712 | assert(tr.llvm_pass_timings.len == 0); | 716 | if (options.time_report) |time_report| { |
| 713 | tr.llvm_pass_timings = try comp.gpa.dupe(u8, time_report_data); | 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,10 +2191,10 @@ pub const Object = struct { |
| 2184 | .value = try o.builder.string(s), | 2191 | .value = try o.builder.string(s), |
| 2185 | } }, &o.builder); | 2192 | } }, &o.builder); |
| 2186 | } | 2193 | } |
| 2187 | if (owner_mod.resolved_target.llvm_cpu_features) |s| { | 2194 | if (owner_mod.llvm_cpu_features) |s| { |
| 2188 | try attributes.addFnAttr(.{ .string = .{ | 2195 | try attributes.addFnAttr(.{ .string = .{ |
| 2189 | .kind = try o.builder.string("target-features"), | 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 | } }, &o.builder); | 2198 | } }, &o.builder); |
| 2192 | } | 2199 | } |
| 2193 | 2200 |
src/codegen/llvm/bindings.zig+3-2| ... | @@ -51,7 +51,7 @@ pub const Module = opaque { | ... | @@ -51,7 +51,7 @@ pub const Module = opaque { |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | pub const disposeMessage = LLVMDisposeMessage; | 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 | pub const TargetMachine = opaque { | 56 | pub const TargetMachine = opaque { |
| 57 | pub const FloatABI = enum(c_int) { | 57 | pub const FloatABI = enum(c_int) { |
| ... | @@ -85,7 +85,7 @@ pub const TargetMachine = opaque { | ... | @@ -85,7 +85,7 @@ pub const TargetMachine = opaque { |
| 85 | pub const EmitOptions = extern struct { | 85 | pub const EmitOptions = extern struct { |
| 86 | is_debug: bool, | 86 | is_debug: bool, |
| 87 | is_small: bool, | 87 | is_small: bool, |
| 88 | time_report_out: ?*[*:0]u8, | 88 | time_report_out: ?*?[*:0]u8, |
| 89 | tsan: bool, | 89 | tsan: bool, |
| 90 | sancov: bool, | 90 | sancov: bool, |
| 91 | lto: LtoPhase, | 91 | lto: LtoPhase, |
| ... | @@ -95,6 +95,7 @@ pub const TargetMachine = opaque { | ... | @@ -95,6 +95,7 @@ pub const TargetMachine = opaque { |
| 95 | bin_filename: ?[*:0]const u8, | 95 | bin_filename: ?[*:0]const u8, |
| 96 | llvm_ir_filename: ?[*:0]const u8, | 96 | llvm_ir_filename: ?[*:0]const u8, |
| 97 | bitcode_filename: ?[*:0]const u8, | 97 | bitcode_filename: ?[*:0]const u8, |
| 98 | llvm_ir_out: ?*?[*:0]u8, | ||
| 98 | coverage: Coverage, | 99 | coverage: Coverage, |
| 99 | 100 | ||
| 100 | pub const LtoPhase = enum(c_int) { | 101 | pub const LtoPhase = enum(c_int) { |
src/codegen/riscv64/CodeGen.zig+1-1| ... | @@ -27,7 +27,7 @@ const Target = std.Target; | ... | @@ -27,7 +27,7 @@ const Target = std.Target; |
| 27 | const log = std.log.scoped(.riscv_codegen); | 27 | const log = std.log.scoped(.riscv_codegen); |
| 28 | const tracking_log = std.log.scoped(.tracking); | 28 | const tracking_log = std.log.scoped(.tracking); |
| 29 | const verbose_tracking_log = std.log.scoped(.verbose_tracking); | 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 | const Alignment = InternPool.Alignment; | 31 | const Alignment = InternPool.Alignment; |
| 32 | 32 | ||
| 33 | const bits = @import("bits.zig"); | 33 | const bits = @import("bits.zig"); |
src/codegen/x86_64/CodeGen.zig+1-1| ... | @@ -5,7 +5,7 @@ const link = @import("../../link.zig"); | ... | @@ -5,7 +5,7 @@ const link = @import("../../link.zig"); |
| 5 | const log = std.log.scoped(.codegen); | 5 | const log = std.log.scoped(.codegen); |
| 6 | const tracking_log = std.log.scoped(.tracking); | 6 | const tracking_log = std.log.scoped(.tracking); |
| 7 | const verbose_tracking_log = std.log.scoped(.verbose_tracking); | 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 | const Writer = std.Io.Writer; | 9 | const Writer = std.Io.Writer; |
| 10 | 10 | ||
| 11 | const Air = @import("../../Air.zig"); | 11 | const Air = @import("../../Air.zig"); |
src/dev.zig+2| ... | @@ -112,6 +112,7 @@ pub const Env = enum { | ... | @@ -112,6 +112,7 @@ pub const Env = enum { |
| 112 | .loongarch_backend, | 112 | .loongarch_backend, |
| 113 | .spork8_backend, | 113 | .spork8_backend, |
| 114 | .lld_linker, | 114 | .lld_linker, |
| 115 | .llvm_linker, | ||
| 115 | .coff_linker, | 116 | .coff_linker, |
| 116 | .elf_linker, | 117 | .elf_linker, |
| 117 | .elf2_linker, | 118 | .elf2_linker, |
| ... | @@ -333,6 +334,7 @@ pub const Feature = enum { | ... | @@ -333,6 +334,7 @@ pub const Feature = enum { |
| 333 | spork8_backend, | 334 | spork8_backend, |
| 334 | 335 | ||
| 335 | lld_linker, | 336 | lld_linker, |
| 337 | llvm_linker, | ||
| 336 | coff_linker, | 338 | coff_linker, |
| 337 | elf_linker, | 339 | elf_linker, |
| 338 | elf2_linker, | 340 | elf2_linker, |
src/libs/freebsd.zig-4| ... | @@ -1120,10 +1120,6 @@ fn buildSharedLib( | ... | @@ -1120,10 +1120,6 @@ fn buildSharedLib( |
| 1120 | .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, | 1120 | .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, |
| 1121 | .verbose_cc = comp.verbose_cc, | 1121 | .verbose_cc = comp.verbose_cc, |
| 1122 | .verbose_link = comp.verbose_link, | 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 | .clang_passthrough_mode = comp.clang_passthrough_mode, | 1123 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 1128 | .version = version, | 1124 | .version = version, |
| 1129 | .version_script = .{ | 1125 | .version_script = .{ |
src/libs/glibc.zig-4| ... | @@ -1268,10 +1268,6 @@ fn buildSharedLib( | ... | @@ -1268,10 +1268,6 @@ fn buildSharedLib( |
| 1268 | .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, | 1268 | .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, |
| 1269 | .verbose_cc = comp.verbose_cc, | 1269 | .verbose_cc = comp.verbose_cc, |
| 1270 | .verbose_link = comp.verbose_link, | 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 | .clang_passthrough_mode = comp.clang_passthrough_mode, | 1271 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 1276 | .version = version, | 1272 | .version = version, |
| 1277 | .version_script = .{ | 1273 | .version_script = .{ |
src/libs/libcxx.zig-8| ... | @@ -260,10 +260,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError! | ... | @@ -260,10 +260,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError! |
| 260 | .c_source_files = c_source_files.items, | 260 | .c_source_files = c_source_files.items, |
| 261 | .verbose_cc = comp.verbose_cc, | 261 | .verbose_cc = comp.verbose_cc, |
| 262 | .verbose_link = comp.verbose_link, | 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 | .clang_passthrough_mode = comp.clang_passthrough_mode, | 263 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 268 | .skip_linker_dependencies = true, | 264 | .skip_linker_dependencies = true, |
| 269 | .environ_map = comp.environ_map, | 265 | .environ_map = comp.environ_map, |
| ... | @@ -445,10 +441,6 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr | ... | @@ -445,10 +441,6 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 445 | .c_source_files = c_source_files.items, | 441 | .c_source_files = c_source_files.items, |
| 446 | .verbose_cc = comp.verbose_cc, | 442 | .verbose_cc = comp.verbose_cc, |
| 447 | .verbose_link = comp.verbose_link, | 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 | .clang_passthrough_mode = comp.clang_passthrough_mode, | 444 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 453 | .skip_linker_dependencies = true, | 445 | .skip_linker_dependencies = true, |
| 454 | .environ_map = comp.environ_map, | 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,10 +295,6 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo |
| 295 | .c_source_files = c_source_files.items, | 295 | .c_source_files = c_source_files.items, |
| 296 | .verbose_cc = comp.verbose_cc, | 296 | .verbose_cc = comp.verbose_cc, |
| 297 | .verbose_link = comp.verbose_link, | 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 | .clang_passthrough_mode = comp.clang_passthrough_mode, | 298 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 303 | .skip_linker_dependencies = skip_linker_dependencies, | 299 | .skip_linker_dependencies = skip_linker_dependencies, |
| 304 | .linker_allow_shlib_undefined = linker_allow_shlib_undefined, | 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,10 +157,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 157 | .c_source_files = &c_source_files, | 157 | .c_source_files = &c_source_files, |
| 158 | .verbose_cc = comp.verbose_cc, | 158 | .verbose_cc = comp.verbose_cc, |
| 159 | .verbose_link = comp.verbose_link, | 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 | .clang_passthrough_mode = comp.clang_passthrough_mode, | 160 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 165 | .skip_linker_dependencies = true, | 161 | .skip_linker_dependencies = true, |
| 166 | .environ_map = comp.environ_map, | 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,9 +246,6 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro |
| 246 | .emit_bin = .yes_cache, | 246 | .emit_bin = .yes_cache, |
| 247 | .verbose_cc = comp.verbose_cc, | 247 | .verbose_cc = comp.verbose_cc, |
| 248 | .verbose_link = comp.verbose_link, | 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 | .clang_passthrough_mode = comp.clang_passthrough_mode, | 249 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 253 | .c_source_files = &.{ | 250 | .c_source_files = &.{ |
| 254 | .{ | 251 | .{ |
src/libs/netbsd.zig-4| ... | @@ -771,10 +771,6 @@ fn buildSharedLib( | ... | @@ -771,10 +771,6 @@ fn buildSharedLib( |
| 771 | .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, | 771 | .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, |
| 772 | .verbose_cc = comp.verbose_cc, | 772 | .verbose_cc = comp.verbose_cc, |
| 773 | .verbose_link = comp.verbose_link, | 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 | .clang_passthrough_mode = comp.clang_passthrough_mode, | 774 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 779 | .version = version, | 775 | .version = version, |
| 780 | .soname = soname, | 776 | .soname = soname, |
src/libs/openbsd.zig-4| ... | @@ -691,10 +691,6 @@ fn buildSharedLib( | ... | @@ -691,10 +691,6 @@ fn buildSharedLib( |
| 691 | .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, | 691 | .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, |
| 692 | .verbose_cc = comp.verbose_cc, | 692 | .verbose_cc = comp.verbose_cc, |
| 693 | .verbose_link = comp.verbose_link, | 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 | .clang_passthrough_mode = comp.clang_passthrough_mode, | 694 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 699 | .soname = soname, | 695 | .soname = soname, |
| 700 | .c_source_files = &c_source_files, | 696 | .c_source_files = &c_source_files, |
src/link.zig+35-4| ... | @@ -550,6 +550,7 @@ pub const File = struct { | ... | @@ -550,6 +550,7 @@ pub const File = struct { |
| 550 | return &ptr.base; | 550 | return &ptr.base; |
| 551 | }, | 551 | }, |
| 552 | .lld => unreachable, // not known from ofmt | 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,9 +574,26 @@ pub const File = struct { |
| 573 | return &ptr.base; | 574 | return &ptr.base; |
| 574 | }, | 575 | }, |
| 575 | .lld => unreachable, // not known from ofmt | 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 | pub fn cast(base: *File, comptime tag: Tag) if (dev.env.supports(tag.devFeature())) ?*tag.Type() else ?noreturn { | 597 | pub fn cast(base: *File, comptime tag: Tag) if (dev.env.supports(tag.devFeature())) ?*tag.Type() else ?noreturn { |
| 580 | return if (dev.env.supports(tag.devFeature()) and base.tag == tag) @fieldParentPtr("base", base) else null; | 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,7 +624,7 @@ pub const File = struct { |
| 606 | const gpa = comp.gpa; | 624 | const gpa = comp.gpa; |
| 607 | const io = comp.io; | 625 | const io = comp.io; |
| 608 | switch (base.tag) { | 626 | switch (base.tag) { |
| 609 | .lld => assert(base.file == null), | 627 | .lld, .llvm => assert(base.file == null), |
| 610 | .elf, .macho, .wasm => { | 628 | .elf, .macho, .wasm => { |
| 611 | dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker }); | 629 | dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker }); |
| 612 | if (base.file != null) return; | 630 | if (base.file != null) return; |
| ... | @@ -706,7 +724,7 @@ pub const File = struct { | ... | @@ -706,7 +724,7 @@ pub const File = struct { |
| 706 | if (!base.canMakeExecutable()) | 724 | if (!base.canMakeExecutable()) |
| 707 | return; | 725 | return; |
| 708 | switch (base.tag) { | 726 | switch (base.tag) { |
| 709 | .lld => assert(base.file == null), | 727 | .lld, .llvm => assert(base.file == null), |
| 710 | .elf => if (base.file) |f| { | 728 | .elf => if (base.file) |f| { |
| 711 | dev.check(.elf_linker); | 729 | dev.check(.elf_linker); |
| 712 | f.close(io); | 730 | f.close(io); |
| ... | @@ -827,6 +845,7 @@ pub const File = struct { | ... | @@ -827,6 +845,7 @@ pub const File = struct { |
| 827 | 845 | ||
| 828 | switch (base.tag) { | 846 | switch (base.tag) { |
| 829 | .lld => unreachable, | 847 | .lld => unreachable, |
| 848 | .llvm => unreachable, | ||
| 830 | .plan9 => unreachable, | 849 | .plan9 => unreachable, |
| 831 | inline else => |tag| { | 850 | inline else => |tag| { |
| 832 | dev.check(tag.devFeature()); | 851 | dev.check(tag.devFeature()); |
| ... | @@ -862,6 +881,7 @@ pub const File = struct { | ... | @@ -862,6 +881,7 @@ pub const File = struct { |
| 862 | assert(pt.zcu.llvm_object == null); | 881 | assert(pt.zcu.llvm_object == null); |
| 863 | switch (base.tag) { | 882 | switch (base.tag) { |
| 864 | .lld => unreachable, | 883 | .lld => unreachable, |
| 884 | .llvm => unreachable, | ||
| 865 | .plan9 => unreachable, | 885 | .plan9 => unreachable, |
| 866 | inline else => |tag| { | 886 | inline else => |tag| { |
| 867 | dev.check(tag.devFeature()); | 887 | dev.check(tag.devFeature()); |
| ... | @@ -897,6 +917,7 @@ pub const File = struct { | ... | @@ -897,6 +917,7 @@ pub const File = struct { |
| 897 | } | 917 | } |
| 898 | switch (base.tag) { | 918 | switch (base.tag) { |
| 899 | .lld => unreachable, | 919 | .lld => unreachable, |
| 920 | .llvm => unreachable, | ||
| 900 | .plan9 => unreachable, | 921 | .plan9 => unreachable, |
| 901 | .spirv => {}, | 922 | .spirv => {}, |
| 902 | .coff => {}, | 923 | .coff => {}, |
| ... | @@ -941,6 +962,7 @@ pub const File = struct { | ... | @@ -941,6 +962,7 @@ pub const File = struct { |
| 941 | base.releaseLock(); | 962 | base.releaseLock(); |
| 942 | if (base.file) |f| f.close(io); | 963 | if (base.file) |f| f.close(io); |
| 943 | switch (base.tag) { | 964 | switch (base.tag) { |
| 965 | .llvm => {}, | ||
| 944 | .plan9 => unreachable, | 966 | .plan9 => unreachable, |
| 945 | inline else => |tag| { | 967 | inline else => |tag| { |
| 946 | dev.check(tag.devFeature()); | 968 | dev.check(tag.devFeature()); |
| ... | @@ -1003,6 +1025,7 @@ pub const File = struct { | ... | @@ -1003,6 +1025,7 @@ pub const File = struct { |
| 1003 | } | 1025 | } |
| 1004 | assert(base.post_prelink); | 1026 | assert(base.post_prelink); |
| 1005 | switch (base.tag) { | 1027 | switch (base.tag) { |
| 1028 | .llvm => {}, | ||
| 1006 | .plan9 => unreachable, | 1029 | .plan9 => unreachable, |
| 1007 | inline else => |tag| { | 1030 | inline else => |tag| { |
| 1008 | dev.check(tag.devFeature()); | 1031 | dev.check(tag.devFeature()); |
| ... | @@ -1030,6 +1053,7 @@ pub const File = struct { | ... | @@ -1030,6 +1053,7 @@ pub const File = struct { |
| 1030 | 1053 | ||
| 1031 | switch (base.tag) { | 1054 | switch (base.tag) { |
| 1032 | .lld => unreachable, | 1055 | .lld => unreachable, |
| 1056 | .llvm => unreachable, | ||
| 1033 | .plan9 => unreachable, | 1057 | .plan9 => unreachable, |
| 1034 | inline else => |tag| { | 1058 | inline else => |tag| { |
| 1035 | dev.check(tag.devFeature()); | 1059 | dev.check(tag.devFeature()); |
| ... | @@ -1056,6 +1080,7 @@ pub const File = struct { | ... | @@ -1056,6 +1080,7 @@ pub const File = struct { |
| 1056 | assert(base.comp.zcu.?.llvm_object == null); | 1080 | assert(base.comp.zcu.?.llvm_object == null); |
| 1057 | switch (base.tag) { | 1081 | switch (base.tag) { |
| 1058 | .lld => unreachable, | 1082 | .lld => unreachable, |
| 1083 | .llvm => unreachable, | ||
| 1059 | .c => unreachable, | 1084 | .c => unreachable, |
| 1060 | .spirv => unreachable, | 1085 | .spirv => unreachable, |
| 1061 | .wasm => unreachable, | 1086 | .wasm => unreachable, |
| ... | @@ -1078,6 +1103,7 @@ pub const File = struct { | ... | @@ -1078,6 +1103,7 @@ pub const File = struct { |
| 1078 | assert(pt.zcu.llvm_object == null); | 1103 | assert(pt.zcu.llvm_object == null); |
| 1079 | switch (base.tag) { | 1104 | switch (base.tag) { |
| 1080 | .lld => unreachable, | 1105 | .lld => unreachable, |
| 1106 | .llvm => unreachable, | ||
| 1081 | .c => unreachable, | 1107 | .c => unreachable, |
| 1082 | .spirv => unreachable, | 1108 | .spirv => unreachable, |
| 1083 | .wasm => unreachable, | 1109 | .wasm => unreachable, |
| ... | @@ -1095,6 +1121,7 @@ pub const File = struct { | ... | @@ -1095,6 +1121,7 @@ pub const File = struct { |
| 1095 | assert(base.comp.zcu.?.llvm_object == null); | 1121 | assert(base.comp.zcu.?.llvm_object == null); |
| 1096 | switch (base.tag) { | 1122 | switch (base.tag) { |
| 1097 | .lld => unreachable, | 1123 | .lld => unreachable, |
| 1124 | .llvm => unreachable, | ||
| 1098 | .c => unreachable, | 1125 | .c => unreachable, |
| 1099 | .spirv => unreachable, | 1126 | .spirv => unreachable, |
| 1100 | .wasm => unreachable, | 1127 | .wasm => unreachable, |
| ... | @@ -1124,6 +1151,7 @@ pub const File = struct { | ... | @@ -1124,6 +1151,7 @@ pub const File = struct { |
| 1124 | .spirv, | 1151 | .spirv, |
| 1125 | .plan9, | 1152 | .plan9, |
| 1126 | .lld, | 1153 | .lld, |
| 1154 | .llvm, | ||
| 1127 | .spork8, | 1155 | .spork8, |
| 1128 | => return .unimplemented, | 1156 | => return .unimplemented, |
| 1129 | inline else => |tag| { | 1157 | inline else => |tag| { |
| ... | @@ -1240,7 +1268,7 @@ pub const File = struct { | ... | @@ -1240,7 +1268,7 @@ pub const File = struct { |
| 1240 | dev.check(tag.devFeature()); | 1268 | dev.check(tag.devFeature()); |
| 1241 | return @as(*tag.Type(), @fieldParentPtr("base", base)).loadInput(input); | 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,6 +1380,7 @@ pub const File = struct { |
| 1352 | coff, | 1380 | coff, |
| 1353 | elf, | 1381 | elf, |
| 1354 | elf2, | 1382 | elf2, |
| 1383 | llvm, | ||
| 1355 | macho, | 1384 | macho, |
| 1356 | macho2, | 1385 | macho2, |
| 1357 | c, | 1386 | c, |
| ... | @@ -1366,13 +1395,14 @@ pub const File = struct { | ... | @@ -1366,13 +1395,14 @@ pub const File = struct { |
| 1366 | .coff => Coff, | 1395 | .coff => Coff, |
| 1367 | .elf => Elf, | 1396 | .elf => Elf, |
| 1368 | .elf2 => Elf2, | 1397 | .elf2 => Elf2, |
| 1398 | .llvm => File, | ||
| 1369 | .macho => MachO, | 1399 | .macho => MachO, |
| 1370 | .macho2 => MachO2, | 1400 | .macho2 => MachO2, |
| 1371 | .c => C, | 1401 | .c => C, |
| 1372 | .wasm => Wasm, | 1402 | .wasm => Wasm, |
| 1373 | .spirv => Spirv, | 1403 | .spirv => Spirv, |
| 1374 | .lld => Lld, | 1404 | .lld => Lld, |
| 1375 | .plan9 => comptime unreachable, | 1405 | .plan9 => unreachable, |
| 1376 | .spork8 => Spork8, | 1406 | .spork8 => Spork8, |
| 1377 | }; | 1407 | }; |
| 1378 | } | 1408 | } |
| ... | @@ -1381,6 +1411,7 @@ pub const File = struct { | ... | @@ -1381,6 +1411,7 @@ pub const File = struct { |
| 1381 | return switch (ofmt) { | 1411 | return switch (ofmt) { |
| 1382 | .coff => .coff, | 1412 | .coff => .coff, |
| 1383 | .elf => if (use_new_linker) .elf2 else .elf, | 1413 | .elf => if (use_new_linker) .elf2 else .elf, |
| 1414 | .llvmbc, .llvmir => .llvm, | ||
| 1384 | .macho => if (use_new_linker) .macho2 else .macho, | 1415 | .macho => if (use_new_linker) .macho2 else .macho, |
| 1385 | .wasm => .wasm, | 1416 | .wasm => .wasm, |
| 1386 | .plan9 => .plan9, | 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,9 +860,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void { |
| 860 | 860 | ||
| 861 | // Dump the state for easy debugging. | 861 | // Dump the state for easy debugging. |
| 862 | // State can be dumped via `--debug-log link_state`. | 862 | // State can be dumped via `--debug-log link_state`. |
| 863 | if (build_options.enable_logging) { | 863 | state_log.debug("{f}", .{self.dumpState()}); |
| 864 | state_log.debug("{f}", .{self.dumpState()}); | ||
| 865 | } | ||
| 866 | 864 | ||
| 867 | // Beyond this point, everything has been allocated a virtual address and we can resolve | 865 | // Beyond this point, everything has been allocated a virtual address and we can resolve |
| 868 | // the relocations, and commit objects to file. | 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,7 +291,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void { |
| 291 | if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed; | 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 | const active = elf_file.base.comp.zcu.?.activate(tid); | 295 | const active = elf_file.base.comp.zcu.?.activate(tid); |
| 296 | defer active.deactivate(); | 296 | defer active.deactivate(); |
| 297 | for (self.navs.keys(), self.navs.values()) |nav_index, meta| { | 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,7 +98,7 @@ fn markAtom(atom: *Atom) bool { |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | fn markLive(atom: *Atom, elf_file: *Elf) void { | 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 | assert(atom.visited); | 103 | assert(atom.visited); |
| 104 | const file = atom.file(elf_file).?; | 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,9 +51,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { |
| 51 | try allocateAllocSections(elf_file); | 51 | try allocateAllocSections(elf_file); |
| 52 | try elf_file.allocateNonAllocSections(); | 52 | try elf_file.allocateNonAllocSections(); |
| 53 | 53 | ||
| 54 | if (build_options.enable_logging) { | 54 | state_log.debug("{f}", .{elf_file.dumpState()}); |
| 55 | state_log.debug("{f}", .{elf_file.dumpState()}); | ||
| 56 | } | ||
| 57 | 55 | ||
| 58 | try elf_file.writeMergeSections(); | 56 | try elf_file.writeMergeSections(); |
| 59 | try writeSyntheticSections(elf_file); | 57 | try writeSyntheticSections(elf_file); |
| ... | @@ -117,10 +115,8 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { | ... | @@ -117,10 +115,8 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { |
| 117 | break :blk pos; | 115 | break :blk pos; |
| 118 | }; | 116 | }; |
| 119 | 117 | ||
| 120 | if (build_options.enable_logging) { | 118 | state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(elf_file)}); |
| 121 | state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(elf_file)}); | 119 | state_log.debug("ar_strtab\n{f}\n", .{ar_strtab}); |
| 122 | state_log.debug("ar_strtab\n{f}\n", .{ar_strtab}); | ||
| 123 | } | ||
| 124 | 120 | ||
| 125 | const buffer = try gpa.alloc(u8, total_size); | 121 | const buffer = try gpa.alloc(u8, total_size); |
| 126 | defer gpa.free(buffer); | 122 | defer gpa.free(buffer); |
| ... | @@ -193,9 +189,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void { | ... | @@ -193,9 +189,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void { |
| 193 | try allocateAllocSections(elf_file); | 189 | try allocateAllocSections(elf_file); |
| 194 | try elf_file.allocateNonAllocSections(); | 190 | try elf_file.allocateNonAllocSections(); |
| 195 | 191 | ||
| 196 | if (build_options.enable_logging) { | 192 | state_log.debug("{f}", .{elf_file.dumpState()}); |
| 197 | state_log.debug("{f}", .{elf_file.dumpState()}); | ||
| 198 | } | ||
| 199 | 193 | ||
| 200 | try writeAtoms(elf_file); | 194 | try writeAtoms(elf_file); |
| 201 | try elf_file.writeMergeSections(); | 195 | try elf_file.writeMergeSections(); |
src/link/MachO.zig+1-3| ... | @@ -456,9 +456,7 @@ pub fn flush( | ... | @@ -456,9 +456,7 @@ pub fn flush( |
| 456 | self.allocateSegments(); | 456 | self.allocateSegments(); |
| 457 | self.allocateSyntheticSymbols(); | 457 | self.allocateSyntheticSymbols(); |
| 458 | 458 | ||
| 459 | if (build_options.enable_logging) { | 459 | state_log.debug("{f}", .{self.dumpState()}); |
| 460 | state_log.debug("{f}", .{self.dumpState()}); | ||
| 461 | } | ||
| 462 | 460 | ||
| 463 | // Beyond this point, everything has been allocated a virtual address and we can resolve | 461 | // Beyond this point, everything has been allocated a virtual address and we can resolve |
| 464 | // the relocations, and commit objects to file. | 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,8 +123,9 @@ fn markLive(atom: *Atom, macho_file: *MachO) void { |
| 123 | atom.getName(macho_file), | 123 | atom.getName(macho_file), |
| 124 | }); | 124 | }); |
| 125 | 125 | ||
| 126 | if (build_options.enable_logging) | 126 | if (build_options.enable_debug_extensions) { |
| 127 | track_live_level.incr(); | 127 | track_live_level.incr(); |
| 128 | } | ||
| 128 | 129 | ||
| 129 | for (atom.getRelocs(macho_file)) |rel| { | 130 | for (atom.getRelocs(macho_file)) |rel| { |
| 130 | const target_atom = switch (rel.tag) { | 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,9 +61,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation) link.Error!void { |
| 61 | }; | 61 | }; |
| 62 | allocateSegment(macho_file); | 62 | allocateSegment(macho_file); |
| 63 | 63 | ||
| 64 | if (build_options.enable_logging) { | 64 | state_log.debug("{f}", .{macho_file.dumpState()}); |
| 65 | state_log.debug("{f}", .{macho_file.dumpState()}); | ||
| 66 | } | ||
| 67 | 65 | ||
| 68 | try writeSections(macho_file); | 66 | try writeSections(macho_file); |
| 69 | sortRelocs(macho_file); | 67 | sortRelocs(macho_file); |
| ... | @@ -107,9 +105,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation) link.Error!void { | ... | @@ -107,9 +105,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation) link.Error!void { |
| 107 | return diags.fail("failed to allocate sections: {s}", .{@errorName(err)}); | 105 | return diags.fail("failed to allocate sections: {s}", .{@errorName(err)}); |
| 108 | allocateSegment(macho_file); | 106 | allocateSegment(macho_file); |
| 109 | 107 | ||
| 110 | if (build_options.enable_logging) { | 108 | state_log.debug("{f}", .{macho_file.dumpState()}); |
| 111 | state_log.debug("{f}", .{macho_file.dumpState()}); | ||
| 112 | } | ||
| 113 | 109 | ||
| 114 | try writeSections(macho_file); | 110 | try writeSections(macho_file); |
| 115 | sortRelocs(macho_file); | 111 | sortRelocs(macho_file); |
| ... | @@ -185,9 +181,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation) link.Error!void { | ... | @@ -185,9 +181,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation) link.Error!void { |
| 185 | break :blk pos; | 181 | break :blk pos; |
| 186 | }; | 182 | }; |
| 187 | 183 | ||
| 188 | if (build_options.enable_logging) { | 184 | state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)}); |
| 189 | state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)}); | ||
| 190 | } | ||
| 191 | 185 | ||
| 192 | const buffer = try gpa.alloc(u8, total_size); | 186 | const buffer = try gpa.alloc(u8, total_size); |
| 193 | defer gpa.free(buffer); | 187 | defer gpa.free(buffer); |
src/main.zig+40-74| ... | @@ -42,11 +42,8 @@ const thread_stack_size = 60 << 20; | ... | @@ -42,11 +42,8 @@ const thread_stack_size = 60 << 20; |
| 42 | 42 | ||
| 43 | pub const std_options: std.Options = .{ | 43 | pub const std_options: std.Options = .{ |
| 44 | .logFn = log, | 44 | .logFn = log, |
| 45 | 45 | .log_level = switch (build_options.log_level) { | |
| 46 | .log_level = switch (builtin.mode) { | 46 | inline else => |log_level| @field(std.log.Level, @tagName(log_level)), |
| 47 | .debug => .debug, | ||
| 48 | .safe, .fast => .info, | ||
| 49 | .small => .err, | ||
| 50 | }, | 47 | }, |
| 51 | }; | 48 | }; |
| 52 | pub const std_options_cwd = if (native_os == .wasi) wasi_cwd else null; | 49 | pub const std_options_cwd = if (native_os == .wasi) wasi_cwd else null; |
| ... | @@ -104,7 +101,7 @@ const normal_usage = | ... | @@ -104,7 +101,7 @@ const normal_usage = |
| 104 | \\ help Print this help and exit | 101 | \\ help Print this help and exit |
| 105 | \\ cache-cat Print a zig-cache manifest file as zon | 102 | \\ cache-cat Print a zig-cache manifest file as zon |
| 106 | \\ std View standard library documentation in a browser | 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 | \\ targets List available compilation targets | 105 | \\ targets List available compilation targets |
| 109 | \\ version Print version number and exit | 106 | \\ version Print version number and exit |
| 110 | \\ zen Print Zen of Zig and exit | 107 | \\ zen Print Zen of Zig and exit |
| ... | @@ -126,7 +123,15 @@ const debug_usage = normal_usage ++ | ... | @@ -126,7 +123,15 @@ const debug_usage = normal_usage ++ |
| 126 | 123 | ||
| 127 | const usage = if (build_options.enable_debug_extensions) debug_usage else normal_usage; | 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 | pub fn log( | 136 | pub fn log( |
| 132 | comptime level: std.log.Level, | 137 | comptime level: std.log.Level, |
| ... | @@ -135,18 +140,11 @@ pub fn log( | ... | @@ -135,18 +140,11 @@ pub fn log( |
| 135 | args: anytype, | 140 | args: anytype, |
| 136 | ) void { | 141 | ) void { |
| 137 | // Hide debug messages unless: | 142 | // Hide debug messages unless: |
| 138 | // * logging enabled with `-Dlog`. | 143 | // * logging enabled with `-Ddebug-extensions` or `-Dlog=debug`. |
| 139 | // * the --debug-log arg for the scope has been provided | 144 | // * the --debug-log arg for the scope has been provided |
| 140 | if (@backingInt(level) > @backingInt(std.options.log_level) or | 145 | switch (level) { |
| 141 | @backingInt(level) > @backingInt(std.log.Level.info)) | 146 | else => {}, |
| 142 | { | 147 | .debug => if (!debugLogScopeEnabled(@tagName(scope))) return, |
| 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; | ||
| 150 | } | 148 | } |
| 151 | 149 | ||
| 152 | // Otherwise, use the default implementation. | 150 | // Otherwise, use the default implementation. |
| ... | @@ -557,11 +555,14 @@ const compile_usage = | ... | @@ -557,11 +555,14 @@ const compile_usage = |
| 557 | \\ -fno-emit-docs (default) Do not produce docs/ dir with html documentation | 555 | \\ -fno-emit-docs (default) Do not produce docs/ dir with html documentation |
| 558 | \\ -femit-implib[=path] (default) Produce an import .lib when building a Windows DLL | 556 | \\ -femit-implib[=path] (default) Produce an import .lib when building a Windows DLL |
| 559 | \\ -fno-emit-implib Do not produce an import .lib when building a Windows DLL | 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 | \\ --cache-dir [path] Override the local cache directory | 558 | \\ --cache-dir [path] Override the local cache directory |
| 562 | \\ --global-cache-dir [path] Override the global cache directory | 559 | \\ --global-cache-dir [path] Override the global cache directory |
| 563 | \\ --zig-lib-dir [path] Override path to Zig installation lib directory | 560 | \\ --zig-lib-dir [path] Override path to Zig installation lib directory |
| 564 | \\ --build-root [path] Override path to project source files | 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 | \\Global Compile Options: | 567 | \\Global Compile Options: |
| 567 | \\ --name [name] Compilation unit name (not a file path) | 568 | \\ --name [name] Compilation unit name (not a file path) |
| ... | @@ -593,7 +594,6 @@ const compile_usage = | ... | @@ -593,7 +594,6 @@ const compile_usage = |
| 593 | \\ -fpatchable-function-entry=[num] Add num NOPs of padding in function prologues | 594 | \\ -fpatchable-function-entry=[num] Add num NOPs of padding in function prologues |
| 594 | \\ -mexec-model=[value] (WASI) Execution model | 595 | \\ -mexec-model=[value] (WASI) Execution model |
| 595 | \\ -municode (Windows) Use wmain/wWinMain as entry point | 596 | \\ -municode (Windows) Use wmain/wWinMain as entry point |
| 596 | \\ --time-report Send timing diagnostics to '--listen' clients | ||
| 597 | \\ | 597 | \\ |
| 598 | \\Per-Module Compile Options: | 598 | \\Per-Module Compile Options: |
| 599 | \\ --dep [[import=]name] Add an entry to the next module's import table | 599 | \\ --dep [[import=]name] Add an entry to the next module's import table |
| ... | @@ -604,13 +604,15 @@ const compile_usage = | ... | @@ -604,13 +604,15 @@ const compile_usage = |
| 604 | \\ safe Enable both safety checks and machine code optimizations | 604 | \\ safe Enable both safety checks and machine code optimizations |
| 605 | \\ small Prioritize small binary size. Safety checks off. | 605 | \\ small Prioritize small binary size. Safety checks off. |
| 606 | \\ -ofmt=[fmt] Override target object format | 606 | \\ -ofmt=[fmt] Override target object format |
| 607 | \\ elf Executable and Linking Format | ||
| 608 | \\ c C source code | 607 | \\ c C source code |
| 609 | \\ wasm WebAssembly | ||
| 610 | \\ coff Common Object File Format (Windows) | 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 | \\ macho macOS relocatables | 612 | \\ macho macOS relocatables |
| 612 | \\ spirv Standard, Portable Intermediate Representation V (SPIR-V) | ||
| 613 | \\ plan9 Plan 9 from Bell Labs object format | 613 | \\ plan9 Plan 9 from Bell Labs object format |
| 614 | \\ spirv Standard, Portable Intermediate Representation V (SPIR-V) | ||
| 615 | \\ wasm WebAssembly | ||
| 614 | \\ hex (planned feature) Intel IHEX | 616 | \\ hex (planned feature) Intel IHEX |
| 615 | \\ raw (planned feature) Dump machine code directly | 617 | \\ raw (planned feature) Dump machine code directly |
| 616 | \\ -mcpu [cpu] Specify target CPU and feature set | 618 | \\ -mcpu [cpu] Specify target CPU and feature set |
| ... | @@ -791,15 +793,6 @@ const compile_usage = | ... | @@ -791,15 +793,6 @@ const compile_usage = |
| 791 | \\Debug Options (Zig Compiler Development): | 793 | \\Debug Options (Zig Compiler Development): |
| 792 | \\ -fopt-bisect-limit=[limit] Only run [limit] first LLVM optimization passes | 794 | \\ -fopt-bisect-limit=[limit] Only run [limit] first LLVM optimization passes |
| 793 | \\ -fstack-report Print stack size diagnostics | 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 | \\ --debug-log [scope] Enable printing debug/info log messages for scope | 796 | \\ --debug-log [scope] Enable printing debug/info log messages for scope |
| 804 | \\ --debug-compile-errors Crash with helpful diagnostics at the first compile error | 797 | \\ --debug-compile-errors Crash with helpful diagnostics at the first compile error |
| 805 | \\ --debug-link-snapshot Dump linker state and output file information for troubleshooting | 798 | \\ --debug-link-snapshot Dump linker state and output file information for troubleshooting |
| ... | @@ -933,17 +926,11 @@ fn buildOutputType( | ... | @@ -933,17 +926,11 @@ fn buildOutputType( |
| 933 | var listen: Listen = .none; | 926 | var listen: Listen = .none; |
| 934 | var debug_compile_errors = false; | 927 | var debug_compile_errors = false; |
| 935 | var debug_incremental = false; | 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 | var verbose_cc = (native_os != .wasi or builtin.link_libc) and | 929 | var verbose_cc = (native_os != .wasi or builtin.link_libc) and |
| 939 | EnvVar.ZIG_VERBOSE_CC.isSet(environ_map); | 930 | EnvVar.ZIG_VERBOSE_CC.isSet(environ_map); |
| 940 | var verbose_air = false; | 931 | var verbose_link = (native_os != .wasi or builtin.link_libc) and |
| 941 | var verbose_intern_pool = false; | 932 | EnvVar.ZIG_VERBOSE_LINK.isSet(environ_map); |
| 942 | var verbose_generic_instances = false; | ||
| 943 | var verbose_llvm_ir: ?[]const u8 = null; | ||
| 944 | var verbose_llvm_bc: ?[]const u8 = null; | ||
| 945 | var link_depfile: ?[]const u8 = null; | 933 | var link_depfile: ?[]const u8 = null; |
| 946 | var verbose_llvm_cpu_features = false; | ||
| 947 | var time_report = false; | 934 | var time_report = false; |
| 948 | var stack_report = false; | 935 | var stack_report = false; |
| 949 | var show_builtin = false; | 936 | var show_builtin = false; |
| ... | @@ -1809,24 +1796,10 @@ fn buildOutputType( | ... | @@ -1809,24 +1796,10 @@ fn buildOutputType( |
| 1809 | } else { | 1796 | } else { |
| 1810 | warn("Zig was compiled without debug extensions. --debug-compile-errors has no effect.", .{}); | 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 | } else if (mem.eql(u8, arg, "--verbose-cc")) { | 1799 | } else if (mem.eql(u8, arg, "--verbose-cc")) { |
| 1815 | verbose_cc = true; | 1800 | verbose_cc = true; |
| 1816 | } else if (mem.eql(u8, arg, "--verbose-air")) { | 1801 | } else if (mem.eql(u8, arg, "--verbose-link")) { |
| 1817 | verbose_air = true; | 1802 | verbose_link = 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; | ||
| 1830 | } else if (mem.cutPrefix(u8, arg, "-T")) |rest| { | 1803 | } else if (mem.cutPrefix(u8, arg, "-T")) |rest| { |
| 1831 | linker_script = rest; | 1804 | linker_script = rest; |
| 1832 | } else if (mem.cutPrefix(u8, arg, "-L")) |rest| { | 1805 | } else if (mem.cutPrefix(u8, arg, "-L")) |rest| { |
| ... | @@ -3729,13 +3702,7 @@ fn buildOutputType( | ... | @@ -3729,13 +3702,7 @@ fn buildOutputType( |
| 3729 | .libc_installation = if (create_module.libc_installation) |*lci| lci else null, | 3702 | .libc_installation = if (create_module.libc_installation) |*lci| lci else null, |
| 3730 | .verbose_cc = verbose_cc, | 3703 | .verbose_cc = verbose_cc, |
| 3731 | .verbose_link = verbose_link, | 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 | .link_depfile = link_depfile, | 3705 | .link_depfile = link_depfile, |
| 3738 | .verbose_llvm_cpu_features = verbose_llvm_cpu_features, | ||
| 3739 | .time_report = time_report, | 3706 | .time_report = time_report, |
| 3740 | .stack_report = stack_report, | 3707 | .stack_report = stack_report, |
| 3741 | .build_id = build_id, | 3708 | .build_id = build_id, |
| ... | @@ -3956,10 +3923,10 @@ fn buildOutputType( | ... | @@ -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)); | 3926 | try test_exec_args.ensureUnusedCapacity(arena, 2 * log_scopes.count() + @intFromBool(verbose_link) + @intFromBool(verbose_cc)); |
| 3960 | for (log_scopes.items) |log_scope| test_exec_args.appendSliceAssumeCapacity(&.{ "--debug-log", log_scope }); | 3927 | for (log_scopes.keys()) |log_scope| test_exec_args.appendSliceAssumeCapacity(&.{ "--debug-log", log_scope }); |
| 3961 | if (verbose_link) test_exec_args.appendAssumeCapacity("--verbose-link"); | ||
| 3962 | if (verbose_cc) test_exec_args.appendAssumeCapacity("--verbose-cc"); | 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 | try runOrTest( | 3932 | try runOrTest( |
| ... | @@ -5627,17 +5594,17 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map: | ... | @@ -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 | const source: [:0]const u8 = s: { | 5598 | const source: [:0]const u8 = s: { |
| 5632 | var f = if (zig_source_path) |p| file: { | 5599 | var f = if (zig_source_path) |p| file: { |
| 5633 | break :file Io.Dir.cwd().openFile(io, p, .{}) catch |err| { | 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 | } else Io.File.stdin(); | 5603 | } else Io.File.stdin(); |
| 5637 | defer if (zig_source_path != null) f.close(io); | 5604 | defer if (zig_source_path != null) f.close(io); |
| 5638 | var file_reader: Io.File.Reader = f.reader(io, &stdin_buffer); | 5605 | var file_reader: Io.File.Reader = f.reader(io, &stdin_buffer); |
| 5639 | break :s std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| { | 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,7 +5628,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map: |
| 5661 | 5628 | ||
| 5662 | if (zir.hasCompileErrors()) { | 5629 | if (zir.hasCompileErrors()) { |
| 5663 | var wip_errors: std.zig.ErrorBundle.Wip = try .init(arena); | 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 | var error_bundle = try wip_errors.toOwnedBundle(""); | 5632 | var error_bundle = try wip_errors.toOwnedBundle(""); |
| 5666 | try error_bundle.renderToStderr(io, .{}, color); | 5633 | try error_bundle.renderToStderr(io, .{}, color); |
| 5667 | if (zir.loweringFailed()) { | 5634 | if (zir.loweringFailed()) { |
| ... | @@ -5731,7 +5698,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map: | ... | @@ -5731,7 +5698,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map: |
| 5731 | const zoir = try ZonGen.generate(arena, tree, .{}); | 5698 | const zoir = try ZonGen.generate(arena, tree, .{}); |
| 5732 | if (zoir.hasCompileErrors()) { | 5699 | if (zoir.hasCompileErrors()) { |
| 5733 | var wip_errors: std.zig.ErrorBundle.Wip = try .init(arena); | 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 | var error_bundle = try wip_errors.toOwnedBundle(""); | 5702 | var error_bundle = try wip_errors.toOwnedBundle(""); |
| 5736 | error_bundle.renderToStderr(io, .{}, color) catch {}; | 5703 | error_bundle.renderToStderr(io, .{}, color) catch {}; |
| 5737 | process.exit(1); | 5704 | process.exit(1); |
| ... | @@ -6254,9 +6221,8 @@ fn randInt(io: Io, comptime T: type) T { | ... | @@ -6254,9 +6221,8 @@ fn randInt(io: Io, comptime T: type) T { |
| 6254 | } | 6221 | } |
| 6255 | 6222 | ||
| 6256 | fn addDebugLog(arena: Allocator, scope_name: []const u8) error{OutOfMemory}!void { | 6223 | fn addDebugLog(arena: Allocator, scope_name: []const u8) error{OutOfMemory}!void { |
| 6257 | if (!build_options.enable_logging) { | 6224 | switch (build_options.log_level) { |
| 6258 | warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); | 6225 | else => warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}), |
| 6259 | } else { | 6226 | .debug => try log_scopes.put(arena, try arena.dupe(u8, scope_name), {}), |
| 6260 | try log_scopes.append(arena, 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,6 +193,8 @@ pub fn hasLlvmSupport(target: *const std.Target, ofmt: std.Target.ObjectFormat) |
| 193 | .coff, | 193 | .coff, |
| 194 | .elf, | 194 | .elf, |
| 195 | .hex, | 195 | .hex, |
| 196 | .llvmbc, | ||
| 197 | .llvmir, | ||
| 196 | .macho, | 198 | .macho, |
| 197 | .spirv, | 199 | .spirv, |
| 198 | .raw, | 200 | .raw, |
src/zig_llvm.cpp+5-3| ... | @@ -410,6 +410,10 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi | ... | @@ -410,6 +410,10 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi |
| 410 | // Code generation phase | 410 | // Code generation phase |
| 411 | codegen_pm.run(llvm_module); | 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 | if (options->llvm_ir_filename) { | 417 | if (options->llvm_ir_filename) { |
| 414 | if (LLVMPrintModuleToFile(module_ref, options->llvm_ir_filename, error_message)) { | 418 | if (LLVMPrintModuleToFile(module_ref, options->llvm_ir_filename, error_message)) { |
| 415 | return true; | 419 | return true; |
| ... | @@ -430,9 +434,7 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi | ... | @@ -430,9 +434,7 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi |
| 430 | auto os = raw_string_ostream(out_str); | 434 | auto os = raw_string_ostream(out_str); |
| 431 | TimerGroup::printAll(os); | 435 | TimerGroup::printAll(os); |
| 432 | TimerGroup::clearAll(); | 436 | TimerGroup::clearAll(); |
| 433 | auto c_str = (char *)malloc(out_str.length() + 1); | 437 | *options->time_report_out = LLVMCreateMessage(out_str.c_str()); |
| 434 | strcpy(c_str, out_str.c_str()); | ||
| 435 | *options->time_report_out = c_str; | ||
| 436 | } | 438 | } |
| 437 | return false; | 439 | return false; |
| 438 | } | 440 | } |
src/zig_llvm.h+6-2| ... | @@ -67,8 +67,8 @@ struct ZigLLVMEmitOptions { | ... | @@ -67,8 +67,8 @@ struct ZigLLVMEmitOptions { |
| 67 | bool is_debug; | 67 | bool is_debug; |
| 68 | bool is_small; | 68 | bool is_small; |
| 69 | // If not null, and `ZigLLVMTargetMachineEmitToFile` returns `false` indicating success, this | 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 | 70 | // `char *` will be populated with the serialized (as JSON) time report data. The caller is |
| 71 | // JSON) time report data. The caller is responsible for freeing that memory. | 71 | // responsible for freeing that memory with `disposeMessage`. |
| 72 | char **time_report_out; | 72 | char **time_report_out; |
| 73 | bool tsan; | 73 | bool tsan; |
| 74 | bool sancov; | 74 | bool sancov; |
| ... | @@ -79,6 +79,10 @@ struct ZigLLVMEmitOptions { | ... | @@ -79,6 +79,10 @@ struct ZigLLVMEmitOptions { |
| 79 | const char *bin_filename; | 79 | const char *bin_filename; |
| 80 | const char *llvm_ir_filename; | 80 | const char *llvm_ir_filename; |
| 81 | const char *bitcode_filename; | 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 | ZigLLVMCoverageOptions coverage; | 86 | ZigLLVMCoverageOptions coverage; |
| 83 | }; | 87 | }; |
| 84 | 88 |
stage1/config.zig.in+1-1| ... | @@ -6,7 +6,7 @@ pub const llvm_has_xtensa = false; | ... | @@ -6,7 +6,7 @@ pub const llvm_has_xtensa = false; |
| 6 | pub const version: [:0]const u8 = "@RESOLVED_ZIG_VERSION@"; | 6 | pub const version: [:0]const u8 = "@RESOLVED_ZIG_VERSION@"; |
| 7 | pub const semver = @import("std").SemanticVersion.parse(version) catch unreachable; | 7 | pub const semver = @import("std").SemanticVersion.parse(version) catch unreachable; |
| 8 | pub const enable_debug_extensions = false; | 8 | pub const enable_debug_extensions = false; |
| 9 | pub const enable_logging = false; | 9 | pub const log_level: @import("std").log.Level = .err; |
| 10 | pub const enable_link_snapshots = false; | 10 | pub const enable_link_snapshots = false; |
| 11 | pub const enable_tracy = false; | 11 | pub const enable_tracy = false; |
| 12 | pub const value_tracing = false; | 12 | pub const value_tracing = false; |