authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-06-12 20:46:36-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-06-12 20:46:36-04:00
logdcdb4422b801f2d184107fdd7b9493f7840a0244
treeca7a37c544382c10e45fbad68ea7701a05d0543c
parent5e3c0b7af7cd866f5464c244b9775e488b93ae48
parent43d01ff69f6c6c46bef81dd4de2c78fb0a942b65
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #24124 from mlugg/better-backend-pipeline-2

compiler: threaded codegen (and more goodies)

74 files changed, 8061 insertions(+), 7609 deletions(-)

CMakeLists.txt+2-1
......@@ -535,7 +535,6 @@ set(ZIG_STAGE2_SOURCES
535535 src/Sema.zig
536536 src/Sema/bitcast.zig
537537 src/Sema/comptime_ptr_access.zig
538 src/ThreadSafeQueue.zig
539538 src/Type.zig
540539 src/Value.zig
541540 src/Zcu.zig
......@@ -624,6 +623,7 @@ set(ZIG_STAGE2_SOURCES
624623 src/link/Elf/synthetic_sections.zig
625624 src/link/Goff.zig
626625 src/link/LdScript.zig
626 src/link/Lld.zig
627627 src/link/MachO.zig
628628 src/link/MachO/Archive.zig
629629 src/link/MachO/Atom.zig
......@@ -652,6 +652,7 @@ set(ZIG_STAGE2_SOURCES
652652 src/link/MachO/uuid.zig
653653 src/link/Plan9.zig
654654 src/link/Plan9/aout.zig
655 src/link/Queue.zig
655656 src/link/SpirV.zig
656657 src/link/SpirV/BinaryModule.zig
657658 src/link/SpirV/deduplicate.zig
lib/std/Build/Step/Compile.zig+25-41
......@@ -1834,47 +1834,16 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
18341834 lp.path = b.fmt("{}", .{output_dir});
18351835 }
18361836
1837 // -femit-bin[=path] (default) Output machine code
1838 if (compile.generated_bin) |bin| {
1839 bin.path = output_dir.joinString(b.allocator, compile.out_filename) catch @panic("OOM");
1840 }
1841
1842 const sep = std.fs.path.sep_str;
1843
1844 // output PDB if someone requested it
1845 if (compile.generated_pdb) |pdb| {
1846 pdb.path = b.fmt("{}" ++ sep ++ "{s}.pdb", .{ output_dir, compile.name });
1847 }
1848
1849 // -femit-implib[=path] (default) Produce an import .lib when building a Windows DLL
1850 if (compile.generated_implib) |implib| {
1851 implib.path = b.fmt("{}" ++ sep ++ "{s}.lib", .{ output_dir, compile.name });
1852 }
1853
1854 // -femit-h[=path] Generate a C header file (.h)
1855 if (compile.generated_h) |lp| {
1856 lp.path = b.fmt("{}" ++ sep ++ "{s}.h", .{ output_dir, compile.name });
1857 }
1858
1859 // -femit-docs[=path] Create a docs/ dir with html documentation
1860 if (compile.generated_docs) |generated_docs| {
1861 generated_docs.path = output_dir.joinString(b.allocator, "docs") catch @panic("OOM");
1862 }
1863
1864 // -femit-asm[=path] Output .s (assembly code)
1865 if (compile.generated_asm) |lp| {
1866 lp.path = b.fmt("{}" ++ sep ++ "{s}.s", .{ output_dir, compile.name });
1867 }
1868
1869 // -femit-llvm-ir[=path] Produce a .ll file with optimized LLVM IR (requires LLVM extensions)
1870 if (compile.generated_llvm_ir) |lp| {
1871 lp.path = b.fmt("{}" ++ sep ++ "{s}.ll", .{ output_dir, compile.name });
1872 }
1873
1874 // -femit-llvm-bc[=path] Produce an optimized LLVM module as a .bc file (requires LLVM extensions)
1875 if (compile.generated_llvm_bc) |lp| {
1876 lp.path = b.fmt("{}" ++ sep ++ "{s}.bc", .{ output_dir, compile.name });
1877 }
1837 // zig fmt: off
1838 if (compile.generated_bin) |lp| lp.path = compile.outputPath(output_dir, .bin);
1839 if (compile.generated_pdb) |lp| lp.path = compile.outputPath(output_dir, .pdb);
1840 if (compile.generated_implib) |lp| lp.path = compile.outputPath(output_dir, .implib);
1841 if (compile.generated_h) |lp| lp.path = compile.outputPath(output_dir, .h);
1842 if (compile.generated_docs) |lp| lp.path = compile.outputPath(output_dir, .docs);
1843 if (compile.generated_asm) |lp| lp.path = compile.outputPath(output_dir, .@"asm");
1844 if (compile.generated_llvm_ir) |lp| lp.path = compile.outputPath(output_dir, .llvm_ir);
1845 if (compile.generated_llvm_bc) |lp| lp.path = compile.outputPath(output_dir, .llvm_bc);
1846 // zig fmt: on
18781847 }
18791848
18801849 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic and
......@@ -1888,6 +1857,21 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
18881857 );
18891858 }
18901859}
1860fn outputPath(c: *Compile, out_dir: std.Build.Cache.Path, ea: std.zig.EmitArtifact) []const u8 {
1861 const arena = c.step.owner.graph.arena;
1862 const name = ea.cacheName(arena, .{
1863 .root_name = c.name,
1864 .target = c.root_module.resolved_target.?.result,
1865 .output_mode = switch (c.kind) {
1866 .lib => .Lib,
1867 .obj, .test_obj => .Obj,
1868 .exe, .@"test" => .Exe,
1869 },
1870 .link_mode = c.linkage,
1871 .version = c.version,
1872 }) catch @panic("OOM");
1873 return out_dir.joinString(arena, name) catch @panic("OOM");
1874}
18911875
18921876pub fn rebuildInFuzzMode(c: *Compile, progress_node: std.Progress.Node) !Path {
18931877 const gpa = c.step.owner.allocator;
lib/std/Progress.zig+22
......@@ -234,6 +234,28 @@ pub const Node = struct {
234234 _ = @atomicRmw(u32, &storage.completed_count, .Add, 1, .monotonic);
235235 }
236236
237 /// Thread-safe. Bytes after '0' in `new_name` are ignored.
238 pub fn setName(n: Node, new_name: []const u8) void {
239 const index = n.index.unwrap() orelse return;
240 const storage = storageByIndex(index);
241
242 const name_len = @min(max_name_len, std.mem.indexOfScalar(u8, new_name, 0) orelse new_name.len);
243
244 copyAtomicStore(storage.name[0..name_len], new_name[0..name_len]);
245 if (name_len < storage.name.len)
246 @atomicStore(u8, &storage.name[name_len], 0, .monotonic);
247 }
248
249 /// Gets the name of this `Node`.
250 /// A pointer to this array can later be passed to `setName` to restore the name.
251 pub fn getName(n: Node) [max_name_len]u8 {
252 var dest: [max_name_len]u8 align(@alignOf(usize)) = undefined;
253 if (n.index.unwrap()) |index| {
254 copyAtomicLoad(&dest, &storageByIndex(index).name);
255 }
256 return dest;
257 }
258
237259 /// Thread-safe.
238260 pub fn setCompletedItems(n: Node, completed_items: usize) void {
239261 const index = n.index.unwrap() orelse return;
lib/std/heap/debug_allocator.zig+2-2
......@@ -212,8 +212,8 @@ pub fn DebugAllocator(comptime config: Config) type {
212212 DummyMutex{};
213213
214214 const DummyMutex = struct {
215 inline fn lock(_: *DummyMutex) void {}
216 inline fn unlock(_: *DummyMutex) void {}
215 inline fn lock(_: DummyMutex) void {}
216 inline fn unlock(_: DummyMutex) void {}
217217 };
218218
219219 const stack_n = config.stack_trace_frames;
lib/std/multi_array_list.zig+16
......@@ -135,6 +135,22 @@ pub fn MultiArrayList(comptime T: type) type {
135135 self.* = undefined;
136136 }
137137
138 /// Returns a `Slice` representing a range of elements in `s`, analagous to `arr[off..len]`.
139 /// It is illegal to call `deinit` or `toMultiArrayList` on the returned `Slice`.
140 /// Asserts that `off + len <= s.len`.
141 pub fn subslice(s: Slice, off: usize, len: usize) Slice {
142 assert(off + len <= s.len);
143 var ptrs: [fields.len][*]u8 = undefined;
144 inline for (s.ptrs, &ptrs, fields) |in, *out, field| {
145 out.* = in + (off * @sizeOf(field.type));
146 }
147 return .{
148 .ptrs = ptrs,
149 .len = len,
150 .capacity = len,
151 };
152 }
153
138154 /// This function is used in the debugger pretty formatters in tools/ to fetch the
139155 /// child field order and entry type to facilitate fancy debug printing for this type.
140156 fn dbHelper(self: *Slice, child: *Elem, field: *Field, entry: *Entry) void {
lib/std/zig.zig+29
......@@ -884,6 +884,35 @@ pub const SimpleComptimeReason = enum(u32) {
884884 }
885885};
886886
887/// Every kind of artifact which the compiler can emit.
888pub const EmitArtifact = enum {
889 bin,
890 @"asm",
891 implib,
892 llvm_ir,
893 llvm_bc,
894 docs,
895 pdb,
896 h,
897
898 /// If using `Server` to communicate with the compiler, it will place requested artifacts in
899 /// paths under the output directory, where those paths are named according to this function.
900 /// Returned string is allocated with `gpa` and owned by the caller.
901 pub fn cacheName(ea: EmitArtifact, gpa: Allocator, opts: BinNameOptions) Allocator.Error![]const u8 {
902 const suffix: []const u8 = switch (ea) {
903 .bin => return binNameAlloc(gpa, opts),
904 .@"asm" => ".s",
905 .implib => ".lib",
906 .llvm_ir => ".ll",
907 .llvm_bc => ".bc",
908 .docs => "-docs",
909 .pdb => ".pdb",
910 .h => ".h",
911 };
912 return std.fmt.allocPrint(gpa, "{s}{s}", .{ opts.root_name, suffix });
913 }
914};
915
887916test {
888917 _ = Ast;
889918 _ = AstRlAnnotate;
lib/std/zig/Zir.zig+9
......@@ -4861,6 +4861,15 @@ pub fn getParamBody(zir: Zir, fn_inst: Inst.Index) []const Zir.Inst.Index {
48614861 }
48624862}
48634863
4864pub fn getParamName(zir: Zir, param_inst: Inst.Index) ?NullTerminatedString {
4865 const inst = zir.instructions.get(@intFromEnum(param_inst));
4866 return switch (inst.tag) {
4867 .param, .param_comptime => zir.extraData(Inst.Param, inst.data.pl_tok.payload_index).data.name,
4868 .param_anytype, .param_anytype_comptime => inst.data.str_tok.start,
4869 else => null,
4870 };
4871}
4872
48644873pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
48654874 const tags = zir.instructions.items(.tag);
48664875 const datas = zir.instructions.items(.data);
src/Air.zig+1-3
......@@ -1153,9 +1153,7 @@ pub const Inst = struct {
11531153 ty: Type,
11541154 arg: struct {
11551155 ty: Ref,
1156 /// Index into `extra` of a null-terminated string representing the parameter name.
1157 /// This is `.none` if debug info is stripped.
1158 name: NullTerminatedString,
1156 zir_param_index: u32,
11591157 },
11601158 ty_op: struct {
11611159 ty: Ref,
src/Air/print.zig+1-4
......@@ -363,10 +363,7 @@ const Writer = struct {
363363 fn writeArg(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
364364 const arg = w.air.instructions.items(.data)[@intFromEnum(inst)].arg;
365365 try w.writeType(s, arg.ty.toType());
366 switch (arg.name) {
367 .none => {},
368 _ => try s.print(", \"{}\"", .{std.zig.fmtEscapes(arg.name.toSlice(w.air))}),
369 }
366 try s.print(", {d}", .{arg.zir_param_index});
370367 }
371368
372369 fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
src/Compilation.zig+611-497
......@@ -43,7 +43,6 @@ const Air = @import("Air.zig");
4343const Builtin = @import("Builtin.zig");
4444const LlvmObject = @import("codegen/llvm.zig").Object;
4545const dev = @import("dev.zig");
46const ThreadSafeQueue = @import("ThreadSafeQueue.zig").ThreadSafeQueue;
4746
4847pub const Config = @import("Compilation/Config.zig");
4948
......@@ -56,8 +55,7 @@ gpa: Allocator,
5655arena: Allocator,
5756/// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
5857zcu: ?*Zcu,
59/// Contains different state depending on whether the Compilation uses
60/// incremental or whole cache mode.
58/// Contains different state depending on the `CacheMode` used by this `Compilation`.
6159cache_use: CacheUse,
6260/// All compilations have a root module because this is where some important
6361/// settings are stored, such as target and optimization mode. This module
......@@ -68,17 +66,13 @@ root_mod: *Package.Module,
6866config: Config,
6967
7068/// The main output file.
71/// In whole cache mode, this is null except for during the body of the update
72/// function. In incremental cache mode, this is a long-lived object.
73/// In both cases, this is `null` when `-fno-emit-bin` is used.
69/// In `CacheMode.whole`, this is null except for during the body of `update`.
70/// In `CacheMode.none` and `CacheMode.incremental`, this is long-lived.
71/// Regardless of cache mode, this is `null` when `-fno-emit-bin` is used.
7472bin_file: ?*link.File,
7573
7674/// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin)
7775sysroot: ?[]const u8,
78/// This is `null` when not building a Windows DLL, or when `-fno-emit-implib` is used.
79implib_emit: ?Cache.Path,
80/// This is non-null when `-femit-docs` is provided.
81docs_emit: ?Cache.Path,
8276root_name: [:0]const u8,
8377compiler_rt_strat: RtStrat,
8478ubsan_rt_strat: RtStrat,
......@@ -113,17 +107,7 @@ win32_resource_table: if (dev.env.supports(.win32_resource)) std.AutoArrayHashMa
113107} = .{},
114108
115109link_diags: link.Diags,
116link_task_queue: ThreadSafeQueue(link.Task) = .empty,
117/// Ensure only 1 simultaneous call to `flushTaskQueue`.
118link_task_queue_safety: std.debug.SafetyLock = .{},
119/// If any tasks are queued up that depend on prelink being finished, they are moved
120/// here until prelink finishes.
121link_task_queue_postponed: std.ArrayListUnmanaged(link.Task) = .empty,
122/// Initialized with how many link input tasks are expected. After this reaches zero
123/// the linker will begin the prelink phase.
124/// Initialized in the Compilation main thread before the pipeline; modified only in
125/// the linker task thread.
126remaining_prelink_tasks: u32,
110link_task_queue: link.Queue = .empty,
127111
128112/// Set of work that can be represented by only flags to determine whether the
129113/// work is queued or not.
......@@ -270,12 +254,8 @@ mutex: if (builtin.single_threaded) struct {
270254test_filters: []const []const u8,
271255test_name_prefix: ?[]const u8,
272256
273emit_asm: ?EmitLoc,
274emit_llvm_ir: ?EmitLoc,
275emit_llvm_bc: ?EmitLoc,
276
277257link_task_wait_group: WaitGroup = .{},
278work_queue_progress_node: std.Progress.Node = .none,
258link_prog_node: std.Progress.Node = std.Progress.Node.none,
279259
280260llvm_opt_bisect_limit: c_int,
281261
......@@ -285,6 +265,31 @@ file_system_inputs: ?*std.ArrayListUnmanaged(u8),
285265/// This digest will be known after update() is called.
286266digest: ?[Cache.bin_digest_len]u8 = null,
287267
268/// Non-`null` iff we are emitting a binary.
269/// Does not change for the lifetime of this `Compilation`.
270/// Cwd-relative if `cache_use == .none`. Otherwise, relative to our subdirectory in the cache.
271emit_bin: ?[]const u8,
272/// Non-`null` iff we are emitting assembly.
273/// Does not change for the lifetime of this `Compilation`.
274/// Cwd-relative if `cache_use == .none`. Otherwise, relative to our subdirectory in the cache.
275emit_asm: ?[]const u8,
276/// Non-`null` iff we are emitting an implib.
277/// Does not change for the lifetime of this `Compilation`.
278/// Cwd-relative if `cache_use == .none`. Otherwise, relative to our subdirectory in the cache.
279emit_implib: ?[]const u8,
280/// Non-`null` iff we are emitting LLVM IR.
281/// Does not change for the lifetime of this `Compilation`.
282/// Cwd-relative if `cache_use == .none`. Otherwise, relative to our subdirectory in the cache.
283emit_llvm_ir: ?[]const u8,
284/// Non-`null` iff we are emitting LLVM bitcode.
285/// Does not change for the lifetime of this `Compilation`.
286/// Cwd-relative if `cache_use == .none`. Otherwise, relative to our subdirectory in the cache.
287emit_llvm_bc: ?[]const u8,
288/// Non-`null` iff we are emitting documentation.
289/// Does not change for the lifetime of this `Compilation`.
290/// Cwd-relative if `cache_use == .none`. Otherwise, relative to our subdirectory in the cache.
291emit_docs: ?[]const u8,
292
288293const QueuedJobs = struct {
289294 compiler_rt_lib: bool = false,
290295 compiler_rt_obj: bool = false,
......@@ -785,13 +790,6 @@ pub const CrtFile = struct {
785790 lock: Cache.Lock,
786791 full_object_path: Cache.Path,
787792
788 pub fn isObject(cf: CrtFile) bool {
789 return switch (classifyFileExt(cf.full_object_path.sub_path)) {
790 .object => true,
791 else => false,
792 };
793 }
794
795793 pub fn deinit(self: *CrtFile, gpa: Allocator) void {
796794 self.lock.release();
797795 gpa.free(self.full_object_path.sub_path);
......@@ -846,19 +844,34 @@ pub const RcIncludes = enum {
846844};
847845
848846const Job = union(enum) {
849 /// Corresponds to the task in `link.Task`.
850 /// Only needed for backends that haven't yet been updated to not race against Sema.
851 codegen_nav: InternPool.Nav.Index,
852 /// Corresponds to the task in `link.Task`.
853 /// Only needed for backends that haven't yet been updated to not race against Sema.
854 codegen_func: link.Task.CodegenFunc,
855 /// Corresponds to the task in `link.Task`.
856 /// Only needed for backends that haven't yet been updated to not race against Sema.
857 codegen_type: InternPool.Index,
847 /// Given the generated AIR for a function, put it onto the code generation queue.
848 /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that
849 /// all types are resolved before the linker task is queued.
850 /// If the backend does not support `Zcu.Feature.separate_thread`, codegen and linking happen immediately.
851 /// Before queueing this `Job`, increase the estimated total item count for both
852 /// `comp.zcu.?.codegen_prog_node` and `comp.link_prog_node`.
853 codegen_func: struct {
854 func: InternPool.Index,
855 /// The AIR emitted from analyzing `func`; owned by this `Job` in `gpa`.
856 air: Air,
857 },
858 /// Queue a `link.ZcuTask` to emit this non-function `Nav` into the output binary.
859 /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that
860 /// all types are resolved before the linker task is queued.
861 /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately.
862 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
863 link_nav: InternPool.Nav.Index,
864 /// Queue a `link.ZcuTask` to emit debug information for this container type.
865 /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that
866 /// all types are resolved before the linker task is queued.
867 /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately.
868 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
869 link_type: InternPool.Index,
870 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
858871 update_line_number: InternPool.TrackedInst.Index,
859872 /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed.
860873 /// This may be its first time being analyzed, or it may be outdated.
861 /// If the unit is a function, a `codegen_func` job will then be queued.
874 /// If the unit is a test function, an `analyze_func` job will then be queued.
862875 analyze_comptime_unit: InternPool.AnalUnit,
863876 /// This function must be semantically analyzed.
864877 /// This may be its first time being analyzed, or it may be outdated.
......@@ -1322,14 +1335,6 @@ pub const MiscError = struct {
13221335 }
13231336};
13241337
1325pub const EmitLoc = struct {
1326 /// If this is `null` it means the file will be output to the cache directory.
1327 /// When provided, both the open file handle and the path name must outlive the `Compilation`.
1328 directory: ?Cache.Directory,
1329 /// This may not have sub-directories in it.
1330 basename: []const u8,
1331};
1332
13331338pub const cache_helpers = struct {
13341339 pub fn addModule(hh: *Cache.HashHelper, mod: *const Package.Module) void {
13351340 addResolvedTarget(hh, mod.resolved_target);
......@@ -1369,15 +1374,6 @@ pub const cache_helpers = struct {
13691374 hh.add(resolved_target.is_explicit_dynamic_linker);
13701375 }
13711376
1372 pub fn addEmitLoc(hh: *Cache.HashHelper, emit_loc: EmitLoc) void {
1373 hh.addBytes(emit_loc.basename);
1374 }
1375
1376 pub fn addOptionalEmitLoc(hh: *Cache.HashHelper, optional_emit_loc: ?EmitLoc) void {
1377 hh.add(optional_emit_loc != null);
1378 addEmitLoc(hh, optional_emit_loc orelse return);
1379 }
1380
13811377 pub fn addOptionalDebugFormat(hh: *Cache.HashHelper, x: ?Config.DebugFormat) void {
13821378 hh.add(x != null);
13831379 addDebugFormat(hh, x orelse return);
......@@ -1424,7 +1420,38 @@ pub const ClangPreprocessorMode = enum {
14241420pub const Framework = link.File.MachO.Framework;
14251421pub const SystemLib = link.SystemLib;
14261422
1427pub const CacheMode = enum { incremental, whole };
1423pub const CacheMode = enum {
1424 /// The results of this compilation are not cached. The compilation is always performed, and the
1425 /// results are emitted directly to their output locations. Temporary files will be placed in a
1426 /// temporary directory in the cache, but deleted after the compilation is done.
1427 ///
1428 /// This mode is typically used for direct CLI invocations like `zig build-exe`, because such
1429 /// processes are typically low-level usages which would not make efficient use of the cache.
1430 none,
1431 /// The compilation is cached based only on the options given when creating the `Compilation`.
1432 /// In particular, Zig source file contents are not included in the cache manifest. This mode
1433 /// allows incremental compilation, because the old cached compilation state can be restored
1434 /// and the old binary patched up with the changes. All files, including temporary files, are
1435 /// stored in the cache directory like '<cache>/o/<hash>/'. Temporary files are not deleted.
1436 ///
1437 /// At the time of writing, incremental compilation is only supported with the `-fincremental`
1438 /// command line flag, so this mode is rarely used. However, it is required in order to use
1439 /// incremental compilation.
1440 incremental,
1441 /// The compilation is cached based on the `Compilation` options and every input, including Zig
1442 /// source files, linker inputs, and `@embedFile` targets. If any of them change, we will see a
1443 /// cache miss, and the entire compilation will be re-run. On a cache miss, we initially write
1444 /// all output files to a directory under '<cache>/tmp/', because we don't know the final
1445 /// manifest digest until the update is almost done. Once we can compute the final digest, this
1446 /// directory is moved to '<cache>/o/<hash>/'. Temporary files are not deleted.
1447 ///
1448 /// At the time of writing, this is the most commonly used cache mode: it is used by the build
1449 /// system (and any other parent using `--listen`) unless incremental compilation is enabled.
1450 /// Once incremental compilation is more mature, it will be replaced by `incremental` in many
1451 /// cases, but still has use cases, such as for release binaries, particularly globally cached
1452 /// artifacts like compiler_rt.
1453 whole,
1454};
14281455
14291456pub const ParentWholeCache = struct {
14301457 manifest: *Cache.Manifest,
......@@ -1433,22 +1460,33 @@ pub const ParentWholeCache = struct {
14331460};
14341461
14351462const CacheUse = union(CacheMode) {
1463 none: *None,
14361464 incremental: *Incremental,
14371465 whole: *Whole,
14381466
1467 const None = struct {
1468 /// User-requested artifacts are written directly to their output path in this cache mode.
1469 /// However, if we need to emit any temporary files, they are placed in this directory.
1470 /// We will recursively delete this directory at the end of this update. This field is
1471 /// non-`null` only inside `update`.
1472 tmp_artifact_directory: ?Cache.Directory,
1473 };
1474
1475 const Incremental = struct {
1476 /// All output files, including artifacts and incremental compilation metadata, are placed
1477 /// in this directory, which is some 'o/<hash>' in a cache directory.
1478 artifact_directory: Cache.Directory,
1479 };
1480
14391481 const Whole = struct {
1440 /// This is a pointer to a local variable inside `update()`.
1441 cache_manifest: ?*Cache.Manifest = null,
1442 cache_manifest_mutex: std.Thread.Mutex = .{},
1443 /// null means -fno-emit-bin.
1444 /// This is mutable memory allocated into the Compilation-lifetime arena (`arena`)
1445 /// of exactly the correct size for "o/[digest]/[basename]".
1446 /// The basename is of the outputted binary file in case we don't know the directory yet.
1447 bin_sub_path: ?[]u8,
1448 /// Same as `bin_sub_path` but for implibs.
1449 implib_sub_path: ?[]u8,
1450 docs_sub_path: ?[]u8,
1482 /// Since we don't open the output file until `update`, we must save these options for then.
14511483 lf_open_opts: link.File.OpenOptions,
1484 /// This is a pointer to a local variable inside `update`.
1485 cache_manifest: ?*Cache.Manifest,
1486 cache_manifest_mutex: std.Thread.Mutex,
1487 /// This is non-`null` for most of the body of `update`. It is the temporary directory which
1488 /// we initially emit our artifacts to. After the main part of the update is done, it will
1489 /// be closed and moved to its final location, and this field set to `null`.
14521490 tmp_artifact_directory: ?Cache.Directory,
14531491 /// Prevents other processes from clobbering files in the output directory.
14541492 lock: ?Cache.Lock,
......@@ -1467,17 +1505,16 @@ const CacheUse = union(CacheMode) {
14671505 }
14681506 };
14691507
1470 const Incremental = struct {
1471 /// Where build artifacts and incremental compilation metadata serialization go.
1472 artifact_directory: Cache.Directory,
1473 };
1474
14751508 fn deinit(cu: CacheUse) void {
14761509 switch (cu) {
1510 .none => |none| {
1511 assert(none.tmp_artifact_directory == null);
1512 },
14771513 .incremental => |incremental| {
14781514 incremental.artifact_directory.handle.close();
14791515 },
14801516 .whole => |whole| {
1517 assert(whole.tmp_artifact_directory == null);
14811518 whole.releaseLock();
14821519 },
14831520 }
......@@ -1504,28 +1541,14 @@ pub const CreateOptions = struct {
15041541 std_mod: ?*Package.Module = null,
15051542 root_name: []const u8,
15061543 sysroot: ?[]const u8 = null,
1507 /// `null` means to not emit a binary file.
1508 emit_bin: ?EmitLoc,
1509 /// `null` means to not emit a C header file.
1510 emit_h: ?EmitLoc = null,
1511 /// `null` means to not emit assembly.
1512 emit_asm: ?EmitLoc = null,
1513 /// `null` means to not emit LLVM IR.
1514 emit_llvm_ir: ?EmitLoc = null,
1515 /// `null` means to not emit LLVM module bitcode.
1516 emit_llvm_bc: ?EmitLoc = null,
1517 /// `null` means to not emit docs.
1518 emit_docs: ?EmitLoc = null,
1519 /// `null` means to not emit an import lib.
1520 emit_implib: ?EmitLoc = null,
1521 /// Normally when using LLD to link, Zig uses a file named "lld.id" in the
1522 /// same directory as the output binary which contains the hash of the link
1523 /// operation, allowing Zig to skip linking when the hash would be unchanged.
1524 /// In the case that the output binary is being emitted into a directory which
1525 /// is externally modified - essentially anything other than zig-cache - then
1526 /// this flag would be set to disable this machinery to avoid false positives.
1527 disable_lld_caching: bool = false,
1528 cache_mode: CacheMode = .incremental,
1544 cache_mode: CacheMode,
1545 emit_h: Emit = .no,
1546 emit_bin: Emit,
1547 emit_asm: Emit = .no,
1548 emit_implib: Emit = .no,
1549 emit_llvm_ir: Emit = .no,
1550 emit_llvm_bc: Emit = .no,
1551 emit_docs: Emit = .no,
15291552 /// This field is intended to be removed.
15301553 /// The ELF implementation no longer uses this data, however the MachO and COFF
15311554 /// implementations still do.
......@@ -1591,9 +1614,9 @@ pub const CreateOptions = struct {
15911614 linker_tsaware: bool = false,
15921615 linker_nxcompat: bool = false,
15931616 linker_dynamicbase: bool = true,
1594 linker_compress_debug_sections: ?link.File.Elf.CompressDebugSections = null,
1617 linker_compress_debug_sections: ?link.File.Lld.Elf.CompressDebugSections = null,
15951618 linker_module_definition_file: ?[]const u8 = null,
1596 linker_sort_section: ?link.File.Elf.SortSection = null,
1619 linker_sort_section: ?link.File.Lld.Elf.SortSection = null,
15971620 major_subsystem_version: ?u16 = null,
15981621 minor_subsystem_version: ?u16 = null,
15991622 clang_passthrough_mode: bool = false,
......@@ -1615,7 +1638,7 @@ pub const CreateOptions = struct {
16151638 /// building such dependencies themselves, this flag must be set to avoid
16161639 /// infinite recursion.
16171640 skip_linker_dependencies: bool = false,
1618 hash_style: link.File.Elf.HashStyle = .both,
1641 hash_style: link.File.Lld.Elf.HashStyle = .both,
16191642 entry: Entry = .default,
16201643 force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .empty,
16211644 stack_size: ?u64 = null,
......@@ -1663,6 +1686,38 @@ pub const CreateOptions = struct {
16631686 parent_whole_cache: ?ParentWholeCache = null,
16641687
16651688 pub const Entry = link.File.OpenOptions.Entry;
1689
1690 /// Which fields are valid depends on the `cache_mode` given.
1691 pub const Emit = union(enum) {
1692 /// Do not emit this file. Always valid.
1693 no,
1694 /// Emit this file into its default name in the cache directory.
1695 /// Requires `cache_mode` to not be `.none`.
1696 yes_cache,
1697 /// Emit this file to the given path (absolute or cwd-relative).
1698 /// Requires `cache_mode` to be `.none`.
1699 yes_path: []const u8,
1700
1701 fn resolve(emit: Emit, arena: Allocator, opts: *const CreateOptions, ea: std.zig.EmitArtifact) Allocator.Error!?[]const u8 {
1702 switch (emit) {
1703 .no => return null,
1704 .yes_cache => {
1705 assert(opts.cache_mode != .none);
1706 return try ea.cacheName(arena, .{
1707 .root_name = opts.root_name,
1708 .target = opts.root_mod.resolved_target.result,
1709 .output_mode = opts.config.output_mode,
1710 .link_mode = opts.config.link_mode,
1711 .version = opts.version,
1712 });
1713 },
1714 .yes_path => |path| {
1715 assert(opts.cache_mode == .none);
1716 return try arena.dupe(u8, path);
1717 },
1718 }
1719 }
1720 };
16661721};
16671722
16681723fn addModuleTableToCacheHash(
......@@ -1870,13 +1925,18 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
18701925 cache.hash.add(options.config.link_libunwind);
18711926 cache.hash.add(output_mode);
18721927 cache_helpers.addDebugFormat(&cache.hash, options.config.debug_format);
1873 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin);
1874 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib);
1875 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);
18761928 cache.hash.addBytes(options.root_name);
18771929 cache.hash.add(options.config.wasi_exec_model);
18781930 cache.hash.add(options.config.san_cov_trace_pc_guard);
18791931 cache.hash.add(options.debug_compiler_runtime_libs);
1932 // The actual emit paths don't matter. They're only user-specified if we aren't using the
1933 // cache! However, it does matter whether the files are emitted at all.
1934 cache.hash.add(options.emit_bin != .no);
1935 cache.hash.add(options.emit_asm != .no);
1936 cache.hash.add(options.emit_implib != .no);
1937 cache.hash.add(options.emit_llvm_ir != .no);
1938 cache.hash.add(options.emit_llvm_bc != .no);
1939 cache.hash.add(options.emit_docs != .no);
18801940 // TODO audit this and make sure everything is in it
18811941
18821942 const main_mod = options.main_mod orelse options.root_mod;
......@@ -1926,7 +1986,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
19261986 try zcu.init(options.thread_pool.getIdCount());
19271987 break :blk zcu;
19281988 } else blk: {
1929 if (options.emit_h != null) return error.NoZigModuleForCHeader;
1989 if (options.emit_h != .no) return error.NoZigModuleForCHeader;
19301990 break :blk null;
19311991 };
19321992 errdefer if (opt_zcu) |zcu| zcu.deinit();
......@@ -1939,18 +1999,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
19391999 .arena = arena,
19402000 .zcu = opt_zcu,
19412001 .cache_use = undefined, // populated below
1942 .bin_file = null, // populated below
1943 .implib_emit = null, // handled below
1944 .docs_emit = null, // handled below
2002 .bin_file = null, // populated below if necessary
19452003 .root_mod = options.root_mod,
19462004 .config = options.config,
19472005 .dirs = options.dirs,
1948 .emit_asm = options.emit_asm,
1949 .emit_llvm_ir = options.emit_llvm_ir,
1950 .emit_llvm_bc = options.emit_llvm_bc,
19512006 .work_queues = @splat(.init(gpa)),
1952 .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),
1953 .win32_resource_work_queue = if (dev.env.supports(.win32_resource)) std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa) else .{},
2007 .c_object_work_queue = .init(gpa),
2008 .win32_resource_work_queue = if (dev.env.supports(.win32_resource)) .init(gpa) else .{},
19542009 .c_source_files = options.c_source_files,
19552010 .rc_source_files = options.rc_source_files,
19562011 .cache_parent = cache,
......@@ -2003,7 +2058,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
20032058 .file_system_inputs = options.file_system_inputs,
20042059 .parent_whole_cache = options.parent_whole_cache,
20052060 .link_diags = .init(gpa),
2006 .remaining_prelink_tasks = 0,
2061 .emit_bin = try options.emit_bin.resolve(arena, &options, .bin),
2062 .emit_asm = try options.emit_asm.resolve(arena, &options, .@"asm"),
2063 .emit_implib = try options.emit_implib.resolve(arena, &options, .implib),
2064 .emit_llvm_ir = try options.emit_llvm_ir.resolve(arena, &options, .llvm_ir),
2065 .emit_llvm_bc = try options.emit_llvm_bc.resolve(arena, &options, .llvm_bc),
2066 .emit_docs = try options.emit_docs.resolve(arena, &options, .docs),
20072067 };
20082068
20092069 // Prevent some footguns by making the "any" fields of config reflect
......@@ -2070,7 +2130,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
20702130 .soname = options.soname,
20712131 .compatibility_version = options.compatibility_version,
20722132 .build_id = build_id,
2073 .disable_lld_caching = options.disable_lld_caching or options.cache_mode == .whole,
20742133 .subsystem = options.subsystem,
20752134 .hash_style = options.hash_style,
20762135 .enable_link_snapshots = options.enable_link_snapshots,
......@@ -2089,6 +2148,17 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
20892148 };
20902149
20912150 switch (options.cache_mode) {
2151 .none => {
2152 const none = try arena.create(CacheUse.None);
2153 none.* = .{ .tmp_artifact_directory = null };
2154 comp.cache_use = .{ .none = none };
2155 if (comp.emit_bin) |path| {
2156 comp.bin_file = try link.File.open(arena, comp, .{
2157 .root_dir = .cwd(),
2158 .sub_path = path,
2159 }, lf_open_opts);
2160 }
2161 },
20922162 .incremental => {
20932163 // Options that are specific to zig source files, that cannot be
20942164 // modified between incremental updates.
......@@ -2102,7 +2172,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
21022172 hash.addListOfBytes(options.test_filters);
21032173 hash.addOptionalBytes(options.test_name_prefix);
21042174 hash.add(options.skip_linker_dependencies);
2105 hash.add(options.emit_h != null);
2175 hash.add(options.emit_h != .no);
21062176 hash.add(error_limit);
21072177
21082178 // Here we put the root source file path name, but *not* with addFile.
......@@ -2137,49 +2207,26 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
21372207 };
21382208 comp.cache_use = .{ .incremental = incremental };
21392209
2140 if (options.emit_bin) |emit_bin| {
2210 if (comp.emit_bin) |cache_rel_path| {
21412211 const emit: Cache.Path = .{
2142 .root_dir = emit_bin.directory orelse artifact_directory,
2143 .sub_path = emit_bin.basename,
2212 .root_dir = artifact_directory,
2213 .sub_path = cache_rel_path,
21442214 };
21452215 comp.bin_file = try link.File.open(arena, comp, emit, lf_open_opts);
21462216 }
2147
2148 if (options.emit_implib) |emit_implib| {
2149 comp.implib_emit = .{
2150 .root_dir = emit_implib.directory orelse artifact_directory,
2151 .sub_path = emit_implib.basename,
2152 };
2153 }
2154
2155 if (options.emit_docs) |emit_docs| {
2156 comp.docs_emit = .{
2157 .root_dir = emit_docs.directory orelse artifact_directory,
2158 .sub_path = emit_docs.basename,
2159 };
2160 }
21612217 },
21622218 .whole => {
2163 // For whole cache mode, we don't know where to put outputs from
2164 // the linker until the final cache hash, which is available after
2165 // the compilation is complete.
2219 // For whole cache mode, we don't know where to put outputs from the linker until
2220 // the final cache hash, which is available after the compilation is complete.
21662221 //
2167 // Therefore, bin_file is left null until the beginning of update(),
2168 // where it may find a cache hit, or use a temporary directory to
2169 // hold output artifacts.
2222 // Therefore, `comp.bin_file` is left `null` (already done) until `update`, where
2223 // it may find a cache hit, or else will use a temporary directory to hold output
2224 // artifacts.
21702225 const whole = try arena.create(CacheUse.Whole);
21712226 whole.* = .{
2172 // This is kept here so that link.File.open can be called later.
21732227 .lf_open_opts = lf_open_opts,
2174 // This is so that when doing `CacheMode.whole`, the mechanism in update()
2175 // can use it for communicating the result directory via `bin_file.emit`.
2176 // This is used to distinguish between -fno-emit-bin and -femit-bin
2177 // for `CacheMode.whole`.
2178 // This memory will be overwritten with the real digest in update() but
2179 // the basename will be preserved.
2180 .bin_sub_path = try prepareWholeEmitSubPath(arena, options.emit_bin),
2181 .implib_sub_path = try prepareWholeEmitSubPath(arena, options.emit_implib),
2182 .docs_sub_path = try prepareWholeEmitSubPath(arena, options.emit_docs),
2228 .cache_manifest = null,
2229 .cache_manifest_mutex = .{},
21832230 .tmp_artifact_directory = null,
21842231 .lock = null,
21852232 };
......@@ -2187,14 +2234,10 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
21872234 },
21882235 }
21892236
2190 // Handle the case of e.g. -fno-emit-bin -femit-llvm-ir.
2191 if (options.emit_bin == null and (comp.verbose_llvm_ir != null or
2192 comp.verbose_llvm_bc != null or
2193 (use_llvm and comp.emit_asm != null) or
2194 comp.emit_llvm_ir != null or
2195 comp.emit_llvm_bc != null))
2196 {
2197 if (opt_zcu) |zcu| zcu.llvm_object = try LlvmObject.create(arena, comp);
2237 if (use_llvm) {
2238 if (opt_zcu) |zcu| {
2239 zcu.llvm_object = try LlvmObject.create(arena, comp);
2240 }
21982241 }
21992242
22002243 break :comp comp;
......@@ -2216,7 +2259,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
22162259 };
22172260 comp.c_object_table.putAssumeCapacityNoClobber(c_object, {});
22182261 }
2219 comp.remaining_prelink_tasks += @intCast(comp.c_object_table.count());
2262 comp.link_task_queue.pending_prelink_tasks += @intCast(comp.c_object_table.count());
22202263
22212264 // Add a `Win32Resource` for each `rc_source_files` and one for `manifest_file`.
22222265 const win32_resource_count =
......@@ -2227,7 +2270,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
22272270 // Add this after adding logic to updateWin32Resource to pass the
22282271 // result into link.loadInput. loadInput integration is not implemented
22292272 // for Windows linking logic yet.
2230 //comp.remaining_prelink_tasks += @intCast(win32_resource_count);
2273 //comp.link_task_queue.pending_prelink_tasks += @intCast(win32_resource_count);
22312274 for (options.rc_source_files) |rc_source_file| {
22322275 const win32_resource = try gpa.create(Win32Resource);
22332276 errdefer gpa.destroy(win32_resource);
......@@ -2251,12 +2294,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
22512294 }
22522295 }
22532296
2254 const have_bin_emit = switch (comp.cache_use) {
2255 .whole => |whole| whole.bin_sub_path != null,
2256 .incremental => comp.bin_file != null,
2257 };
2258
2259 if (have_bin_emit and target.ofmt != .c) {
2297 if (comp.emit_bin != null and target.ofmt != .c) {
22602298 if (!comp.skip_linker_dependencies) {
22612299 // If we need to build libc for the target, add work items for it.
22622300 // We go through the work queue so that building can be done in parallel.
......@@ -2278,78 +2316,76 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
22782316 const paths = try lci.resolveCrtPaths(arena, basenames, target);
22792317
22802318 const fields = @typeInfo(@TypeOf(paths)).@"struct".fields;
2281 try comp.link_task_queue.shared.ensureUnusedCapacity(gpa, fields.len + 1);
2319 try comp.link_task_queue.queued_prelink.ensureUnusedCapacity(gpa, fields.len + 1);
22822320 inline for (fields) |field| {
22832321 if (@field(paths, field.name)) |path| {
2284 comp.link_task_queue.shared.appendAssumeCapacity(.{ .load_object = path });
2285 comp.remaining_prelink_tasks += 1;
2322 comp.link_task_queue.queued_prelink.appendAssumeCapacity(.{ .load_object = path });
22862323 }
22872324 }
22882325 // Loads the libraries provided by `target_util.libcFullLinkFlags(target)`.
2289 comp.link_task_queue.shared.appendAssumeCapacity(.load_host_libc);
2290 comp.remaining_prelink_tasks += 1;
2326 comp.link_task_queue.queued_prelink.appendAssumeCapacity(.load_host_libc);
22912327 } else if (target.isMuslLibC()) {
22922328 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
22932329
22942330 if (musl.needsCrt0(comp.config.output_mode, comp.config.link_mode, comp.config.pie)) |f| {
22952331 comp.queued_jobs.musl_crt_file[@intFromEnum(f)] = true;
2296 comp.remaining_prelink_tasks += 1;
2332 comp.link_task_queue.pending_prelink_tasks += 1;
22972333 }
22982334 switch (comp.config.link_mode) {
22992335 .static => comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.libc_a)] = true,
23002336 .dynamic => comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.libc_so)] = true,
23012337 }
2302 comp.remaining_prelink_tasks += 1;
2338 comp.link_task_queue.pending_prelink_tasks += 1;
23032339 } else if (target.isGnuLibC()) {
23042340 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
23052341
23062342 if (glibc.needsCrt0(comp.config.output_mode)) |f| {
23072343 comp.queued_jobs.glibc_crt_file[@intFromEnum(f)] = true;
2308 comp.remaining_prelink_tasks += 1;
2344 comp.link_task_queue.pending_prelink_tasks += 1;
23092345 }
23102346 comp.queued_jobs.glibc_shared_objects = true;
2311 comp.remaining_prelink_tasks += glibc.sharedObjectsCount(&target);
2347 comp.link_task_queue.pending_prelink_tasks += glibc.sharedObjectsCount(&target);
23122348
23132349 comp.queued_jobs.glibc_crt_file[@intFromEnum(glibc.CrtFile.libc_nonshared_a)] = true;
2314 comp.remaining_prelink_tasks += 1;
2350 comp.link_task_queue.pending_prelink_tasks += 1;
23152351 } else if (target.isFreeBSDLibC()) {
23162352 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
23172353
23182354 if (freebsd.needsCrt0(comp.config.output_mode)) |f| {
23192355 comp.queued_jobs.freebsd_crt_file[@intFromEnum(f)] = true;
2320 comp.remaining_prelink_tasks += 1;
2356 comp.link_task_queue.pending_prelink_tasks += 1;
23212357 }
23222358
23232359 comp.queued_jobs.freebsd_shared_objects = true;
2324 comp.remaining_prelink_tasks += freebsd.sharedObjectsCount();
2360 comp.link_task_queue.pending_prelink_tasks += freebsd.sharedObjectsCount();
23252361 } else if (target.isNetBSDLibC()) {
23262362 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
23272363
23282364 if (netbsd.needsCrt0(comp.config.output_mode)) |f| {
23292365 comp.queued_jobs.netbsd_crt_file[@intFromEnum(f)] = true;
2330 comp.remaining_prelink_tasks += 1;
2366 comp.link_task_queue.pending_prelink_tasks += 1;
23312367 }
23322368
23332369 comp.queued_jobs.netbsd_shared_objects = true;
2334 comp.remaining_prelink_tasks += netbsd.sharedObjectsCount();
2370 comp.link_task_queue.pending_prelink_tasks += netbsd.sharedObjectsCount();
23352371 } else if (target.isWasiLibC()) {
23362372 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
23372373
23382374 for (comp.wasi_emulated_libs) |crt_file| {
23392375 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = true;
23402376 }
2341 comp.remaining_prelink_tasks += @intCast(comp.wasi_emulated_libs.len);
2377 comp.link_task_queue.pending_prelink_tasks += @intCast(comp.wasi_emulated_libs.len);
23422378
23432379 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.execModelCrtFile(comp.config.wasi_exec_model))] = true;
23442380 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.CrtFile.libc_a)] = true;
2345 comp.remaining_prelink_tasks += 2;
2381 comp.link_task_queue.pending_prelink_tasks += 2;
23462382 } else if (target.isMinGW()) {
23472383 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
23482384
23492385 const main_crt_file: mingw.CrtFile = if (is_dyn_lib) .dllcrt2_o else .crt2_o;
23502386 comp.queued_jobs.mingw_crt_file[@intFromEnum(main_crt_file)] = true;
23512387 comp.queued_jobs.mingw_crt_file[@intFromEnum(mingw.CrtFile.libmingw32_lib)] = true;
2352 comp.remaining_prelink_tasks += 2;
2388 comp.link_task_queue.pending_prelink_tasks += 2;
23532389
23542390 // When linking mingw-w64 there are some import libs we always need.
23552391 try comp.windows_libs.ensureUnusedCapacity(gpa, mingw.always_link_libs.len);
......@@ -2363,7 +2399,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
23632399 target.isMinGW())
23642400 {
23652401 comp.queued_jobs.zigc_lib = true;
2366 comp.remaining_prelink_tasks += 1;
2402 comp.link_task_queue.pending_prelink_tasks += 1;
23672403 }
23682404 }
23692405
......@@ -2380,53 +2416,53 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
23802416 }
23812417 if (comp.wantBuildLibUnwindFromSource()) {
23822418 comp.queued_jobs.libunwind = true;
2383 comp.remaining_prelink_tasks += 1;
2419 comp.link_task_queue.pending_prelink_tasks += 1;
23842420 }
23852421 if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.link_libcpp) {
23862422 comp.queued_jobs.libcxx = true;
23872423 comp.queued_jobs.libcxxabi = true;
2388 comp.remaining_prelink_tasks += 2;
2424 comp.link_task_queue.pending_prelink_tasks += 2;
23892425 }
23902426 if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.any_sanitize_thread) {
23912427 comp.queued_jobs.libtsan = true;
2392 comp.remaining_prelink_tasks += 1;
2428 comp.link_task_queue.pending_prelink_tasks += 1;
23932429 }
23942430
23952431 if (can_build_compiler_rt) {
23962432 if (comp.compiler_rt_strat == .lib) {
23972433 log.debug("queuing a job to build compiler_rt_lib", .{});
23982434 comp.queued_jobs.compiler_rt_lib = true;
2399 comp.remaining_prelink_tasks += 1;
2435 comp.link_task_queue.pending_prelink_tasks += 1;
24002436 } else if (comp.compiler_rt_strat == .obj) {
24012437 log.debug("queuing a job to build compiler_rt_obj", .{});
24022438 // In this case we are making a static library, so we ask
24032439 // for a compiler-rt object to put in it.
24042440 comp.queued_jobs.compiler_rt_obj = true;
2405 comp.remaining_prelink_tasks += 1;
2441 comp.link_task_queue.pending_prelink_tasks += 1;
24062442 }
24072443
24082444 if (comp.ubsan_rt_strat == .lib) {
24092445 log.debug("queuing a job to build ubsan_rt_lib", .{});
24102446 comp.queued_jobs.ubsan_rt_lib = true;
2411 comp.remaining_prelink_tasks += 1;
2447 comp.link_task_queue.pending_prelink_tasks += 1;
24122448 } else if (comp.ubsan_rt_strat == .obj) {
24132449 log.debug("queuing a job to build ubsan_rt_obj", .{});
24142450 comp.queued_jobs.ubsan_rt_obj = true;
2415 comp.remaining_prelink_tasks += 1;
2451 comp.link_task_queue.pending_prelink_tasks += 1;
24162452 }
24172453
24182454 if (is_exe_or_dyn_lib and comp.config.any_fuzz) {
24192455 log.debug("queuing a job to build libfuzzer", .{});
24202456 comp.queued_jobs.fuzzer_lib = true;
2421 comp.remaining_prelink_tasks += 1;
2457 comp.link_task_queue.pending_prelink_tasks += 1;
24222458 }
24232459 }
24242460 }
24252461
2426 try comp.link_task_queue.shared.append(gpa, .load_explicitly_provided);
2427 comp.remaining_prelink_tasks += 1;
2462 try comp.link_task_queue.queued_prelink.append(gpa, .load_explicitly_provided);
24282463 }
2429 log.debug("total prelink tasks: {d}", .{comp.remaining_prelink_tasks});
2464 log.debug("queued prelink tasks: {d}", .{comp.link_task_queue.queued_prelink.items.len});
2465 log.debug("pending prelink tasks: {d}", .{comp.link_task_queue.pending_prelink_tasks});
24302466
24312467 return comp;
24322468}
......@@ -2434,6 +2470,10 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
24342470pub fn destroy(comp: *Compilation) void {
24352471 const gpa = comp.gpa;
24362472
2473 // This needs to be destroyed first, because it might contain MIR which we only know
2474 // how to interpret (which kind of MIR it is) from `comp.bin_file`.
2475 comp.link_task_queue.deinit(comp);
2476
24372477 if (comp.bin_file) |lf| lf.destroy();
24382478 if (comp.zcu) |zcu| zcu.deinit();
24392479 comp.cache_use.deinit();
......@@ -2515,8 +2555,6 @@ pub fn destroy(comp: *Compilation) void {
25152555 comp.failed_win32_resources.deinit(gpa);
25162556
25172557 comp.link_diags.deinit();
2518 comp.link_task_queue.deinit(gpa);
2519 comp.link_task_queue_postponed.deinit(gpa);
25202558
25212559 comp.clearMiscFailures();
25222560
......@@ -2550,8 +2588,28 @@ pub fn hotCodeSwap(
25502588 try lf.makeExecutable();
25512589}
25522590
2553fn cleanupAfterUpdate(comp: *Compilation) void {
2591fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void {
25542592 switch (comp.cache_use) {
2593 .none => |none| {
2594 if (none.tmp_artifact_directory) |*tmp_dir| {
2595 tmp_dir.handle.close();
2596 none.tmp_artifact_directory = null;
2597 if (dev.env == .bootstrap) {
2598 // zig1 uses `CacheMode.none`, but it doesn't need to know how to delete
2599 // temporary directories; it doesn't have a real cache directory anyway.
2600 return;
2601 }
2602 const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
2603 comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| {
2604 log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{
2605 comp.dirs.local_cache.path orelse ".",
2606 std.fs.path.sep,
2607 tmp_dir_sub_path,
2608 @errorName(err),
2609 });
2610 };
2611 }
2612 },
25552613 .incremental => return,
25562614 .whole => |whole| {
25572615 if (whole.cache_manifest) |man| {
......@@ -2562,10 +2620,18 @@ fn cleanupAfterUpdate(comp: *Compilation) void {
25622620 lf.destroy();
25632621 comp.bin_file = null;
25642622 }
2565 if (whole.tmp_artifact_directory) |*directory| {
2566 directory.handle.close();
2567 if (directory.path) |p| comp.gpa.free(p);
2623 if (whole.tmp_artifact_directory) |*tmp_dir| {
2624 tmp_dir.handle.close();
25682625 whole.tmp_artifact_directory = null;
2626 const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
2627 comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| {
2628 log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{
2629 comp.dirs.local_cache.path orelse ".",
2630 std.fs.path.sep,
2631 tmp_dir_sub_path,
2632 @errorName(err),
2633 });
2634 };
25692635 }
25702636 },
25712637 }
......@@ -2585,14 +2651,27 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
25852651 comp.clearMiscFailures();
25862652 comp.last_update_was_cache_hit = false;
25872653
2588 var man: Cache.Manifest = undefined;
2589 defer cleanupAfterUpdate(comp);
2590
25912654 var tmp_dir_rand_int: u64 = undefined;
2655 var man: Cache.Manifest = undefined;
2656 defer cleanupAfterUpdate(comp, tmp_dir_rand_int);
25922657
25932658 // If using the whole caching strategy, we check for *everything* up front, including
25942659 // C source files.
2660 log.debug("Compilation.update for {s}, CacheMode.{s}", .{ comp.root_name, @tagName(comp.cache_use) });
25952661 switch (comp.cache_use) {
2662 .none => |none| {
2663 assert(none.tmp_artifact_directory == null);
2664 none.tmp_artifact_directory = d: {
2665 tmp_dir_rand_int = std.crypto.random.int(u64);
2666 const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
2667 const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});
2668 break :d .{
2669 .path = path,
2670 .handle = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}),
2671 };
2672 };
2673 },
2674 .incremental => {},
25962675 .whole => |whole| {
25972676 assert(comp.bin_file == null);
25982677 // We are about to obtain this lock, so here we give other processes a chance first.
......@@ -2639,10 +2718,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
26392718 comp.last_update_was_cache_hit = true;
26402719 log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name});
26412720 const bin_digest = man.finalBin();
2642 const hex_digest = Cache.binToHex(bin_digest);
26432721
26442722 comp.digest = bin_digest;
2645 comp.wholeCacheModeSetBinFilePath(whole, &hex_digest);
26462723
26472724 assert(whole.lock == null);
26482725 whole.lock = man.toOwnedLock();
......@@ -2651,52 +2728,23 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
26512728 log.debug("CacheMode.whole cache miss for {s}", .{comp.root_name});
26522729
26532730 // Compile the artifacts to a temporary directory.
2654 const tmp_artifact_directory: Cache.Directory = d: {
2655 const s = std.fs.path.sep_str;
2731 whole.tmp_artifact_directory = d: {
26562732 tmp_dir_rand_int = std.crypto.random.int(u64);
2657 const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);
2658
2659 const path = try comp.dirs.local_cache.join(gpa, &.{tmp_dir_sub_path});
2660 errdefer gpa.free(path);
2661
2662 const handle = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{});
2663 errdefer handle.close();
2664
2733 const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
2734 const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});
26652735 break :d .{
26662736 .path = path,
2667 .handle = handle,
2737 .handle = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}),
26682738 };
26692739 };
2670 whole.tmp_artifact_directory = tmp_artifact_directory;
2671
2672 // Now that the directory is known, it is time to create the Emit
2673 // objects and call link.File.open.
2674
2675 if (whole.implib_sub_path) |sub_path| {
2676 comp.implib_emit = .{
2677 .root_dir = tmp_artifact_directory,
2678 .sub_path = std.fs.path.basename(sub_path),
2679 };
2680 }
2681
2682 if (whole.docs_sub_path) |sub_path| {
2683 comp.docs_emit = .{
2684 .root_dir = tmp_artifact_directory,
2685 .sub_path = std.fs.path.basename(sub_path),
2686 };
2687 }
2688
2689 if (whole.bin_sub_path) |sub_path| {
2740 if (comp.emit_bin) |sub_path| {
26902741 const emit: Cache.Path = .{
2691 .root_dir = tmp_artifact_directory,
2692 .sub_path = std.fs.path.basename(sub_path),
2742 .root_dir = whole.tmp_artifact_directory.?,
2743 .sub_path = sub_path,
26932744 };
26942745 comp.bin_file = try link.File.createEmpty(arena, comp, emit, whole.lf_open_opts);
26952746 }
26962747 },
2697 .incremental => {
2698 log.debug("Compilation.update for {s}, CacheMode.incremental", .{comp.root_name});
2699 },
27002748 }
27012749
27022750 // From this point we add a preliminary set of file system inputs that
......@@ -2757,6 +2805,17 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
27572805 }
27582806 }
27592807
2808 // The linker progress node is set up here instead of in `performAllTheWork`, because
2809 // we also want it around during `flush`.
2810 const have_link_node = comp.bin_file != null;
2811 if (have_link_node) {
2812 comp.link_prog_node = main_progress_node.start("Linking", 0);
2813 }
2814 defer if (have_link_node) {
2815 comp.link_prog_node.end();
2816 comp.link_prog_node = .none;
2817 };
2818
27602819 try comp.performAllTheWork(main_progress_node);
27612820
27622821 if (comp.zcu) |zcu| {
......@@ -2768,7 +2827,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
27682827 // The `test_functions` decl has been intentionally postponed until now,
27692828 // at which point we must populate it with the list of test functions that
27702829 // have been discovered and not filtered out.
2771 try pt.populateTestFunctions(main_progress_node);
2830 try pt.populateTestFunctions();
27722831 }
27732832
27742833 try pt.processExports();
......@@ -2795,11 +2854,18 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
27952854 return;
27962855 }
27972856
2798 // Flush below handles -femit-bin but there is still -femit-llvm-ir,
2799 // -femit-llvm-bc, and -femit-asm, in the case of C objects.
2800 comp.emitOthers();
2857 if (comp.zcu == null and comp.config.output_mode == .Obj and comp.c_object_table.count() == 1) {
2858 // This is `zig build-obj foo.c`. We can emit asm and LLVM IR/bitcode.
2859 const c_obj_path = comp.c_object_table.keys()[0].status.success.object_path;
2860 if (comp.emit_asm) |path| try comp.emitFromCObject(arena, c_obj_path, ".s", path);
2861 if (comp.emit_llvm_ir) |path| try comp.emitFromCObject(arena, c_obj_path, ".ll", path);
2862 if (comp.emit_llvm_bc) |path| try comp.emitFromCObject(arena, c_obj_path, ".bc", path);
2863 }
28012864
28022865 switch (comp.cache_use) {
2866 .none, .incremental => {
2867 try flush(comp, arena, .main);
2868 },
28032869 .whole => |whole| {
28042870 if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
28052871 if (comp.parent_whole_cache) |pwc| {
......@@ -2811,18 +2877,6 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
28112877 const bin_digest = man.finalBin();
28122878 const hex_digest = Cache.binToHex(bin_digest);
28132879
2814 // Rename the temporary directory into place.
2815 // Close tmp dir and link.File to avoid open handle during rename.
2816 if (whole.tmp_artifact_directory) |*tmp_directory| {
2817 tmp_directory.handle.close();
2818 if (tmp_directory.path) |p| gpa.free(p);
2819 whole.tmp_artifact_directory = null;
2820 } else unreachable;
2821
2822 const s = std.fs.path.sep_str;
2823 const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);
2824 const o_sub_path = "o" ++ s ++ hex_digest;
2825
28262880 // Work around windows `AccessDenied` if any files within this
28272881 // directory are open by closing and reopening the file handles.
28282882 const need_writable_dance: enum { no, lf_only, lf_and_debug } = w: {
......@@ -2847,6 +2901,13 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
28472901 break :w .no;
28482902 };
28492903
2904 // Rename the temporary directory into place.
2905 // Close tmp dir and link.File to avoid open handle during rename.
2906 whole.tmp_artifact_directory.?.handle.close();
2907 whole.tmp_artifact_directory = null;
2908 const s = std.fs.path.sep_str;
2909 const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);
2910 const o_sub_path = "o" ++ s ++ hex_digest;
28502911 renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| {
28512912 return comp.setMiscFailure(
28522913 .rename_results,
......@@ -2859,7 +2920,6 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
28592920 );
28602921 };
28612922 comp.digest = bin_digest;
2862 comp.wholeCacheModeSetBinFilePath(whole, &hex_digest);
28632923
28642924 // The linker flush functions need to know the final output path
28652925 // for debug info purposes because executable debug info contains
......@@ -2867,10 +2927,9 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
28672927 if (comp.bin_file) |lf| {
28682928 lf.emit = .{
28692929 .root_dir = comp.dirs.local_cache,
2870 .sub_path = whole.bin_sub_path.?,
2930 .sub_path = try std.fs.path.join(arena, &.{ o_sub_path, comp.emit_bin.? }),
28712931 };
28722932
2873 // Has to be after the `wholeCacheModeSetBinFilePath` above.
28742933 switch (need_writable_dance) {
28752934 .no => {},
28762935 .lf_only => try lf.makeWritable(),
......@@ -2881,10 +2940,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
28812940 }
28822941 }
28832942
2884 try flush(comp, arena, .{
2885 .root_dir = comp.dirs.local_cache,
2886 .sub_path = o_sub_path,
2887 }, .main, main_progress_node);
2943 try flush(comp, arena, .main);
28882944
28892945 // Calling `flush` may have produced errors, in which case the
28902946 // cache manifest must not be written.
......@@ -2903,11 +2959,6 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
29032959 assert(whole.lock == null);
29042960 whole.lock = man.toOwnedLock();
29052961 },
2906 .incremental => |incremental| {
2907 try flush(comp, arena, .{
2908 .root_dir = incremental.artifact_directory,
2909 }, .main, main_progress_node);
2910 },
29112962 }
29122963}
29132964
......@@ -2937,27 +2988,98 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat
29372988 fsi.appendSliceAssumeCapacity(path.sub_path);
29382989}
29392990
2991fn resolveEmitPath(comp: *Compilation, path: []const u8) Cache.Path {
2992 return .{
2993 .root_dir = switch (comp.cache_use) {
2994 .none => .cwd(),
2995 .incremental => |i| i.artifact_directory,
2996 .whole => |w| w.tmp_artifact_directory.?,
2997 },
2998 .sub_path = path,
2999 };
3000}
3001/// Like `resolveEmitPath`, but for calling during `flush`. The returned `Cache.Path` may reference
3002/// memory from `arena`, and may reference `path` itself.
3003/// If `kind == .temp`, then the returned path will be in a temporary or cache directory. This is
3004/// useful for intermediate files, such as the ZCU object file emitted by the LLVM backend.
3005pub fn resolveEmitPathFlush(
3006 comp: *Compilation,
3007 arena: Allocator,
3008 kind: enum { temp, artifact },
3009 path: []const u8,
3010) Allocator.Error!Cache.Path {
3011 switch (comp.cache_use) {
3012 .none => |none| return .{
3013 .root_dir = switch (kind) {
3014 .temp => none.tmp_artifact_directory.?,
3015 .artifact => .cwd(),
3016 },
3017 .sub_path = path,
3018 },
3019 .incremental, .whole => return .{
3020 .root_dir = comp.dirs.local_cache,
3021 .sub_path = try fs.path.join(arena, &.{
3022 "o",
3023 &Cache.binToHex(comp.digest.?),
3024 path,
3025 }),
3026 },
3027 }
3028}
29403029fn flush(
29413030 comp: *Compilation,
29423031 arena: Allocator,
2943 default_artifact_directory: Cache.Path,
29443032 tid: Zcu.PerThread.Id,
2945 prog_node: std.Progress.Node,
29463033) !void {
3034 if (comp.zcu) |zcu| {
3035 if (zcu.llvm_object) |llvm_object| {
3036 // Emit the ZCU object from LLVM now; it's required to flush the output file.
3037 // If there's an output file, it wants to decide where the LLVM object goes!
3038 const sub_prog_node = comp.link_prog_node.start("LLVM Emit Object", 0);
3039 defer sub_prog_node.end();
3040 try llvm_object.emit(.{
3041 .pre_ir_path = comp.verbose_llvm_ir,
3042 .pre_bc_path = comp.verbose_llvm_bc,
3043
3044 .bin_path = p: {
3045 const lf = comp.bin_file orelse break :p null;
3046 const p = try comp.resolveEmitPathFlush(arena, .temp, lf.zcu_object_basename.?);
3047 break :p try p.toStringZ(arena);
3048 },
3049 .asm_path = p: {
3050 const raw = comp.emit_asm orelse break :p null;
3051 const p = try comp.resolveEmitPathFlush(arena, .artifact, raw);
3052 break :p try p.toStringZ(arena);
3053 },
3054 .post_ir_path = p: {
3055 const raw = comp.emit_llvm_ir orelse break :p null;
3056 const p = try comp.resolveEmitPathFlush(arena, .artifact, raw);
3057 break :p try p.toStringZ(arena);
3058 },
3059 .post_bc_path = p: {
3060 const raw = comp.emit_llvm_bc orelse break :p null;
3061 const p = try comp.resolveEmitPathFlush(arena, .artifact, raw);
3062 break :p try p.toStringZ(arena);
3063 },
3064
3065 .is_debug = comp.root_mod.optimize_mode == .Debug,
3066 .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
3067 .time_report = comp.time_report,
3068 .sanitize_thread = comp.config.any_sanitize_thread,
3069 .fuzz = comp.config.any_fuzz,
3070 .lto = comp.config.lto,
3071 });
3072 }
3073 }
29473074 if (comp.bin_file) |lf| {
29483075 // This is needed before reading the error flags.
2949 lf.flush(arena, tid, prog_node) catch |err| switch (err) {
3076 lf.flush(arena, tid, comp.link_prog_node) catch |err| switch (err) {
29503077 error.LinkFailure => {}, // Already reported.
29513078 error.OutOfMemory => return error.OutOfMemory,
29523079 };
29533080 }
2954
29553081 if (comp.zcu) |zcu| {
29563082 try link.File.C.flushEmitH(zcu);
2957
2958 if (zcu.llvm_object) |llvm_object| {
2959 try emitLlvmObject(comp, arena, default_artifact_directory, null, llvm_object, prog_node);
2960 }
29613083 }
29623084}
29633085
......@@ -3009,45 +3131,6 @@ fn renameTmpIntoCache(
30093131 }
30103132}
30113133
3012/// Communicate the output binary location to parent Compilations.
3013fn wholeCacheModeSetBinFilePath(
3014 comp: *Compilation,
3015 whole: *CacheUse.Whole,
3016 digest: *const [Cache.hex_digest_len]u8,
3017) void {
3018 const digest_start = 2; // "o/[digest]/[basename]"
3019
3020 if (whole.bin_sub_path) |sub_path| {
3021 @memcpy(sub_path[digest_start..][0..digest.len], digest);
3022 }
3023
3024 if (whole.implib_sub_path) |sub_path| {
3025 @memcpy(sub_path[digest_start..][0..digest.len], digest);
3026
3027 comp.implib_emit = .{
3028 .root_dir = comp.dirs.local_cache,
3029 .sub_path = sub_path,
3030 };
3031 }
3032
3033 if (whole.docs_sub_path) |sub_path| {
3034 @memcpy(sub_path[digest_start..][0..digest.len], digest);
3035
3036 comp.docs_emit = .{
3037 .root_dir = comp.dirs.local_cache,
3038 .sub_path = sub_path,
3039 };
3040 }
3041}
3042
3043fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemory}!?[]u8 {
3044 const emit = opt_emit orelse return null;
3045 if (emit.directory != null) return null;
3046 const s = std.fs.path.sep_str;
3047 const format = "o" ++ s ++ ("x" ** Cache.hex_digest_len) ++ s ++ "{s}";
3048 return try std.fmt.allocPrint(arena, format, .{emit.basename});
3049}
3050
30513134/// This is only observed at compile-time and used to emit a compile error
30523135/// to remind the programmer to update multiple related pieces of code that
30533136/// are in different locations. Bump this number when adding or deleting
......@@ -3068,7 +3151,7 @@ fn addNonIncrementalStuffToCacheManifest(
30683151 man.hash.addListOfBytes(comp.test_filters);
30693152 man.hash.addOptionalBytes(comp.test_name_prefix);
30703153 man.hash.add(comp.skip_linker_dependencies);
3071 //man.hash.add(zcu.emit_h != null);
3154 //man.hash.add(zcu.emit_h != .no);
30723155 man.hash.add(zcu.error_limit);
30733156 } else {
30743157 cache_helpers.addModule(&man.hash, comp.root_mod);
......@@ -3114,10 +3197,6 @@ fn addNonIncrementalStuffToCacheManifest(
31143197 man.hash.addListOfBytes(comp.framework_dirs);
31153198 man.hash.addListOfBytes(comp.windows_libs.keys());
31163199
3117 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_asm);
3118 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir);
3119 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc);
3120
31213200 man.hash.addListOfBytes(comp.global_cc_argv);
31223201
31233202 const opts = comp.cache_use.whole.lf_open_opts;
......@@ -3195,82 +3274,39 @@ fn addNonIncrementalStuffToCacheManifest(
31953274 man.hash.addOptional(opts.minor_subsystem_version);
31963275}
31973276
3198fn emitOthers(comp: *Compilation) void {
3199 if (comp.config.output_mode != .Obj or comp.zcu != null or
3200 comp.c_object_table.count() == 0)
3201 {
3202 return;
3203 }
3204 const obj_path = comp.c_object_table.keys()[0].status.success.object_path;
3205 const ext = std.fs.path.extension(obj_path.sub_path);
3206 const dirname = obj_path.sub_path[0 .. obj_path.sub_path.len - ext.len];
3207 // This obj path always ends with the object file extension, but if we change the
3208 // extension to .ll, .bc, or .s, then it will be the path to those things.
3209 const outs = [_]struct {
3210 emit: ?EmitLoc,
3211 ext: []const u8,
3212 }{
3213 .{ .emit = comp.emit_asm, .ext = ".s" },
3214 .{ .emit = comp.emit_llvm_ir, .ext = ".ll" },
3215 .{ .emit = comp.emit_llvm_bc, .ext = ".bc" },
3216 };
3217 for (outs) |out| {
3218 if (out.emit) |loc| {
3219 if (loc.directory) |directory| {
3220 const src_path = std.fmt.allocPrint(comp.gpa, "{s}{s}", .{
3221 dirname, out.ext,
3222 }) catch |err| {
3223 log.err("unable to copy {s}{s}: {s}", .{ dirname, out.ext, @errorName(err) });
3224 continue;
3225 };
3226 defer comp.gpa.free(src_path);
3227 obj_path.root_dir.handle.copyFile(src_path, directory.handle, loc.basename, .{}) catch |err| {
3228 log.err("unable to copy {s}: {s}", .{ src_path, @errorName(err) });
3229 };
3230 }
3231 }
3232 }
3233}
3234
3235pub fn emitLlvmObject(
3277fn emitFromCObject(
32363278 comp: *Compilation,
32373279 arena: Allocator,
3238 default_artifact_directory: Cache.Path,
3239 bin_emit_loc: ?EmitLoc,
3240 llvm_object: LlvmObject.Ptr,
3241 prog_node: std.Progress.Node,
3242) !void {
3243 const sub_prog_node = prog_node.start("LLVM Emit Object", 0);
3244 defer sub_prog_node.end();
3245
3246 try llvm_object.emit(.{
3247 .pre_ir_path = comp.verbose_llvm_ir,
3248 .pre_bc_path = comp.verbose_llvm_bc,
3249 .bin_path = try resolveEmitLoc(arena, default_artifact_directory, bin_emit_loc),
3250 .asm_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_asm),
3251 .post_ir_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_ir),
3252 .post_bc_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_bc),
3253
3254 .is_debug = comp.root_mod.optimize_mode == .Debug,
3255 .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
3256 .time_report = comp.time_report,
3257 .sanitize_thread = comp.config.any_sanitize_thread,
3258 .fuzz = comp.config.any_fuzz,
3259 .lto = comp.config.lto,
3260 });
3261}
3280 c_obj_path: Cache.Path,
3281 new_ext: []const u8,
3282 unresolved_emit_path: []const u8,
3283) Allocator.Error!void {
3284 // The dirname and stem (i.e. everything but the extension), of the sub path of the C object.
3285 // We'll append `new_ext` to it to get the path to the right thing (asm, LLVM IR, etc).
3286 const c_obj_dir_and_stem: []const u8 = p: {
3287 const p = c_obj_path.sub_path;
3288 const ext_len = fs.path.extension(p).len;
3289 break :p p[0 .. p.len - ext_len];
3290 };
3291 const src_path: Cache.Path = .{
3292 .root_dir = c_obj_path.root_dir,
3293 .sub_path = try std.fmt.allocPrint(arena, "{s}{s}", .{
3294 c_obj_dir_and_stem,
3295 new_ext,
3296 }),
3297 };
3298 const emit_path = comp.resolveEmitPath(unresolved_emit_path);
32623299
3263fn resolveEmitLoc(
3264 arena: Allocator,
3265 default_artifact_directory: Cache.Path,
3266 opt_loc: ?EmitLoc,
3267) Allocator.Error!?[*:0]const u8 {
3268 const loc = opt_loc orelse return null;
3269 const slice = if (loc.directory) |directory|
3270 try directory.joinZ(arena, &.{loc.basename})
3271 else
3272 try default_artifact_directory.joinStringZ(arena, loc.basename);
3273 return slice.ptr;
3300 src_path.root_dir.handle.copyFile(
3301 src_path.sub_path,
3302 emit_path.root_dir.handle,
3303 emit_path.sub_path,
3304 .{},
3305 ) catch |err| log.err("unable to copy '{}' to '{}': {s}", .{
3306 src_path,
3307 emit_path,
3308 @errorName(err),
3309 });
32743310}
32753311
32763312/// Having the file open for writing is problematic as far as executing the
......@@ -3512,7 +3548,7 @@ pub fn saveState(comp: *Compilation) !void {
35123548 // TODO handle the union safety field
35133549 //addBuf(&bufs, mem.sliceAsBytes(wasm.mir_instructions.items(.data)));
35143550 addBuf(&bufs, mem.sliceAsBytes(wasm.mir_extra.items));
3515 addBuf(&bufs, mem.sliceAsBytes(wasm.all_zcu_locals.items));
3551 addBuf(&bufs, mem.sliceAsBytes(wasm.mir_locals.items));
35163552 addBuf(&bufs, mem.sliceAsBytes(wasm.tag_name_bytes.items));
35173553 addBuf(&bufs, mem.sliceAsBytes(wasm.tag_name_offs.items));
35183554
......@@ -4156,28 +4192,15 @@ pub fn addWholeFileError(
41564192 }
41574193}
41584194
4159pub fn performAllTheWork(
4195fn performAllTheWork(
41604196 comp: *Compilation,
41614197 main_progress_node: std.Progress.Node,
41624198) JobError!void {
4163 comp.work_queue_progress_node = main_progress_node;
4164 defer comp.work_queue_progress_node = .none;
4165
4199 // Regardless of errors, `comp.zcu` needs to update its generation number.
41664200 defer if (comp.zcu) |zcu| {
4167 zcu.sema_prog_node.end();
4168 zcu.sema_prog_node = .none;
4169 zcu.codegen_prog_node.end();
4170 zcu.codegen_prog_node = .none;
4171
41724201 zcu.generation += 1;
41734202 };
4174 try comp.performAllTheWorkInner(main_progress_node);
4175}
41764203
4177fn performAllTheWorkInner(
4178 comp: *Compilation,
4179 main_progress_node: std.Progress.Node,
4180) JobError!void {
41814204 // Here we queue up all the AstGen tasks first, followed by C object compilation.
41824205 // We wait until the AstGen tasks are all completed before proceeding to the
41834206 // (at least for now) single-threaded main work queue. However, C object compilation
......@@ -4189,11 +4212,13 @@ fn performAllTheWorkInner(
41894212 comp.link_task_wait_group.reset();
41904213 defer comp.link_task_wait_group.wait();
41914214
4192 if (comp.link_task_queue.start()) {
4193 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, link.flushTaskQueue, .{comp});
4194 }
4215 comp.link_prog_node.increaseEstimatedTotalItems(
4216 comp.link_task_queue.queued_prelink.items.len + // already queued prelink tasks
4217 comp.link_task_queue.pending_prelink_tasks, // prelink tasks which will be queued
4218 );
4219 comp.link_task_queue.start(comp);
41954220
4196 if (comp.docs_emit != null) {
4221 if (comp.emit_docs != null) {
41974222 dev.check(.docs_emit);
41984223 comp.thread_pool.spawnWg(&work_queue_wait_group, workerDocsCopy, .{comp});
41994224 work_queue_wait_group.spawnManager(workerDocsWasm, .{ comp, main_progress_node });
......@@ -4471,7 +4496,7 @@ fn performAllTheWorkInner(
44714496 };
44724497 }
44734498 },
4474 .incremental => {},
4499 .none, .incremental => {},
44754500 }
44764501
44774502 if (any_fatal_files or
......@@ -4499,15 +4524,31 @@ fn performAllTheWorkInner(
44994524 }
45004525
45014526 zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
4502 zcu.codegen_prog_node = if (comp.bin_file != null) main_progress_node.start("Code Generation", 0) else .none;
4527 if (comp.bin_file != null) {
4528 zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0);
4529 }
4530 // We increment `pending_codegen_jobs` so that it doesn't reach 0 until after analysis finishes.
4531 // That prevents the "Code Generation" node from constantly disappearing and reappearing when
4532 // we're probably going to analyze more functions at some point.
4533 assert(zcu.pending_codegen_jobs.swap(1, .monotonic) == 0); // don't let this become 0 until analysis finishes
45034534 }
4535 // When analysis ends, delete the progress nodes for "Semantic Analysis" and possibly "Code Generation".
4536 defer if (comp.zcu) |zcu| {
4537 zcu.sema_prog_node.end();
4538 zcu.sema_prog_node = .none;
4539 if (zcu.pending_codegen_jobs.rmw(.Sub, 1, .monotonic) == 1) {
4540 // Decremented to 0, so all done.
4541 zcu.codegen_prog_node.end();
4542 zcu.codegen_prog_node = .none;
4543 }
4544 };
45044545
45054546 if (!comp.separateCodegenThreadOk()) {
45064547 // Waits until all input files have been parsed.
45074548 comp.link_task_wait_group.wait();
45084549 comp.link_task_wait_group.reset();
45094550 std.log.scoped(.link).debug("finished waiting for link_task_wait_group", .{});
4510 if (comp.remaining_prelink_tasks > 0) {
4551 if (comp.link_task_queue.pending_prelink_tasks > 0) {
45114552 // Indicates an error occurred preventing prelink phase from completing.
45124553 return;
45134554 }
......@@ -4552,26 +4593,91 @@ pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void {
45524593
45534594fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
45544595 switch (job) {
4555 .codegen_nav => |nav_index| {
4596 .codegen_func => |func| {
4597 const zcu = comp.zcu.?;
4598 const gpa = zcu.gpa;
4599 var air = func.air;
4600 errdefer {
4601 zcu.codegen_prog_node.completeOne();
4602 comp.link_prog_node.completeOne();
4603 air.deinit(gpa);
4604 }
4605 if (!air.typesFullyResolved(zcu)) {
4606 // Type resolution failed in a way which affects this function. This is a transitive
4607 // failure, but it doesn't need recording, because this function semantically depends
4608 // on the failed type, so when it is changed the function is updated.
4609 zcu.codegen_prog_node.completeOne();
4610 comp.link_prog_node.completeOne();
4611 air.deinit(gpa);
4612 return;
4613 }
4614 const shared_mir = try gpa.create(link.ZcuTask.LinkFunc.SharedMir);
4615 shared_mir.* = .{
4616 .status = .init(.pending),
4617 .value = undefined,
4618 };
4619 assert(zcu.pending_codegen_jobs.rmw(.Add, 1, .monotonic) > 0); // the "Code Generation" node hasn't been ended
4620 // This value is used as a heuristic to avoid queueing too much AIR/MIR at once (hence
4621 // using a lot of memory). If this would cause too many AIR bytes to be in-flight, we
4622 // will block on the `dispatchZcuLinkTask` call below.
4623 const air_bytes: u32 = @intCast(air.instructions.len * 5 + air.extra.items.len * 4);
4624 if (comp.separateCodegenThreadOk()) {
4625 // `workerZcuCodegen` takes ownership of `air`.
4626 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, workerZcuCodegen, .{ comp, func.func, air, shared_mir });
4627 comp.dispatchZcuLinkTask(tid, .{ .link_func = .{
4628 .func = func.func,
4629 .mir = shared_mir,
4630 .air_bytes = air_bytes,
4631 } });
4632 } else {
4633 {
4634 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
4635 defer pt.deactivate();
4636 pt.runCodegen(func.func, &air, shared_mir);
4637 }
4638 assert(shared_mir.status.load(.monotonic) != .pending);
4639 comp.dispatchZcuLinkTask(tid, .{ .link_func = .{
4640 .func = func.func,
4641 .mir = shared_mir,
4642 .air_bytes = air_bytes,
4643 } });
4644 air.deinit(gpa);
4645 }
4646 },
4647 .link_nav => |nav_index| {
45564648 const zcu = comp.zcu.?;
45574649 const nav = zcu.intern_pool.getNav(nav_index);
45584650 if (nav.analysis != null) {
45594651 const unit: InternPool.AnalUnit = .wrap(.{ .nav_val = nav_index });
45604652 if (zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit)) {
4653 comp.link_prog_node.completeOne();
45614654 return;
45624655 }
45634656 }
45644657 assert(nav.status == .fully_resolved);
4565 comp.dispatchCodegenTask(tid, .{ .codegen_nav = nav_index });
4566 },
4567 .codegen_func => |func| {
4568 comp.dispatchCodegenTask(tid, .{ .codegen_func = func });
4658 if (!Air.valFullyResolved(zcu.navValue(nav_index), zcu)) {
4659 // Type resolution failed in a way which affects this `Nav`. This is a transitive
4660 // failure, but it doesn't need recording, because this `Nav` semantically depends
4661 // on the failed type, so when it is changed the `Nav` will be updated.
4662 comp.link_prog_node.completeOne();
4663 return;
4664 }
4665 comp.dispatchZcuLinkTask(tid, .{ .link_nav = nav_index });
45694666 },
4570 .codegen_type => |ty| {
4571 comp.dispatchCodegenTask(tid, .{ .codegen_type = ty });
4667 .link_type => |ty| {
4668 const zcu = comp.zcu.?;
4669 if (zcu.failed_types.fetchSwapRemove(ty)) |*entry| entry.value.deinit(zcu.gpa);
4670 if (!Air.typeFullyResolved(.fromInterned(ty), zcu)) {
4671 // Type resolution failed in a way which affects this type. This is a transitive
4672 // failure, but it doesn't need recording, because this type semantically depends
4673 // on the failed type, so when that is changed, this type will be updated.
4674 comp.link_prog_node.completeOne();
4675 return;
4676 }
4677 comp.dispatchZcuLinkTask(tid, .{ .link_type = ty });
45724678 },
45734679 .update_line_number => |ti| {
4574 comp.dispatchCodegenTask(tid, .{ .update_line_number = ti });
4680 comp.dispatchZcuLinkTask(tid, .{ .update_line_number = ti });
45754681 },
45764682 .analyze_func => |func| {
45774683 const named_frame = tracy.namedFrame("analyze_func");
......@@ -4663,18 +4769,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
46634769 }
46644770}
46654771
4666/// The reason for the double-queue here is that the first queue ensures any
4667/// resolve_type_fully tasks are complete before this dispatch function is called.
4668fn dispatchCodegenTask(comp: *Compilation, tid: usize, link_task: link.Task) void {
4669 if (comp.separateCodegenThreadOk()) {
4670 comp.queueLinkTasks(&.{link_task});
4671 } else {
4672 assert(comp.remaining_prelink_tasks == 0);
4673 link.doTask(comp, tid, link_task);
4674 }
4675}
4676
4677fn separateCodegenThreadOk(comp: *const Compilation) bool {
4772pub fn separateCodegenThreadOk(comp: *const Compilation) bool {
46784773 if (InternPool.single_threaded) return false;
46794774 const zcu = comp.zcu orelse return true;
46804775 return zcu.backendSupportsFeature(.separate_thread);
......@@ -4694,12 +4789,12 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
46944789 const zcu = comp.zcu orelse
46954790 return comp.lockAndSetMiscFailure(.docs_copy, "no Zig code to document", .{});
46964791
4697 const emit = comp.docs_emit.?;
4698 var out_dir = emit.root_dir.handle.makeOpenPath(emit.sub_path, .{}) catch |err| {
4792 const docs_path = comp.resolveEmitPath(comp.emit_docs.?);
4793 var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| {
46994794 return comp.lockAndSetMiscFailure(
47004795 .docs_copy,
4701 "unable to create output directory '{}{s}': {s}",
4702 .{ emit.root_dir, emit.sub_path, @errorName(err) },
4796 "unable to create output directory '{}': {s}",
4797 .{ docs_path, @errorName(err) },
47034798 );
47044799 };
47054800 defer out_dir.close();
......@@ -4718,8 +4813,8 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
47184813 var tar_file = out_dir.createFile("sources.tar", .{}) catch |err| {
47194814 return comp.lockAndSetMiscFailure(
47204815 .docs_copy,
4721 "unable to create '{}{s}/sources.tar': {s}",
4722 .{ emit.root_dir, emit.sub_path, @errorName(err) },
4816 "unable to create '{}/sources.tar': {s}",
4817 .{ docs_path, @errorName(err) },
47234818 );
47244819 };
47254820 defer tar_file.close();
......@@ -4869,11 +4964,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
48694964 .parent = root_mod,
48704965 });
48714966 try root_mod.deps.put(arena, "Walk", walk_mod);
4872 const bin_basename = try std.zig.binNameAlloc(arena, .{
4873 .root_name = root_name,
4874 .target = resolved_target.result,
4875 .output_mode = output_mode,
4876 });
48774967
48784968 const sub_compilation = try Compilation.create(gpa, arena, .{
48794969 .dirs = dirs,
......@@ -4885,10 +4975,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
48854975 .root_name = root_name,
48864976 .thread_pool = comp.thread_pool,
48874977 .libc_installation = comp.libc_installation,
4888 .emit_bin = .{
4889 .directory = null, // Put it in the cache directory.
4890 .basename = bin_basename,
4891 },
4978 .emit_bin = .yes_cache,
48924979 .verbose_cc = comp.verbose_cc,
48934980 .verbose_link = comp.verbose_link,
48944981 .verbose_air = comp.verbose_air,
......@@ -4903,27 +4990,31 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
49034990
49044991 try comp.updateSubCompilation(sub_compilation, .docs_wasm, prog_node);
49054992
4906 const emit = comp.docs_emit.?;
4907 var out_dir = emit.root_dir.handle.makeOpenPath(emit.sub_path, .{}) catch |err| {
4993 var crt_file = try sub_compilation.toCrtFile();
4994 defer crt_file.deinit(gpa);
4995
4996 const docs_bin_file = crt_file.full_object_path;
4997 assert(docs_bin_file.sub_path.len > 0); // emitted binary is not a directory
4998
4999 const docs_path = comp.resolveEmitPath(comp.emit_docs.?);
5000 var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| {
49085001 return comp.lockAndSetMiscFailure(
49095002 .docs_copy,
4910 "unable to create output directory '{}{s}': {s}",
4911 .{ emit.root_dir, emit.sub_path, @errorName(err) },
5003 "unable to create output directory '{}': {s}",
5004 .{ docs_path, @errorName(err) },
49125005 );
49135006 };
49145007 defer out_dir.close();
49155008
4916 sub_compilation.dirs.local_cache.handle.copyFile(
4917 sub_compilation.cache_use.whole.bin_sub_path.?,
5009 crt_file.full_object_path.root_dir.handle.copyFile(
5010 crt_file.full_object_path.sub_path,
49185011 out_dir,
49195012 "main.wasm",
49205013 .{},
49215014 ) catch |err| {
4922 return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{}{s}' to '{}{s}': {s}", .{
4923 sub_compilation.dirs.local_cache,
4924 sub_compilation.cache_use.whole.bin_sub_path.?,
4925 emit.root_dir,
4926 emit.sub_path,
5015 return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{}' to '{}': {s}", .{
5016 crt_file.full_object_path,
5017 docs_path,
49275018 @errorName(err),
49285019 });
49295020 };
......@@ -5185,7 +5276,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
51855276 defer whole.cache_manifest_mutex.unlock();
51865277 try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);
51875278 },
5188 .incremental => {},
5279 .incremental, .none => {},
51895280 }
51905281
51915282 const bin_digest = man.finalBin();
......@@ -5261,6 +5352,21 @@ pub const RtOptions = struct {
52615352 allow_lto: bool = true,
52625353};
52635354
5355fn workerZcuCodegen(
5356 tid: usize,
5357 comp: *Compilation,
5358 func_index: InternPool.Index,
5359 orig_air: Air,
5360 out: *link.ZcuTask.LinkFunc.SharedMir,
5361) void {
5362 var air = orig_air;
5363 // We own `air` now, so we are responsbile for freeing it.
5364 defer air.deinit(comp.gpa);
5365 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
5366 defer pt.deactivate();
5367 pt.runCodegen(func_index, &air, out);
5368}
5369
52645370fn buildRt(
52655371 comp: *Compilation,
52665372 root_source_name: []const u8,
......@@ -5515,9 +5621,9 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
55155621 defer man.deinit();
55165622
55175623 man.hash.add(comp.clang_preprocessor_mode);
5518 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_asm);
5519 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir);
5520 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc);
5624 man.hash.addOptionalBytes(comp.emit_asm);
5625 man.hash.addOptionalBytes(comp.emit_llvm_ir);
5626 man.hash.addOptionalBytes(comp.emit_llvm_bc);
55215627
55225628 try cache_helpers.hashCSource(&man, c_object.src);
55235629
......@@ -5751,7 +5857,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
57515857 try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);
57525858 }
57535859 },
5754 .incremental => {},
5860 .incremental, .none => {},
57555861 }
57565862 }
57575863
......@@ -5792,7 +5898,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
57925898 },
57935899 };
57945900
5795 comp.queueLinkTasks(&.{.{ .load_object = c_object.status.success.object_path }});
5901 comp.queuePrelinkTasks(&.{.{ .load_object = c_object.status.success.object_path }});
57965902}
57975903
57985904fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32_resource_prog_node: std.Progress.Node) !void {
......@@ -5995,7 +6101,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
59956101 defer whole.cache_manifest_mutex.unlock();
59966102 try whole_cache_manifest.addFilePost(dep_file_path);
59976103 },
5998 .incremental => {},
6104 .incremental, .none => {},
59996105 }
60006106 }
60016107 }
......@@ -7167,12 +7273,6 @@ fn buildOutputFromZig(
71677273 .cc_argv = &.{},
71687274 .parent = null,
71697275 });
7170 const target = comp.getTarget();
7171 const bin_basename = try std.zig.binNameAlloc(arena, .{
7172 .root_name = root_name,
7173 .target = target,
7174 .output_mode = output_mode,
7175 });
71767276
71777277 const parent_whole_cache: ?ParentWholeCache = switch (comp.cache_use) {
71787278 .whole => |whole| .{
......@@ -7185,7 +7285,7 @@ fn buildOutputFromZig(
71857285 3, // global cache is the same
71867286 },
71877287 },
7188 .incremental => null,
7288 .incremental, .none => null,
71897289 };
71907290
71917291 const sub_compilation = try Compilation.create(gpa, arena, .{
......@@ -7198,13 +7298,9 @@ fn buildOutputFromZig(
71987298 .root_name = root_name,
71997299 .thread_pool = comp.thread_pool,
72007300 .libc_installation = comp.libc_installation,
7201 .emit_bin = .{
7202 .directory = null, // Put it in the cache directory.
7203 .basename = bin_basename,
7204 },
7301 .emit_bin = .yes_cache,
72057302 .function_sections = true,
72067303 .data_sections = true,
7207 .emit_h = null,
72087304 .verbose_cc = comp.verbose_cc,
72097305 .verbose_link = comp.verbose_link,
72107306 .verbose_air = comp.verbose_air,
......@@ -7225,7 +7321,7 @@ fn buildOutputFromZig(
72257321 assert(out.* == null);
72267322 out.* = crt_file;
72277323
7228 comp.queueLinkTaskMode(crt_file.full_object_path, &config);
7324 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
72297325}
72307326
72317327pub const CrtFileOptions = struct {
......@@ -7324,13 +7420,9 @@ pub fn build_crt_file(
73247420 .root_name = root_name,
73257421 .thread_pool = comp.thread_pool,
73267422 .libc_installation = comp.libc_installation,
7327 .emit_bin = .{
7328 .directory = null, // Put it in the cache directory.
7329 .basename = basename,
7330 },
7423 .emit_bin = .yes_cache,
73317424 .function_sections = options.function_sections orelse false,
73327425 .data_sections = options.data_sections orelse false,
7333 .emit_h = null,
73347426 .c_source_files = c_source_files,
73357427 .verbose_cc = comp.verbose_cc,
73367428 .verbose_link = comp.verbose_link,
......@@ -7349,7 +7441,7 @@ pub fn build_crt_file(
73497441 try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node);
73507442
73517443 const crt_file = try sub_compilation.toCrtFile();
7352 comp.queueLinkTaskMode(crt_file.full_object_path, &config);
7444 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
73537445
73547446 {
73557447 comp.mutex.lock();
......@@ -7359,8 +7451,8 @@ pub fn build_crt_file(
73597451 }
73607452}
73617453
7362pub fn queueLinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Compilation.Config) void {
7363 comp.queueLinkTasks(switch (config.output_mode) {
7454pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Compilation.Config) void {
7455 comp.queuePrelinkTasks(switch (config.output_mode) {
73647456 .Exe => unreachable,
73657457 .Obj => &.{.{ .load_object = path }},
73667458 .Lib => &.{switch (config.link_mode) {
......@@ -7372,19 +7464,41 @@ pub fn queueLinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Co
73727464
73737465/// Only valid to call during `update`. Automatically handles queuing up a
73747466/// linker worker task if there is not already one.
7375pub fn queueLinkTasks(comp: *Compilation, tasks: []const link.Task) void {
7376 if (comp.link_task_queue.enqueue(comp.gpa, tasks) catch |err| switch (err) {
7467pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) void {
7468 comp.link_task_queue.enqueuePrelink(comp, tasks) catch |err| switch (err) {
73777469 error.OutOfMemory => return comp.setAllocFailure(),
7378 }) {
7379 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, link.flushTaskQueue, .{comp});
7470 };
7471}
7472
7473/// The reason for the double-queue here is that the first queue ensures any
7474/// resolve_type_fully tasks are complete before this dispatch function is called.
7475fn dispatchZcuLinkTask(comp: *Compilation, tid: usize, task: link.ZcuTask) void {
7476 if (!comp.separateCodegenThreadOk()) {
7477 assert(tid == 0);
7478 if (task == .link_func) {
7479 assert(task.link_func.mir.status.load(.monotonic) != .pending);
7480 }
7481 link.doZcuTask(comp, tid, task);
7482 task.deinit(comp.zcu.?);
7483 return;
73807484 }
7485 comp.link_task_queue.enqueueZcu(comp, task) catch |err| switch (err) {
7486 error.OutOfMemory => {
7487 task.deinit(comp.zcu.?);
7488 comp.setAllocFailure();
7489 },
7490 };
73817491}
73827492
73837493pub fn toCrtFile(comp: *Compilation) Allocator.Error!CrtFile {
73847494 return .{
73857495 .full_object_path = .{
73867496 .root_dir = comp.dirs.local_cache,
7387 .sub_path = try comp.gpa.dupe(u8, comp.cache_use.whole.bin_sub_path.?),
7497 .sub_path = try std.fs.path.join(comp.gpa, &.{
7498 "o",
7499 &Cache.binToHex(comp.digest.?),
7500 comp.emit_bin.?,
7501 }),
73887502 },
73897503 .lock = comp.cache_use.whole.moveLock(),
73907504 };
src/InternPool.zig+51
......@@ -3249,6 +3249,9 @@ pub const LoadedUnionType = struct {
32493249 name: NullTerminatedString,
32503250 /// Represents the declarations inside this union.
32513251 namespace: NamespaceIndex,
3252 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
3253 /// Otherwise, this is `.none`.
3254 name_nav: Nav.Index.Optional,
32523255 /// The enum tag type.
32533256 enum_tag_ty: Index,
32543257 /// List of field types in declaration order.
......@@ -3567,6 +3570,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
35673570 .tid = unwrapped_index.tid,
35683571 .extra_index = data,
35693572 .name = type_union.data.name,
3573 .name_nav = type_union.data.name_nav,
35703574 .namespace = type_union.data.namespace,
35713575 .enum_tag_ty = type_union.data.tag_ty,
35723576 .field_types = field_types,
......@@ -3584,6 +3588,9 @@ pub const LoadedStructType = struct {
35843588 /// The name of this struct type.
35853589 name: NullTerminatedString,
35863590 namespace: NamespaceIndex,
3591 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
3592 /// Otherwise, or if this is a file's root struct type, this is `.none`.
3593 name_nav: Nav.Index.Optional,
35873594 /// Index of the `struct_decl` or `reify` ZIR instruction.
35883595 zir_index: TrackedInst.Index,
35893596 layout: std.builtin.Type.ContainerLayout,
......@@ -4173,6 +4180,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
41734180 switch (item.tag) {
41744181 .type_struct => {
41754182 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]);
4183 const name_nav: Nav.Index.Optional = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?]);
41764184 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]);
41774185 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);
41784186 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "fields_len").?];
......@@ -4259,6 +4267,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
42594267 .tid = unwrapped_index.tid,
42604268 .extra_index = item.data,
42614269 .name = name,
4270 .name_nav = name_nav,
42624271 .namespace = namespace,
42634272 .zir_index = zir_index,
42644273 .layout = if (flags.is_extern) .@"extern" else .auto,
......@@ -4275,6 +4284,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
42754284 },
42764285 .type_struct_packed, .type_struct_packed_inits => {
42774286 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?]);
4287 const name_nav: Nav.Index.Optional = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?]);
42784288 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]);
42794289 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "fields_len").?];
42804290 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?]);
......@@ -4321,6 +4331,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
43214331 .tid = unwrapped_index.tid,
43224332 .extra_index = item.data,
43234333 .name = name,
4334 .name_nav = name_nav,
43244335 .namespace = namespace,
43254336 .zir_index = zir_index,
43264337 .layout = .@"packed",
......@@ -4345,6 +4356,9 @@ pub const LoadedEnumType = struct {
43454356 name: NullTerminatedString,
43464357 /// Represents the declarations inside this enum.
43474358 namespace: NamespaceIndex,
4359 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
4360 /// Otherwise, this is `.none`.
4361 name_nav: Nav.Index.Optional,
43484362 /// An integer type which is used for the numerical value of the enum.
43494363 /// This field is present regardless of whether the enum has an
43504364 /// explicitly provided tag type or auto-numbered.
......@@ -4428,6 +4442,7 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
44284442 } else extra.data.captures_len;
44294443 return .{
44304444 .name = extra.data.name,
4445 .name_nav = extra.data.name_nav,
44314446 .namespace = extra.data.namespace,
44324447 .tag_ty = extra.data.int_tag_type,
44334448 .names = .{
......@@ -4462,6 +4477,7 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
44624477 } else extra.data.captures_len;
44634478 return .{
44644479 .name = extra.data.name,
4480 .name_nav = extra.data.name_nav,
44654481 .namespace = extra.data.namespace,
44664482 .tag_ty = extra.data.int_tag_type,
44674483 .names = .{
......@@ -4493,6 +4509,9 @@ pub const LoadedOpaqueType = struct {
44934509 // TODO: the non-fqn will be needed by the new dwarf structure
44944510 /// The name of this opaque type.
44954511 name: NullTerminatedString,
4512 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
4513 /// Otherwise, this is `.none`.
4514 name_nav: Nav.Index.Optional,
44964515 /// Index of the `opaque_decl` or `reify` instruction.
44974516 zir_index: TrackedInst.Index,
44984517 captures: CaptureValue.Slice,
......@@ -4509,6 +4528,7 @@ pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType {
45094528 extra.data.captures_len;
45104529 return .{
45114530 .name = extra.data.name,
4531 .name_nav = extra.data.name_nav,
45124532 .namespace = extra.data.namespace,
45134533 .zir_index = extra.data.zir_index,
45144534 .captures = .{
......@@ -6022,6 +6042,7 @@ pub const Tag = enum(u8) {
60226042 /// 4. field align: Alignment for each field; declaration order
60236043 pub const TypeUnion = struct {
60246044 name: NullTerminatedString,
6045 name_nav: Nav.Index.Optional,
60256046 flags: Flags,
60266047 /// This could be provided through the tag type, but it is more convenient
60276048 /// to store it directly. This is also necessary for `dumpStatsFallible` to
......@@ -6061,6 +6082,7 @@ pub const Tag = enum(u8) {
60616082 /// 5. init: Index for each fields_len // if tag is type_struct_packed_inits
60626083 pub const TypeStructPacked = struct {
60636084 name: NullTerminatedString,
6085 name_nav: Nav.Index.Optional,
60646086 zir_index: TrackedInst.Index,
60656087 fields_len: u32,
60666088 namespace: NamespaceIndex,
......@@ -6108,6 +6130,7 @@ pub const Tag = enum(u8) {
61086130 /// 8. field_offset: u32 // for each field in declared order, undef until layout_resolved
61096131 pub const TypeStruct = struct {
61106132 name: NullTerminatedString,
6133 name_nav: Nav.Index.Optional,
61116134 zir_index: TrackedInst.Index,
61126135 namespace: NamespaceIndex,
61136136 fields_len: u32,
......@@ -6151,6 +6174,7 @@ pub const Tag = enum(u8) {
61516174 /// 0. capture: CaptureValue // for each `captures_len`
61526175 pub const TypeOpaque = struct {
61536176 name: NullTerminatedString,
6177 name_nav: Nav.Index.Optional,
61546178 /// Contains the declarations inside this opaque.
61556179 namespace: NamespaceIndex,
61566180 /// The index of the `opaque_decl` instruction.
......@@ -6429,6 +6453,7 @@ pub const Array = struct {
64296453/// 4. tag value: Index for each fields_len; declaration order
64306454pub const EnumExplicit = struct {
64316455 name: NullTerminatedString,
6456 name_nav: Nav.Index.Optional,
64326457 /// `std.math.maxInt(u32)` indicates this type is reified.
64336458 captures_len: u32,
64346459 namespace: NamespaceIndex,
......@@ -6454,6 +6479,7 @@ pub const EnumExplicit = struct {
64546479/// 3. field name: NullTerminatedString for each fields_len; declaration order
64556480pub const EnumAuto = struct {
64566481 name: NullTerminatedString,
6482 name_nav: Nav.Index.Optional,
64576483 /// `std.math.maxInt(u32)` indicates this type is reified.
64586484 captures_len: u32,
64596485 namespace: NamespaceIndex,
......@@ -8666,6 +8692,7 @@ pub fn getUnionType(
86668692 .size = std.math.maxInt(u32),
86678693 .padding = std.math.maxInt(u32),
86688694 .name = undefined, // set by `finish`
8695 .name_nav = undefined, // set by `finish`
86698696 .namespace = undefined, // set by `finish`
86708697 .tag_ty = ini.enum_tag_ty,
86718698 .zir_index = switch (ini.key) {
......@@ -8717,6 +8744,7 @@ pub fn getUnionType(
87178744 .tid = tid,
87188745 .index = gop.put(),
87198746 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?,
8747 .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?,
87208748 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?,
87218749 } };
87228750}
......@@ -8726,15 +8754,20 @@ pub const WipNamespaceType = struct {
87268754 index: Index,
87278755 type_name_extra_index: u32,
87288756 namespace_extra_index: u32,
8757 name_nav_extra_index: u32,
87298758
87308759 pub fn setName(
87318760 wip: WipNamespaceType,
87328761 ip: *InternPool,
87338762 type_name: NullTerminatedString,
8763 /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise.
8764 /// This is also `.none` if we use `.parent` because we are the root struct type for a file.
8765 name_nav: Nav.Index.Optional,
87348766 ) void {
87358767 const extra = ip.getLocalShared(wip.tid).extra.acquire();
87368768 const extra_items = extra.view().items(.@"0");
87378769 extra_items[wip.type_name_extra_index] = @intFromEnum(type_name);
8770 extra_items[wip.name_nav_extra_index] = @intFromEnum(name_nav);
87388771 }
87398772
87408773 pub fn finish(
......@@ -8843,6 +8876,7 @@ pub fn getStructType(
88438876 ini.fields_len); // inits
88448877 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{
88458878 .name = undefined, // set by `finish`
8879 .name_nav = undefined, // set by `finish`
88468880 .zir_index = zir_index,
88478881 .fields_len = ini.fields_len,
88488882 .namespace = undefined, // set by `finish`
......@@ -8887,6 +8921,7 @@ pub fn getStructType(
88878921 .tid = tid,
88888922 .index = gop.put(),
88898923 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?,
8924 .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?,
88908925 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?,
88918926 } };
88928927 },
......@@ -8909,6 +8944,7 @@ pub fn getStructType(
89098944 1); // names_map
89108945 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{
89118946 .name = undefined, // set by `finish`
8947 .name_nav = undefined, // set by `finish`
89128948 .zir_index = zir_index,
89138949 .namespace = undefined, // set by `finish`
89148950 .fields_len = ini.fields_len,
......@@ -8977,6 +9013,7 @@ pub fn getStructType(
89779013 .tid = tid,
89789014 .index = gop.put(),
89799015 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?,
9016 .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?,
89809017 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?,
89819018 } };
89829019}
......@@ -9766,6 +9803,7 @@ pub const WipEnumType = struct {
97669803 tag_ty_index: u32,
97679804 type_name_extra_index: u32,
97689805 namespace_extra_index: u32,
9806 name_nav_extra_index: u32,
97699807 names_map: MapIndex,
97709808 names_start: u32,
97719809 values_map: OptionalMapIndex,
......@@ -9775,10 +9813,13 @@ pub const WipEnumType = struct {
97759813 wip: WipEnumType,
97769814 ip: *InternPool,
97779815 type_name: NullTerminatedString,
9816 /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise.
9817 name_nav: Nav.Index.Optional,
97789818 ) void {
97799819 const extra = ip.getLocalShared(wip.tid).extra.acquire();
97809820 const extra_items = extra.view().items(.@"0");
97819821 extra_items[wip.type_name_extra_index] = @intFromEnum(type_name);
9822 extra_items[wip.name_nav_extra_index] = @intFromEnum(name_nav);
97829823 }
97839824
97849825 pub fn prepare(
......@@ -9893,6 +9934,7 @@ pub fn getEnumType(
98939934
98949935 const extra_index = addExtraAssumeCapacity(extra, EnumAuto{
98959936 .name = undefined, // set by `prepare`
9937 .name_nav = undefined, // set by `prepare`
98969938 .captures_len = switch (ini.key) {
98979939 inline .declared, .declared_owned_captures => |d| @intCast(d.captures.len),
98989940 .reified => std.math.maxInt(u32),
......@@ -9921,6 +9963,7 @@ pub fn getEnumType(
99219963 .index = gop.put(),
99229964 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?,
99239965 .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name").?,
9966 .name_nav_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name_nav").?,
99249967 .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "namespace").?,
99259968 .names_map = names_map,
99269969 .names_start = @intCast(names_start),
......@@ -9950,6 +9993,7 @@ pub fn getEnumType(
99509993
99519994 const extra_index = addExtraAssumeCapacity(extra, EnumExplicit{
99529995 .name = undefined, // set by `prepare`
9996 .name_nav = undefined, // set by `prepare`
99539997 .captures_len = switch (ini.key) {
99549998 inline .declared, .declared_owned_captures => |d| @intCast(d.captures.len),
99559999 .reified => std.math.maxInt(u32),
......@@ -9987,6 +10031,7 @@ pub fn getEnumType(
998710031 .index = gop.put(),
998810032 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?,
998910033 .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name").?,
10034 .name_nav_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name_nav").?,
999010035 .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "namespace").?,
999110036 .names_map = names_map,
999210037 .names_start = @intCast(names_start),
......@@ -10055,6 +10100,7 @@ pub fn getGeneratedTagEnumType(
1005510100 .tag = .type_enum_auto,
1005610101 .data = addExtraAssumeCapacity(extra, EnumAuto{
1005710102 .name = ini.name,
10103 .name_nav = .none,
1005810104 .captures_len = 0,
1005910105 .namespace = namespace,
1006010106 .int_tag_type = ini.tag_ty,
......@@ -10088,6 +10134,7 @@ pub fn getGeneratedTagEnumType(
1008810134 },
1008910135 .data = addExtraAssumeCapacity(extra, EnumExplicit{
1009010136 .name = ini.name,
10137 .name_nav = .none,
1009110138 .captures_len = 0,
1009210139 .namespace = namespace,
1009310140 .int_tag_type = ini.tag_ty,
......@@ -10161,6 +10208,7 @@ pub fn getOpaqueType(
1016110208 });
1016210209 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{
1016310210 .name = undefined, // set by `finish`
10211 .name_nav = undefined, // set by `finish`
1016410212 .namespace = undefined, // set by `finish`
1016510213 .zir_index = switch (ini.key) {
1016610214 inline else => |x| x.zir_index,
......@@ -10183,6 +10231,7 @@ pub fn getOpaqueType(
1018310231 .tid = tid,
1018410232 .index = gop.put(),
1018510233 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?,
10234 .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name_nav").?,
1018610235 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?,
1018710236 },
1018810237 };
......@@ -10299,6 +10348,7 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 {
1029910348 extra.appendAssumeCapacity(.{switch (field.type) {
1030010349 Index,
1030110350 Nav.Index,
10351 Nav.Index.Optional,
1030210352 NamespaceIndex,
1030310353 OptionalNamespaceIndex,
1030410354 MapIndex,
......@@ -10361,6 +10411,7 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat
1036110411 @field(result, field.name) = switch (field.type) {
1036210412 Index,
1036310413 Nav.Index,
10414 Nav.Index.Optional,
1036410415 NamespaceIndex,
1036510416 OptionalNamespaceIndex,
1036610417 MapIndex,
src/Sema.zig+85-47
......@@ -2963,13 +2963,14 @@ fn zirStructDecl(
29632963 };
29642964 errdefer wip_ty.cancel(ip, pt.tid);
29652965
2966 wip_ty.setName(ip, try sema.createTypeName(
2966 const type_name = try sema.createTypeName(
29672967 block,
29682968 small.name_strategy,
29692969 "struct",
29702970 inst,
29712971 wip_ty.index,
2972 ));
2972 );
2973 wip_ty.setName(ip, type_name.name, type_name.nav);
29732974
29742975 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
29752976 .parent = block.namespace.toOptional(),
......@@ -2991,7 +2992,8 @@ fn zirStructDecl(
29912992 if (zcu.comp.config.use_llvm) break :codegen_type;
29922993 if (block.ownerModule().strip) break :codegen_type;
29932994 // This job depends on any resolve_type_fully jobs queued up before it.
2994 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
2995 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
2996 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
29952997 }
29962998 try sema.declareDependency(.{ .interned = wip_ty.index });
29972999 try sema.addTypeReferenceEntry(src, wip_ty.index);
......@@ -3007,7 +3009,10 @@ pub fn createTypeName(
30073009 inst: ?Zir.Inst.Index,
30083010 /// This is used purely to give the type a unique name in the `anon` case.
30093011 type_index: InternPool.Index,
3010) !InternPool.NullTerminatedString {
3012) !struct {
3013 name: InternPool.NullTerminatedString,
3014 nav: InternPool.Nav.Index.Optional,
3015} {
30113016 const pt = sema.pt;
30123017 const zcu = pt.zcu;
30133018 const gpa = zcu.gpa;
......@@ -3015,7 +3020,10 @@ pub fn createTypeName(
30153020
30163021 switch (name_strategy) {
30173022 .anon => {}, // handled after switch
3018 .parent => return block.type_name_ctx,
3023 .parent => return .{
3024 .name = block.type_name_ctx,
3025 .nav = sema.owner.unwrap().nav_val.toOptional(),
3026 },
30193027 .func => func_strat: {
30203028 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail);
30213029 const zir_tags = sema.code.instructions.items(.tag);
......@@ -3057,7 +3065,10 @@ pub fn createTypeName(
30573065 };
30583066
30593067 try writer.writeByte(')');
3060 return ip.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls);
3068 return .{
3069 .name = try ip.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls),
3070 .nav = .none,
3071 };
30613072 },
30623073 .dbg_var => {
30633074 // TODO: this logic is questionable. We ideally should be traversing the `Block` rather than relying on the order of AstGen instructions.
......@@ -3066,9 +3077,12 @@ pub fn createTypeName(
30663077 const zir_data = sema.code.instructions.items(.data);
30673078 for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) {
30683079 .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) {
3069 return ip.getOrPutStringFmt(gpa, pt.tid, "{}.{s}", .{
3070 block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),
3071 }, .no_embedded_nulls);
3080 return .{
3081 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.{s}", .{
3082 block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),
3083 }, .no_embedded_nulls),
3084 .nav = .none,
3085 };
30723086 },
30733087 else => {},
30743088 };
......@@ -3086,9 +3100,12 @@ pub fn createTypeName(
30863100 // types appropriately. However, `@typeName` becomes a problem then. If we remove
30873101 // that builtin from the language, we can consider this.
30883102
3089 return ip.getOrPutStringFmt(gpa, pt.tid, "{}__{s}_{d}", .{
3090 block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index),
3091 }, .no_embedded_nulls);
3103 return .{
3104 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}__{s}_{d}", .{
3105 block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index),
3106 }, .no_embedded_nulls),
3107 .nav = .none,
3108 };
30923109}
30933110
30943111fn zirEnumDecl(
......@@ -3209,7 +3226,7 @@ fn zirEnumDecl(
32093226 inst,
32103227 wip_ty.index,
32113228 );
3212 wip_ty.setName(ip, type_name);
3229 wip_ty.setName(ip, type_name.name, type_name.nav);
32133230
32143231 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
32153232 .parent = block.namespace.toOptional(),
......@@ -3236,7 +3253,7 @@ fn zirEnumDecl(
32363253 inst,
32373254 tracked_inst,
32383255 new_namespace_index,
3239 type_name,
3256 type_name.name,
32403257 small,
32413258 body,
32423259 tag_type_ref,
......@@ -3250,7 +3267,8 @@ fn zirEnumDecl(
32503267 if (zcu.comp.config.use_llvm) break :codegen_type;
32513268 if (block.ownerModule().strip) break :codegen_type;
32523269 // This job depends on any resolve_type_fully jobs queued up before it.
3253 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
3270 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3271 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
32543272 }
32553273 return Air.internedToRef(wip_ty.index);
32563274}
......@@ -3340,13 +3358,14 @@ fn zirUnionDecl(
33403358 };
33413359 errdefer wip_ty.cancel(ip, pt.tid);
33423360
3343 wip_ty.setName(ip, try sema.createTypeName(
3361 const type_name = try sema.createTypeName(
33443362 block,
33453363 small.name_strategy,
33463364 "union",
33473365 inst,
33483366 wip_ty.index,
3349 ));
3367 );
3368 wip_ty.setName(ip, type_name.name, type_name.nav);
33503369
33513370 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
33523371 .parent = block.namespace.toOptional(),
......@@ -3368,7 +3387,8 @@ fn zirUnionDecl(
33683387 if (zcu.comp.config.use_llvm) break :codegen_type;
33693388 if (block.ownerModule().strip) break :codegen_type;
33703389 // This job depends on any resolve_type_fully jobs queued up before it.
3371 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
3390 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3391 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
33723392 }
33733393 try sema.declareDependency(.{ .interned = wip_ty.index });
33743394 try sema.addTypeReferenceEntry(src, wip_ty.index);
......@@ -3432,13 +3452,14 @@ fn zirOpaqueDecl(
34323452 };
34333453 errdefer wip_ty.cancel(ip, pt.tid);
34343454
3435 wip_ty.setName(ip, try sema.createTypeName(
3455 const type_name = try sema.createTypeName(
34363456 block,
34373457 small.name_strategy,
34383458 "opaque",
34393459 inst,
34403460 wip_ty.index,
3441 ));
3461 );
3462 wip_ty.setName(ip, type_name.name, type_name.nav);
34423463
34433464 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
34443465 .parent = block.namespace.toOptional(),
......@@ -3455,7 +3476,8 @@ fn zirOpaqueDecl(
34553476 if (zcu.comp.config.use_llvm) break :codegen_type;
34563477 if (block.ownerModule().strip) break :codegen_type;
34573478 // This job depends on any resolve_type_fully jobs queued up before it.
3458 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
3479 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3480 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
34593481 }
34603482 try sema.addTypeReferenceEntry(src, wip_ty.index);
34613483 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
......@@ -20052,7 +20074,8 @@ fn structInitAnon(
2005220074 }, false)) {
2005320075 .wip => |wip| ty: {
2005420076 errdefer wip.cancel(ip, pt.tid);
20055 wip.setName(ip, try sema.createTypeName(block, .anon, "struct", inst, wip.index));
20077 const type_name = try sema.createTypeName(block, .anon, "struct", inst, wip.index);
20078 wip.setName(ip, type_name.name, type_name.nav);
2005620079
2005720080 const struct_type = ip.loadStructType(wip.index);
2005820081
......@@ -20076,7 +20099,8 @@ fn structInitAnon(
2007620099 codegen_type: {
2007720100 if (zcu.comp.config.use_llvm) break :codegen_type;
2007820101 if (block.ownerModule().strip) break :codegen_type;
20079 try zcu.comp.queueJob(.{ .codegen_type = wip.index });
20102 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
20103 try zcu.comp.queueJob(.{ .link_type = wip.index });
2008020104 }
2008120105 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index);
2008220106 break :ty wip.finish(ip, new_namespace_index);
......@@ -21112,13 +21136,14 @@ fn zirReify(
2111221136 };
2111321137 errdefer wip_ty.cancel(ip, pt.tid);
2111421138
21115 wip_ty.setName(ip, try sema.createTypeName(
21139 const type_name = try sema.createTypeName(
2111621140 block,
2111721141 name_strategy,
2111821142 "opaque",
2111921143 inst,
2112021144 wip_ty.index,
21121 ));
21145 );
21146 wip_ty.setName(ip, type_name.name, type_name.nav);
2112221147
2112321148 const new_namespace_index = try pt.createNamespace(.{
2112421149 .parent = block.namespace.toOptional(),
......@@ -21317,13 +21342,14 @@ fn reifyEnum(
2131721342 return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{});
2131821343 }
2131921344
21320 wip_ty.setName(ip, try sema.createTypeName(
21345 const type_name = try sema.createTypeName(
2132121346 block,
2132221347 name_strategy,
2132321348 "enum",
2132421349 inst,
2132521350 wip_ty.index,
21326 ));
21351 );
21352 wip_ty.setName(ip, type_name.name, type_name.nav);
2132721353
2132821354 const new_namespace_index = try pt.createNamespace(.{
2132921355 .parent = block.namespace.toOptional(),
......@@ -21386,7 +21412,8 @@ fn reifyEnum(
2138621412 if (zcu.comp.config.use_llvm) break :codegen_type;
2138721413 if (block.ownerModule().strip) break :codegen_type;
2138821414 // This job depends on any resolve_type_fully jobs queued up before it.
21389 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
21415 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
21416 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
2139021417 }
2139121418 return Air.internedToRef(wip_ty.index);
2139221419}
......@@ -21488,7 +21515,7 @@ fn reifyUnion(
2148821515 inst,
2148921516 wip_ty.index,
2149021517 );
21491 wip_ty.setName(ip, type_name);
21518 wip_ty.setName(ip, type_name.name, type_name.nav);
2149221519
2149321520 const field_types = try sema.arena.alloc(InternPool.Index, fields_len);
2149421521 const field_aligns = if (any_aligns) try sema.arena.alloc(InternPool.Alignment, fields_len) else undefined;
......@@ -21581,7 +21608,7 @@ fn reifyUnion(
2158121608 }
2158221609 }
2158321610
21584 const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), wip_ty.index, type_name);
21611 const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), wip_ty.index, type_name.name);
2158521612 break :tag_ty .{ enum_tag_ty, false };
2158621613 };
2158721614 errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error
......@@ -21640,7 +21667,8 @@ fn reifyUnion(
2164021667 if (zcu.comp.config.use_llvm) break :codegen_type;
2164121668 if (block.ownerModule().strip) break :codegen_type;
2164221669 // This job depends on any resolve_type_fully jobs queued up before it.
21643 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
21670 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
21671 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
2164421672 }
2164521673 try sema.declareDependency(.{ .interned = wip_ty.index });
2164621674 try sema.addTypeReferenceEntry(src, wip_ty.index);
......@@ -21843,13 +21871,14 @@ fn reifyStruct(
2184321871 };
2184421872 errdefer wip_ty.cancel(ip, pt.tid);
2184521873
21846 wip_ty.setName(ip, try sema.createTypeName(
21874 const type_name = try sema.createTypeName(
2184721875 block,
2184821876 name_strategy,
2184921877 "struct",
2185021878 inst,
2185121879 wip_ty.index,
21852 ));
21880 );
21881 wip_ty.setName(ip, type_name.name, type_name.nav);
2185321882
2185421883 const struct_type = ip.loadStructType(wip_ty.index);
2185521884
......@@ -21994,7 +22023,8 @@ fn reifyStruct(
2199422023 if (zcu.comp.config.use_llvm) break :codegen_type;
2199522024 if (block.ownerModule().strip) break :codegen_type;
2199622025 // This job depends on any resolve_type_fully jobs queued up before it.
21997 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
22026 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
22027 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
2199822028 }
2199922029 try sema.declareDependency(.{ .interned = wip_ty.index });
2200022030 try sema.addTypeReferenceEntry(src, wip_ty.index);
......@@ -35022,7 +35052,7 @@ pub fn resolveUnionAlignment(
3502235052 union_type.setAlignment(ip, max_align);
3502335053}
3502435054
35025/// This logic must be kept in sync with `Zcu.getUnionLayout`.
35055/// This logic must be kept in sync with `Type.getUnionLayout`.
3502635056pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
3502735057 const pt = sema.pt;
3502835058 const ip = &pt.zcu.intern_pool;
......@@ -35056,24 +35086,32 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
3505635086 var max_align: Alignment = .@"1";
3505735087 for (0..union_type.field_types.len) |field_index| {
3505835088 const field_ty: Type = .fromInterned(union_type.field_types.get(ip)[field_index]);
35059
35060 if (try field_ty.comptimeOnlySema(pt) or field_ty.zigTypeTag(pt.zcu) == .noreturn) continue; // TODO: should this affect alignment?
35061
35062 max_size = @max(max_size, field_ty.abiSizeSema(pt) catch |err| switch (err) {
35063 error.AnalysisFail => {
35064 const msg = sema.err orelse return err;
35065 try sema.addFieldErrNote(ty, field_index, msg, "while checking this field", .{});
35066 return err;
35067 },
35068 else => return err,
35069 });
35089 if (field_ty.isNoReturn(pt.zcu)) continue;
35090
35091 // We need to call `hasRuntimeBits` before calling `abiSize` to prevent reachable `unreachable`s,
35092 // but `hasRuntimeBits` only resolves field types and so may infinite recurse on a layout wip type,
35093 // so we must resolve the layout manually first, instead of waiting for `abiSize` to do it for us.
35094 // This is arguably just hacking around bugs in both `abiSize` for not allowing arbitrary types to
35095 // be queried, enabling failures to be handled with the emission of a compile error, and also in
35096 // `hasRuntimeBits` for ever being able to infinite recurse in the first place.
35097 try field_ty.resolveLayout(pt);
35098
35099 if (try field_ty.hasRuntimeBitsSema(pt)) {
35100 max_size = @max(max_size, field_ty.abiSizeSema(pt) catch |err| switch (err) {
35101 error.AnalysisFail => {
35102 const msg = sema.err orelse return err;
35103 try sema.addFieldErrNote(ty, field_index, msg, "while checking this field", .{});
35104 return err;
35105 },
35106 else => return err,
35107 });
35108 }
3507035109
3507135110 const explicit_align = union_type.fieldAlign(ip, field_index);
3507235111 const field_align = if (explicit_align != .none)
3507335112 explicit_align
3507435113 else
3507535114 try field_ty.abiAlignmentSema(pt);
35076
3507735115 max_align = max_align.max(field_align);
3507835116 }
3507935117
src/Sema/LowerZon.zig+5-3
......@@ -157,13 +157,14 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter
157157 )) {
158158 .wip => |wip| ty: {
159159 errdefer wip.cancel(ip, pt.tid);
160 wip.setName(ip, try self.sema.createTypeName(
160 const type_name = try self.sema.createTypeName(
161161 self.block,
162162 .anon,
163163 "struct",
164164 self.base_node_inst.resolve(ip),
165165 wip.index,
166 ));
166 );
167 wip.setName(ip, type_name.name, type_name.nav);
167168
168169 const struct_type = ip.loadStructType(wip.index);
169170
......@@ -194,7 +195,8 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter
194195 codegen_type: {
195196 if (pt.zcu.comp.config.use_llvm) break :codegen_type;
196197 if (self.block.ownerModule().strip) break :codegen_type;
197 try pt.zcu.comp.queueJob(.{ .codegen_type = wip.index });
198 pt.zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
199 try pt.zcu.comp.queueJob(.{ .link_type = wip.index });
198200 }
199201 break :ty wip.finish(ip, new_namespace_index);
200202 },
src/ThreadSafeQueue.zig deleted-72
......@@ -1,72 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const Allocator = std.mem.Allocator;
4
5pub fn ThreadSafeQueue(comptime T: type) type {
6 return struct {
7 worker_owned: std.ArrayListUnmanaged(T),
8 /// Protected by `mutex`.
9 shared: std.ArrayListUnmanaged(T),
10 mutex: std.Thread.Mutex,
11 state: State,
12
13 const Self = @This();
14
15 pub const State = enum { wait, run };
16
17 pub const empty: Self = .{
18 .worker_owned = .empty,
19 .shared = .empty,
20 .mutex = .{},
21 .state = .wait,
22 };
23
24 pub fn deinit(self: *Self, gpa: Allocator) void {
25 self.worker_owned.deinit(gpa);
26 self.shared.deinit(gpa);
27 self.* = undefined;
28 }
29
30 /// Must be called from the worker thread.
31 pub fn check(self: *Self) ?[]T {
32 assert(self.worker_owned.items.len == 0);
33 {
34 self.mutex.lock();
35 defer self.mutex.unlock();
36 assert(self.state == .run);
37 if (self.shared.items.len == 0) {
38 self.state = .wait;
39 return null;
40 }
41 std.mem.swap(std.ArrayListUnmanaged(T), &self.worker_owned, &self.shared);
42 }
43 const result = self.worker_owned.items;
44 self.worker_owned.clearRetainingCapacity();
45 return result;
46 }
47
48 /// Adds items to the queue, returning true if and only if the worker
49 /// thread is waiting. Thread-safe.
50 /// Not safe to call from the worker thread.
51 pub fn enqueue(self: *Self, gpa: Allocator, items: []const T) error{OutOfMemory}!bool {
52 self.mutex.lock();
53 defer self.mutex.unlock();
54 try self.shared.appendSlice(gpa, items);
55 return switch (self.state) {
56 .run => false,
57 .wait => {
58 self.state = .run;
59 return true;
60 },
61 };
62 }
63
64 /// Safe only to call exactly once when initially starting the worker.
65 pub fn start(self: *Self) bool {
66 assert(self.state == .wait);
67 if (self.shared.items.len == 0) return false;
68 self.state = .run;
69 return true;
70 }
71 };
72}
src/Type.zig+13-10
......@@ -177,6 +177,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
177177 const zcu = pt.zcu;
178178 const ip = &zcu.intern_pool;
179179 switch (ip.indexToKey(ty.toIntern())) {
180 .undef => return writer.writeAll("@as(type, undefined)"),
180181 .int_type => |int_type| {
181182 const sign_char: u8 = switch (int_type.signedness) {
182183 .signed => 'i',
......@@ -398,7 +399,6 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
398399 },
399400
400401 // values, not types
401 .undef,
402402 .simple_value,
403403 .variable,
404404 .@"extern",
......@@ -3915,29 +3915,32 @@ fn resolveUnionInner(
39153915pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) Zcu.UnionLayout {
39163916 const ip = &zcu.intern_pool;
39173917 assert(loaded_union.haveLayout(ip));
3918 var most_aligned_field: u32 = undefined;
3919 var most_aligned_field_size: u64 = undefined;
3920 var biggest_field: u32 = undefined;
3918 var most_aligned_field: u32 = 0;
3919 var most_aligned_field_align: InternPool.Alignment = .@"1";
3920 var most_aligned_field_size: u64 = 0;
3921 var biggest_field: u32 = 0;
39213922 var payload_size: u64 = 0;
39223923 var payload_align: InternPool.Alignment = .@"1";
3923 for (loaded_union.field_types.get(ip), 0..) |field_ty, field_index| {
3924 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue;
3924 for (loaded_union.field_types.get(ip), 0..) |field_ty_ip_index, field_index| {
3925 const field_ty: Type = .fromInterned(field_ty_ip_index);
3926 if (field_ty.isNoReturn(zcu)) continue;
39253927
39263928 const explicit_align = loaded_union.fieldAlign(ip, field_index);
39273929 const field_align = if (explicit_align != .none)
39283930 explicit_align
39293931 else
3930 Type.fromInterned(field_ty).abiAlignment(zcu);
3931 const field_size = Type.fromInterned(field_ty).abiSize(zcu);
3932 field_ty.abiAlignment(zcu);
3933 const field_size = field_ty.abiSize(zcu);
39323934 if (field_size > payload_size) {
39333935 payload_size = field_size;
39343936 biggest_field = @intCast(field_index);
39353937 }
3936 if (field_align.compare(.gte, payload_align)) {
3937 payload_align = field_align;
3938 if (field_size > 0 and field_align.compare(.gte, most_aligned_field_align)) {
39383939 most_aligned_field = @intCast(field_index);
3940 most_aligned_field_align = field_align;
39393941 most_aligned_field_size = field_size;
39403942 }
3943 payload_align = payload_align.max(field_align);
39413944 }
39423945 const have_tag = loaded_union.flagsUnordered(ip).runtime_tag.hasTag();
39433946 if (!have_tag or !Type.fromInterned(loaded_union.enum_tag_ty).hasRuntimeBits(zcu)) {
src/Zcu.zig+82-21
......@@ -56,9 +56,8 @@ comptime {
5656/// General-purpose allocator. Used for both temporary and long-term storage.
5757gpa: Allocator,
5858comp: *Compilation,
59/// Usually, the LlvmObject is managed by linker code, however, in the case
60/// that -fno-emit-bin is specified, the linker code never executes, so we
61/// store the LlvmObject here.
59/// If the ZCU is emitting an LLVM object (i.e. we are using the LLVM backend), then this is the
60/// `LlvmObject` we are emitting to.
6261llvm_object: ?LlvmObject.Ptr,
6362
6463/// Pointer to externally managed resource.
......@@ -67,8 +66,18 @@ root_mod: *Package.Module,
6766/// `root_mod` is the test runner, and `main_mod` is the user's source file which has the tests.
6867main_mod: *Package.Module,
6968std_mod: *Package.Module,
70sema_prog_node: std.Progress.Node = std.Progress.Node.none,
71codegen_prog_node: std.Progress.Node = std.Progress.Node.none,
69sema_prog_node: std.Progress.Node = .none,
70codegen_prog_node: std.Progress.Node = .none,
71/// The number of codegen jobs which are pending or in-progress. Whichever thread drops this value
72/// to 0 is responsible for ending `codegen_prog_node`. While semantic analysis is happening, this
73/// value bottoms out at 1 instead of 0, to ensure that it can only drop to 0 after analysis is
74/// completed (since semantic analysis could trigger more codegen work).
75pending_codegen_jobs: std.atomic.Value(u32) = .init(0),
76
77/// This is the progress node *under* `sema_prog_node` which is currently running.
78/// When we have to pause to analyze something else, we just temporarily rename this node.
79/// Eventually, when we thread semantic analysis, we will want one of these per thread.
80cur_sema_prog_node: std.Progress.Node = .none,
7281
7382/// Used by AstGen worker to load and store ZIR cache.
7483global_zir_cache: Cache.Directory,
......@@ -172,6 +181,8 @@ transitive_failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .emp
172181/// This `Nav` succeeded analysis, but failed codegen.
173182/// This may be a simple "value" `Nav`, or it may be a function.
174183/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
184/// While multiple threads are active (most of the time!), this is guarded by `zcu.comp.mutex`, as
185/// codegen and linking run on a separate thread.
175186failed_codegen: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, *ErrorMsg) = .empty,
176187failed_types: std.AutoArrayHashMapUnmanaged(InternPool.Index, *ErrorMsg) = .empty,
177188/// Keep track of `@compileLog`s per `AnalUnit`.
......@@ -267,16 +278,6 @@ resolved_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) = n
267278/// Reset to `false` at the start of each update in `Compilation.update`.
268279skip_analysis_this_update: bool = false,
269280
270stage1_flags: packed struct {
271 have_winmain: bool = false,
272 have_wwinmain: bool = false,
273 have_winmain_crt_startup: bool = false,
274 have_wwinmain_crt_startup: bool = false,
275 have_dllmain_crt_startup: bool = false,
276 have_c_main: bool = false,
277 reserved: u2 = 0,
278} = .{},
279
280281test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
281282
282283global_assembly: std.AutoArrayHashMapUnmanaged(AnalUnit, []u8) = .empty,
......@@ -3828,7 +3829,36 @@ pub const Feature = enum {
38283829 is_named_enum_value,
38293830 error_set_has_value,
38303831 field_reordering,
3831 /// If the backend supports running from another thread.
3832 /// In theory, backends are supposed to work like this:
3833 ///
3834 /// * The AIR emitted by `Sema` is converted into MIR by `codegen.generateFunction`. This pass
3835 /// is "pure", in that it does not depend on or modify any external mutable state.
3836 ///
3837 /// * That MIR is sent to the linker, which calls `codegen.emitFunction` to convert the MIR to
3838 /// finalized machine code. This process is permitted to query and modify linker state.
3839 ///
3840 /// * The linker stores the resulting machine code in the binary as needed.
3841 ///
3842 /// The first stage described above can run in parallel to the rest of the compiler, and even to
3843 /// other code generation work; we can run as many codegen threads as we want in parallel because
3844 /// of the fact that this pass is pure. Emit and link must be single-threaded, but are generally
3845 /// very fast, so that isn't a problem.
3846 ///
3847 /// Unfortunately, some code generation implementations currently query and/or mutate linker state
3848 /// or even (in the case of the LLVM backend) semantic analysis state. Such backends cannot be run
3849 /// in parallel with each other, with linking, or (potentially) with semantic analysis.
3850 ///
3851 /// Additionally, some backends continue to need the AIR in the "emit" stage, despite this pass
3852 /// operating on MIR. This complicates memory management under the threading model above.
3853 ///
3854 /// These are both **bugs** in backend implementations, left over from legacy code. However, they
3855 /// are difficult to fix. So, this `Feature` currently guards correct threading of code generation:
3856 ///
3857 /// * With this feature enabled, the backend is threaded as described above. The "emit" stage does
3858 /// not have access to AIR (it will be `undefined`; see `codegen.emitFunction`).
3859 ///
3860 /// * With this feature disabled, semantic analysis, code generation, and linking all occur on the
3861 /// same thread, and the "emit" stage has access to AIR.
38323862 separate_thread,
38333863};
38343864
......@@ -4577,22 +4607,29 @@ pub fn codegenFail(
45774607 comptime format: []const u8,
45784608 args: anytype,
45794609) CodegenFailError {
4580 const gpa = zcu.gpa;
4581 try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1);
4582 const msg = try Zcu.ErrorMsg.create(gpa, zcu.navSrcLoc(nav_index), format, args);
4583 zcu.failed_codegen.putAssumeCapacityNoClobber(nav_index, msg);
4584 return error.CodegenFail;
4610 const msg = try Zcu.ErrorMsg.create(zcu.gpa, zcu.navSrcLoc(nav_index), format, args);
4611 return zcu.codegenFailMsg(nav_index, msg);
45854612}
45864613
4614/// Takes ownership of `msg`, even on OOM.
45874615pub fn codegenFailMsg(zcu: *Zcu, nav_index: InternPool.Nav.Index, msg: *ErrorMsg) CodegenFailError {
45884616 const gpa = zcu.gpa;
45894617 {
4618 zcu.comp.mutex.lock();
4619 defer zcu.comp.mutex.unlock();
45904620 errdefer msg.deinit(gpa);
45914621 try zcu.failed_codegen.putNoClobber(gpa, nav_index, msg);
45924622 }
45934623 return error.CodegenFail;
45944624}
45954625
4626/// Asserts that `zcu.failed_codegen` contains the key `nav`, with the necessary lock held.
4627pub fn assertCodegenFailed(zcu: *Zcu, nav: InternPool.Nav.Index) void {
4628 zcu.comp.mutex.lock();
4629 defer zcu.comp.mutex.unlock();
4630 assert(zcu.failed_codegen.contains(nav));
4631}
4632
45964633pub fn codegenFailType(
45974634 zcu: *Zcu,
45984635 ty_index: InternPool.Index,
......@@ -4726,3 +4763,27 @@ fn explainWhyFileIsInModule(
47264763 import = importer_ref.import;
47274764 }
47284765}
4766
4767const SemaProgNode = struct {
4768 /// `null` means we created the node, so should end it.
4769 old_name: ?[std.Progress.Node.max_name_len]u8,
4770 pub fn end(spn: SemaProgNode, zcu: *Zcu) void {
4771 if (spn.old_name) |old_name| {
4772 zcu.sema_prog_node.completeOne(); // we're just renaming, but it's effectively completion
4773 zcu.cur_sema_prog_node.setName(&old_name);
4774 } else {
4775 zcu.cur_sema_prog_node.end();
4776 zcu.cur_sema_prog_node = .none;
4777 }
4778 }
4779};
4780pub fn startSemaProgNode(zcu: *Zcu, name: []const u8) SemaProgNode {
4781 if (zcu.cur_sema_prog_node.index != .none) {
4782 const old_name = zcu.cur_sema_prog_node.getName();
4783 zcu.cur_sema_prog_node.setName(name);
4784 return .{ .old_name = old_name };
4785 } else {
4786 zcu.cur_sema_prog_node = zcu.sema_prog_node.start(name, 0);
4787 return .{ .old_name = null };
4788 }
4789}
src/Zcu/PerThread.zig+189-216
......@@ -27,6 +27,7 @@ const Type = @import("../Type.zig");
2727const Value = @import("../Value.zig");
2828const Zcu = @import("../Zcu.zig");
2929const Compilation = @import("../Compilation.zig");
30const codegen = @import("../codegen.zig");
3031const Zir = std.zig.Zir;
3132const Zoir = std.zig.Zoir;
3233const ZonGen = std.zig.ZonGen;
......@@ -795,8 +796,8 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
795796 info.deps.clearRetainingCapacity();
796797 }
797798
798 const unit_prog_node = zcu.sema_prog_node.start("comptime", 0);
799 defer unit_prog_node.end();
799 const unit_prog_node = zcu.startSemaProgNode("comptime");
800 defer unit_prog_node.end(zcu);
800801
801802 return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) {
802803 error.AnalysisFail => {
......@@ -975,8 +976,8 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu
975976 info.deps.clearRetainingCapacity();
976977 }
977978
978 const unit_prog_node = zcu.sema_prog_node.start(nav.fqn.toSlice(ip), 0);
979 defer unit_prog_node.end();
979 const unit_prog_node = zcu.startSemaProgNode(nav.fqn.toSlice(ip));
980 defer unit_prog_node.end(zcu);
980981
981982 const invalidate_value: bool, const new_failed: bool = if (pt.analyzeNavVal(nav_id)) |result| res: {
982983 break :res .{
......@@ -1320,7 +1321,8 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
13201321 }
13211322
13221323 // This job depends on any resolve_type_fully jobs queued up before it.
1323 try zcu.comp.queueJob(.{ .codegen_nav = nav_id });
1324 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
1325 try zcu.comp.queueJob(.{ .link_nav = nav_id });
13241326 }
13251327
13261328 switch (old_nav.status) {
......@@ -1395,8 +1397,8 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc
13951397 info.deps.clearRetainingCapacity();
13961398 }
13971399
1398 const unit_prog_node = zcu.sema_prog_node.start(nav.fqn.toSlice(ip), 0);
1399 defer unit_prog_node.end();
1400 const unit_prog_node = zcu.startSemaProgNode(nav.fqn.toSlice(ip));
1401 defer unit_prog_node.end(zcu);
14001402
14011403 const invalidate_type: bool, const new_failed: bool = if (pt.analyzeNavType(nav_id)) |result| res: {
14021404 break :res .{
......@@ -1616,8 +1618,8 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter
16161618 info.deps.clearRetainingCapacity();
16171619 }
16181620
1619 const func_prog_node = zcu.sema_prog_node.start(ip.getNav(func.owner_nav).fqn.toSlice(ip), 0);
1620 defer func_prog_node.end();
1621 const func_prog_node = zcu.startSemaProgNode(ip.getNav(func.owner_nav).fqn.toSlice(ip));
1622 defer func_prog_node.end(zcu);
16211623
16221624 const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index)) |result|
16231625 .{ prev_failed or result.ies_outdated, false }
......@@ -1716,6 +1718,8 @@ fn analyzeFuncBody(
17161718 }
17171719
17181720 // This job depends on any resolve_type_fully jobs queued up before it.
1721 zcu.codegen_prog_node.increaseEstimatedTotalItems(1);
1722 comp.link_prog_node.increaseEstimatedTotalItems(1);
17191723 try comp.queueJob(.{ .codegen_func = .{
17201724 .func = func_index,
17211725 .air = air,
......@@ -1724,87 +1728,6 @@ fn analyzeFuncBody(
17241728 return .{ .ies_outdated = ies_outdated };
17251729}
17261730
1727/// Takes ownership of `air`, even on error.
1728/// If any types referenced by `air` are unresolved, marks the codegen as failed.
1729pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) Allocator.Error!void {
1730 const zcu = pt.zcu;
1731 const gpa = zcu.gpa;
1732 const ip = &zcu.intern_pool;
1733 const comp = zcu.comp;
1734
1735 const func = zcu.funcInfo(func_index);
1736 const nav_index = func.owner_nav;
1737 const nav = ip.getNav(nav_index);
1738
1739 const codegen_prog_node = zcu.codegen_prog_node.start(nav.fqn.toSlice(ip), 0);
1740 defer codegen_prog_node.end();
1741
1742 if (!air.typesFullyResolved(zcu)) {
1743 // A type we depend on failed to resolve. This is a transitive failure.
1744 // Correcting this failure will involve changing a type this function
1745 // depends on, hence triggering re-analysis of this function, so this
1746 // interacts correctly with incremental compilation.
1747 return;
1748 }
1749
1750 legalize: {
1751 try air.legalize(pt, @import("../codegen.zig").legalizeFeatures(pt, nav_index) orelse break :legalize);
1752 }
1753
1754 var liveness = try Air.Liveness.analyze(zcu, air.*, ip);
1755 defer liveness.deinit(gpa);
1756
1757 if (build_options.enable_debug_extensions and comp.verbose_air) {
1758 std.debug.print("# Begin Function AIR: {}:\n", .{nav.fqn.fmt(ip)});
1759 air.dump(pt, liveness);
1760 std.debug.print("# End Function AIR: {}\n\n", .{nav.fqn.fmt(ip)});
1761 }
1762
1763 if (std.debug.runtime_safety) {
1764 var verify: Air.Liveness.Verify = .{
1765 .gpa = gpa,
1766 .zcu = zcu,
1767 .air = air.*,
1768 .liveness = liveness,
1769 .intern_pool = ip,
1770 };
1771 defer verify.deinit();
1772
1773 verify.verify() catch |err| switch (err) {
1774 error.OutOfMemory => return error.OutOfMemory,
1775 else => {
1776 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
1777 gpa,
1778 zcu.navSrcLoc(nav_index),
1779 "invalid liveness: {s}",
1780 .{@errorName(err)},
1781 ));
1782 return;
1783 },
1784 };
1785 }
1786
1787 if (comp.bin_file) |lf| {
1788 lf.updateFunc(pt, func_index, air.*, liveness) catch |err| switch (err) {
1789 error.OutOfMemory => return error.OutOfMemory,
1790 error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
1791 error.Overflow, error.RelocationNotByteAligned => {
1792 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
1793 gpa,
1794 zcu.navSrcLoc(nav_index),
1795 "unable to codegen: {s}",
1796 .{@errorName(err)},
1797 ));
1798 // Not a retryable failure.
1799 },
1800 };
1801 } else if (zcu.llvm_object) |llvm_object| {
1802 llvm_object.updateFunc(pt, func_index, air.*, liveness) catch |err| switch (err) {
1803 error.OutOfMemory => return error.OutOfMemory,
1804 };
1805 }
1806}
1807
18081731pub fn semaMod(pt: Zcu.PerThread, mod: *Module) !void {
18091732 dev.check(.sema);
18101733 const file_index = pt.zcu.module_roots.get(mod).?.unwrap().?;
......@@ -1867,7 +1790,7 @@ fn createFileRootStruct(
18671790 };
18681791 errdefer wip_ty.cancel(ip, pt.tid);
18691792
1870 wip_ty.setName(ip, try file.internFullyQualifiedName(pt));
1793 wip_ty.setName(ip, try file.internFullyQualifiedName(pt), .none);
18711794 ip.namespacePtr(namespace_index).owner_type = wip_ty.index;
18721795
18731796 if (zcu.comp.incremental) {
......@@ -1877,10 +1800,10 @@ fn createFileRootStruct(
18771800 try pt.scanNamespace(namespace_index, decls);
18781801 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
18791802 codegen_type: {
1880 if (zcu.comp.config.use_llvm) break :codegen_type;
18811803 if (file.mod.?.strip) break :codegen_type;
18821804 // This job depends on any resolve_type_fully jobs queued up before it.
1883 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
1805 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
1806 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
18841807 }
18851808 zcu.setFileRootType(file_index, wip_ty.index);
18861809 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
......@@ -2574,7 +2497,7 @@ fn newEmbedFile(
25742497 cache: {
25752498 const whole = switch (zcu.comp.cache_use) {
25762499 .whole => |whole| whole,
2577 .incremental => break :cache,
2500 .incremental, .none => break :cache,
25782501 };
25792502 const man = whole.cache_manifest orelse break :cache;
25802503 const ip_str = opt_ip_str orelse break :cache; // this will be a compile error
......@@ -2974,17 +2897,10 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
29742897 runtime_params_len;
29752898
29762899 var runtime_param_index: usize = 0;
2977 for (fn_info.param_body[0..src_params_len]) |inst| {
2900 for (fn_info.param_body[0..src_params_len], 0..) |inst, zir_param_index| {
29782901 const gop = sema.inst_map.getOrPutAssumeCapacity(inst);
29792902 if (gop.found_existing) continue; // provided above by comptime arg
29802903
2981 const param_inst_info = sema.code.instructions.get(@intFromEnum(inst));
2982 const param_name: Zir.NullTerminatedString = switch (param_inst_info.tag) {
2983 .param_anytype => param_inst_info.data.str_tok.start,
2984 .param => sema.code.extraData(Zir.Inst.Param, param_inst_info.data.pl_tok.payload_index).data.name,
2985 else => unreachable,
2986 };
2987
29882904 const param_ty = fn_ty_info.param_types.get(ip)[runtime_param_index];
29892905 runtime_param_index += 1;
29902906
......@@ -3004,10 +2920,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
30042920 .tag = .arg,
30052921 .data = .{ .arg = .{
30062922 .ty = Air.internedToRef(param_ty),
3007 .name = if (inner_block.ownerModule().strip)
3008 .none
3009 else
3010 try sema.appendAirString(sema.code.nullTerminatedString(param_name)),
2923 .zir_param_index = @intCast(zir_param_index),
30112924 } },
30122925 });
30132926 }
......@@ -3189,7 +3102,9 @@ pub fn processExports(pt: Zcu.PerThread) !void {
31893102 // This export might already have been sent to the linker on a previous update, in which case we need to delete it.
31903103 // The linker export API should be modified to eliminate this call. #23616
31913104 if (zcu.comp.bin_file) |lf| {
3192 lf.deleteExport(exp.exported, exp.opts.name);
3105 if (zcu.llvm_object == null) {
3106 lf.deleteExport(exp.exported, exp.opts.name);
3107 }
31933108 }
31943109 continue;
31953110 }
......@@ -3213,8 +3128,10 @@ pub fn processExports(pt: Zcu.PerThread) !void {
32133128 // This export might already have been sent to the linker on a previous update, in which case we need to delete it.
32143129 // The linker export API should be modified to eliminate this loop. #23616
32153130 if (zcu.comp.bin_file) |lf| {
3216 for (exports) |exp| {
3217 lf.deleteExport(exp.exported, exp.opts.name);
3131 if (zcu.llvm_object == null) {
3132 for (exports) |exp| {
3133 lf.deleteExport(exp.exported, exp.opts.name);
3134 }
32183135 }
32193136 }
32203137 continue;
......@@ -3309,46 +3226,49 @@ fn processExportsInner(
33093226 .uav => {},
33103227 }
33113228
3312 if (zcu.comp.bin_file) |lf| {
3313 try zcu.handleUpdateExports(export_indices, lf.updateExports(pt, exported, export_indices));
3314 } else if (zcu.llvm_object) |llvm_object| {
3229 if (zcu.llvm_object) |llvm_object| {
33153230 try zcu.handleUpdateExports(export_indices, llvm_object.updateExports(pt, exported, export_indices));
3231 } else if (zcu.comp.bin_file) |lf| {
3232 try zcu.handleUpdateExports(export_indices, lf.updateExports(pt, exported, export_indices));
33163233 }
33173234}
33183235
3319pub fn populateTestFunctions(
3320 pt: Zcu.PerThread,
3321 main_progress_node: std.Progress.Node,
3322) Allocator.Error!void {
3236pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {
33233237 const zcu = pt.zcu;
33243238 const gpa = zcu.gpa;
33253239 const ip = &zcu.intern_pool;
3240
3241 // Our job is to correctly set the value of the `test_functions` declaration if it has been
3242 // analyzed and sent to codegen, It usually will have been, because the test runner will
3243 // reference it, and `std.builtin` shouldn't have type errors. However, if it hasn't been
3244 // analyzed, we will just terminate early, since clearly the test runner hasn't referenced
3245 // `test_functions` so there's no point populating it. More to the the point, we potentially
3246 // *can't* populate it without doing some type resolution, and... let's try to leave Sema in
3247 // the past here.
3248
33263249 const builtin_mod = zcu.builtin_modules.get(zcu.root_mod.getBuiltinOptions(zcu.comp.config).hash()).?;
33273250 const builtin_file_index = zcu.module_roots.get(builtin_mod).?.unwrap().?;
3328 pt.ensureFileAnalyzed(builtin_file_index) catch |err| switch (err) {
3329 error.AnalysisFail => unreachable, // builtin module is generated so cannot be corrupt
3330 error.OutOfMemory => |e| return e,
3331 };
3332 const builtin_root_type = Type.fromInterned(zcu.fileRootType(builtin_file_index));
3333 const builtin_namespace = builtin_root_type.getNamespace(zcu).unwrap().?;
3251 const builtin_root_type = zcu.fileRootType(builtin_file_index);
3252 if (builtin_root_type == .none) return; // `@import("builtin")` never analyzed
3253 const builtin_namespace = Type.fromInterned(builtin_root_type).getNamespace(zcu).unwrap().?;
3254 // We know that the namespace has a `test_functions`...
33343255 const nav_index = zcu.namespacePtr(builtin_namespace).pub_decls.getKeyAdapted(
33353256 try ip.getOrPutString(gpa, pt.tid, "test_functions", .no_embedded_nulls),
33363257 Zcu.Namespace.NameAdapter{ .zcu = zcu },
33373258 ).?;
3259 // ...but it might not be populated, so let's check that!
3260 if (zcu.failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or
3261 zcu.transitive_failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or
3262 ip.getNav(nav_index).status != .fully_resolved)
33383263 {
3339 // We have to call `ensureNavValUpToDate` here in case `builtin.test_functions`
3340 // was not referenced by start code.
3341 zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
3342 defer {
3343 zcu.sema_prog_node.end();
3344 zcu.sema_prog_node = std.Progress.Node.none;
3345 }
3346 pt.ensureNavValUpToDate(nav_index) catch |err| switch (err) {
3347 error.AnalysisFail => return,
3348 error.OutOfMemory => return error.OutOfMemory,
3349 };
3264 // The value of `builtin.test_functions` was either never referenced, or failed analysis.
3265 // Either way, we don't need to do anything.
3266 return;
33503267 }
33513268
3269 // Okay, `builtin.test_functions` is (potentially) referenced and valid. Our job now is to swap
3270 // its placeholder `&.{}` value for the actual list of all test functions.
3271
33523272 const test_fns_val = zcu.navValue(nav_index);
33533273 const test_fn_ty = test_fns_val.typeOf(zcu).slicePtrFieldType(zcu).childType(zcu);
33543274
......@@ -3450,81 +3370,8 @@ pub fn populateTestFunctions(
34503370 } });
34513371 ip.mutateVarInit(test_fns_val.toIntern(), new_init);
34523372 }
3453 {
3454 zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0);
3455 defer {
3456 zcu.codegen_prog_node.end();
3457 zcu.codegen_prog_node = std.Progress.Node.none;
3458 }
3459
3460 try pt.linkerUpdateNav(nav_index);
3461 }
3462}
3463
3464pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{OutOfMemory}!void {
3465 const zcu = pt.zcu;
3466 const comp = zcu.comp;
3467 const gpa = zcu.gpa;
3468 const ip = &zcu.intern_pool;
3469
3470 const nav = zcu.intern_pool.getNav(nav_index);
3471 const codegen_prog_node = zcu.codegen_prog_node.start(nav.fqn.toSlice(ip), 0);
3472 defer codegen_prog_node.end();
3473
3474 if (!Air.valFullyResolved(zcu.navValue(nav_index), zcu)) {
3475 // The value of this nav failed to resolve. This is a transitive failure.
3476 // TODO: do we need to mark this failure anywhere? I don't think so, since compilation
3477 // will fail due to the type error anyway.
3478 } else if (comp.bin_file) |lf| {
3479 lf.updateNav(pt, nav_index) catch |err| switch (err) {
3480 error.OutOfMemory => return error.OutOfMemory,
3481 error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
3482 error.Overflow, error.RelocationNotByteAligned => {
3483 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
3484 gpa,
3485 zcu.navSrcLoc(nav_index),
3486 "unable to codegen: {s}",
3487 .{@errorName(err)},
3488 ));
3489 // Not a retryable failure.
3490 },
3491 };
3492 } else if (zcu.llvm_object) |llvm_object| {
3493 llvm_object.updateNav(pt, nav_index) catch |err| switch (err) {
3494 error.OutOfMemory => return error.OutOfMemory,
3495 };
3496 }
3497}
3498
3499pub fn linkerUpdateContainerType(pt: Zcu.PerThread, ty: InternPool.Index) error{OutOfMemory}!void {
3500 const zcu = pt.zcu;
3501 const gpa = zcu.gpa;
3502 const comp = zcu.comp;
3503 const ip = &zcu.intern_pool;
3504
3505 const codegen_prog_node = zcu.codegen_prog_node.start(Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), 0);
3506 defer codegen_prog_node.end();
3507
3508 if (zcu.failed_types.fetchSwapRemove(ty)) |*entry| entry.value.deinit(gpa);
3509
3510 if (!Air.typeFullyResolved(Type.fromInterned(ty), zcu)) {
3511 // This type failed to resolve. This is a transitive failure.
3512 return;
3513 }
3514
3515 if (comp.bin_file) |lf| lf.updateContainerType(pt, ty) catch |err| switch (err) {
3516 error.OutOfMemory => return error.OutOfMemory,
3517 error.TypeFailureReported => assert(zcu.failed_types.contains(ty)),
3518 };
3519}
3520
3521pub fn linkerUpdateLineNumber(pt: Zcu.PerThread, ti: InternPool.TrackedInst.Index) !void {
3522 if (pt.zcu.comp.bin_file) |lf| {
3523 lf.updateLineNumber(pt, ti) catch |err| switch (err) {
3524 error.OutOfMemory => return error.OutOfMemory,
3525 else => |e| log.err("update line number failed: {s}", .{@errorName(e)}),
3526 };
3527 }
3373 // The linker thread is not running, so we actually need to dispatch this task directly.
3374 @import("../link.zig").linkTestFunctionsNav(pt, nav_index);
35283375}
35293376
35303377/// Stores an error in `pt.zcu.failed_files` for this file, and sets the file
......@@ -3984,7 +3831,8 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!
39843831 const result = try pt.zcu.intern_pool.getExtern(pt.zcu.gpa, pt.tid, key);
39853832 if (result.new_nav.unwrap()) |nav| {
39863833 // This job depends on any resolve_type_fully jobs queued up before it.
3987 try pt.zcu.comp.queueJob(.{ .codegen_nav = nav });
3834 pt.zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3835 try pt.zcu.comp.queueJob(.{ .link_nav = nav });
39883836 if (pt.zcu.comp.debugIncremental()) try pt.zcu.incremental_debug_state.newNav(pt.zcu, nav);
39893837 }
39903838 return result.index;
......@@ -4122,17 +3970,17 @@ fn recreateStructType(
41223970 };
41233971 errdefer wip_ty.cancel(ip, pt.tid);
41243972
4125 wip_ty.setName(ip, struct_obj.name);
3973 wip_ty.setName(ip, struct_obj.name, struct_obj.name_nav);
41263974 try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = key.zir_index });
41273975 zcu.namespacePtr(struct_obj.namespace).owner_type = wip_ty.index;
41283976 // No need to re-scan the namespace -- `zirStructDecl` will ultimately do that if the type is still alive.
41293977 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
41303978
41313979 codegen_type: {
4132 if (zcu.comp.config.use_llvm) break :codegen_type;
41333980 if (file.mod.?.strip) break :codegen_type;
41343981 // This job depends on any resolve_type_fully jobs queued up before it.
4135 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
3982 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3983 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
41363984 }
41373985
41383986 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
......@@ -4215,17 +4063,17 @@ fn recreateUnionType(
42154063 };
42164064 errdefer wip_ty.cancel(ip, pt.tid);
42174065
4218 wip_ty.setName(ip, union_obj.name);
4066 wip_ty.setName(ip, union_obj.name, union_obj.name_nav);
42194067 try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = key.zir_index });
42204068 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;
42214069 // No need to re-scan the namespace -- `zirUnionDecl` will ultimately do that if the type is still alive.
42224070 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
42234071
42244072 codegen_type: {
4225 if (zcu.comp.config.use_llvm) break :codegen_type;
42264073 if (file.mod.?.strip) break :codegen_type;
42274074 // This job depends on any resolve_type_fully jobs queued up before it.
4228 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
4075 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
4076 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
42294077 }
42304078
42314079 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
......@@ -4325,7 +4173,7 @@ fn recreateEnumType(
43254173 var done = true;
43264174 errdefer if (!done) wip_ty.cancel(ip, pt.tid);
43274175
4328 wip_ty.setName(ip, enum_obj.name);
4176 wip_ty.setName(ip, enum_obj.name, enum_obj.name_nav);
43294177
43304178 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;
43314179 // No need to re-scan the namespace -- `zirEnumDecl` will ultimately do that if the type is still alive.
......@@ -4518,3 +4366,128 @@ pub fn addDependency(pt: Zcu.PerThread, unit: AnalUnit, dependee: InternPool.Dep
45184366 try info.deps.append(gpa, dependee);
45194367 }
45204368}
4369
4370/// Performs code generation, which comes after `Sema` but before `link` in the pipeline.
4371/// This part of the pipeline is self-contained/"pure", so can be run in parallel with most
4372/// other code. This function is currently run either on the main thread, or on a separate
4373/// codegen thread, depending on whether the backend supports `Zcu.Feature.separate_thread`.
4374pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air, out: *@import("../link.zig").ZcuTask.LinkFunc.SharedMir) void {
4375 const zcu = pt.zcu;
4376 if (runCodegenInner(pt, func_index, air)) |mir| {
4377 out.value = mir;
4378 out.status.store(.ready, .release);
4379 } else |err| switch (err) {
4380 error.OutOfMemory => {
4381 zcu.comp.setAllocFailure();
4382 out.status.store(.failed, .monotonic);
4383 },
4384 error.CodegenFail => {
4385 zcu.assertCodegenFailed(zcu.funcInfo(func_index).owner_nav);
4386 out.status.store(.failed, .monotonic);
4387 },
4388 error.NoLinkFile => {
4389 assert(zcu.comp.bin_file == null);
4390 out.status.store(.failed, .monotonic);
4391 },
4392 error.BackendDoesNotProduceMir => {
4393 const backend = target_util.zigBackend(zcu.root_mod.resolved_target.result, zcu.comp.config.use_llvm);
4394 switch (backend) {
4395 else => unreachable, // assertion failure
4396 .stage2_spirv64,
4397 .stage2_llvm,
4398 => {},
4399 }
4400 out.status.store(.failed, .monotonic);
4401 },
4402 }
4403 zcu.comp.link_task_queue.mirReady(zcu.comp, out);
4404 if (zcu.pending_codegen_jobs.rmw(.Sub, 1, .monotonic) == 1) {
4405 // Decremented to 0, so all done.
4406 zcu.codegen_prog_node.end();
4407 zcu.codegen_prog_node = .none;
4408 }
4409}
4410fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) error{
4411 OutOfMemory,
4412 CodegenFail,
4413 NoLinkFile,
4414 BackendDoesNotProduceMir,
4415}!codegen.AnyMir {
4416 const zcu = pt.zcu;
4417 const gpa = zcu.gpa;
4418 const ip = &zcu.intern_pool;
4419 const comp = zcu.comp;
4420
4421 const nav = zcu.funcInfo(func_index).owner_nav;
4422 const fqn = ip.getNav(nav).fqn;
4423
4424 const codegen_prog_node = zcu.codegen_prog_node.start(fqn.toSlice(ip), 0);
4425 defer codegen_prog_node.end();
4426
4427 if (codegen.legalizeFeatures(pt, nav)) |features| {
4428 try air.legalize(pt, features);
4429 }
4430
4431 var liveness: Air.Liveness = try .analyze(zcu, air.*, ip);
4432 defer liveness.deinit(gpa);
4433
4434 if (build_options.enable_debug_extensions and comp.verbose_air) {
4435 std.debug.lockStdErr();
4436 defer std.debug.unlockStdErr();
4437 const stderr = std.io.getStdErr().writer();
4438 stderr.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)}) catch {};
4439 air.write(stderr, pt, liveness);
4440 stderr.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)}) catch {};
4441 }
4442
4443 if (std.debug.runtime_safety) {
4444 var verify: Air.Liveness.Verify = .{
4445 .gpa = gpa,
4446 .zcu = zcu,
4447 .air = air.*,
4448 .liveness = liveness,
4449 .intern_pool = ip,
4450 };
4451 defer verify.deinit();
4452
4453 verify.verify() catch |err| switch (err) {
4454 error.OutOfMemory => return error.OutOfMemory,
4455 else => return zcu.codegenFail(nav, "invalid liveness: {s}", .{@errorName(err)}),
4456 };
4457 }
4458
4459 // The LLVM backend is special, because we only need to do codegen. There is no equivalent to the
4460 // "emit" step because LLVM does not support incremental linking. Our linker (LLD or self-hosted)
4461 // will just see the ZCU object file which LLVM ultimately emits.
4462 if (zcu.llvm_object) |llvm_object| {
4463 assert(pt.tid == .main); // LLVM has a lot of shared state
4464 try llvm_object.updateFunc(pt, func_index, air, &liveness);
4465 return error.BackendDoesNotProduceMir;
4466 }
4467
4468 const lf = comp.bin_file orelse return error.NoLinkFile;
4469
4470 // TODO: self-hosted codegen should always have a type of MIR; codegen should produce that MIR,
4471 // and the linker should consume it. However, our SPIR-V backend is currently tightly coupled
4472 // with our SPIR-V linker, so needs to work more like the LLVM backend. This should be fixed to
4473 // unblock threaded codegen for SPIR-V.
4474 if (lf.cast(.spirv)) |spirv_file| {
4475 assert(pt.tid == .main); // SPIR-V has a lot of shared state
4476 spirv_file.object.updateFunc(pt, func_index, air, &liveness) catch |err| {
4477 switch (err) {
4478 error.OutOfMemory => comp.link_diags.setAllocFailure(),
4479 }
4480 return error.CodegenFail;
4481 };
4482 return error.BackendDoesNotProduceMir;
4483 }
4484
4485 return codegen.generateFunction(lf, pt, zcu.navSrcLoc(nav), func_index, air, &liveness) catch |err| switch (err) {
4486 error.OutOfMemory,
4487 error.CodegenFail,
4488 => |e| return e,
4489 error.Overflow,
4490 error.RelocationNotByteAligned,
4491 => return zcu.codegenFail(nav, "unable to codegen: {s}", .{@errorName(err)}),
4492 };
4493}
src/arch/aarch64/CodeGen.zig+32-39
......@@ -49,7 +49,6 @@ pt: Zcu.PerThread,
4949air: Air,
5050liveness: Air.Liveness,
5151bin_file: *link.File,
52debug_output: link.File.DebugInfoOutput,
5352target: *const std.Target,
5453func_index: InternPool.Index,
5554owner_nav: InternPool.Nav.Index,
......@@ -185,6 +184,9 @@ const DbgInfoReloc = struct {
185184 }
186185
187186 fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
187 // TODO: Add a pseudo-instruction or something to defer this work until Emit.
188 // We aren't allowed to interact with linker state here.
189 if (true) return;
188190 switch (function.debug_output) {
189191 .dwarf => |dw| {
190192 const loc: link.File.Dwarf.Loc = switch (reloc.mcv) {
......@@ -213,6 +215,9 @@ const DbgInfoReloc = struct {
213215 }
214216
215217 fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
218 // TODO: Add a pseudo-instruction or something to defer this work until Emit.
219 // We aren't allowed to interact with linker state here.
220 if (true) return;
216221 switch (function.debug_output) {
217222 .dwarf => |dwarf| {
218223 const loc: link.File.Dwarf.Loc = switch (reloc.mcv) {
......@@ -326,11 +331,9 @@ pub fn generate(
326331 pt: Zcu.PerThread,
327332 src_loc: Zcu.LazySrcLoc,
328333 func_index: InternPool.Index,
329 air: Air,
330 liveness: Air.Liveness,
331 code: *std.ArrayListUnmanaged(u8),
332 debug_output: link.File.DebugInfoOutput,
333) CodeGenError!void {
334 air: *const Air,
335 liveness: *const Air.Liveness,
336) CodeGenError!Mir {
334337 const zcu = pt.zcu;
335338 const gpa = zcu.gpa;
336339 const func = zcu.funcInfo(func_index);
......@@ -349,9 +352,8 @@ pub fn generate(
349352 var function: Self = .{
350353 .gpa = gpa,
351354 .pt = pt,
352 .air = air,
353 .liveness = liveness,
354 .debug_output = debug_output,
355 .air = air.*,
356 .liveness = liveness.*,
355357 .target = target,
356358 .bin_file = lf,
357359 .func_index = func_index,
......@@ -395,29 +397,13 @@ pub fn generate(
395397
396398 var mir: Mir = .{
397399 .instructions = function.mir_instructions.toOwnedSlice(),
398 .extra = try function.mir_extra.toOwnedSlice(gpa),
399 };
400 defer mir.deinit(gpa);
401
402 var emit: Emit = .{
403 .mir = mir,
404 .bin_file = lf,
405 .debug_output = debug_output,
406 .target = target,
407 .src_loc = src_loc,
408 .code = code,
409 .prev_di_pc = 0,
410 .prev_di_line = func.lbrace_line,
411 .prev_di_column = func.lbrace_column,
412 .stack_size = function.max_end_stack,
400 .extra = &.{}, // fallible, so assign after errdefer
401 .max_end_stack = function.max_end_stack,
413402 .saved_regs_stack_space = function.saved_regs_stack_space,
414403 };
415 defer emit.deinit();
416
417 emit.emitMir() catch |err| switch (err) {
418 error.EmitFail => return function.failMsg(emit.err_msg.?),
419 else => |e| return e,
420 };
404 errdefer mir.deinit(gpa);
405 mir.extra = try function.mir_extra.toOwnedSlice(gpa);
406 return mir;
421407}
422408
423409fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
......@@ -4222,15 +4208,22 @@ fn airArg(self: *Self, inst: Air.Inst.Index) InnerError!void {
42224208 while (self.args[arg_index] == .none) arg_index += 1;
42234209 self.arg_index = arg_index + 1;
42244210
4225 const ty = self.typeOfIndex(inst);
4226 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
4227 const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
4228 if (name != .none) try self.dbg_info_relocs.append(self.gpa, .{
4229 .tag = tag,
4230 .ty = ty,
4231 .name = name.toSlice(self.air),
4232 .mcv = self.args[arg_index],
4233 });
4211 const zcu = self.pt.zcu;
4212 const func_zir = zcu.funcInfo(self.func_index).zir_body_inst.resolveFull(&zcu.intern_pool).?;
4213 const file = zcu.fileByIndex(func_zir.file);
4214 if (!file.mod.?.strip) {
4215 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
4216 const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
4217 const ty = self.typeOfIndex(inst);
4218 const zir = &file.zir.?;
4219 const name = zir.nullTerminatedString(zir.getParamName(zir.getParamBody(func_zir.inst)[arg.zir_param_index]).?);
4220 try self.dbg_info_relocs.append(self.gpa, .{
4221 .tag = tag,
4222 .ty = ty,
4223 .name = name,
4224 .mcv = self.args[arg_index],
4225 });
4226 }
42344227
42354228 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
42364229 return self.finishAir(inst, result, .{ .none, .none, .none });
src/arch/aarch64/Mir.zig+41
......@@ -13,6 +13,14 @@ const assert = std.debug.assert;
1313
1414const bits = @import("bits.zig");
1515const Register = bits.Register;
16const InternPool = @import("../../InternPool.zig");
17const Emit = @import("Emit.zig");
18const codegen = @import("../../codegen.zig");
19const link = @import("../../link.zig");
20const Zcu = @import("../../Zcu.zig");
21
22max_end_stack: u32,
23saved_regs_stack_space: u32,
1624
1725instructions: std.MultiArrayList(Inst).Slice,
1826/// The meaning of this data is determined by `Inst.Tag` value.
......@@ -498,6 +506,39 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
498506 mir.* = undefined;
499507}
500508
509pub fn emit(
510 mir: Mir,
511 lf: *link.File,
512 pt: Zcu.PerThread,
513 src_loc: Zcu.LazySrcLoc,
514 func_index: InternPool.Index,
515 code: *std.ArrayListUnmanaged(u8),
516 debug_output: link.File.DebugInfoOutput,
517) codegen.CodeGenError!void {
518 const zcu = pt.zcu;
519 const func = zcu.funcInfo(func_index);
520 const nav = func.owner_nav;
521 const mod = zcu.navFileScope(nav).mod.?;
522 var e: Emit = .{
523 .mir = mir,
524 .bin_file = lf,
525 .debug_output = debug_output,
526 .target = &mod.resolved_target.result,
527 .src_loc = src_loc,
528 .code = code,
529 .prev_di_pc = 0,
530 .prev_di_line = func.lbrace_line,
531 .prev_di_column = func.lbrace_column,
532 .stack_size = mir.max_end_stack,
533 .saved_regs_stack_space = mir.saved_regs_stack_space,
534 };
535 defer e.deinit();
536 e.emitMir() catch |err| switch (err) {
537 error.EmitFail => return zcu.codegenFailMsg(nav, e.err_msg.?),
538 else => |e1| return e1,
539 };
540}
541
501542/// Returns the requested data, as well as the new index which is at the start of the
502543/// trailers for the object.
503544pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end: usize } {
src/arch/arm/CodeGen.zig+33-41
......@@ -50,7 +50,6 @@ pt: Zcu.PerThread,
5050air: Air,
5151liveness: Air.Liveness,
5252bin_file: *link.File,
53debug_output: link.File.DebugInfoOutput,
5453target: *const std.Target,
5554func_index: InternPool.Index,
5655err_msg: ?*ErrorMsg,
......@@ -264,6 +263,9 @@ const DbgInfoReloc = struct {
264263 }
265264
266265 fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
266 // TODO: Add a pseudo-instruction or something to defer this work until Emit.
267 // We aren't allowed to interact with linker state here.
268 if (true) return;
267269 switch (function.debug_output) {
268270 .dwarf => |dw| {
269271 const loc: link.File.Dwarf.Loc = switch (reloc.mcv) {
......@@ -292,6 +294,9 @@ const DbgInfoReloc = struct {
292294 }
293295
294296 fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
297 // TODO: Add a pseudo-instruction or something to defer this work until Emit.
298 // We aren't allowed to interact with linker state here.
299 if (true) return;
295300 switch (function.debug_output) {
296301 .dwarf => |dw| {
297302 const loc: link.File.Dwarf.Loc = switch (reloc.mcv) {
......@@ -335,11 +340,9 @@ pub fn generate(
335340 pt: Zcu.PerThread,
336341 src_loc: Zcu.LazySrcLoc,
337342 func_index: InternPool.Index,
338 air: Air,
339 liveness: Air.Liveness,
340 code: *std.ArrayListUnmanaged(u8),
341 debug_output: link.File.DebugInfoOutput,
342) CodeGenError!void {
343 air: *const Air,
344 liveness: *const Air.Liveness,
345) CodeGenError!Mir {
343346 const zcu = pt.zcu;
344347 const gpa = zcu.gpa;
345348 const func = zcu.funcInfo(func_index);
......@@ -358,11 +361,10 @@ pub fn generate(
358361 var function: Self = .{
359362 .gpa = gpa,
360363 .pt = pt,
361 .air = air,
362 .liveness = liveness,
364 .air = air.*,
365 .liveness = liveness.*,
363366 .target = target,
364367 .bin_file = lf,
365 .debug_output = debug_output,
366368 .func_index = func_index,
367369 .err_msg = null,
368370 .args = undefined, // populated after `resolveCallingConventionValues`
......@@ -402,31 +404,15 @@ pub fn generate(
402404 return function.fail("failed to generate debug info: {s}", .{@errorName(err)});
403405 }
404406
405 var mir = Mir{
407 var mir: Mir = .{
406408 .instructions = function.mir_instructions.toOwnedSlice(),
407 .extra = try function.mir_extra.toOwnedSlice(gpa),
408 };
409 defer mir.deinit(gpa);
410
411 var emit = Emit{
412 .mir = mir,
413 .bin_file = lf,
414 .debug_output = debug_output,
415 .target = target,
416 .src_loc = src_loc,
417 .code = code,
418 .prev_di_pc = 0,
419 .prev_di_line = func.lbrace_line,
420 .prev_di_column = func.lbrace_column,
421 .stack_size = function.max_end_stack,
409 .extra = &.{}, // fallible, so assign after errdefer
410 .max_end_stack = function.max_end_stack,
422411 .saved_regs_stack_space = function.saved_regs_stack_space,
423412 };
424 defer emit.deinit();
425
426 emit.emitMir() catch |err| switch (err) {
427 error.EmitFail => return function.failMsg(emit.err_msg.?),
428 else => |e| return e,
429 };
413 errdefer mir.deinit(gpa);
414 mir.extra = try function.mir_extra.toOwnedSlice(gpa);
415 return mir;
430416}
431417
432418fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
......@@ -4205,16 +4191,22 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
42054191 while (self.args[arg_index] == .none) arg_index += 1;
42064192 self.arg_index = arg_index + 1;
42074193
4208 const ty = self.typeOfIndex(inst);
4209 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
4210
4211 const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
4212 if (name != .none) try self.dbg_info_relocs.append(self.gpa, .{
4213 .tag = tag,
4214 .ty = ty,
4215 .name = name.toSlice(self.air),
4216 .mcv = self.args[arg_index],
4217 });
4194 const zcu = self.pt.zcu;
4195 const func_zir = zcu.funcInfo(self.func_index).zir_body_inst.resolveFull(&zcu.intern_pool).?;
4196 const file = zcu.fileByIndex(func_zir.file);
4197 if (!file.mod.?.strip) {
4198 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
4199 const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
4200 const ty = self.typeOfIndex(inst);
4201 const zir = &file.zir.?;
4202 const name = zir.nullTerminatedString(zir.getParamName(zir.getParamBody(func_zir.inst)[arg.zir_param_index]).?);
4203 try self.dbg_info_relocs.append(self.gpa, .{
4204 .tag = tag,
4205 .ty = ty,
4206 .name = name,
4207 .mcv = self.args[arg_index],
4208 });
4209 }
42184210
42194211 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
42204212 return self.finishAir(inst, result, .{ .none, .none, .none });
src/arch/arm/Mir.zig+41
......@@ -13,6 +13,14 @@ const assert = std.debug.assert;
1313
1414const bits = @import("bits.zig");
1515const Register = bits.Register;
16const InternPool = @import("../../InternPool.zig");
17const Emit = @import("Emit.zig");
18const codegen = @import("../../codegen.zig");
19const link = @import("../../link.zig");
20const Zcu = @import("../../Zcu.zig");
21
22max_end_stack: u32,
23saved_regs_stack_space: u32,
1624
1725instructions: std.MultiArrayList(Inst).Slice,
1826/// The meaning of this data is determined by `Inst.Tag` value.
......@@ -278,6 +286,39 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
278286 mir.* = undefined;
279287}
280288
289pub fn emit(
290 mir: Mir,
291 lf: *link.File,
292 pt: Zcu.PerThread,
293 src_loc: Zcu.LazySrcLoc,
294 func_index: InternPool.Index,
295 code: *std.ArrayListUnmanaged(u8),
296 debug_output: link.File.DebugInfoOutput,
297) codegen.CodeGenError!void {
298 const zcu = pt.zcu;
299 const func = zcu.funcInfo(func_index);
300 const nav = func.owner_nav;
301 const mod = zcu.navFileScope(nav).mod.?;
302 var e: Emit = .{
303 .mir = mir,
304 .bin_file = lf,
305 .debug_output = debug_output,
306 .target = &mod.resolved_target.result,
307 .src_loc = src_loc,
308 .code = code,
309 .prev_di_pc = 0,
310 .prev_di_line = func.lbrace_line,
311 .prev_di_column = func.lbrace_column,
312 .stack_size = mir.max_end_stack,
313 .saved_regs_stack_space = mir.saved_regs_stack_space,
314 };
315 defer e.deinit();
316 e.emitMir() catch |err| switch (err) {
317 error.EmitFail => return zcu.codegenFailMsg(nav, e.err_msg.?),
318 else => |e1| return e1,
319 };
320}
321
281322/// Returns the requested data, as well as the new index which is at the start of the
282323/// trailers for the object.
283324pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end: usize } {
src/arch/powerpc/CodeGen.zig+3-7
......@@ -19,19 +19,15 @@ pub fn generate(
1919 pt: Zcu.PerThread,
2020 src_loc: Zcu.LazySrcLoc,
2121 func_index: InternPool.Index,
22 air: Air,
23 liveness: Air.Liveness,
24 code: *std.ArrayListUnmanaged(u8),
25 debug_output: link.File.DebugInfoOutput,
26) codegen.CodeGenError!void {
22 air: *const Air,
23 liveness: *const Air.Liveness,
24) codegen.CodeGenError!noreturn {
2725 _ = bin_file;
2826 _ = pt;
2927 _ = src_loc;
3028 _ = func_index;
3129 _ = air;
3230 _ = liveness;
33 _ = code;
34 _ = debug_output;
3531
3632 unreachable;
3733}
src/arch/riscv64/CodeGen.zig+30-47
......@@ -68,9 +68,9 @@ gpa: Allocator,
6868
6969mod: *Package.Module,
7070target: *const std.Target,
71debug_output: link.File.DebugInfoOutput,
7271args: []MCValue,
7372ret_mcv: InstTracking,
73func_index: InternPool.Index,
7474fn_type: Type,
7575arg_index: usize,
7676src_loc: Zcu.LazySrcLoc,
......@@ -746,13 +746,10 @@ pub fn generate(
746746 pt: Zcu.PerThread,
747747 src_loc: Zcu.LazySrcLoc,
748748 func_index: InternPool.Index,
749 air: Air,
750 liveness: Air.Liveness,
751 code: *std.ArrayListUnmanaged(u8),
752 debug_output: link.File.DebugInfoOutput,
753) CodeGenError!void {
749 air: *const Air,
750 liveness: *const Air.Liveness,
751) CodeGenError!Mir {
754752 const zcu = pt.zcu;
755 const comp = zcu.comp;
756753 const gpa = zcu.gpa;
757754 const ip = &zcu.intern_pool;
758755 const func = zcu.funcInfo(func_index);
......@@ -769,16 +766,16 @@ pub fn generate(
769766
770767 var function: Func = .{
771768 .gpa = gpa,
772 .air = air,
769 .air = air.*,
773770 .pt = pt,
774771 .mod = mod,
775772 .bin_file = bin_file,
776 .liveness = liveness,
773 .liveness = liveness.*,
777774 .target = &mod.resolved_target.result,
778 .debug_output = debug_output,
779775 .owner = .{ .nav_index = func.owner_nav },
780776 .args = undefined, // populated after `resolveCallingConventionValues`
781777 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
778 .func_index = func_index,
782779 .fn_type = fn_type,
783780 .arg_index = 0,
784781 .branch_stack = &branch_stack,
......@@ -855,33 +852,8 @@ pub fn generate(
855852 .instructions = function.mir_instructions.toOwnedSlice(),
856853 .frame_locs = function.frame_locs.toOwnedSlice(),
857854 };
858 defer mir.deinit(gpa);
859
860 var emit: Emit = .{
861 .lower = .{
862 .pt = pt,
863 .allocator = gpa,
864 .mir = mir,
865 .cc = fn_info.cc,
866 .src_loc = src_loc,
867 .output_mode = comp.config.output_mode,
868 .link_mode = comp.config.link_mode,
869 .pic = mod.pic,
870 },
871 .bin_file = bin_file,
872 .debug_output = debug_output,
873 .code = code,
874 .prev_di_pc = 0,
875 .prev_di_line = func.lbrace_line,
876 .prev_di_column = func.lbrace_column,
877 };
878 defer emit.deinit();
879
880 emit.emitMir() catch |err| switch (err) {
881 error.LowerFail, error.EmitFail => return function.failMsg(emit.lower.err_msg.?),
882 error.InvalidInstruction => |e| return function.fail("emit MIR failed: {s} (Zig compiler bug)", .{@errorName(e)}),
883 else => |e| return e,
884 };
855 errdefer mir.deinit(gpa);
856 return mir;
885857}
886858
887859pub fn generateLazy(
......@@ -904,10 +876,10 @@ pub fn generateLazy(
904876 .bin_file = bin_file,
905877 .liveness = undefined,
906878 .target = &mod.resolved_target.result,
907 .debug_output = debug_output,
908879 .owner = .{ .lazy_sym = lazy_sym },
909880 .args = undefined, // populated after `resolveCallingConventionValues`
910881 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
882 .func_index = undefined,
911883 .fn_type = undefined,
912884 .arg_index = 0,
913885 .branch_stack = undefined,
......@@ -3631,9 +3603,7 @@ fn airRuntimeNavPtr(func: *Func, inst: Air.Inst.Index) !void {
36313603 const tlv_sym_index = if (func.bin_file.cast(.elf)) |elf_file| sym: {
36323604 const zo = elf_file.zigObjectPtr().?;
36333605 if (nav.getExtern(ip)) |e| {
3634 const sym = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip));
3635 zo.symbol(sym).flags.is_extern_ptr = true;
3636 break :sym sym;
3606 break :sym try elf_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip));
36373607 }
36383608 break :sym try zo.getOrCreateMetadataForNav(zcu, ty_nav.nav);
36393609 } else return func.fail("TODO runtime_nav_ptr on {}", .{func.bin_file.tag});
......@@ -4755,16 +4725,17 @@ fn airFieldParentPtr(func: *Func, inst: Air.Inst.Index) !void {
47554725 return func.fail("TODO implement codegen airFieldParentPtr", .{});
47564726}
47574727
4758fn genArgDbgInfo(func: *const Func, inst: Air.Inst.Index, mcv: MCValue) InnerError!void {
4759 const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
4760 const ty = arg.ty.toType();
4761 if (arg.name == .none) return;
4728fn genArgDbgInfo(func: *const Func, name: []const u8, ty: Type, mcv: MCValue) InnerError!void {
4729 assert(!func.mod.strip);
47624730
4731 // TODO: Add a pseudo-instruction or something to defer this work until Emit.
4732 // We aren't allowed to interact with linker state here.
4733 if (true) return;
47634734 switch (func.debug_output) {
47644735 .dwarf => |dw| switch (mcv) {
47654736 .register => |reg| dw.genLocalDebugInfo(
47664737 .local_arg,
4767 arg.name.toSlice(func.air),
4738 name,
47684739 ty,
47694740 .{ .reg = reg.dwarfNum() },
47704741 ) catch |err| return func.fail("failed to generate debug info: {s}", .{@errorName(err)}),
......@@ -4777,6 +4748,8 @@ fn genArgDbgInfo(func: *const Func, inst: Air.Inst.Index, mcv: MCValue) InnerErr
47774748}
47784749
47794750fn airArg(func: *Func, inst: Air.Inst.Index) InnerError!void {
4751 const zcu = func.pt.zcu;
4752
47804753 var arg_index = func.arg_index;
47814754
47824755 // we skip over args that have no bits
......@@ -4793,7 +4766,14 @@ fn airArg(func: *Func, inst: Air.Inst.Index) InnerError!void {
47934766
47944767 try func.genCopy(arg_ty, dst_mcv, src_mcv);
47954768
4796 try func.genArgDbgInfo(inst, src_mcv);
4769 const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
4770 // can delete `func.func_index` if this logic is moved to emit
4771 const func_zir = zcu.funcInfo(func.func_index).zir_body_inst.resolveFull(&zcu.intern_pool).?;
4772 const file = zcu.fileByIndex(func_zir.file);
4773 const zir = &file.zir.?;
4774 const name = zir.nullTerminatedString(zir.getParamName(zir.getParamBody(func_zir.inst)[arg.zir_param_index]).?);
4775
4776 try func.genArgDbgInfo(name, arg_ty, src_mcv);
47974777 break :result dst_mcv;
47984778 };
47994779
......@@ -5273,6 +5253,9 @@ fn genVarDbgInfo(
52735253 mcv: MCValue,
52745254 name: []const u8,
52755255) !void {
5256 // TODO: Add a pseudo-instruction or something to defer this work until Emit.
5257 // We aren't allowed to interact with linker state here.
5258 if (true) return;
52765259 switch (func.debug_output) {
52775260 .dwarf => |dwarf| {
52785261 const loc: link.File.Dwarf.Loc = switch (mcv) {
src/arch/riscv64/Emit.zig+2-2
......@@ -50,8 +50,8 @@ pub fn emitMir(emit: *Emit) Error!void {
5050 const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;
5151 const sym = zo.symbol(symbol.sym_index);
5252
53 if (sym.flags.is_extern_ptr and emit.lower.pic) {
54 return emit.fail("emit GOT relocation for symbol '{s}'", .{sym.name(elf_file)});
53 if (emit.lower.pic) {
54 return emit.fail("know when to emit GOT relocation for symbol '{s}'", .{sym.name(elf_file)});
5555 }
5656
5757 const hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
src/arch/riscv64/Mir.zig+48
......@@ -109,6 +109,48 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
109109 mir.* = undefined;
110110}
111111
112pub fn emit(
113 mir: Mir,
114 lf: *link.File,
115 pt: Zcu.PerThread,
116 src_loc: Zcu.LazySrcLoc,
117 func_index: InternPool.Index,
118 code: *std.ArrayListUnmanaged(u8),
119 debug_output: link.File.DebugInfoOutput,
120) codegen.CodeGenError!void {
121 const zcu = pt.zcu;
122 const comp = zcu.comp;
123 const gpa = comp.gpa;
124 const func = zcu.funcInfo(func_index);
125 const fn_info = zcu.typeToFunc(.fromInterned(func.ty)).?;
126 const nav = func.owner_nav;
127 const mod = zcu.navFileScope(nav).mod.?;
128 var e: Emit = .{
129 .lower = .{
130 .pt = pt,
131 .allocator = gpa,
132 .mir = mir,
133 .cc = fn_info.cc,
134 .src_loc = src_loc,
135 .output_mode = comp.config.output_mode,
136 .link_mode = comp.config.link_mode,
137 .pic = mod.pic,
138 },
139 .bin_file = lf,
140 .debug_output = debug_output,
141 .code = code,
142 .prev_di_pc = 0,
143 .prev_di_line = func.lbrace_line,
144 .prev_di_column = func.lbrace_column,
145 };
146 defer e.deinit();
147 e.emitMir() catch |err| switch (err) {
148 error.LowerFail, error.EmitFail => return zcu.codegenFailMsg(nav, e.lower.err_msg.?),
149 error.InvalidInstruction => return zcu.codegenFail(nav, "emit MIR failed: {s} (Zig compiler bug)", .{@errorName(err)}),
150 else => |err1| return err1,
151 };
152}
153
112154pub const FrameLoc = struct {
113155 base: Register,
114156 disp: i32,
......@@ -202,3 +244,9 @@ const FrameIndex = bits.FrameIndex;
202244const FrameAddr = @import("CodeGen.zig").FrameAddr;
203245const IntegerBitSet = std.bit_set.IntegerBitSet;
204246const Mnemonic = @import("mnem.zig").Mnemonic;
247
248const InternPool = @import("../../InternPool.zig");
249const Emit = @import("Emit.zig");
250const codegen = @import("../../codegen.zig");
251const link = @import("../../link.zig");
252const Zcu = @import("../../Zcu.zig");
src/arch/sparc64/CodeGen.zig+29-46
......@@ -57,8 +57,6 @@ liveness: Air.Liveness,
5757bin_file: *link.File,
5858target: *const std.Target,
5959func_index: InternPool.Index,
60code: *std.ArrayListUnmanaged(u8),
61debug_output: link.File.DebugInfoOutput,
6260err_msg: ?*ErrorMsg,
6361args: []MCValue,
6462ret_mcv: MCValue,
......@@ -268,11 +266,9 @@ pub fn generate(
268266 pt: Zcu.PerThread,
269267 src_loc: Zcu.LazySrcLoc,
270268 func_index: InternPool.Index,
271 air: Air,
272 liveness: Air.Liveness,
273 code: *std.ArrayListUnmanaged(u8),
274 debug_output: link.File.DebugInfoOutput,
275) CodeGenError!void {
269 air: *const Air,
270 liveness: *const Air.Liveness,
271) CodeGenError!Mir {
276272 const zcu = pt.zcu;
277273 const gpa = zcu.gpa;
278274 const func = zcu.funcInfo(func_index);
......@@ -291,13 +287,11 @@ pub fn generate(
291287 var function: Self = .{
292288 .gpa = gpa,
293289 .pt = pt,
294 .air = air,
295 .liveness = liveness,
290 .air = air.*,
291 .liveness = liveness.*,
296292 .target = target,
297293 .bin_file = lf,
298294 .func_index = func_index,
299 .code = code,
300 .debug_output = debug_output,
301295 .err_msg = null,
302296 .args = undefined, // populated after `resolveCallingConventionValues`
303297 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
......@@ -330,29 +324,13 @@ pub fn generate(
330324 else => |e| return e,
331325 };
332326
333 var mir = Mir{
327 var mir: Mir = .{
334328 .instructions = function.mir_instructions.toOwnedSlice(),
335 .extra = try function.mir_extra.toOwnedSlice(gpa),
336 };
337 defer mir.deinit(gpa);
338
339 var emit: Emit = .{
340 .mir = mir,
341 .bin_file = lf,
342 .debug_output = debug_output,
343 .target = target,
344 .src_loc = src_loc,
345 .code = code,
346 .prev_di_pc = 0,
347 .prev_di_line = func.lbrace_line,
348 .prev_di_column = func.lbrace_column,
349 };
350 defer emit.deinit();
351
352 emit.emitMir() catch |err| switch (err) {
353 error.EmitFail => return function.failMsg(emit.err_msg.?),
354 else => |e| return e,
329 .extra = &.{}, // fallible, so populated after errdefer
355330 };
331 errdefer mir.deinit(gpa);
332 mir.extra = try function.mir_extra.toOwnedSlice(gpa);
333 return mir;
356334}
357335
358336fn gen(self: *Self) !void {
......@@ -1017,23 +995,29 @@ fn airArg(self: *Self, inst: Air.Inst.Index) InnerError!void {
1017995 self.arg_index += 1;
1018996
1019997 const ty = self.typeOfIndex(inst);
1020
1021 const arg = self.args[arg_index];
1022 const mcv = blk: {
1023 switch (arg) {
998 const mcv: MCValue = blk: {
999 switch (self.args[arg_index]) {
10241000 .stack_offset => |off| {
10251001 const abi_size = math.cast(u32, ty.abiSize(zcu)) orelse {
10261002 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(pt)});
10271003 };
10281004 const offset = off + abi_size;
1029 break :blk MCValue{ .stack_offset = offset };
1005 break :blk .{ .stack_offset = offset };
10301006 },
1031 else => break :blk arg,
1007 else => |mcv| break :blk mcv,
10321008 }
10331009 };
10341010
1035 self.genArgDbgInfo(inst, mcv) catch |err|
1036 return self.fail("failed to generate debug info for parameter: {s}", .{@errorName(err)});
1011 const func_zir = zcu.funcInfo(self.func_index).zir_body_inst.resolveFull(&zcu.intern_pool).?;
1012 const file = zcu.fileByIndex(func_zir.file);
1013 if (!file.mod.?.strip) {
1014 const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
1015 const zir = &file.zir.?;
1016 const name = zir.nullTerminatedString(zir.getParamName(zir.getParamBody(func_zir.inst)[arg.zir_param_index]).?);
1017
1018 self.genArgDbgInfo(name, ty, mcv) catch |err|
1019 return self.fail("failed to generate debug info for parameter: {s}", .{@errorName(err)});
1020 }
10371021
10381022 if (self.liveness.isUnused(inst))
10391023 return self.finishAirBookkeeping();
......@@ -3561,16 +3545,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Air.
35613545 self.finishAirBookkeeping();
35623546}
35633547
3564fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
3565 const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
3566 const ty = arg.ty.toType();
3567 if (arg.name == .none) return;
3568
3548fn genArgDbgInfo(self: Self, name: []const u8, ty: Type, mcv: MCValue) !void {
3549 // TODO: Add a pseudo-instruction or something to defer this work until Emit.
3550 // We aren't allowed to interact with linker state here.
3551 if (true) return;
35693552 switch (self.debug_output) {
35703553 .dwarf => |dw| switch (mcv) {
35713554 .register => |reg| try dw.genLocalDebugInfo(
35723555 .local_arg,
3573 arg.name.toSlice(self.air),
3556 name,
35743557 ty,
35753558 .{ .reg = reg.dwarfNum() },
35763559 ),
src/arch/sparc64/Mir.zig+36-1
......@@ -12,7 +12,11 @@ const assert = std.debug.assert;
1212
1313const Mir = @This();
1414const bits = @import("bits.zig");
15const Air = @import("../../Air.zig");
15const InternPool = @import("../../InternPool.zig");
16const Emit = @import("Emit.zig");
17const codegen = @import("../../codegen.zig");
18const link = @import("../../link.zig");
19const Zcu = @import("../../Zcu.zig");
1620
1721const Instruction = bits.Instruction;
1822const ASI = bits.Instruction.ASI;
......@@ -370,6 +374,37 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
370374 mir.* = undefined;
371375}
372376
377pub fn emit(
378 mir: Mir,
379 lf: *link.File,
380 pt: Zcu.PerThread,
381 src_loc: Zcu.LazySrcLoc,
382 func_index: InternPool.Index,
383 code: *std.ArrayListUnmanaged(u8),
384 debug_output: link.File.DebugInfoOutput,
385) codegen.CodeGenError!void {
386 const zcu = pt.zcu;
387 const func = zcu.funcInfo(func_index);
388 const nav = func.owner_nav;
389 const mod = zcu.navFileScope(nav).mod.?;
390 var e: Emit = .{
391 .mir = mir,
392 .bin_file = lf,
393 .debug_output = debug_output,
394 .target = &mod.resolved_target.result,
395 .src_loc = src_loc,
396 .code = code,
397 .prev_di_pc = 0,
398 .prev_di_line = func.lbrace_line,
399 .prev_di_column = func.lbrace_column,
400 };
401 defer e.deinit();
402 e.emitMir() catch |err| switch (err) {
403 error.EmitFail => return zcu.codegenFailMsg(nav, e.err_msg.?),
404 else => |err1| return err1,
405 };
406}
407
373408/// Returns the requested data, as well as the new index which is at the start of the
374409/// trailers for the object.
375410pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end: usize } {
src/arch/wasm/CodeGen.zig+105-200
......@@ -3,7 +3,6 @@ const builtin = @import("builtin");
33const Allocator = std.mem.Allocator;
44const assert = std.debug.assert;
55const testing = std.testing;
6const leb = std.leb;
76const mem = std.mem;
87const log = std.log.scoped(.codegen);
98
......@@ -18,12 +17,10 @@ const Compilation = @import("../../Compilation.zig");
1817const link = @import("../../link.zig");
1918const Air = @import("../../Air.zig");
2019const Mir = @import("Mir.zig");
21const Emit = @import("Emit.zig");
2220const abi = @import("abi.zig");
2321const Alignment = InternPool.Alignment;
2422const errUnionPayloadOffset = codegen.errUnionPayloadOffset;
2523const errUnionErrorOffset = codegen.errUnionErrorOffset;
26const Wasm = link.File.Wasm;
2724
2825const target_util = @import("../../target.zig");
2926const libcFloatPrefix = target_util.libcFloatPrefix;
......@@ -78,17 +75,24 @@ simd_immediates: std.ArrayListUnmanaged([16]u8) = .empty,
7875/// The Target we're emitting (used to call intInfo)
7976target: *const std.Target,
8077ptr_size: enum { wasm32, wasm64 },
81wasm: *link.File.Wasm,
8278pt: Zcu.PerThread,
8379/// List of MIR Instructions
84mir_instructions: *std.MultiArrayList(Mir.Inst),
80mir_instructions: std.MultiArrayList(Mir.Inst),
8581/// Contains extra data for MIR
86mir_extra: *std.ArrayListUnmanaged(u32),
87start_mir_extra_off: u32,
88start_locals_off: u32,
82mir_extra: std.ArrayListUnmanaged(u32),
8983/// List of all locals' types generated throughout this declaration
9084/// used to emit locals count at start of 'code' section.
91locals: *std.ArrayListUnmanaged(std.wasm.Valtype),
85mir_locals: std.ArrayListUnmanaged(std.wasm.Valtype),
86/// Set of all UAVs referenced by this function. Key is the UAV value, value is the alignment.
87/// `.none` means naturally aligned. An explicit alignment is never less than the natural alignment.
88mir_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
89/// Set of all functions whose address this function has taken and which therefore might be called
90/// via a `call_indirect` function.
91mir_indirect_function_set: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
92/// Set of all function types used by this function. These must be interned by the linker.
93mir_func_tys: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
94/// The number of `error_name_table_ref` instructions emitted.
95error_name_table_ref_count: u32,
9296/// When a function is executing, we store the the current stack pointer's value within this local.
9397/// This value is then used to restore the stack pointer to the original value at the return of the function.
9498initial_stack_value: WValue = .none,
......@@ -219,7 +223,7 @@ const WValue = union(enum) {
219223 if (local_value < reserved + 2) return; // reserved locals may never be re-used. Also accounts for 2 stack locals.
220224
221225 const index = local_value - reserved;
222 const valtype = gen.locals.items[gen.start_locals_off + index];
226 const valtype = gen.mir_locals.items[index];
223227 switch (valtype) {
224228 .i32 => gen.free_locals_i32.append(gen.gpa, local_value) catch return, // It's ok to fail any of those, a new local can be allocated instead
225229 .i64 => gen.free_locals_i64.append(gen.gpa, local_value) catch return,
......@@ -716,6 +720,12 @@ pub fn deinit(cg: *CodeGen) void {
716720 cg.free_locals_f32.deinit(gpa);
717721 cg.free_locals_f64.deinit(gpa);
718722 cg.free_locals_v128.deinit(gpa);
723 cg.mir_instructions.deinit(gpa);
724 cg.mir_extra.deinit(gpa);
725 cg.mir_locals.deinit(gpa);
726 cg.mir_uavs.deinit(gpa);
727 cg.mir_indirect_function_set.deinit(gpa);
728 cg.mir_func_tys.deinit(gpa);
719729 cg.* = undefined;
720730}
721731
......@@ -876,7 +886,7 @@ fn addTag(cg: *CodeGen, tag: Mir.Inst.Tag) error{OutOfMemory}!void {
876886}
877887
878888fn addExtended(cg: *CodeGen, opcode: std.wasm.MiscOpcode) error{OutOfMemory}!void {
879 const extra_index = cg.extraLen();
889 const extra_index: u32 = @intCast(cg.mir_extra.items.len);
880890 try cg.mir_extra.append(cg.gpa, @intFromEnum(opcode));
881891 try cg.addInst(.{ .tag = .misc_prefix, .data = .{ .payload = extra_index } });
882892}
......@@ -889,10 +899,6 @@ fn addLocal(cg: *CodeGen, tag: Mir.Inst.Tag, local: u32) error{OutOfMemory}!void
889899 try cg.addInst(.{ .tag = tag, .data = .{ .local = local } });
890900}
891901
892fn addFuncTy(cg: *CodeGen, tag: Mir.Inst.Tag, i: Wasm.FunctionType.Index) error{OutOfMemory}!void {
893 try cg.addInst(.{ .tag = tag, .data = .{ .func_ty = i } });
894}
895
896902/// Accepts an unsigned 32bit integer rather than a signed integer to
897903/// prevent us from having to bitcast multiple times as most values
898904/// within codegen are represented as unsigned rather than signed.
......@@ -911,7 +917,7 @@ fn addImm64(cg: *CodeGen, imm: u64) error{OutOfMemory}!void {
911917/// Accepts the index into the list of 128bit-immediates
912918fn addImm128(cg: *CodeGen, index: u32) error{OutOfMemory}!void {
913919 const simd_values = cg.simd_immediates.items[index];
914 const extra_index = cg.extraLen();
920 const extra_index: u32 = @intCast(cg.mir_extra.items.len);
915921 // tag + 128bit value
916922 try cg.mir_extra.ensureUnusedCapacity(cg.gpa, 5);
917923 cg.mir_extra.appendAssumeCapacity(@intFromEnum(std.wasm.SimdOpcode.v128_const));
......@@ -956,15 +962,13 @@ fn addExtra(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 {
956962/// Returns the index into `mir_extra`
957963fn addExtraAssumeCapacity(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 {
958964 const fields = std.meta.fields(@TypeOf(extra));
959 const result = cg.extraLen();
965 const result: u32 = @intCast(cg.mir_extra.items.len);
960966 inline for (fields) |field| {
961967 cg.mir_extra.appendAssumeCapacity(switch (field.type) {
962968 u32 => @field(extra, field.name),
963969 i32 => @bitCast(@field(extra, field.name)),
964970 InternPool.Index,
965971 InternPool.Nav.Index,
966 Wasm.UavsObjIndex,
967 Wasm.UavsExeIndex,
968972 => @intFromEnum(@field(extra, field.name)),
969973 else => |field_type| @compileError("Unsupported field type " ++ @typeName(field_type)),
970974 });
......@@ -1034,18 +1038,12 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
10341038 .float32 => |val| try cg.addInst(.{ .tag = .f32_const, .data = .{ .float32 = val } }),
10351039 .float64 => |val| try cg.addFloat64(val),
10361040 .nav_ref => |nav_ref| {
1037 const wasm = cg.wasm;
1038 const comp = wasm.base.comp;
1039 const zcu = comp.zcu.?;
1041 const zcu = cg.pt.zcu;
10401042 const ip = &zcu.intern_pool;
10411043 if (ip.getNav(nav_ref.nav_index).isFn(ip)) {
10421044 assert(nav_ref.offset == 0);
1043 const gop = try wasm.zcu_indirect_function_set.getOrPut(comp.gpa, nav_ref.nav_index);
1044 if (!gop.found_existing) gop.value_ptr.* = {};
1045 try cg.addInst(.{
1046 .tag = .func_ref,
1047 .data = .{ .indirect_function_table_index = @enumFromInt(gop.index) },
1048 });
1045 try cg.mir_indirect_function_set.put(cg.gpa, nav_ref.nav_index, {});
1046 try cg.addInst(.{ .tag = .func_ref, .data = .{ .nav_index = nav_ref.nav_index } });
10491047 } else if (nav_ref.offset == 0) {
10501048 try cg.addInst(.{ .tag = .nav_ref, .data = .{ .nav_index = nav_ref.nav_index } });
10511049 } else {
......@@ -1061,41 +1059,37 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
10611059 }
10621060 },
10631061 .uav_ref => |uav| {
1064 const wasm = cg.wasm;
1065 const comp = wasm.base.comp;
1066 const is_obj = comp.config.output_mode == .Obj;
1067 const zcu = comp.zcu.?;
1062 const zcu = cg.pt.zcu;
10681063 const ip = &zcu.intern_pool;
1069 if (ip.isFunctionType(ip.typeOf(uav.ip_index))) {
1070 assert(uav.offset == 0);
1071 const owner_nav = ip.toFunc(uav.ip_index).owner_nav;
1072 const gop = try wasm.zcu_indirect_function_set.getOrPut(comp.gpa, owner_nav);
1073 if (!gop.found_existing) gop.value_ptr.* = {};
1074 try cg.addInst(.{
1075 .tag = .func_ref,
1076 .data = .{ .indirect_function_table_index = @enumFromInt(gop.index) },
1077 });
1078 } else if (uav.offset == 0) {
1064 assert(!ip.isFunctionType(ip.typeOf(uav.ip_index)));
1065 const gop = try cg.mir_uavs.getOrPut(cg.gpa, uav.ip_index);
1066 const this_align: Alignment = a: {
1067 if (uav.orig_ptr_ty == .none) break :a .none;
1068 const ptr_type = ip.indexToKey(uav.orig_ptr_ty).ptr_type;
1069 const this_align = ptr_type.flags.alignment;
1070 if (this_align == .none) break :a .none;
1071 const abi_align = Type.fromInterned(ptr_type.child).abiAlignment(zcu);
1072 if (this_align.compare(.lte, abi_align)) break :a .none;
1073 break :a this_align;
1074 };
1075 if (!gop.found_existing or
1076 gop.value_ptr.* == .none or
1077 (this_align != .none and this_align.compare(.gt, gop.value_ptr.*)))
1078 {
1079 gop.value_ptr.* = this_align;
1080 }
1081 if (uav.offset == 0) {
10791082 try cg.addInst(.{
10801083 .tag = .uav_ref,
1081 .data = if (is_obj) .{
1082 .uav_obj = try wasm.refUavObj(uav.ip_index, uav.orig_ptr_ty),
1083 } else .{
1084 .uav_exe = try wasm.refUavExe(uav.ip_index, uav.orig_ptr_ty),
1085 },
1084 .data = .{ .ip_index = uav.ip_index },
10861085 });
10871086 } else {
10881087 try cg.addInst(.{
10891088 .tag = .uav_ref_off,
1090 .data = .{
1091 .payload = if (is_obj) try cg.addExtra(Mir.UavRefOffObj{
1092 .uav_obj = try wasm.refUavObj(uav.ip_index, uav.orig_ptr_ty),
1093 .offset = uav.offset,
1094 }) else try cg.addExtra(Mir.UavRefOffExe{
1095 .uav_exe = try wasm.refUavExe(uav.ip_index, uav.orig_ptr_ty),
1096 .offset = uav.offset,
1097 }),
1098 },
1089 .data = .{ .payload = try cg.addExtra(@as(Mir.UavRefOff, .{
1090 .value = uav.ip_index,
1091 .offset = uav.offset,
1092 })) },
10991093 });
11001094 }
11011095 },
......@@ -1157,106 +1151,12 @@ fn allocLocal(cg: *CodeGen, ty: Type) InnerError!WValue {
11571151/// to use a zero-initialized local.
11581152fn ensureAllocLocal(cg: *CodeGen, ty: Type) InnerError!WValue {
11591153 const zcu = cg.pt.zcu;
1160 try cg.locals.append(cg.gpa, typeToValtype(ty, zcu, cg.target));
1154 try cg.mir_locals.append(cg.gpa, typeToValtype(ty, zcu, cg.target));
11611155 const initial_index = cg.local_index;
11621156 cg.local_index += 1;
11631157 return .{ .local = .{ .value = initial_index, .references = 1 } };
11641158}
11651159
1166pub const Function = extern struct {
1167 /// Index into `Wasm.mir_instructions`.
1168 mir_off: u32,
1169 /// This is unused except for as a safety slice bound and could be removed.
1170 mir_len: u32,
1171 /// Index into `Wasm.mir_extra`.
1172 mir_extra_off: u32,
1173 /// This is unused except for as a safety slice bound and could be removed.
1174 mir_extra_len: u32,
1175 locals_off: u32,
1176 locals_len: u32,
1177 prologue: Prologue,
1178
1179 pub const Prologue = extern struct {
1180 flags: Flags,
1181 sp_local: u32,
1182 stack_size: u32,
1183 bottom_stack_local: u32,
1184
1185 pub const Flags = packed struct(u32) {
1186 stack_alignment: Alignment,
1187 padding: u26 = 0,
1188 };
1189
1190 pub const none: Prologue = .{
1191 .sp_local = 0,
1192 .flags = .{ .stack_alignment = .none },
1193 .stack_size = 0,
1194 .bottom_stack_local = 0,
1195 };
1196
1197 pub fn isNone(p: *const Prologue) bool {
1198 return p.flags.stack_alignment != .none;
1199 }
1200 };
1201
1202 pub fn lower(f: *Function, wasm: *Wasm, code: *std.ArrayListUnmanaged(u8)) Allocator.Error!void {
1203 const gpa = wasm.base.comp.gpa;
1204
1205 // Write the locals in the prologue of the function body.
1206 const locals = wasm.all_zcu_locals.items[f.locals_off..][0..f.locals_len];
1207 try code.ensureUnusedCapacity(gpa, 5 + locals.len * 6 + 38);
1208
1209 std.leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(locals.len))) catch unreachable;
1210 for (locals) |local| {
1211 std.leb.writeUleb128(code.fixedWriter(), @as(u32, 1)) catch unreachable;
1212 code.appendAssumeCapacity(@intFromEnum(local));
1213 }
1214
1215 // Stack management section of function prologue.
1216 const stack_alignment = f.prologue.flags.stack_alignment;
1217 if (stack_alignment.toByteUnits()) |align_bytes| {
1218 const sp_global: Wasm.GlobalIndex = .stack_pointer;
1219 // load stack pointer
1220 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_get));
1221 std.leb.writeULEB128(code.fixedWriter(), @intFromEnum(sp_global)) catch unreachable;
1222 // store stack pointer so we can restore it when we return from the function
1223 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_tee));
1224 leb.writeUleb128(code.fixedWriter(), f.prologue.sp_local) catch unreachable;
1225 // get the total stack size
1226 const aligned_stack: i32 = @intCast(stack_alignment.forward(f.prologue.stack_size));
1227 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));
1228 leb.writeIleb128(code.fixedWriter(), aligned_stack) catch unreachable;
1229 // subtract it from the current stack pointer
1230 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_sub));
1231 // Get negative stack alignment
1232 const neg_stack_align = @as(i32, @intCast(align_bytes)) * -1;
1233 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));
1234 leb.writeIleb128(code.fixedWriter(), neg_stack_align) catch unreachable;
1235 // Bitwise-and the value to get the new stack pointer to ensure the
1236 // pointers are aligned with the abi alignment.
1237 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_and));
1238 // The bottom will be used to calculate all stack pointer offsets.
1239 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_tee));
1240 leb.writeUleb128(code.fixedWriter(), f.prologue.bottom_stack_local) catch unreachable;
1241 // Store the current stack pointer value into the global stack pointer so other function calls will
1242 // start from this value instead and not overwrite the current stack.
1243 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_set));
1244 std.leb.writeULEB128(code.fixedWriter(), @intFromEnum(sp_global)) catch unreachable;
1245 }
1246
1247 var emit: Emit = .{
1248 .mir = .{
1249 .instruction_tags = wasm.mir_instructions.items(.tag)[f.mir_off..][0..f.mir_len],
1250 .instruction_datas = wasm.mir_instructions.items(.data)[f.mir_off..][0..f.mir_len],
1251 .extra = wasm.mir_extra.items[f.mir_extra_off..][0..f.mir_extra_len],
1252 },
1253 .wasm = wasm,
1254 .code = code,
1255 };
1256 try emit.lowerToCode();
1257 }
1258};
1259
12601160pub const Error = error{
12611161 OutOfMemory,
12621162 /// Compiler was asked to operate on a number larger than supported.
......@@ -1265,13 +1165,16 @@ pub const Error = error{
12651165 CodegenFail,
12661166};
12671167
1268pub fn function(
1269 wasm: *Wasm,
1168pub fn generate(
1169 bin_file: *link.File,
12701170 pt: Zcu.PerThread,
1171 src_loc: Zcu.LazySrcLoc,
12711172 func_index: InternPool.Index,
1272 air: Air,
1273 liveness: Air.Liveness,
1274) Error!Function {
1173 air: *const Air,
1174 liveness: *const Air.Liveness,
1175) Error!Mir {
1176 _ = src_loc;
1177 _ = bin_file;
12751178 const zcu = pt.zcu;
12761179 const gpa = zcu.gpa;
12771180 const cg = zcu.funcInfo(func_index);
......@@ -1279,10 +1182,8 @@ pub fn function(
12791182 const target = &file_scope.mod.?.resolved_target.result;
12801183 const fn_ty = zcu.navValue(cg.owner_nav).typeOf(zcu);
12811184 const fn_info = zcu.typeToFunc(fn_ty).?;
1282 const ip = &zcu.intern_pool;
1283 const fn_ty_index = try wasm.internFunctionType(fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target);
1284 const returns = fn_ty_index.ptr(wasm).returns.slice(wasm);
1285 const any_returns = returns.len != 0;
1185 const ret_ty: Type = .fromInterned(fn_info.return_type);
1186 const any_returns = !firstParamSRet(fn_info.cc, ret_ty, zcu, target) and ret_ty.hasRuntimeBitsIgnoreComptime(zcu);
12861187
12871188 var cc_result = try resolveCallingConventionValues(zcu, fn_ty, target);
12881189 defer cc_result.deinit(gpa);
......@@ -1290,8 +1191,8 @@ pub fn function(
12901191 var code_gen: CodeGen = .{
12911192 .gpa = gpa,
12921193 .pt = pt,
1293 .air = air,
1294 .liveness = liveness,
1194 .air = air.*,
1195 .liveness = liveness.*,
12951196 .owner_nav = cg.owner_nav,
12961197 .target = target,
12971198 .ptr_size = switch (target.cpu.arch) {
......@@ -1299,31 +1200,33 @@ pub fn function(
12991200 .wasm64 => .wasm64,
13001201 else => unreachable,
13011202 },
1302 .wasm = wasm,
13031203 .func_index = func_index,
13041204 .args = cc_result.args,
13051205 .return_value = cc_result.return_value,
13061206 .local_index = cc_result.local_index,
1307 .mir_instructions = &wasm.mir_instructions,
1308 .mir_extra = &wasm.mir_extra,
1309 .locals = &wasm.all_zcu_locals,
1310 .start_mir_extra_off = @intCast(wasm.mir_extra.items.len),
1311 .start_locals_off = @intCast(wasm.all_zcu_locals.items.len),
1207 .mir_instructions = .empty,
1208 .mir_extra = .empty,
1209 .mir_locals = .empty,
1210 .mir_uavs = .empty,
1211 .mir_indirect_function_set = .empty,
1212 .mir_func_tys = .empty,
1213 .error_name_table_ref_count = 0,
13121214 };
13131215 defer code_gen.deinit();
13141216
1315 return functionInner(&code_gen, any_returns) catch |err| switch (err) {
1316 error.CodegenFail => return error.CodegenFail,
1217 try code_gen.mir_func_tys.putNoClobber(gpa, fn_ty.toIntern(), {});
1218
1219 return generateInner(&code_gen, any_returns) catch |err| switch (err) {
1220 error.CodegenFail,
1221 error.OutOfMemory,
1222 error.Overflow,
1223 => |e| return e,
13171224 else => |e| return code_gen.fail("failed to generate function: {s}", .{@errorName(e)}),
13181225 };
13191226}
13201227
1321fn functionInner(cg: *CodeGen, any_returns: bool) InnerError!Function {
1322 const wasm = cg.wasm;
1228fn generateInner(cg: *CodeGen, any_returns: bool) InnerError!Mir {
13231229 const zcu = cg.pt.zcu;
1324
1325 const start_mir_off: u32 = @intCast(wasm.mir_instructions.len);
1326
13271230 try cg.branches.append(cg.gpa, .{});
13281231 // clean up outer branch
13291232 defer {
......@@ -1347,20 +1250,25 @@ fn functionInner(cg: *CodeGen, any_returns: bool) InnerError!Function {
13471250 try cg.addTag(.end);
13481251 try cg.addTag(.dbg_epilogue_begin);
13491252
1350 return .{
1351 .mir_off = start_mir_off,
1352 .mir_len = @intCast(wasm.mir_instructions.len - start_mir_off),
1353 .mir_extra_off = cg.start_mir_extra_off,
1354 .mir_extra_len = cg.extraLen(),
1355 .locals_off = cg.start_locals_off,
1356 .locals_len = @intCast(wasm.all_zcu_locals.items.len - cg.start_locals_off),
1253 var mir: Mir = .{
1254 .instructions = cg.mir_instructions.toOwnedSlice(),
1255 .extra = &.{}, // fallible so assigned after errdefer
1256 .locals = &.{}, // fallible so assigned after errdefer
13571257 .prologue = if (cg.initial_stack_value == .none) .none else .{
13581258 .sp_local = cg.initial_stack_value.local.value,
13591259 .flags = .{ .stack_alignment = cg.stack_alignment },
13601260 .stack_size = cg.stack_size,
13611261 .bottom_stack_local = cg.bottom_stack_value.local.value,
13621262 },
1263 .uavs = cg.mir_uavs.move(),
1264 .indirect_function_set = cg.mir_indirect_function_set.move(),
1265 .func_tys = cg.mir_func_tys.move(),
1266 .error_name_table_ref_count = cg.error_name_table_ref_count,
13631267 };
1268 errdefer mir.deinit(cg.gpa);
1269 mir.extra = try cg.mir_extra.toOwnedSlice(cg.gpa);
1270 mir.locals = try cg.mir_locals.toOwnedSlice(cg.gpa);
1271 return mir;
13641272}
13651273
13661274const CallWValues = struct {
......@@ -1969,7 +1877,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
19691877 .dbg_inline_block => cg.airDbgInlineBlock(inst),
19701878 .dbg_var_ptr => cg.airDbgVar(inst, .local_var, true),
19711879 .dbg_var_val => cg.airDbgVar(inst, .local_var, false),
1972 .dbg_arg_inline => cg.airDbgVar(inst, .local_arg, false),
1880 .dbg_arg_inline => cg.airDbgVar(inst, .arg, false),
19731881
19741882 .call => cg.airCall(inst, .auto),
19751883 .call_always_tail => cg.airCall(inst, .always_tail),
......@@ -2220,7 +2128,6 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
22202128}
22212129
22222130fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) InnerError!void {
2223 const wasm = cg.wasm;
22242131 if (modifier == .always_tail) return cg.fail("TODO implement tail calls for wasm", .{});
22252132 const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
22262133 const extra = cg.air.extraData(Air.Call, pl_op.payload);
......@@ -2277,8 +2184,11 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie
22772184 const operand = try cg.resolveInst(pl_op.operand);
22782185 try cg.emitWValue(operand);
22792186
2280 const fn_type_index = try wasm.internFunctionType(fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), cg.target);
2281 try cg.addFuncTy(.call_indirect, fn_type_index);
2187 try cg.mir_func_tys.put(cg.gpa, fn_ty.toIntern(), {});
2188 try cg.addInst(.{
2189 .tag = .call_indirect,
2190 .data = .{ .ip_index = fn_ty.toIntern() },
2191 });
22822192 }
22832193
22842194 const result_value = result_value: {
......@@ -2449,7 +2359,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
24492359 try cg.emitWValue(lhs);
24502360 try cg.lowerToStack(rhs);
24512361 // TODO: Add helper functions for simd opcodes
2452 const extra_index = cg.extraLen();
2362 const extra_index: u32 = @intCast(cg.mir_extra.items.len);
24532363 // stores as := opcode, offset, alignment (opcode::memarg)
24542364 try cg.mir_extra.appendSlice(cg.gpa, &[_]u32{
24552365 @intFromEnum(std.wasm.SimdOpcode.v128_store),
......@@ -2574,7 +2484,7 @@ fn load(cg: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue
25742484
25752485 if (ty.zigTypeTag(zcu) == .vector) {
25762486 // TODO: Add helper functions for simd opcodes
2577 const extra_index = cg.extraLen();
2487 const extra_index: u32 = @intCast(cg.mir_extra.items.len);
25782488 // stores as := opcode, offset, alignment (opcode::memarg)
25792489 try cg.mir_extra.appendSlice(cg.gpa, &[_]u32{
25802490 @intFromEnum(std.wasm.SimdOpcode.v128_load),
......@@ -4971,7 +4881,7 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
49714881
49724882 try cg.emitWValue(array);
49734883
4974 const extra_index = cg.extraLen();
4884 const extra_index: u32 = @intCast(cg.mir_extra.items.len);
49754885 try cg.mir_extra.appendSlice(cg.gpa, &operands);
49764886 try cg.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
49774887
......@@ -5123,7 +5033,7 @@ fn airSplat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
51235033 else => break :blk, // Cannot make use of simd-instructions
51245034 };
51255035 try cg.emitWValue(operand);
5126 const extra_index: u32 = cg.extraLen();
5036 const extra_index: u32 = @intCast(cg.mir_extra.items.len);
51275037 // stores as := opcode, offset, alignment (opcode::memarg)
51285038 try cg.mir_extra.appendSlice(cg.gpa, &[_]u32{
51295039 opcode,
......@@ -5142,7 +5052,7 @@ fn airSplat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
51425052 else => break :blk, // Cannot make use of simd-instructions
51435053 };
51445054 try cg.emitWValue(operand);
5145 const extra_index = cg.extraLen();
5055 const extra_index: u32 = @intCast(cg.mir_extra.items.len);
51465056 try cg.mir_extra.append(cg.gpa, opcode);
51475057 try cg.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
51485058 return cg.finishAir(inst, .stack, &.{ty_op.operand});
......@@ -5246,7 +5156,7 @@ fn airShuffleTwo(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
52465156 }
52475157 try cg.emitWValue(operand_a);
52485158 try cg.emitWValue(operand_b);
5249 const extra_index = cg.extraLen();
5159 const extra_index: u32 = @intCast(cg.mir_extra.items.len);
52505160 try cg.mir_extra.appendSlice(cg.gpa, &.{
52515161 @intFromEnum(std.wasm.SimdOpcode.i8x16_shuffle),
52525162 @bitCast(lane_map[0..4].*),
......@@ -6016,9 +5926,8 @@ fn airErrorName(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
60165926 const name_ty = Type.slice_const_u8_sentinel_0;
60175927 const abi_size = name_ty.abiSize(pt.zcu);
60185928
6019 cg.wasm.error_name_table_ref_count += 1;
6020
60215929 // Lowers to a i32.const or i64.const with the error table memory address.
5930 cg.error_name_table_ref_count += 1;
60225931 try cg.addTag(.error_name_table_ref);
60235932 try cg.emitWValue(operand);
60245933 switch (cg.ptr_size) {
......@@ -6046,7 +5955,7 @@ fn airPtrSliceFieldPtr(cg: *CodeGen, inst: Air.Inst.Index, offset: u32) InnerErr
60465955
60475956/// NOTE: Allocates place for result on virtual stack, when integer size > 64 bits
60485957fn intZeroValue(cg: *CodeGen, ty: Type) InnerError!WValue {
6049 const zcu = cg.wasm.base.comp.zcu.?;
5958 const zcu = cg.pt.zcu;
60505959 const int_info = ty.intInfo(zcu);
60515960 const wasm_bits = toWasmBits(int_info.bits) orelse {
60525961 return cg.fail("TODO: Implement intZeroValue for integer bitsize: {d}", .{int_info.bits});
......@@ -6518,7 +6427,7 @@ fn airDbgInlineBlock(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
65186427fn airDbgVar(
65196428 cg: *CodeGen,
65206429 inst: Air.Inst.Index,
6521 local_tag: link.File.Dwarf.WipNav.LocalTag,
6430 local_tag: link.File.Dwarf.WipNav.LocalVarTag,
65226431 is_ptr: bool,
65236432) InnerError!void {
65246433 _ = is_ptr;
......@@ -7673,7 +7582,3 @@ fn floatCmpIntrinsic(op: std.math.CompareOperator, bits: u16) Mir.Intrinsic {
76737582 },
76747583 };
76757584}
7676
7677fn extraLen(cg: *const CodeGen) u32 {
7678 return @intCast(cg.mir_extra.items.len - cg.start_mir_extra_off);
7679}
src/arch/wasm/Emit.zig+25-14
......@@ -31,8 +31,8 @@ pub fn lowerToCode(emit: *Emit) Error!void {
3131 const target = &comp.root_mod.resolved_target.result;
3232 const is_wasm32 = target.cpu.arch == .wasm32;
3333
34 const tags = mir.instruction_tags;
35 const datas = mir.instruction_datas;
34 const tags = mir.instructions.items(.tag);
35 const datas = mir.instructions.items(.data);
3636 var inst: u32 = 0;
3737
3838 loop: switch (tags[inst]) {
......@@ -50,18 +50,19 @@ pub fn lowerToCode(emit: *Emit) Error!void {
5050 },
5151 .uav_ref => {
5252 if (is_obj) {
53 try uavRefOffObj(wasm, code, .{ .uav_obj = datas[inst].uav_obj, .offset = 0 }, is_wasm32);
53 try uavRefObj(wasm, code, datas[inst].ip_index, 0, is_wasm32);
5454 } else {
55 try uavRefOffExe(wasm, code, .{ .uav_exe = datas[inst].uav_exe, .offset = 0 }, is_wasm32);
55 try uavRefExe(wasm, code, datas[inst].ip_index, 0, is_wasm32);
5656 }
5757 inst += 1;
5858 continue :loop tags[inst];
5959 },
6060 .uav_ref_off => {
61 const extra = mir.extraData(Mir.UavRefOff, datas[inst].payload).data;
6162 if (is_obj) {
62 try uavRefOffObj(wasm, code, mir.extraData(Mir.UavRefOffObj, datas[inst].payload).data, is_wasm32);
63 try uavRefObj(wasm, code, extra.value, extra.offset, is_wasm32);
6364 } else {
64 try uavRefOffExe(wasm, code, mir.extraData(Mir.UavRefOffExe, datas[inst].payload).data, is_wasm32);
65 try uavRefExe(wasm, code, extra.value, extra.offset, is_wasm32);
6566 }
6667 inst += 1;
6768 continue :loop tags[inst];
......@@ -77,11 +78,14 @@ pub fn lowerToCode(emit: *Emit) Error!void {
7778 continue :loop tags[inst];
7879 },
7980 .func_ref => {
81 const indirect_func_idx: Wasm.ZcuIndirectFunctionSetIndex = @enumFromInt(
82 wasm.zcu_indirect_function_set.getIndex(datas[inst].nav_index).?,
83 );
8084 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));
8185 if (is_obj) {
8286 @panic("TODO");
8387 } else {
84 leb.writeUleb128(code.fixedWriter(), 1 + @intFromEnum(datas[inst].indirect_function_table_index)) catch unreachable;
88 leb.writeUleb128(code.fixedWriter(), 1 + @intFromEnum(indirect_func_idx)) catch unreachable;
8589 }
8690 inst += 1;
8791 continue :loop tags[inst];
......@@ -101,6 +105,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {
101105 continue :loop tags[inst];
102106 },
103107 .error_name_table_ref => {
108 wasm.error_name_table_ref_count += 1;
104109 try code.ensureUnusedCapacity(gpa, 11);
105110 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
106111 code.appendAssumeCapacity(@intFromEnum(opcode));
......@@ -176,7 +181,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {
176181
177182 .call_indirect => {
178183 try code.ensureUnusedCapacity(gpa, 11);
179 const func_ty_index = datas[inst].func_ty;
184 const fn_info = comp.zcu.?.typeToFunc(.fromInterned(datas[inst].ip_index)).?;
185 const func_ty_index = wasm.getExistingFunctionType(
186 fn_info.cc,
187 fn_info.param_types.get(&comp.zcu.?.intern_pool),
188 .fromInterned(fn_info.return_type),
189 target,
190 ).?;
180191 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.call_indirect));
181192 if (is_obj) {
182193 try wasm.out_relocs.append(gpa, .{
......@@ -912,7 +923,7 @@ fn encodeMemArg(code: *std.ArrayListUnmanaged(u8), mem_arg: Mir.MemArg) void {
912923 leb.writeUleb128(code.fixedWriter(), mem_arg.offset) catch unreachable;
913924}
914925
915fn uavRefOffObj(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.UavRefOffObj, is_wasm32: bool) !void {
926fn uavRefObj(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void {
916927 const comp = wasm.base.comp;
917928 const gpa = comp.gpa;
918929 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
......@@ -922,14 +933,14 @@ fn uavRefOffObj(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.UavRef
922933
923934 try wasm.out_relocs.append(gpa, .{
924935 .offset = @intCast(code.items.len),
925 .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(data.uav_obj.key(wasm).*) },
936 .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(value) },
926937 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,
927 .addend = data.offset,
938 .addend = offset,
928939 });
929940 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);
930941}
931942
932fn uavRefOffExe(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.UavRefOffExe, is_wasm32: bool) !void {
943fn uavRefExe(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void {
933944 const comp = wasm.base.comp;
934945 const gpa = comp.gpa;
935946 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
......@@ -937,8 +948,8 @@ fn uavRefOffExe(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.UavRef
937948 try code.ensureUnusedCapacity(gpa, 11);
938949 code.appendAssumeCapacity(@intFromEnum(opcode));
939950
940 const addr = wasm.uavAddr(data.uav_exe);
941 leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable;
951 const addr = wasm.uavAddr(value);
952 leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + offset))) catch unreachable;
942953}
943954
944955fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff, is_wasm32: bool) !void {
src/arch/wasm/Mir.zig+104-19
......@@ -9,16 +9,53 @@
99const Mir = @This();
1010const InternPool = @import("../../InternPool.zig");
1111const Wasm = @import("../../link/Wasm.zig");
12const Emit = @import("Emit.zig");
13const Alignment = InternPool.Alignment;
1214
1315const builtin = @import("builtin");
1416const std = @import("std");
1517const assert = std.debug.assert;
18const leb = std.leb;
1619
17instruction_tags: []const Inst.Tag,
18instruction_datas: []const Inst.Data,
20instructions: std.MultiArrayList(Inst).Slice,
1921/// A slice of indexes where the meaning of the data is determined by the
2022/// `Inst.Tag` value.
2123extra: []const u32,
24locals: []const std.wasm.Valtype,
25prologue: Prologue,
26
27/// Not directly used by `Emit`, but the linker needs this to merge it with a global set.
28/// Value is the explicit alignment if greater than natural alignment, `.none` otherwise.
29uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
30/// Not directly used by `Emit`, but the linker needs this to merge it with a global set.
31indirect_function_set: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
32/// Not directly used by `Emit`, but the linker needs this to ensure these types are interned.
33func_tys: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
34/// Not directly used by `Emit`, but the linker needs this to add it to its own refcount.
35error_name_table_ref_count: u32,
36
37pub const Prologue = extern struct {
38 flags: Flags,
39 sp_local: u32,
40 stack_size: u32,
41 bottom_stack_local: u32,
42
43 pub const Flags = packed struct(u32) {
44 stack_alignment: Alignment,
45 padding: u26 = 0,
46 };
47
48 pub const none: Prologue = .{
49 .sp_local = 0,
50 .flags = .{ .stack_alignment = .none },
51 .stack_size = 0,
52 .bottom_stack_local = 0,
53 };
54
55 pub fn isNone(p: *const Prologue) bool {
56 return p.flags.stack_alignment != .none;
57 }
58};
2259
2360pub const Inst = struct {
2461 /// The opcode that represents this instruction
......@@ -80,7 +117,7 @@ pub const Inst = struct {
80117 /// Lowers to an i32_const which is the index of the function in the
81118 /// table section.
82119 ///
83 /// Uses `indirect_function_table_index`.
120 /// Uses `nav_index`.
84121 func_ref,
85122 /// Inserts debug information about the current line and column
86123 /// of the source code
......@@ -123,7 +160,7 @@ pub const Inst = struct {
123160 /// Calls a function pointer by its function signature
124161 /// and index into the function table.
125162 ///
126 /// Uses `func_ty`
163 /// Uses `ip_index`; the `InternPool.Index` is the function type.
127164 call_indirect,
128165 /// Calls a function by its index.
129166 ///
......@@ -611,11 +648,7 @@ pub const Inst = struct {
611648
612649 ip_index: InternPool.Index,
613650 nav_index: InternPool.Nav.Index,
614 func_ty: Wasm.FunctionType.Index,
615651 intrinsic: Intrinsic,
616 uav_obj: Wasm.UavsObjIndex,
617 uav_exe: Wasm.UavsExeIndex,
618 indirect_function_table_index: Wasm.ZcuIndirectFunctionSetIndex,
619652
620653 comptime {
621654 switch (builtin.mode) {
......@@ -626,10 +659,66 @@ pub const Inst = struct {
626659 };
627660};
628661
629pub fn deinit(self: *Mir, gpa: std.mem.Allocator) void {
630 self.instructions.deinit(gpa);
631 gpa.free(self.extra);
632 self.* = undefined;
662pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
663 mir.instructions.deinit(gpa);
664 gpa.free(mir.extra);
665 gpa.free(mir.locals);
666 mir.uavs.deinit(gpa);
667 mir.indirect_function_set.deinit(gpa);
668 mir.func_tys.deinit(gpa);
669 mir.* = undefined;
670}
671
672pub fn lower(mir: *const Mir, wasm: *Wasm, code: *std.ArrayListUnmanaged(u8)) std.mem.Allocator.Error!void {
673 const gpa = wasm.base.comp.gpa;
674
675 // Write the locals in the prologue of the function body.
676 try code.ensureUnusedCapacity(gpa, 5 + mir.locals.len * 6 + 38);
677
678 std.leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(mir.locals.len))) catch unreachable;
679 for (mir.locals) |local| {
680 std.leb.writeUleb128(code.fixedWriter(), @as(u32, 1)) catch unreachable;
681 code.appendAssumeCapacity(@intFromEnum(local));
682 }
683
684 // Stack management section of function prologue.
685 const stack_alignment = mir.prologue.flags.stack_alignment;
686 if (stack_alignment.toByteUnits()) |align_bytes| {
687 const sp_global: Wasm.GlobalIndex = .stack_pointer;
688 // load stack pointer
689 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_get));
690 std.leb.writeULEB128(code.fixedWriter(), @intFromEnum(sp_global)) catch unreachable;
691 // store stack pointer so we can restore it when we return from the function
692 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_tee));
693 leb.writeUleb128(code.fixedWriter(), mir.prologue.sp_local) catch unreachable;
694 // get the total stack size
695 const aligned_stack: i32 = @intCast(stack_alignment.forward(mir.prologue.stack_size));
696 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));
697 leb.writeIleb128(code.fixedWriter(), aligned_stack) catch unreachable;
698 // subtract it from the current stack pointer
699 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_sub));
700 // Get negative stack alignment
701 const neg_stack_align = @as(i32, @intCast(align_bytes)) * -1;
702 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));
703 leb.writeIleb128(code.fixedWriter(), neg_stack_align) catch unreachable;
704 // Bitwise-and the value to get the new stack pointer to ensure the
705 // pointers are aligned with the abi alignment.
706 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_and));
707 // The bottom will be used to calculate all stack pointer offsets.
708 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_tee));
709 leb.writeUleb128(code.fixedWriter(), mir.prologue.bottom_stack_local) catch unreachable;
710 // Store the current stack pointer value into the global stack pointer so other function calls will
711 // start from this value instead and not overwrite the current stack.
712 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_set));
713 std.leb.writeULEB128(code.fixedWriter(), @intFromEnum(sp_global)) catch unreachable;
714 }
715
716 var emit: Emit = .{
717 .mir = mir.*,
718 .wasm = wasm,
719 .code = code,
720 };
721 try emit.lowerToCode();
633722}
634723
635724pub fn extraData(self: *const Mir, comptime T: type, index: usize) struct { data: T, end: usize } {
......@@ -643,6 +732,7 @@ pub fn extraData(self: *const Mir, comptime T: type, index: usize) struct { data
643732 Wasm.UavsObjIndex,
644733 Wasm.UavsExeIndex,
645734 InternPool.Nav.Index,
735 InternPool.Index,
646736 => @enumFromInt(self.extra[i]),
647737 else => |field_type| @compileError("Unsupported field type " ++ @typeName(field_type)),
648738 };
......@@ -695,13 +785,8 @@ pub const MemArg = struct {
695785 alignment: u32,
696786};
697787
698pub const UavRefOffObj = struct {
699 uav_obj: Wasm.UavsObjIndex,
700 offset: i32,
701};
702
703pub const UavRefOffExe = struct {
704 uav_exe: Wasm.UavsExeIndex,
788pub const UavRefOff = struct {
789 value: InternPool.Index,
705790 offset: i32,
706791};
707792
src/arch/x86_64/CodeGen.zig+1964-2233
......@@ -124,13 +124,13 @@ gpa: Allocator,
124124pt: Zcu.PerThread,
125125air: Air,
126126liveness: Air.Liveness,
127bin_file: *link.File,
128debug_output: link.File.DebugInfoOutput,
129127target: *const std.Target,
130owner: Owner,
128owner: union(enum) {
129 nav_index: InternPool.Nav.Index,
130 lazy_sym: link.File.LazySymbol,
131},
131132inline_func: InternPool.Index,
132133mod: *Module,
133arg_index: u32,
134134args: []MCValue,
135135va_info: union {
136136 sysv: struct {
......@@ -152,6 +152,14 @@ eflags_inst: ?Air.Inst.Index = null,
152152mir_instructions: std.MultiArrayList(Mir.Inst) = .empty,
153153/// MIR extra data
154154mir_extra: std.ArrayListUnmanaged(u32) = .empty,
155mir_string_bytes: std.ArrayListUnmanaged(u8) = .empty,
156mir_strings: std.HashMapUnmanaged(
157 u32,
158 void,
159 std.hash_map.StringIndexContext,
160 std.hash_map.default_max_load_percentage,
161) = .empty,
162mir_locals: std.ArrayListUnmanaged(Mir.Local) = .empty,
155163mir_table: std.ArrayListUnmanaged(Mir.Inst.Index) = .empty,
156164
157165/// The value is an offset into the `Function` `code` from the beginning.
......@@ -194,41 +202,6 @@ loop_switches: std.AutoHashMapUnmanaged(Air.Inst.Index, struct {
194202next_temp_index: Temp.Index = @enumFromInt(0),
195203temp_type: [Temp.Index.max]Type = undefined,
196204
197const Owner = union(enum) {
198 nav_index: InternPool.Nav.Index,
199 lazy_sym: link.File.LazySymbol,
200
201 fn getSymbolIndex(owner: Owner, ctx: *CodeGen) !u32 {
202 const pt = ctx.pt;
203 switch (owner) {
204 .nav_index => |nav_index| if (ctx.bin_file.cast(.elf)) |elf_file| {
205 return elf_file.zigObjectPtr().?.getOrCreateMetadataForNav(pt.zcu, nav_index);
206 } else if (ctx.bin_file.cast(.macho)) |macho_file| {
207 return macho_file.getZigObject().?.getOrCreateMetadataForNav(macho_file, nav_index);
208 } else if (ctx.bin_file.cast(.coff)) |coff_file| {
209 const atom = try coff_file.getOrCreateAtomForNav(nav_index);
210 return coff_file.getAtom(atom).getSymbolIndex().?;
211 } else if (ctx.bin_file.cast(.plan9)) |p9_file| {
212 return p9_file.seeNav(pt, nav_index);
213 } else unreachable,
214 .lazy_sym => |lazy_sym| if (ctx.bin_file.cast(.elf)) |elf_file| {
215 return elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
216 ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
217 } else if (ctx.bin_file.cast(.macho)) |macho_file| {
218 return macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym) catch |err|
219 ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
220 } else if (ctx.bin_file.cast(.coff)) |coff_file| {
221 const atom = coff_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
222 return ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
223 return coff_file.getAtom(atom).getSymbolIndex().?;
224 } else if (ctx.bin_file.cast(.plan9)) |p9_file| {
225 return p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
226 return ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
227 } else unreachable,
228 }
229 }
230};
231
232205const MaskInfo = packed struct {
233206 kind: enum(u1) { sign, all },
234207 inverted: bool = false,
......@@ -269,37 +242,22 @@ pub const MCValue = union(enum) {
269242 /// The value is in memory at a hard-coded address.
270243 /// If the type is a pointer, it means the pointer address is stored at this memory location.
271244 memory: u64,
272 /// The value is in memory at an address not-yet-allocated by the linker.
273 /// This traditionally corresponds to a relocation emitted in a relocatable object file.
274 load_symbol: bits.SymbolOffset,
275 /// The address of the memory location not-yet-allocated by the linker.
276 lea_symbol: bits.SymbolOffset,
277 /// The value is in memory at an address not-yet-allocated by the linker.
278 /// This must use a non-got pc-relative relocation.
279 load_pcrel: bits.SymbolOffset,
280 /// The address of the memory location not-yet-allocated by the linker.
281 /// This must use a non-got pc-relative relocation.
282 lea_pcrel: bits.SymbolOffset,
283245 /// The value is in memory at a constant offset from the address in a register.
284246 indirect: bits.RegisterOffset,
285 /// The value is in memory.
286 /// Payload is a symbol index.
287 load_direct: u32,
288 /// The value is a pointer to a value in memory.
289 /// Payload is a symbol index.
290 lea_direct: u32,
291 /// The value is in memory referenced indirectly via GOT.
292 /// Payload is a symbol index.
293 load_got: u32,
294 /// The value is a pointer to a value referenced indirectly via GOT.
295 /// Payload is a symbol index.
296 lea_got: u32,
297247 /// The value stored at an offset from a frame index
298248 /// Payload is a frame address.
299249 load_frame: bits.FrameAddr,
300250 /// The address of an offset from a frame index
301251 /// Payload is a frame address.
302252 lea_frame: bits.FrameAddr,
253 load_nav: InternPool.Nav.Index,
254 lea_nav: InternPool.Nav.Index,
255 load_uav: InternPool.Key.Ptr.BaseAddr.Uav,
256 lea_uav: InternPool.Key.Ptr.BaseAddr.Uav,
257 load_lazy_sym: link.File.LazySymbol,
258 lea_lazy_sym: link.File.LazySymbol,
259 load_extern_func: Mir.NullTerminatedString,
260 lea_extern_func: Mir.NullTerminatedString,
303261 /// Supports integer_per_element abi
304262 elementwise_args: packed struct { regs: u3, frame_off: i29, frame_index: FrameIndex },
305263 /// This indicates that we have already allocated a frame index for this instruction,
......@@ -319,11 +277,14 @@ pub const MCValue = union(enum) {
319277 .register_mask,
320278 .eflags,
321279 .register_overflow,
322 .lea_symbol,
323 .lea_pcrel,
324 .lea_direct,
325 .lea_got,
326280 .lea_frame,
281 .lea_nav,
282 .load_uav,
283 .lea_uav,
284 .load_lazy_sym,
285 .lea_lazy_sym,
286 .lea_extern_func,
287 .load_extern_func,
327288 .elementwise_args,
328289 .reserved_frame,
329290 .air_ref,
......@@ -333,11 +294,8 @@ pub const MCValue = union(enum) {
333294 .register_triple,
334295 .register_quadruple,
335296 .memory,
336 .load_symbol,
337 .load_pcrel,
338 .load_got,
339 .load_direct,
340297 .indirect,
298 .load_nav,
341299 => true,
342300 .load_frame => |frame_addr| !frame_addr.index.isNamed(),
343301 };
......@@ -353,7 +311,14 @@ pub const MCValue = union(enum) {
353311
354312 fn isMemory(mcv: MCValue) bool {
355313 return switch (mcv) {
356 .memory, .indirect, .load_frame, .load_symbol => true,
314 .memory,
315 .indirect,
316 .load_frame,
317 .load_nav,
318 .load_uav,
319 .load_lazy_sym,
320 .load_extern_func,
321 => true,
357322 else => false,
358323 };
359324 }
......@@ -423,7 +388,7 @@ pub const MCValue = union(enum) {
423388
424389 fn address(mcv: MCValue) MCValue {
425390 return switch (mcv) {
426 .none,
391 .none => .none,
427392 .unreach,
428393 .dead,
429394 .undef,
......@@ -436,11 +401,11 @@ pub const MCValue = union(enum) {
436401 .register_offset,
437402 .register_overflow,
438403 .register_mask,
439 .lea_symbol,
440 .lea_pcrel,
441 .lea_direct,
442 .lea_got,
443404 .lea_frame,
405 .lea_nav,
406 .lea_uav,
407 .lea_lazy_sym,
408 .lea_extern_func,
444409 .elementwise_args,
445410 .reserved_frame,
446411 .air_ref,
......@@ -450,17 +415,17 @@ pub const MCValue = union(enum) {
450415 0 => .{ .register = reg_off.reg },
451416 else => .{ .register_offset = reg_off },
452417 },
453 .load_direct => |sym_index| .{ .lea_direct = sym_index },
454 .load_got => |sym_index| .{ .lea_got = sym_index },
455418 .load_frame => |frame_addr| .{ .lea_frame = frame_addr },
456 .load_symbol => |sym_off| .{ .lea_symbol = sym_off },
457 .load_pcrel => |sym_off| .{ .lea_pcrel = sym_off },
419 .load_nav => |nav| .{ .lea_nav = nav },
420 .load_uav => |uav| .{ .lea_uav = uav },
421 .load_lazy_sym => |lazy_sym| .{ .lea_lazy_sym = lazy_sym },
422 .load_extern_func => |extern_func| .{ .lea_extern_func = extern_func },
458423 };
459424 }
460425
461426 fn deref(mcv: MCValue) MCValue {
462427 return switch (mcv) {
463 .none,
428 .none => .none,
464429 .unreach,
465430 .dead,
466431 .undef,
......@@ -472,11 +437,11 @@ pub const MCValue = union(enum) {
472437 .register_mask,
473438 .memory,
474439 .indirect,
475 .load_direct,
476 .load_got,
477440 .load_frame,
478 .load_symbol,
479 .load_pcrel,
441 .load_nav,
442 .load_uav,
443 .load_lazy_sym,
444 .load_extern_func,
480445 .elementwise_args,
481446 .reserved_frame,
482447 .air_ref,
......@@ -484,17 +449,17 @@ pub const MCValue = union(enum) {
484449 .immediate => |addr| .{ .memory = addr },
485450 .register => |reg| .{ .indirect = .{ .reg = reg } },
486451 .register_offset => |reg_off| .{ .indirect = reg_off },
487 .lea_direct => |sym_index| .{ .load_direct = sym_index },
488 .lea_got => |sym_index| .{ .load_got = sym_index },
489452 .lea_frame => |frame_addr| .{ .load_frame = frame_addr },
490 .lea_symbol => |sym_index| .{ .load_symbol = sym_index },
491 .lea_pcrel => |sym_index| .{ .load_pcrel = sym_index },
453 .lea_nav => |nav| .{ .load_nav = nav },
454 .lea_uav => |uav| .{ .load_uav = uav },
455 .lea_lazy_sym => |lazy_sym| .{ .load_lazy_sym = lazy_sym },
456 .lea_extern_func => |extern_func| .{ .load_extern_func = extern_func },
492457 };
493458 }
494459
495460 fn offset(mcv: MCValue, off: i32) MCValue {
496461 return switch (mcv) {
497 .none,
462 .none => .none,
498463 .unreach,
499464 .dead,
500465 .undef,
......@@ -510,15 +475,15 @@ pub const MCValue = union(enum) {
510475 .register_mask,
511476 .memory,
512477 .indirect,
513 .load_direct,
514 .lea_direct,
515 .load_got,
516 .lea_got,
517478 .load_frame,
518 .load_symbol,
519 .lea_symbol,
520 .load_pcrel,
521 .lea_pcrel,
479 .load_nav,
480 .lea_nav,
481 .load_uav,
482 .lea_uav,
483 .load_lazy_sym,
484 .lea_lazy_sym,
485 .load_extern_func,
486 .lea_extern_func,
522487 => switch (off) {
523488 0 => mcv,
524489 else => unreachable, // not offsettable
......@@ -536,7 +501,7 @@ pub const MCValue = union(enum) {
536501
537502 fn mem(mcv: MCValue, function: *CodeGen, mod_rm: Memory.Mod.Rm) !Memory {
538503 return switch (mcv) {
539 .none,
504 .none => .{ .mod = .{ .rm = mod_rm } },
540505 .unreach,
541506 .dead,
542507 .undef,
......@@ -549,15 +514,13 @@ pub const MCValue = union(enum) {
549514 .register_offset,
550515 .register_overflow,
551516 .register_mask,
552 .load_direct,
553 .lea_direct,
554 .load_got,
555 .lea_got,
556517 .lea_frame,
557518 .elementwise_args,
558519 .reserved_frame,
559 .lea_symbol,
560 .lea_pcrel,
520 .lea_nav,
521 .lea_uav,
522 .lea_lazy_sym,
523 .lea_extern_func,
561524 => unreachable,
562525 .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| .{
563526 .base = .{ .reg = .ds },
......@@ -586,30 +549,10 @@ pub const MCValue = union(enum) {
586549 .disp = frame_addr.off + mod_rm.disp,
587550 } },
588551 },
589 .load_symbol => |sym_off| {
590 assert(sym_off.off == 0);
591 return .{
592 .base = .{ .reloc = sym_off.sym_index },
593 .mod = .{ .rm = .{
594 .size = mod_rm.size,
595 .index = mod_rm.index,
596 .scale = mod_rm.scale,
597 .disp = sym_off.off + mod_rm.disp,
598 } },
599 };
600 },
601 .load_pcrel => |sym_off| {
602 assert(sym_off.off == 0);
603 return .{
604 .base = .{ .pcrel = sym_off.sym_index },
605 .mod = .{ .rm = .{
606 .size = mod_rm.size,
607 .index = mod_rm.index,
608 .scale = mod_rm.scale,
609 .disp = sym_off.off + mod_rm.disp,
610 } },
611 };
612 },
552 .load_nav => |nav| .{ .base = .{ .nav = nav }, .mod = .{ .rm = mod_rm } },
553 .load_uav => |uav| .{ .base = .{ .uav = uav }, .mod = .{ .rm = mod_rm } },
554 .load_lazy_sym => |lazy_sym| .{ .base = .{ .lazy_sym = lazy_sym }, .mod = .{ .rm = mod_rm } },
555 .load_extern_func => |extern_func| .{ .base = .{ .extern_func = extern_func }, .mod = .{ .rm = mod_rm } },
613556 .air_ref => |ref| (try function.resolveInst(ref)).mem(function, mod_rm),
614557 };
615558 }
......@@ -643,20 +586,20 @@ pub const MCValue = union(enum) {
643586 @as(u8, if (pl.info.inverted) '!' else ' '),
644587 @tagName(pl.reg),
645588 }),
646 .load_symbol => |pl| try writer.print("[sym:{} + 0x{x}]", .{ pl.sym_index, pl.off }),
647 .lea_symbol => |pl| try writer.print("sym:{} + 0x{x}", .{ pl.sym_index, pl.off }),
648 .load_pcrel => |pl| try writer.print("[sym@pcrel:{} + 0x{x}]", .{ pl.sym_index, pl.off }),
649 .lea_pcrel => |pl| try writer.print("sym@pcrel:{} + 0x{x}", .{ pl.sym_index, pl.off }),
650589 .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
651 .load_direct => |pl| try writer.print("[direct:{d}]", .{pl}),
652 .lea_direct => |pl| try writer.print("direct:{d}", .{pl}),
653 .load_got => |pl| try writer.print("[got:{d}]", .{pl}),
654 .lea_got => |pl| try writer.print("got:{d}", .{pl}),
655590 .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),
591 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),
592 .load_nav => |pl| try writer.print("[nav:{d}]", .{@intFromEnum(pl)}),
593 .lea_nav => |pl| try writer.print("nav:{d}", .{@intFromEnum(pl)}),
594 .load_uav => |pl| try writer.print("[uav:{d}]", .{@intFromEnum(pl.val)}),
595 .lea_uav => |pl| try writer.print("uav:{d}", .{@intFromEnum(pl.val)}),
596 .load_lazy_sym => |pl| try writer.print("[lazy:{s}:{d}]", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
597 .lea_lazy_sym => |pl| try writer.print("lazy:{s}:{d}", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
598 .load_extern_func => |pl| try writer.print("[extern:{d}]", .{@intFromEnum(pl)}),
599 .lea_extern_func => |pl| try writer.print("extern:{d}", .{@intFromEnum(pl)}),
656600 .elementwise_args => |pl| try writer.print("elementwise:{d}:[{} + 0x{x}]", .{
657601 pl.regs, pl.frame_index, pl.frame_off,
658602 }),
659 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),
660603 .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}),
661604 .air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}),
662605 }
......@@ -676,16 +619,16 @@ const InstTracking = struct {
676619 .undef,
677620 .immediate,
678621 .memory,
679 .load_direct,
680 .lea_direct,
681 .load_got,
682 .lea_got,
683622 .load_frame,
684623 .lea_frame,
685 .load_symbol,
686 .lea_symbol,
687 .load_pcrel,
688 .lea_pcrel,
624 .load_nav,
625 .lea_nav,
626 .load_uav,
627 .lea_uav,
628 .load_lazy_sym,
629 .lea_lazy_sym,
630 .load_extern_func,
631 .lea_extern_func,
689632 => result,
690633 .dead,
691634 .elementwise_args,
......@@ -779,15 +722,15 @@ const InstTracking = struct {
779722 .undef,
780723 .immediate,
781724 .memory,
782 .load_direct,
783 .lea_direct,
784 .load_got,
785 .lea_got,
786725 .lea_frame,
787 .load_symbol,
788 .lea_symbol,
789 .load_pcrel,
790 .lea_pcrel,
726 .load_nav,
727 .lea_nav,
728 .load_uav,
729 .lea_uav,
730 .load_lazy_sym,
731 .lea_lazy_sym,
732 .load_extern_func,
733 .lea_extern_func,
791734 => assert(std.meta.eql(self.long, target.long)),
792735 .dead,
793736 .eflags,
......@@ -972,31 +915,28 @@ pub fn generate(
972915 pt: Zcu.PerThread,
973916 src_loc: Zcu.LazySrcLoc,
974917 func_index: InternPool.Index,
975 air: Air,
976 liveness: Air.Liveness,
977 code: *std.ArrayListUnmanaged(u8),
978 debug_output: link.File.DebugInfoOutput,
979) codegen.CodeGenError!void {
918 air: *const Air,
919 liveness: *const Air.Liveness,
920) codegen.CodeGenError!Mir {
921 _ = bin_file;
980922 const zcu = pt.zcu;
981 const comp = zcu.comp;
982923 const gpa = zcu.gpa;
983924 const ip = &zcu.intern_pool;
984925 const func = zcu.funcInfo(func_index);
926 const func_zir = func.zir_body_inst.resolveFull(ip).?;
927 const file = zcu.fileByIndex(func_zir.file);
985928 const fn_type: Type = .fromInterned(func.ty);
986 const mod = zcu.navFileScope(func.owner_nav).mod.?;
929 const mod = file.mod.?;
987930
988931 var function: CodeGen = .{
989932 .gpa = gpa,
990933 .pt = pt,
991 .air = air,
992 .liveness = liveness,
934 .air = air.*,
935 .liveness = liveness.*,
993936 .target = &mod.resolved_target.result,
994937 .mod = mod,
995 .bin_file = bin_file,
996 .debug_output = debug_output,
997938 .owner = .{ .nav_index = func.owner_nav },
998939 .inline_func = func_index,
999 .arg_index = undefined,
1000940 .args = undefined, // populated after `resolveCallingConventionValues`
1001941 .va_info = undefined, // populated after `resolveCallingConventionValues`
1002942 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
......@@ -1016,6 +956,9 @@ pub fn generate(
1016956 function.inst_tracking.deinit(gpa);
1017957 function.epilogue_relocs.deinit(gpa);
1018958 function.mir_instructions.deinit(gpa);
959 function.mir_string_bytes.deinit(gpa);
960 function.mir_strings.deinit(gpa);
961 function.mir_locals.deinit(gpa);
1019962 function.mir_extra.deinit(gpa);
1020963 function.mir_table.deinit(gpa);
1021964 }
......@@ -1083,14 +1026,14 @@ pub fn generate(
10831026 );
10841027 }
10851028
1086 function.gen() catch |err| switch (err) {
1029 function.gen(&file.zir.?, func_zir.inst, func.comptime_args, call_info.air_arg_count) catch |err| switch (err) {
10871030 error.CodegenFail => return error.CodegenFail,
10881031 error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
10891032 else => |e| return e,
10901033 };
10911034
10921035 // Drop them off at the rbrace.
1093 if (debug_output != .none) _ = try function.addInst(.{
1036 if (!mod.strip) _ = try function.addInst(.{
10941037 .tag = .pseudo,
10951038 .ops = .pseudo_dbg_line_line_column,
10961039 .data = .{ .line_column = .{
......@@ -1100,48 +1043,31 @@ pub fn generate(
11001043 });
11011044
11021045 var mir: Mir = .{
1103 .instructions = function.mir_instructions.toOwnedSlice(),
1104 .extra = try function.mir_extra.toOwnedSlice(gpa),
1105 .table = try function.mir_table.toOwnedSlice(gpa),
1106 .frame_locs = function.frame_locs.toOwnedSlice(),
1046 .instructions = .empty,
1047 .extra = &.{},
1048 .string_bytes = &.{},
1049 .locals = &.{},
1050 .table = &.{},
1051 .frame_locs = .empty,
11071052 };
1108 defer mir.deinit(gpa);
1109
1110 var emit: Emit = .{
1111 .air = function.air,
1112 .lower = .{
1113 .bin_file = bin_file,
1114 .target = function.target,
1115 .allocator = gpa,
1116 .mir = mir,
1117 .cc = fn_info.cc,
1118 .src_loc = src_loc,
1119 .output_mode = comp.config.output_mode,
1120 .link_mode = comp.config.link_mode,
1121 .pic = mod.pic,
1122 },
1123 .atom_index = function.owner.getSymbolIndex(&function) catch |err| switch (err) {
1124 error.CodegenFail => return error.CodegenFail,
1125 else => |e| return e,
1126 },
1127 .debug_output = debug_output,
1128 .code = code,
1129 .prev_di_loc = .{
1130 .line = func.lbrace_line,
1131 .column = func.lbrace_column,
1132 .is_stmt = switch (debug_output) {
1133 .dwarf => |dwarf| dwarf.dwarf.debug_line.header.default_is_stmt,
1134 .plan9 => undefined,
1135 .none => undefined,
1136 },
1137 },
1138 .prev_di_pc = 0,
1139 };
1140 emit.emitMir() catch |err| switch (err) {
1141 error.LowerFail, error.EmitFail => return function.failMsg(emit.lower.err_msg.?),
1053 errdefer mir.deinit(gpa);
1054 mir.instructions = function.mir_instructions.toOwnedSlice();
1055 mir.extra = try function.mir_extra.toOwnedSlice(gpa);
1056 mir.string_bytes = try function.mir_string_bytes.toOwnedSlice(gpa);
1057 mir.locals = try function.mir_locals.toOwnedSlice(gpa);
1058 mir.table = try function.mir_table.toOwnedSlice(gpa);
1059 mir.frame_locs = function.frame_locs.toOwnedSlice();
1060 return mir;
1061}
11421062
1143 error.InvalidInstruction, error.CannotEncode => |e| return function.fail("emit MIR failed: {s} (Zig compiler bug)", .{@errorName(e)}),
1144 else => |e| return function.fail("emit MIR failed: {s}", .{@errorName(e)}),
1063pub fn getTmpMir(cg: *CodeGen) Mir {
1064 return .{
1065 .instructions = cg.mir_instructions.slice(),
1066 .extra = cg.mir_extra.items,
1067 .string_bytes = cg.mir_string_bytes.items,
1068 .locals = cg.mir_locals.items,
1069 .table = cg.mir_table.items,
1070 .frame_locs = cg.frame_locs.slice(),
11451071 };
11461072}
11471073
......@@ -1153,10 +1079,9 @@ pub fn generateLazy(
11531079 code: *std.ArrayListUnmanaged(u8),
11541080 debug_output: link.File.DebugInfoOutput,
11551081) codegen.CodeGenError!void {
1156 const comp = bin_file.comp;
1157 const gpa = comp.gpa;
1082 const gpa = pt.zcu.gpa;
11581083 // This function is for generating global code, so we use the root module.
1159 const mod = comp.root_mod;
1084 const mod = pt.zcu.comp.root_mod;
11601085 var function: CodeGen = .{
11611086 .gpa = gpa,
11621087 .pt = pt,
......@@ -1164,11 +1089,8 @@ pub fn generateLazy(
11641089 .liveness = undefined,
11651090 .target = &mod.resolved_target.result,
11661091 .mod = mod,
1167 .bin_file = bin_file,
1168 .debug_output = debug_output,
11691092 .owner = .{ .lazy_sym = lazy_sym },
11701093 .inline_func = undefined,
1171 .arg_index = undefined,
11721094 .args = undefined,
11731095 .va_info = undefined,
11741096 .ret_mcv = undefined,
......@@ -1179,6 +1101,9 @@ pub fn generateLazy(
11791101 defer {
11801102 function.inst_tracking.deinit(gpa);
11811103 function.mir_instructions.deinit(gpa);
1104 function.mir_string_bytes.deinit(gpa);
1105 function.mir_strings.deinit(gpa);
1106 function.mir_locals.deinit(gpa);
11821107 function.mir_extra.deinit(gpa);
11831108 function.mir_table.deinit(gpa);
11841109 }
......@@ -1194,42 +1119,7 @@ pub fn generateLazy(
11941119 else => |e| return e,
11951120 };
11961121
1197 var mir: Mir = .{
1198 .instructions = function.mir_instructions.toOwnedSlice(),
1199 .extra = try function.mir_extra.toOwnedSlice(gpa),
1200 .table = try function.mir_table.toOwnedSlice(gpa),
1201 .frame_locs = function.frame_locs.toOwnedSlice(),
1202 };
1203 defer mir.deinit(gpa);
1204
1205 var emit: Emit = .{
1206 .air = function.air,
1207 .lower = .{
1208 .bin_file = bin_file,
1209 .target = function.target,
1210 .allocator = gpa,
1211 .mir = mir,
1212 .cc = .auto,
1213 .src_loc = src_loc,
1214 .output_mode = comp.config.output_mode,
1215 .link_mode = comp.config.link_mode,
1216 .pic = mod.pic,
1217 },
1218 .atom_index = function.owner.getSymbolIndex(&function) catch |err| switch (err) {
1219 error.CodegenFail => return error.CodegenFail,
1220 else => |e| return e,
1221 },
1222 .debug_output = debug_output,
1223 .code = code,
1224 .prev_di_loc = undefined, // no debug info yet
1225 .prev_di_pc = undefined, // no debug info yet
1226 };
1227 emit.emitMir() catch |err| switch (err) {
1228 error.LowerFail, error.EmitFail => return function.failMsg(emit.lower.err_msg.?),
1229 error.InvalidInstruction => return function.fail("failed to find a viable x86 instruction (Zig compiler bug)", .{}),
1230 error.CannotEncode => return function.fail("failed to encode x86 instruction (Zig compiler bug)", .{}),
1231 else => |e| return function.fail("failed to emit MIR: {s}", .{@errorName(e)}),
1232 };
1122 try function.getTmpMir().emitLazy(bin_file, pt, src_loc, lazy_sym, code, debug_output);
12331123}
12341124
12351125const FormatNavData = struct {
......@@ -1277,23 +1167,12 @@ fn formatWipMir(
12771167 _: std.fmt.FormatOptions,
12781168 writer: anytype,
12791169) @TypeOf(writer).Error!void {
1280 const comp = data.self.bin_file.comp;
1281 const mod = comp.root_mod;
12821170 var lower: Lower = .{
1283 .bin_file = data.self.bin_file,
12841171 .target = data.self.target,
12851172 .allocator = data.self.gpa,
1286 .mir = .{
1287 .instructions = data.self.mir_instructions.slice(),
1288 .extra = data.self.mir_extra.items,
1289 .table = data.self.mir_table.items,
1290 .frame_locs = (std.MultiArrayList(Mir.FrameLoc){}).slice(),
1291 },
1173 .mir = data.self.getTmpMir(),
12921174 .cc = .auto,
12931175 .src_loc = data.self.src_loc,
1294 .output_mode = comp.config.output_mode,
1295 .link_mode = comp.config.link_mode,
1296 .pic = mod.pic,
12971176 };
12981177 var first = true;
12991178 for ((lower.lowerMir(data.inst) catch |err| switch (err) {
......@@ -1329,7 +1208,9 @@ fn formatWipMir(
13291208 .pseudo_dbg_epilogue_begin_none,
13301209 .pseudo_dbg_enter_block_none,
13311210 .pseudo_dbg_leave_block_none,
1211 .pseudo_dbg_arg_none,
13321212 .pseudo_dbg_var_args_none,
1213 .pseudo_dbg_var_none,
13331214 .pseudo_dead_none,
13341215 => {},
13351216 .pseudo_dbg_line_stmt_line_column, .pseudo_dbg_line_line_column => try writer.print(
......@@ -1337,57 +1218,40 @@ fn formatWipMir(
13371218 mir_inst.data.line_column,
13381219 ),
13391220 .pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try writer.print(" {}", .{
1340 ip.getNav(ip.indexToKey(mir_inst.data.func).func.owner_nav).name.fmt(ip),
1221 ip.getNav(ip.indexToKey(mir_inst.data.ip_index).func.owner_nav).name.fmt(ip),
13411222 }),
1342 .pseudo_dbg_local_a => try writer.print(" {}", .{mir_inst.data.a.air_inst}),
1343 .pseudo_dbg_local_ai_s => try writer.print(" {}, {d}", .{
1344 mir_inst.data.ai.air_inst,
1345 @as(i32, @bitCast(mir_inst.data.ai.i)),
1223 .pseudo_dbg_arg_i_s, .pseudo_dbg_var_i_s => try writer.print(" {d}", .{
1224 @as(i32, @bitCast(mir_inst.data.i.i)),
13461225 }),
1347 .pseudo_dbg_local_ai_u => try writer.print(" {}, {d}", .{
1348 mir_inst.data.ai.air_inst,
1349 mir_inst.data.ai.i,
1226 .pseudo_dbg_arg_i_u, .pseudo_dbg_var_i_u => try writer.print(" {d}", .{
1227 mir_inst.data.i.i,
13501228 }),
1351 .pseudo_dbg_local_ai_64 => try writer.print(" {}, {d}", .{
1352 mir_inst.data.ai.air_inst,
1353 lower.mir.extraData(Mir.Imm64, mir_inst.data.ai.i).data.decode(),
1229 .pseudo_dbg_arg_i_64, .pseudo_dbg_var_i_64 => try writer.print(" {d}", .{
1230 mir_inst.data.i64,
13541231 }),
1355 .pseudo_dbg_local_as => {
1356 const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
1357 .base = .{ .reloc = mir_inst.data.as.sym_index },
1358 }) };
1359 try writer.print(" {}, {}", .{ mir_inst.data.as.air_inst, mem_op.fmt(.m) });
1360 },
1361 .pseudo_dbg_local_aso => {
1362 const sym_off = lower.mir.extraData(bits.SymbolOffset, mir_inst.data.ax.payload).data;
1232 .pseudo_dbg_arg_ro, .pseudo_dbg_var_ro => {
13631233 const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
1364 .base = .{ .reloc = sym_off.sym_index },
1365 .disp = sym_off.off,
1234 .base = .{ .reg = mir_inst.data.ro.reg },
1235 .disp = mir_inst.data.ro.off,
13661236 }) };
1367 try writer.print(" {}, {}", .{ mir_inst.data.ax.air_inst, mem_op.fmt(.m) });
1237 try writer.print(" {}", .{mem_op.fmt(.m)});
13681238 },
1369 .pseudo_dbg_local_aro => {
1370 const air_off = lower.mir.extraData(Mir.AirOffset, mir_inst.data.rx.payload).data;
1239 .pseudo_dbg_arg_fa, .pseudo_dbg_var_fa => {
13711240 const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
1372 .base = .{ .reg = mir_inst.data.rx.r1 },
1373 .disp = air_off.off,
1241 .base = .{ .frame = mir_inst.data.fa.index },
1242 .disp = mir_inst.data.fa.off,
13741243 }) };
1375 try writer.print(" {}, {}", .{ air_off.air_inst, mem_op.fmt(.m) });
1244 try writer.print(" {}", .{mem_op.fmt(.m)});
13761245 },
1377 .pseudo_dbg_local_af => {
1378 const frame_addr = lower.mir.extraData(bits.FrameAddr, mir_inst.data.ax.payload).data;
1379 const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
1380 .base = .{ .frame = frame_addr.index },
1381 .disp = frame_addr.off,
1382 }) };
1383 try writer.print(" {}, {}", .{ mir_inst.data.ax.air_inst, mem_op.fmt(.m) });
1384 },
1385 .pseudo_dbg_local_am => {
1246 .pseudo_dbg_arg_m, .pseudo_dbg_var_m => {
13861247 const mem_op: encoder.Instruction.Operand = .{
1387 .mem = lower.mir.extraData(Mir.Memory, mir_inst.data.ax.payload).data.decode(),
1248 .mem = lower.mir.extraData(Mir.Memory, mir_inst.data.x.payload).data.decode(),
13881249 };
1389 try writer.print(" {}, {}", .{ mir_inst.data.ax.air_inst, mem_op.fmt(.m) });
1250 try writer.print(" {}", .{mem_op.fmt(.m)});
13901251 },
1252 .pseudo_dbg_arg_val, .pseudo_dbg_var_val => try writer.print(" {}", .{
1253 Value.fromInterned(mir_inst.data.ip_index).fmtValue(data.self.pt),
1254 }),
13911255 }
13921256 }
13931257}
......@@ -1440,6 +1304,22 @@ fn addExtraAssumeCapacity(self: *CodeGen, extra: anytype) u32 {
14401304 return result;
14411305}
14421306
1307fn addString(cg: *CodeGen, string: []const u8) Allocator.Error!Mir.NullTerminatedString {
1308 try cg.mir_string_bytes.ensureUnusedCapacity(cg.gpa, string.len + 1);
1309 try cg.mir_strings.ensureUnusedCapacityContext(cg.gpa, 1, .{ .bytes = &cg.mir_string_bytes });
1310
1311 const mir_string_gop = cg.mir_strings.getOrPutAssumeCapacityAdapted(
1312 string,
1313 std.hash_map.StringIndexAdapter{ .bytes = &cg.mir_string_bytes },
1314 );
1315 if (!mir_string_gop.found_existing) {
1316 mir_string_gop.key_ptr.* = @intCast(cg.mir_string_bytes.items.len);
1317 cg.mir_string_bytes.appendSliceAssumeCapacity(string);
1318 cg.mir_string_bytes.appendAssumeCapacity(0);
1319 }
1320 return @enumFromInt(mir_string_gop.key_ptr.*);
1321}
1322
14431323fn asmOps(self: *CodeGen, tag: Mir.Inst.FixedTag, ops: [4]Operand) !void {
14441324 return switch (ops[0]) {
14451325 .none => self.asmOpOnly(tag),
......@@ -1678,124 +1558,6 @@ fn asmPlaceholder(self: *CodeGen) !Mir.Inst.Index {
16781558 });
16791559}
16801560
1681const MirTagAir = enum { dbg_local };
1682
1683fn asmAir(self: *CodeGen, tag: MirTagAir, inst: Air.Inst.Index) !void {
1684 _ = try self.addInst(.{
1685 .tag = .pseudo,
1686 .ops = switch (tag) {
1687 .dbg_local => .pseudo_dbg_local_a,
1688 },
1689 .data = .{ .a = .{ .air_inst = inst } },
1690 });
1691}
1692
1693fn asmAirImmediate(self: *CodeGen, tag: MirTagAir, inst: Air.Inst.Index, imm: Immediate) !void {
1694 switch (imm) {
1695 .signed => |s| _ = try self.addInst(.{
1696 .tag = .pseudo,
1697 .ops = switch (tag) {
1698 .dbg_local => .pseudo_dbg_local_ai_s,
1699 },
1700 .data = .{ .ai = .{
1701 .air_inst = inst,
1702 .i = @bitCast(s),
1703 } },
1704 }),
1705 .unsigned => |u| _ = if (std.math.cast(u32, u)) |small| try self.addInst(.{
1706 .tag = .pseudo,
1707 .ops = switch (tag) {
1708 .dbg_local => .pseudo_dbg_local_ai_u,
1709 },
1710 .data = .{ .ai = .{
1711 .air_inst = inst,
1712 .i = small,
1713 } },
1714 }) else try self.addInst(.{
1715 .tag = .pseudo,
1716 .ops = switch (tag) {
1717 .dbg_local => .pseudo_dbg_local_ai_64,
1718 },
1719 .data = .{ .ai = .{
1720 .air_inst = inst,
1721 .i = try self.addExtra(Mir.Imm64.encode(u)),
1722 } },
1723 }),
1724 .reloc => |sym_off| _ = if (sym_off.off == 0) try self.addInst(.{
1725 .tag = .pseudo,
1726 .ops = switch (tag) {
1727 .dbg_local => .pseudo_dbg_local_as,
1728 },
1729 .data = .{ .as = .{
1730 .air_inst = inst,
1731 .sym_index = sym_off.sym_index,
1732 } },
1733 }) else try self.addInst(.{
1734 .tag = .pseudo,
1735 .ops = switch (tag) {
1736 .dbg_local => .pseudo_dbg_local_aso,
1737 },
1738 .data = .{ .ax = .{
1739 .air_inst = inst,
1740 .payload = try self.addExtra(sym_off),
1741 } },
1742 }),
1743 }
1744}
1745
1746fn asmAirRegisterImmediate(
1747 self: *CodeGen,
1748 tag: MirTagAir,
1749 inst: Air.Inst.Index,
1750 reg: Register,
1751 imm: Immediate,
1752) !void {
1753 _ = try self.addInst(.{
1754 .tag = .pseudo,
1755 .ops = switch (tag) {
1756 .dbg_local => .pseudo_dbg_local_aro,
1757 },
1758 .data = .{ .rx = .{
1759 .r1 = reg,
1760 .payload = try self.addExtra(Mir.AirOffset{
1761 .air_inst = inst,
1762 .off = imm.signed,
1763 }),
1764 } },
1765 });
1766}
1767
1768fn asmAirFrameAddress(
1769 self: *CodeGen,
1770 tag: MirTagAir,
1771 inst: Air.Inst.Index,
1772 frame_addr: bits.FrameAddr,
1773) !void {
1774 _ = try self.addInst(.{
1775 .tag = .pseudo,
1776 .ops = switch (tag) {
1777 .dbg_local => .pseudo_dbg_local_af,
1778 },
1779 .data = .{ .ax = .{
1780 .air_inst = inst,
1781 .payload = try self.addExtra(frame_addr),
1782 } },
1783 });
1784}
1785
1786fn asmAirMemory(self: *CodeGen, tag: MirTagAir, inst: Air.Inst.Index, m: Memory) !void {
1787 _ = try self.addInst(.{
1788 .tag = .pseudo,
1789 .ops = switch (tag) {
1790 .dbg_local => .pseudo_dbg_local_am,
1791 },
1792 .data = .{ .ax = .{
1793 .air_inst = inst,
1794 .payload = try self.addExtra(Mir.Memory.encode(m)),
1795 } },
1796 });
1797}
1798
17991561fn asmOpOnly(self: *CodeGen, tag: Mir.Inst.FixedTag) !void {
18001562 _ = try self.addInst(.{
18011563 .tag = tag[1],
......@@ -1873,21 +1635,36 @@ fn asmImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, imm: Immediate) !void {
18731635 .ops = switch (imm) {
18741636 .signed => .i_s,
18751637 .unsigned => .i_u,
1876 .reloc => .rel,
1638 .nav => .nav,
1639 .uav => .uav,
1640 .lazy_sym => .lazy_sym,
1641 .extern_func => .extern_func,
18771642 },
18781643 .data = switch (imm) {
1879 .reloc => |sym_off| reloc: {
1880 assert(tag[0] == ._);
1881 break :reloc .{ .reloc = sym_off };
1882 },
18831644 .signed, .unsigned => .{ .i = .{
18841645 .fixes = tag[0],
18851646 .i = switch (imm) {
18861647 .signed => |s| @bitCast(s),
18871648 .unsigned => |u| @intCast(u),
1888 .reloc => unreachable,
1649 .nav, .uav, .lazy_sym, .extern_func => unreachable,
18891650 },
18901651 } },
1652 .nav => |nav| switch (tag[0]) {
1653 ._ => .{ .nav = nav },
1654 else => unreachable,
1655 },
1656 .uav => |uav| switch (tag[0]) {
1657 ._ => .{ .uav = uav },
1658 else => unreachable,
1659 },
1660 .lazy_sym => |lazy_sym| switch (tag[0]) {
1661 ._ => .{ .lazy_sym = lazy_sym },
1662 else => unreachable,
1663 },
1664 .extern_func => |extern_func| switch (tag[0]) {
1665 ._ => .{ .extern_func = extern_func },
1666 else => unreachable,
1667 },
18911668 },
18921669 });
18931670}
......@@ -1902,7 +1679,7 @@ fn asmImmediateRegister(self: *CodeGen, tag: Mir.Inst.FixedTag, imm: Immediate,
19021679 .i = @as(u8, switch (imm) {
19031680 .signed => |s| @bitCast(@as(i8, @intCast(s))),
19041681 .unsigned => |u| @intCast(u),
1905 .reloc => unreachable,
1682 .nav, .uav, .lazy_sym, .extern_func => unreachable,
19061683 }),
19071684 } },
19081685 });
......@@ -1917,12 +1694,12 @@ fn asmImmediateImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, imm1: Immediate
19171694 .i1 = switch (imm1) {
19181695 .signed => |s| @bitCast(@as(i16, @intCast(s))),
19191696 .unsigned => |u| @intCast(u),
1920 .reloc => unreachable,
1697 .nav, .uav, .lazy_sym, .extern_func => unreachable,
19211698 },
19221699 .i2 = switch (imm2) {
19231700 .signed => |s| @bitCast(@as(i8, @intCast(s))),
19241701 .unsigned => |u| @intCast(u),
1925 .reloc => unreachable,
1702 .nav, .uav, .lazy_sym, .extern_func => unreachable,
19261703 },
19271704 } },
19281705 });
......@@ -1947,7 +1724,7 @@ fn asmRegisterImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, reg: Register, i
19471724 .{ .ri_u, small }
19481725 else
19491726 .{ .ri_64, try self.addExtra(Mir.Imm64.encode(imm.unsigned)) },
1950 .reloc => unreachable,
1727 .nav, .uav, .lazy_sym, .extern_func => unreachable,
19511728 };
19521729 _ = try self.addInst(.{
19531730 .tag = tag[1],
......@@ -2019,7 +1796,7 @@ fn asmRegisterRegisterRegisterImmediate(
20191796 .i = switch (imm) {
20201797 .signed => |s| @bitCast(@as(i8, @intCast(s))),
20211798 .unsigned => |u| @intCast(u),
2022 .reloc => unreachable,
1799 .nav, .uav, .lazy_sym, .extern_func => unreachable,
20231800 },
20241801 } },
20251802 });
......@@ -2037,7 +1814,7 @@ fn asmRegisterRegisterImmediate(
20371814 .ops = switch (imm) {
20381815 .signed => .rri_s,
20391816 .unsigned => .rri_u,
2040 .reloc => unreachable,
1817 .nav, .uav, .lazy_sym, .extern_func => unreachable,
20411818 },
20421819 .data = .{ .rri = .{
20431820 .fixes = tag[0],
......@@ -2046,7 +1823,7 @@ fn asmRegisterRegisterImmediate(
20461823 .i = switch (imm) {
20471824 .signed => |s| @bitCast(s),
20481825 .unsigned => |u| @intCast(u),
2049 .reloc => unreachable,
1826 .nav, .uav, .lazy_sym, .extern_func => unreachable,
20501827 },
20511828 } },
20521829 });
......@@ -2144,7 +1921,7 @@ fn asmRegisterMemoryImmediate(
21441921 if (switch (imm) {
21451922 .signed => |s| if (std.math.cast(i16, s)) |x| @as(u16, @bitCast(x)) else null,
21461923 .unsigned => |u| std.math.cast(u16, u),
2147 .reloc => unreachable,
1924 .nav, .uav, .lazy_sym, .extern_func => unreachable,
21481925 }) |small_imm| {
21491926 _ = try self.addInst(.{
21501927 .tag = tag[1],
......@@ -2160,7 +1937,7 @@ fn asmRegisterMemoryImmediate(
21601937 const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
21611938 .signed => |s| @bitCast(s),
21621939 .unsigned => |u| @as(u32, @intCast(u)),
2163 .reloc => unreachable,
1940 .nav, .uav, .lazy_sym, .extern_func => unreachable,
21641941 } });
21651942 assert(payload + 1 == try self.addExtra(Mir.Memory.encode(m)));
21661943 _ = try self.addInst(.{
......@@ -2168,7 +1945,7 @@ fn asmRegisterMemoryImmediate(
21681945 .ops = switch (imm) {
21691946 .signed => .rmi_s,
21701947 .unsigned => .rmi_u,
2171 .reloc => unreachable,
1948 .nav, .uav, .lazy_sym, .extern_func => unreachable,
21721949 },
21731950 .data = .{ .rx = .{
21741951 .fixes = tag[0],
......@@ -2216,7 +1993,7 @@ fn asmMemoryImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, m: Memory, imm: Im
22161993 const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
22171994 .signed => |s| @bitCast(s),
22181995 .unsigned => |u| @intCast(u),
2219 .reloc => unreachable,
1996 .nav, .uav, .lazy_sym, .extern_func => unreachable,
22201997 } });
22211998 assert(payload + 1 == try self.addExtra(Mir.Memory.encode(m)));
22221999 _ = try self.addInst(.{
......@@ -2224,7 +2001,7 @@ fn asmMemoryImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, m: Memory, imm: Im
22242001 .ops = switch (imm) {
22252002 .signed => .mi_s,
22262003 .unsigned => .mi_u,
2227 .reloc => unreachable,
2004 .nav, .uav, .lazy_sym, .extern_func => unreachable,
22282005 },
22292006 .data = .{ .x = .{
22302007 .fixes = tag[0],
......@@ -2271,7 +2048,13 @@ fn asmMemoryRegisterImmediate(
22712048 });
22722049}
22732050
2274fn gen(self: *CodeGen) InnerError!void {
2051fn gen(
2052 self: *CodeGen,
2053 zir: *const std.zig.Zir,
2054 func_zir_inst: std.zig.Zir.Inst.Index,
2055 comptime_args: InternPool.Index.Slice,
2056 air_arg_count: u32,
2057) InnerError!void {
22752058 const pt = self.pt;
22762059 const zcu = pt.zcu;
22772060 const fn_info = zcu.typeToFunc(self.fn_type).?;
......@@ -2339,9 +2122,9 @@ fn gen(self: *CodeGen) InnerError!void {
23392122 else => |cc| return self.fail("{s} does not support var args", .{@tagName(cc)}),
23402123 };
23412124
2342 if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_prologue_end_none);
2125 if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_prologue_end_none);
23432126
2344 try self.genBody(self.air.getMainBody());
2127 try self.genMainBody(zir, func_zir_inst, comptime_args, air_arg_count);
23452128
23462129 const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: {
23472130 var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1);
......@@ -2356,7 +2139,7 @@ fn gen(self: *CodeGen) InnerError!void {
23562139 }
23572140 for (self.epilogue_relocs.items) |epilogue_reloc| self.performReloc(epilogue_reloc);
23582141
2359 if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);
2142 if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);
23602143 const backpatch_stack_dealloc = try self.asmPlaceholder();
23612144 const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder();
23622145 try self.asmRegister(.{ ._, .pop }, .rbp);
......@@ -2475,21 +2258,88 @@ fn gen(self: *CodeGen) InnerError!void {
24752258 });
24762259 }
24772260 } else {
2478 if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_prologue_end_none);
2479 try self.genBody(self.air.getMainBody());
2480 if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);
2261 if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_prologue_end_none);
2262 try self.genMainBody(zir, func_zir_inst, comptime_args, air_arg_count);
2263 if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);
2264 }
2265}
2266
2267fn genMainBody(
2268 cg: *CodeGen,
2269 zir: *const std.zig.Zir,
2270 func_zir_inst: std.zig.Zir.Inst.Index,
2271 comptime_args: InternPool.Index.Slice,
2272 air_arg_count: u32,
2273) InnerError!void {
2274 const pt = cg.pt;
2275 const zcu = pt.zcu;
2276 const ip = &zcu.intern_pool;
2277
2278 const main_body = cg.air.getMainBody();
2279 const air_args_body = main_body[0..air_arg_count];
2280 try cg.genBody(air_args_body);
2281
2282 if (!cg.mod.strip) {
2283 var air_arg_index: usize = 0;
2284 const fn_info = zcu.typeToFunc(cg.fn_type).?;
2285 var fn_param_index: usize = 0;
2286 var zir_param_index: usize = 0;
2287 for (zir.getParamBody(func_zir_inst)) |zir_param_inst| {
2288 const name = switch (zir.getParamName(zir_param_inst) orelse break) {
2289 .empty => .none,
2290 else => |zir_name| try cg.addString(zir.nullTerminatedString(zir_name)),
2291 };
2292 defer zir_param_index += 1;
2293
2294 if (comptime_args.len > 0) switch (comptime_args.get(ip)[zir_param_index]) {
2295 .none => {},
2296 else => |comptime_arg| {
2297 try cg.mir_locals.append(cg.gpa, .{ .name = name, .type = ip.typeOf(comptime_arg) });
2298 _ = try cg.addInst(.{
2299 .tag = .pseudo,
2300 .ops = .pseudo_dbg_arg_val,
2301 .data = .{ .ip_index = comptime_arg },
2302 });
2303 continue;
2304 },
2305 };
2306
2307 const arg_ty = fn_info.param_types.get(ip)[fn_param_index];
2308 try cg.mir_locals.append(cg.gpa, .{ .name = name, .type = arg_ty });
2309 fn_param_index += 1;
2310
2311 if (air_arg_index == air_args_body.len) {
2312 try cg.asmPseudo(.pseudo_dbg_arg_none);
2313 continue;
2314 }
2315 const air_arg_inst = air_args_body[air_arg_index];
2316 const air_arg_data = cg.air.instructions.items(.data)[air_arg_index].arg;
2317 if (air_arg_data.zir_param_index != zir_param_index) {
2318 try cg.asmPseudo(.pseudo_dbg_arg_none);
2319 continue;
2320 }
2321 air_arg_index += 1;
2322 try cg.genLocalDebugInfo(
2323 .arg,
2324 .fromInterned(arg_ty),
2325 cg.getResolvedInstValue(air_arg_inst).short,
2326 );
2327 }
2328 if (fn_info.is_var_args) try cg.asmPseudo(.pseudo_dbg_var_args_none);
24812329 }
2330
2331 try cg.genBody(main_body[air_arg_count..]);
24822332}
24832333
2484fn checkInvariantsAfterAirInst(self: *CodeGen) void {
2485 assert(!self.register_manager.lockedRegsExist());
2334fn checkInvariantsAfterAirInst(cg: *CodeGen) void {
2335 assert(!cg.register_manager.lockedRegsExist());
24862336
24872337 if (std.debug.runtime_safety) {
24882338 // check consistency of tracked registers
2489 var it = self.register_manager.free_registers.iterator(.{ .kind = .unset });
2339 var it = cg.register_manager.free_registers.iterator(.{ .kind = .unset });
24902340 while (it.next()) |index| {
2491 const tracked_inst = self.register_manager.registers[index];
2492 const tracking = self.getResolvedInstValue(tracked_inst);
2341 const tracked_inst = cg.register_manager.registers[index];
2342 const tracking = cg.getResolvedInstValue(tracked_inst);
24932343 for (tracking.getRegs()) |reg| {
24942344 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
24952345 } else unreachable; // tracked register not in use
......@@ -2497,10 +2347,10 @@ fn checkInvariantsAfterAirInst(self: *CodeGen) void {
24972347 }
24982348}
24992349
2500fn genBodyBlock(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2501 if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_enter_block_none);
2502 try self.genBody(body);
2503 if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_leave_block_none);
2350fn genBodyBlock(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2351 if (!cg.mod.strip) try cg.asmPseudo(.pseudo_dbg_enter_block_none);
2352 try cg.genBody(body);
2353 if (!cg.mod.strip) try cg.asmPseudo(.pseudo_dbg_leave_block_none);
25042354}
25052355
25062356fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
......@@ -2512,25 +2362,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
25122362 const air_datas = cg.air.instructions.items(.data);
25132363 const use_old = cg.target.ofmt == .coff;
25142364
2515 cg.arg_index = 0;
2516 for (body) |inst| switch (air_tags[@intFromEnum(inst)]) {
2517 .arg => {
2518 wip_mir_log.debug("{}", .{cg.fmtAir(inst)});
2519 verbose_tracking_log.debug("{}", .{cg.fmtTracking()});
2520
2521 cg.reused_operands = .initEmpty();
2522 try cg.inst_tracking.ensureUnusedCapacity(cg.gpa, 1);
2523
2524 try cg.airArg(inst);
2525
2526 try cg.resetTemps(@enumFromInt(0));
2527 cg.checkInvariantsAfterAirInst();
2528 },
2529 else => break,
2530 };
2531
2532 if (cg.arg_index == 0) try cg.airDbgVarArgs();
2533 cg.arg_index = 0;
25342365 for (body) |inst| {
25352366 if (cg.liveness.isUnused(inst) and !cg.air.mustLower(inst, ip)) continue;
25362367 wip_mir_log.debug("{}", .{cg.fmtAir(inst)});
......@@ -2544,20 +2375,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
25442375 .shuffle_one, .shuffle_two => @panic("x86_64 TODO: shuffle_one/shuffle_two"),
25452376 // zig fmt: on
25462377
2547 .arg => if (cg.debug_output != .none) {
2548 // skip zero-bit arguments as they don't have a corresponding arg instruction
2549 var arg_index = cg.arg_index;
2550 while (cg.args[arg_index] == .none) arg_index += 1;
2551 cg.arg_index = arg_index + 1;
2552
2553 const name = air_datas[@intFromEnum(inst)].arg.name;
2554 if (name != .none) try cg.genLocalDebugInfo(inst, cg.getResolvedInstValue(inst).short);
2555 if (cg.liveness.isUnused(inst)) try cg.processDeath(inst);
2556
2557 for (cg.args[arg_index + 1 ..]) |arg| {
2558 if (arg != .none) break;
2559 } else try cg.airDbgVarArgs();
2560 },
2378 .arg => try cg.airArg(inst),
25612379 .add, .add_optimized, .add_wrap => |air_tag| if (use_old) try cg.airBinOp(inst, switch (air_tag) {
25622380 else => unreachable,
25632381 .add, .add_optimized => .add,
......@@ -3577,7 +3395,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
35773395 },
35783396 .call_frame = .{ .alignment = .@"16" },
35793397 .extra_temps = .{
3580 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
3398 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
35813399 .unused,
35823400 .unused,
35833401 .unused,
......@@ -3709,7 +3527,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37093527 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
37103528 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
37113529 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
3712 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
3530 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
37133531 .unused,
37143532 .unused,
37153533 .unused,
......@@ -3745,7 +3563,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37453563 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
37463564 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
37473565 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
3748 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
3566 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
37493567 .unused,
37503568 .unused,
37513569 .unused,
......@@ -3782,7 +3600,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37823600 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
37833601 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
37843602 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
3785 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
3603 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
37863604 .{ .type = .f16, .kind = .{ .reg = .ax } },
37873605 .unused,
37883606 .unused,
......@@ -3822,7 +3640,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
38223640 .{ .type = .f32, .kind = .mem },
38233641 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
38243642 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
3825 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
3643 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
38263644 .unused,
38273645 .unused,
38283646 .unused,
......@@ -4307,7 +4125,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
43074125 },
43084126 .call_frame = .{ .alignment = .@"16" },
43094127 .extra_temps = .{
4310 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
4128 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
43114129 .unused,
43124130 .unused,
43134131 .unused,
......@@ -4339,7 +4157,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
43394157 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
43404158 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
43414159 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
4342 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
4160 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
43434161 .unused,
43444162 .unused,
43454163 .unused,
......@@ -4374,7 +4192,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
43744192 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
43754193 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
43764194 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
4377 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
4195 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
43784196 .unused,
43794197 .unused,
43804198 .unused,
......@@ -4409,7 +4227,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
44094227 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
44104228 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
44114229 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
4412 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
4230 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
44134231 .unused,
44144232 .unused,
44154233 .unused,
......@@ -14009,7 +13827,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1400913827 },
1401013828 .call_frame = .{ .alignment = .@"16" },
1401113829 .extra_temps = .{
14012 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subhf3" } } },
13830 .{ .type = .usize, .kind = .{ .extern_func = "__subhf3" } },
1401313831 .unused,
1401413832 .unused,
1401513833 .unused,
......@@ -14141,7 +13959,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1414113959 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
1414213960 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
1414313961 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
14144 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subhf3" } } },
13962 .{ .type = .usize, .kind = .{ .extern_func = "__subhf3" } },
1414513963 .unused,
1414613964 .unused,
1414713965 .unused,
......@@ -14177,7 +13995,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1417713995 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
1417813996 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
1417913997 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
14180 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subhf3" } } },
13998 .{ .type = .usize, .kind = .{ .extern_func = "__subhf3" } },
1418113999 .unused,
1418214000 .unused,
1418314001 .unused,
......@@ -14214,7 +14032,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1421414032 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
1421514033 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
1421614034 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
14217 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subhf3" } } },
14035 .{ .type = .usize, .kind = .{ .extern_func = "__subhf3" } },
1421814036 .{ .type = .f16, .kind = .{ .reg = .ax } },
1421914037 .unused,
1422014038 .unused,
......@@ -14254,7 +14072,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1425414072 .{ .type = .f32, .kind = .mem },
1425514073 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
1425614074 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
14257 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subhf3" } } },
14075 .{ .type = .usize, .kind = .{ .extern_func = "__subhf3" } },
1425814076 .unused,
1425914077 .unused,
1426014078 .unused,
......@@ -14756,7 +14574,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1475614574 },
1475714575 .call_frame = .{ .alignment = .@"16" },
1475814576 .extra_temps = .{
14759 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subtf3" } } },
14577 .{ .type = .usize, .kind = .{ .extern_func = "__subtf3" } },
1476014578 .unused,
1476114579 .unused,
1476214580 .unused,
......@@ -14788,7 +14606,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1478814606 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
1478914607 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
1479014608 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
14791 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subtf3" } } },
14609 .{ .type = .usize, .kind = .{ .extern_func = "__subtf3" } },
1479214610 .unused,
1479314611 .unused,
1479414612 .unused,
......@@ -14823,7 +14641,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1482314641 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
1482414642 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
1482514643 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
14826 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subtf3" } } },
14644 .{ .type = .usize, .kind = .{ .extern_func = "__subtf3" } },
1482714645 .unused,
1482814646 .unused,
1482914647 .unused,
......@@ -14858,7 +14676,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1485814676 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
1485914677 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
1486014678 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
14861 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subtf3" } } },
14679 .{ .type = .usize, .kind = .{ .extern_func = "__subtf3" } },
1486214680 .unused,
1486314681 .unused,
1486414682 .unused,
......@@ -23539,7 +23357,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2353923357 },
2354023358 .call_frame = .{ .alignment = .@"16" },
2354123359 .extra_temps = .{
23542 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
23360 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
2354323361 .unused,
2354423362 .unused,
2354523363 .unused,
......@@ -23671,7 +23489,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2367123489 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
2367223490 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
2367323491 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
23674 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
23492 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
2367523493 .unused,
2367623494 .unused,
2367723495 .unused,
......@@ -23707,7 +23525,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2370723525 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
2370823526 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
2370923527 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
23710 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
23528 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
2371123529 .unused,
2371223530 .unused,
2371323531 .unused,
......@@ -23744,7 +23562,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2374423562 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
2374523563 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
2374623564 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
23747 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
23565 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
2374823566 .{ .type = .f16, .kind = .{ .reg = .ax } },
2374923567 .unused,
2375023568 .unused,
......@@ -23784,7 +23602,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2378423602 .{ .type = .f32, .kind = .mem },
2378523603 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
2378623604 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
23787 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
23605 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
2378823606 .unused,
2378923607 .unused,
2379023608 .unused,
......@@ -24269,7 +24087,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2426924087 },
2427024088 .call_frame = .{ .alignment = .@"16" },
2427124089 .extra_temps = .{
24272 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
24090 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
2427324091 .unused,
2427424092 .unused,
2427524093 .unused,
......@@ -24301,7 +24119,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2430124119 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
2430224120 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
2430324121 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
24304 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
24122 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
2430524123 .unused,
2430624124 .unused,
2430724125 .unused,
......@@ -24336,7 +24154,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2433624154 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
2433724155 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
2433824156 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
24339 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
24157 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
2434024158 .unused,
2434124159 .unused,
2434224160 .unused,
......@@ -24371,7 +24189,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2437124189 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
2437224190 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
2437324191 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
24374 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
24192 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
2437524193 .unused,
2437624194 .unused,
2437724195 .unused,
......@@ -26231,7 +26049,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2623126049 },
2623226050 .call_frame = .{ .alignment = .@"16" },
2623326051 .extra_temps = .{
26234 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
26052 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
2623526053 .unused,
2623626054 .unused,
2623726055 .unused,
......@@ -26363,7 +26181,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2636326181 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
2636426182 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
2636526183 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
26366 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
26184 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
2636726185 .unused,
2636826186 .unused,
2636926187 .unused,
......@@ -26399,7 +26217,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2639926217 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
2640026218 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
2640126219 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
26402 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
26220 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
2640326221 .unused,
2640426222 .unused,
2640526223 .unused,
......@@ -26436,7 +26254,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2643626254 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
2643726255 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
2643826256 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
26439 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
26257 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
2644026258 .{ .type = .f16, .kind = .{ .reg = .ax } },
2644126259 .unused,
2644226260 .unused,
......@@ -26476,7 +26294,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2647626294 .{ .type = .f32, .kind = .mem },
2647726295 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
2647826296 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
26479 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
26297 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
2648026298 .unused,
2648126299 .unused,
2648226300 .unused,
......@@ -26961,7 +26779,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2696126779 },
2696226780 .call_frame = .{ .alignment = .@"16" },
2696326781 .extra_temps = .{
26964 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
26782 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
2696526783 .unused,
2696626784 .unused,
2696726785 .unused,
......@@ -26993,7 +26811,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2699326811 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
2699426812 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
2699526813 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
26996 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
26814 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
2699726815 .unused,
2699826816 .unused,
2699926817 .unused,
......@@ -27028,7 +26846,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2702826846 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
2702926847 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
2703026848 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
27031 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
26849 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
2703226850 .unused,
2703326851 .unused,
2703426852 .unused,
......@@ -27063,7 +26881,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2706326881 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
2706426882 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
2706526883 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
27066 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
26884 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
2706726885 .unused,
2706826886 .unused,
2706926887 .unused,
......@@ -32371,7 +32189,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3237132189 },
3237232190 .call_frame = .{ .alignment = .@"16" },
3237332191 .extra_temps = .{
32374 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
32192 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
3237532193 .unused,
3237632194 .unused,
3237732195 .unused,
......@@ -32503,7 +32321,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3250332321 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3250432322 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3250532323 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
32506 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
32324 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
3250732325 .unused,
3250832326 .unused,
3250932327 .unused,
......@@ -32539,7 +32357,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3253932357 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3254032358 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3254132359 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
32542 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
32360 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
3254332361 .unused,
3254432362 .unused,
3254532363 .unused,
......@@ -32576,7 +32394,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3257632394 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3257732395 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3257832396 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
32579 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
32397 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
3258032398 .{ .type = .f16, .kind = .{ .reg = .ax } },
3258132399 .unused,
3258232400 .unused,
......@@ -32616,7 +32434,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3261632434 .{ .type = .f32, .kind = .mem },
3261732435 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3261832436 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
32619 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
32437 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
3262032438 .unused,
3262132439 .unused,
3262232440 .unused,
......@@ -33119,7 +32937,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3311932937 },
3312032938 .call_frame = .{ .alignment = .@"16" },
3312132939 .extra_temps = .{
33122 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
32940 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3312332941 .unused,
3312432942 .unused,
3312532943 .unused,
......@@ -33151,7 +32969,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3315132969 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3315232970 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3315332971 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
33154 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
32972 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3315532973 .unused,
3315632974 .unused,
3315732975 .unused,
......@@ -33186,7 +33004,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3318633004 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3318733005 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3318833006 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
33189 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
33007 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3319033008 .unused,
3319133009 .unused,
3319233010 .unused,
......@@ -33221,7 +33039,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3322133039 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3322233040 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3322333041 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
33224 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
33042 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
3322533043 .unused,
3322633044 .unused,
3322733045 .unused,
......@@ -33305,8 +33123,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3330533123 },
3330633124 .call_frame = .{ .alignment = .@"16" },
3330733125 .extra_temps = .{
33308 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
33309 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunch" } } },
33126 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
33127 .{ .type = .usize, .kind = .{ .extern_func = "__trunch" } },
3331033128 .unused,
3331133129 .unused,
3331233130 .unused,
......@@ -33447,8 +33265,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3344733265 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3344833266 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3344933267 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
33450 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
33451 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunch" } } },
33268 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
33269 .{ .type = .usize, .kind = .{ .extern_func = "__trunch" } },
3345233270 .unused,
3345333271 .unused,
3345433272 .unused,
......@@ -33484,8 +33302,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3348433302 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3348533303 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3348633304 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
33487 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
33488 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunch" } } },
33305 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
33306 .{ .type = .usize, .kind = .{ .extern_func = "__trunch" } },
3348933307 .unused,
3349033308 .unused,
3349133309 .unused,
......@@ -33522,8 +33340,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3352233340 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3352333341 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3352433342 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
33525 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
33526 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunch" } } },
33343 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
33344 .{ .type = .usize, .kind = .{ .extern_func = "__trunch" } },
3352733345 .{ .type = .f16, .kind = .{ .reg = .ax } },
3352833346 .unused,
3352933347 .unused,
......@@ -33563,8 +33381,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3356333381 .{ .type = .f32, .kind = .mem },
3356433382 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3356533383 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
33566 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
33567 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunch" } } },
33384 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
33385 .{ .type = .usize, .kind = .{ .extern_func = "__trunch" } },
3356833386 .unused,
3356933387 .unused,
3357033388 .unused,
......@@ -33632,7 +33450,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3363233450 },
3363333451 .call_frame = .{ .alignment = .@"16" },
3363433452 .extra_temps = .{
33635 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "truncf" } } },
33453 .{ .type = .usize, .kind = .{ .extern_func = "truncf" } },
3363633454 .unused,
3363733455 .unused,
3363833456 .unused,
......@@ -33696,7 +33514,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3369633514 .extra_temps = .{
3369733515 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3369833516 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
33699 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "truncf" } } },
33517 .{ .type = .usize, .kind = .{ .extern_func = "truncf" } },
3370033518 .unused,
3370133519 .unused,
3370233520 .unused,
......@@ -33845,7 +33663,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3384533663 },
3384633664 .call_frame = .{ .alignment = .@"16" },
3384733665 .extra_temps = .{
33848 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "trunc" } } },
33666 .{ .type = .usize, .kind = .{ .extern_func = "trunc" } },
3384933667 .unused,
3385033668 .unused,
3385133669 .unused,
......@@ -33875,8 +33693,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3387533693 },
3387633694 .call_frame = .{ .alignment = .@"16" },
3387733695 .extra_temps = .{
33878 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divdf3" } } },
33879 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "trunc" } } },
33696 .{ .type = .usize, .kind = .{ .extern_func = "__divdf3" } },
33697 .{ .type = .usize, .kind = .{ .extern_func = "trunc" } },
3388033698 .unused,
3388133699 .unused,
3388233700 .unused,
......@@ -34023,7 +33841,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3402333841 .extra_temps = .{
3402433842 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3402533843 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
34026 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "trunc" } } },
33844 .{ .type = .usize, .kind = .{ .extern_func = "trunc" } },
3402733845 .unused,
3402833846 .unused,
3402933847 .unused,
......@@ -34059,8 +33877,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3405933877 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3406033878 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
3406133879 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
34062 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divdf3" } } },
34063 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "trunc" } } },
33880 .{ .type = .usize, .kind = .{ .extern_func = "__divdf3" } },
33881 .{ .type = .usize, .kind = .{ .extern_func = "trunc" } },
3406433882 .unused,
3406533883 .unused,
3406633884 .unused,
......@@ -34097,7 +33915,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3409733915 .{ .type = .f80, .kind = .{ .reg = .st6 } },
3409833916 .{ .type = .f80, .kind = .{ .reg = .st7 } },
3409933917 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
34100 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncx" } } },
33918 .{ .type = .usize, .kind = .{ .extern_func = "__truncx" } },
3410133919 .unused,
3410233920 .unused,
3410333921 .unused,
......@@ -34131,7 +33949,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3413133949 .{ .type = .f80, .kind = .{ .reg = .st6 } },
3413233950 .{ .type = .f80, .kind = .{ .reg = .st7 } },
3413333951 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
34134 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncx" } } },
33952 .{ .type = .usize, .kind = .{ .extern_func = "__truncx" } },
3413533953 .unused,
3413633954 .unused,
3413733955 .unused,
......@@ -34165,8 +33983,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3416533983 },
3416633984 .call_frame = .{ .alignment = .@"16" },
3416733985 .extra_temps = .{
34168 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
34169 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "truncq" } } },
33986 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
33987 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
3417033988 .unused,
3417133989 .unused,
3417233990 .unused,
......@@ -34198,8 +34016,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3419834016 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3419934017 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3420034018 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
34201 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
34202 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "truncq" } } },
34019 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34020 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
3420334021 .unused,
3420434022 .unused,
3420534023 .unused,
......@@ -34234,8 +34052,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3423434052 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3423534053 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3423634054 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
34237 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
34238 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "truncq" } } },
34055 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34056 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
3423934057 .unused,
3424034058 .unused,
3424134059 .unused,
......@@ -34270,8 +34088,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3427034088 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3427134089 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3427234090 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
34273 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
34274 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "truncq" } } },
34091 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
34092 .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
3427534093 .unused,
3427634094 .unused,
3427734095 .unused,
......@@ -34361,12 +34179,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3436134179 },
3436234180 .call_frame = .{ .alignment = .@"16" },
3436334181 .extra_temps = .{
34364 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
34365 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
34182 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
34183 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3436634184 else => unreachable,
3436734185 .zero => "__trunch",
3436834186 .down => "__floorh",
34369 } } } },
34187 } } },
3437034188 .unused,
3437134189 .unused,
3437234190 .unused,
......@@ -34501,12 +34319,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3450134319 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3450234320 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3450334321 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
34504 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
34505 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
34322 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
34323 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3450634324 else => unreachable,
3450734325 .zero => "__trunch",
3450834326 .down => "__floorh",
34509 } } } },
34327 } } },
3451034328 .unused,
3451134329 .unused,
3451234330 .unused,
......@@ -34542,12 +34360,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3454234360 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3454334361 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3454434362 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
34545 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
34546 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
34363 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
34364 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3454734365 else => unreachable,
3454834366 .zero => "__trunch",
3454934367 .down => "__floorh",
34550 } } } },
34368 } } },
3455134369 .unused,
3455234370 .unused,
3455334371 .unused,
......@@ -34584,12 +34402,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3458434402 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3458534403 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3458634404 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
34587 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
34588 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
34405 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
34406 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3458934407 else => unreachable,
3459034408 .zero => "__trunch",
3459134409 .down => "__floorh",
34592 } } } },
34410 } } },
3459334411 .{ .type = .f16, .kind = .{ .reg = .ax } },
3459434412 .unused,
3459534413 .unused,
......@@ -34629,12 +34447,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3462934447 .{ .type = .f32, .kind = .mem },
3463034448 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3463134449 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
34632 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
34633 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
34450 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
34451 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3463434452 else => unreachable,
3463534453 .zero => "__trunch",
3463634454 .down => "__floorh",
34637 } } } },
34455 } } },
3463834456 .unused,
3463934457 .unused,
3464034458 .unused,
......@@ -34702,11 +34520,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3470234520 },
3470334521 .call_frame = .{ .alignment = .@"16" },
3470434522 .extra_temps = .{
34705 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
34523 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3470634524 else => unreachable,
3470734525 .zero => "truncf",
3470834526 .down => "floorf",
34709 } } } },
34527 } } },
3471034528 .unused,
3471134529 .unused,
3471234530 .unused,
......@@ -34770,11 +34588,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3477034588 .extra_temps = .{
3477134589 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3477234590 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
34773 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
34591 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3477434592 else => unreachable,
3477534593 .zero => "truncf",
3477634594 .down => "floorf",
34777 } } } },
34595 } } },
3477834596 .unused,
3477934597 .unused,
3478034598 .unused,
......@@ -34923,11 +34741,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3492334741 },
3492434742 .call_frame = .{ .alignment = .@"16" },
3492534743 .extra_temps = .{
34926 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
34744 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3492734745 else => unreachable,
3492834746 .zero => "trunc",
3492934747 .down => "floor",
34930 } } } },
34748 } } },
3493134749 .unused,
3493234750 .unused,
3493334751 .unused,
......@@ -34957,12 +34775,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3495734775 },
3495834776 .call_frame = .{ .alignment = .@"16" },
3495934777 .extra_temps = .{
34960 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divdf3" } } },
34961 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
34778 .{ .type = .usize, .kind = .{ .extern_func = "__divdf3" } },
34779 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3496234780 else => unreachable,
3496334781 .zero => "trunc",
3496434782 .down => "floor",
34965 } } } },
34783 } } },
3496634784 .unused,
3496734785 .unused,
3496834786 .unused,
......@@ -35109,11 +34927,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3510934927 .extra_temps = .{
3511034928 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3511134929 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
35112 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
34930 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3511334931 else => unreachable,
3511434932 .zero => "trunc",
3511534933 .down => "floor",
35116 } } } },
34934 } } },
3511734935 .unused,
3511834936 .unused,
3511934937 .unused,
......@@ -35149,12 +34967,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3514934967 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3515034968 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
3515134969 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
35152 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divdf3" } } },
35153 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
34970 .{ .type = .usize, .kind = .{ .extern_func = "__divdf3" } },
34971 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3515434972 else => unreachable,
3515534973 .zero => "trunc",
3515634974 .down => "floor",
35157 } } } },
34975 } } },
3515834976 .unused,
3515934977 .unused,
3516034978 .unused,
......@@ -35191,11 +35009,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3519135009 .{ .type = .f80, .kind = .{ .reg = .st6 } },
3519235010 .{ .type = .f80, .kind = .{ .reg = .st7 } },
3519335011 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
35194 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
35012 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3519535013 else => unreachable,
3519635014 .zero => "__truncx",
3519735015 .down => "__floorx",
35198 } } } },
35016 } } },
3519935017 .unused,
3520035018 .unused,
3520135019 .unused,
......@@ -35227,11 +35045,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3522735045 .extra_temps = .{
3522835046 .{ .type = .f80, .kind = .{ .reg = .st7 } },
3522935047 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
35230 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
35048 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3523135049 else => unreachable,
3523235050 .zero => "__truncx",
3523335051 .down => "__floorx",
35234 } } } },
35052 } } },
3523535053 .unused,
3523635054 .unused,
3523735055 .unused,
......@@ -35264,11 +35082,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3526435082 .extra_temps = .{
3526535083 .{ .type = .f80, .kind = .{ .reg = .st7 } },
3526635084 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
35267 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
35085 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3526835086 else => unreachable,
3526935087 .zero => "__truncx",
3527035088 .down => "__floorx",
35271 } } } },
35089 } } },
3527235090 .unused,
3527335091 .unused,
3527435092 .unused,
......@@ -35302,11 +35120,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3530235120 .{ .type = .f80, .kind = .{ .reg = .st6 } },
3530335121 .{ .type = .f80, .kind = .{ .reg = .st7 } },
3530435122 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
35305 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
35123 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3530635124 else => unreachable,
3530735125 .zero => "__truncx",
3530835126 .down => "__floorx",
35309 } } } },
35127 } } },
3531035128 .unused,
3531135129 .unused,
3531235130 .unused,
......@@ -35340,12 +35158,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3534035158 },
3534135159 .call_frame = .{ .alignment = .@"16" },
3534235160 .extra_temps = .{
35343 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
35344 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
35161 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
35162 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3534535163 else => unreachable,
3534635164 .zero => "truncq",
3534735165 .down => "floorq",
35348 } } } },
35166 } } },
3534935167 .unused,
3535035168 .unused,
3535135169 .unused,
......@@ -35377,12 +35195,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3537735195 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3537835196 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3537935197 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
35380 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
35381 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
35198 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
35199 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3538235200 else => unreachable,
3538335201 .zero => "truncq",
3538435202 .down => "floorq",
35385 } } } },
35203 } } },
3538635204 .unused,
3538735205 .unused,
3538835206 .unused,
......@@ -35417,12 +35235,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3541735235 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3541835236 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3541935237 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
35420 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
35421 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
35238 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
35239 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3542235240 else => unreachable,
3542335241 .zero => "truncq",
3542435242 .down => "floorq",
35425 } } } },
35243 } } },
3542635244 .unused,
3542735245 .unused,
3542835246 .unused,
......@@ -35457,12 +35275,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3545735275 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3545835276 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3545935277 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
35460 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
35461 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
35278 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
35279 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
3546235280 else => unreachable,
3546335281 .zero => "truncq",
3546435282 .down => "floorq",
35465 } } } },
35283 } } },
3546635284 .unused,
3546735285 .unused,
3546835286 .unused,
......@@ -35649,9 +35467,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3564935467 .extra_temps = .{
3565035468 .{ .type = .i128, .kind = .{ .param_gpr_pair = .{ .cc = .ccc, .at = 0 } } },
3565135469 .{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
35652 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modti3" } } },
35470 .{ .type = .usize, .kind = .{ .extern_func = "__modti3" } },
3565335471 .{ .type = .i64, .kind = .{ .rc = .general_purpose } },
35654 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divti3" } } },
35472 .{ .type = .usize, .kind = .{ .extern_func = "__divti3" } },
3565535473 .unused,
3565635474 .unused,
3565735475 .unused,
......@@ -35700,9 +35518,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3570035518 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
3570135519 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
3570235520 .{ .type = .i32, .kind = .{ .rc = .general_purpose } },
35703 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divei4" } } },
35521 .{ .type = .usize, .kind = .{ .extern_func = "__divei4" } },
3570435522 .{ .kind = .{ .mem_of_type = .dst0 } },
35705 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modei4" } } },
35523 .{ .type = .usize, .kind = .{ .extern_func = "__modei4" } },
3570635524 .unused,
3570735525 .unused,
3570835526 .unused,
......@@ -35781,8 +35599,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3578135599 },
3578235600 .call_frame = .{ .alignment = .@"16" },
3578335601 .extra_temps = .{
35784 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
35785 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorh" } } },
35602 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
35603 .{ .type = .usize, .kind = .{ .extern_func = "__floorh" } },
3578635604 .unused,
3578735605 .unused,
3578835606 .unused,
......@@ -35923,8 +35741,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3592335741 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3592435742 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3592535743 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
35926 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
35927 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorh" } } },
35744 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
35745 .{ .type = .usize, .kind = .{ .extern_func = "__floorh" } },
3592835746 .unused,
3592935747 .unused,
3593035748 .unused,
......@@ -35960,8 +35778,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3596035778 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3596135779 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3596235780 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
35963 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
35964 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorh" } } },
35781 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
35782 .{ .type = .usize, .kind = .{ .extern_func = "__floorh" } },
3596535783 .unused,
3596635784 .unused,
3596735785 .unused,
......@@ -35998,8 +35816,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3599835816 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3599935817 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3600035818 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
36001 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
36002 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorh" } } },
35819 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
35820 .{ .type = .usize, .kind = .{ .extern_func = "__floorh" } },
3600335821 .{ .type = .f16, .kind = .{ .reg = .ax } },
3600435822 .unused,
3600535823 .unused,
......@@ -36039,8 +35857,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3603935857 .{ .type = .f32, .kind = .mem },
3604035858 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3604135859 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
36042 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
36043 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorh" } } },
35860 .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
35861 .{ .type = .usize, .kind = .{ .extern_func = "__floorh" } },
3604435862 .unused,
3604535863 .unused,
3604635864 .unused,
......@@ -36108,7 +35926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3610835926 },
3610935927 .call_frame = .{ .alignment = .@"16" },
3611035928 .extra_temps = .{
36111 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floorf" } } },
35929 .{ .type = .usize, .kind = .{ .extern_func = "floorf" } },
3611235930 .unused,
3611335931 .unused,
3611435932 .unused,
......@@ -36172,7 +35990,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3617235990 .extra_temps = .{
3617335991 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3617435992 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
36175 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floorf" } } },
35993 .{ .type = .usize, .kind = .{ .extern_func = "floorf" } },
3617635994 .unused,
3617735995 .unused,
3617835996 .unused,
......@@ -36321,7 +36139,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3632136139 },
3632236140 .call_frame = .{ .alignment = .@"16" },
3632336141 .extra_temps = .{
36324 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floor" } } },
36142 .{ .type = .usize, .kind = .{ .extern_func = "floor" } },
3632536143 .unused,
3632636144 .unused,
3632736145 .unused,
......@@ -36351,8 +36169,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3635136169 },
3635236170 .call_frame = .{ .alignment = .@"16" },
3635336171 .extra_temps = .{
36354 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divdf3" } } },
36355 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floor" } } },
36172 .{ .type = .usize, .kind = .{ .extern_func = "__divdf3" } },
36173 .{ .type = .usize, .kind = .{ .extern_func = "floor" } },
3635636174 .unused,
3635736175 .unused,
3635836176 .unused,
......@@ -36499,7 +36317,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3649936317 .extra_temps = .{
3650036318 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3650136319 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
36502 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floor" } } },
36320 .{ .type = .usize, .kind = .{ .extern_func = "floor" } },
3650336321 .unused,
3650436322 .unused,
3650536323 .unused,
......@@ -36535,8 +36353,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3653536353 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3653636354 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
3653736355 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
36538 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divdf3" } } },
36539 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floor" } } },
36356 .{ .type = .usize, .kind = .{ .extern_func = "__divdf3" } },
36357 .{ .type = .usize, .kind = .{ .extern_func = "floor" } },
3654036358 .unused,
3654136359 .unused,
3654236360 .unused,
......@@ -36573,7 +36391,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3657336391 .{ .type = .f80, .kind = .{ .reg = .st6 } },
3657436392 .{ .type = .f80, .kind = .{ .reg = .st7 } },
3657536393 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
36576 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorx" } } },
36394 .{ .type = .usize, .kind = .{ .extern_func = "__floorx" } },
3657736395 .unused,
3657836396 .unused,
3657936397 .unused,
......@@ -36607,7 +36425,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3660736425 .{ .type = .f80, .kind = .{ .reg = .st6 } },
3660836426 .{ .type = .f80, .kind = .{ .reg = .st7 } },
3660936427 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
36610 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorx" } } },
36428 .{ .type = .usize, .kind = .{ .extern_func = "__floorx" } },
3661136429 .unused,
3661236430 .unused,
3661336431 .unused,
......@@ -36641,8 +36459,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3664136459 },
3664236460 .call_frame = .{ .alignment = .@"16" },
3664336461 .extra_temps = .{
36644 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
36645 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floorq" } } },
36462 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
36463 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
3664636464 .unused,
3664736465 .unused,
3664836466 .unused,
......@@ -36674,8 +36492,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3667436492 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3667536493 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3667636494 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
36677 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
36678 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floorq" } } },
36495 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
36496 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
3667936497 .unused,
3668036498 .unused,
3668136499 .unused,
......@@ -36710,8 +36528,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3671036528 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3671136529 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3671236530 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
36713 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
36714 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floorq" } } },
36531 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
36532 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
3671536533 .unused,
3671636534 .unused,
3671736535 .unused,
......@@ -36746,8 +36564,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3674636564 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3674736565 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3674836566 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
36749 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
36750 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floorq" } } },
36567 .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
36568 .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
3675136569 .unused,
3675236570 .unused,
3675336571 .unused,
......@@ -36903,7 +36721,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3690336721 },
3690436722 .call_frame = .{ .alignment = .@"16" },
3690536723 .extra_temps = .{
36906 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modti3" } } },
36724 .{ .type = .usize, .kind = .{ .extern_func = "__modti3" } },
3690736725 .unused,
3690836726 .unused,
3690936727 .unused,
......@@ -36932,7 +36750,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3693236750 },
3693336751 .call_frame = .{ .alignment = .@"16" },
3693436752 .extra_temps = .{
36935 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodti3" } } },
36753 .{ .type = .usize, .kind = .{ .extern_func = "__umodti3" } },
3693636754 .unused,
3693736755 .unused,
3693836756 .unused,
......@@ -36965,7 +36783,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3696536783 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
3696636784 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
3696736785 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
36968 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modei4" } } },
36786 .{ .type = .usize, .kind = .{ .extern_func = "__modei4" } },
3696936787 .unused,
3697036788 .unused,
3697136789 .unused,
......@@ -36998,7 +36816,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3699836816 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
3699936817 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
3700036818 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
37001 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodei4" } } },
36819 .{ .type = .usize, .kind = .{ .extern_func = "__umodei4" } },
3700236820 .unused,
3700336821 .unused,
3700436822 .unused,
......@@ -37362,7 +37180,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3736237180 .{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
3736337181 .{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
3736437182 .{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
37365 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modti3" } } },
37183 .{ .type = .usize, .kind = .{ .extern_func = "__modti3" } },
3736637184 .{ .type = .u64, .kind = .{ .ret_gpr = .{ .cc = .ccc, .at = 0 } } },
3736737185 .unused,
3736837186 .unused,
......@@ -37400,7 +37218,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3740037218 .{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
3740137219 .{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
3740237220 .{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
37403 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodti3" } } },
37221 .{ .type = .usize, .kind = .{ .extern_func = "__umodti3" } },
3740437222 .{ .type = .u64, .kind = .{ .ret_gpr = .{ .cc = .ccc, .at = 0 } } },
3740537223 .unused,
3740637224 .unused,
......@@ -37438,7 +37256,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3743837256 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
3743937257 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
3744037258 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
37441 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modei4" } } },
37259 .{ .type = .usize, .kind = .{ .extern_func = "__modei4" } },
3744237260 .unused,
3744337261 .unused,
3744437262 .unused,
......@@ -37474,7 +37292,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3747437292 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
3747537293 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
3747637294 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
37477 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodei4" } } },
37295 .{ .type = .usize, .kind = .{ .extern_func = "__umodei4" } },
3747837296 .unused,
3747937297 .unused,
3748037298 .unused,
......@@ -37505,7 +37323,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3750537323 },
3750637324 .call_frame = .{ .alignment = .@"16" },
3750737325 .extra_temps = .{
37508 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
37326 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3750937327 .unused,
3751037328 .unused,
3751137329 .unused,
......@@ -37537,7 +37355,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3753737355 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3753837356 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3753937357 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
37540 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
37358 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3754137359 .unused,
3754237360 .unused,
3754337361 .unused,
......@@ -37573,7 +37391,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3757337391 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3757437392 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3757537393 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
37576 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
37394 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3757737395 .unused,
3757837396 .unused,
3757937397 .unused,
......@@ -37610,7 +37428,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3761037428 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3761137429 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3761237430 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
37613 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
37431 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3761437432 .{ .type = .f16, .kind = .{ .reg = .ax } },
3761537433 .unused,
3761637434 .unused,
......@@ -37650,7 +37468,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3765037468 .{ .type = .f32, .kind = .mem },
3765137469 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3765237470 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
37653 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
37471 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3765437472 .unused,
3765537473 .unused,
3765637474 .unused,
......@@ -37686,7 +37504,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3768637504 },
3768737505 .call_frame = .{ .alignment = .@"16" },
3768837506 .extra_temps = .{
37689 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
37507 .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
3769037508 .unused,
3769137509 .unused,
3769237510 .unused,
......@@ -37718,7 +37536,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3771837536 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3771937537 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
3772037538 .{ .type = .f32, .kind = .{ .reg = .xmm1 } },
37721 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
37539 .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
3772237540 .unused,
3772337541 .unused,
3772437542 .unused,
......@@ -37753,7 +37571,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3775337571 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3775437572 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
3775537573 .{ .type = .f32, .kind = .{ .reg = .xmm1 } },
37756 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
37574 .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
3775737575 .unused,
3775837576 .unused,
3775937577 .unused,
......@@ -37785,7 +37603,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3778537603 },
3778637604 .call_frame = .{ .alignment = .@"16" },
3778737605 .extra_temps = .{
37788 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
37606 .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
3778937607 .unused,
3779037608 .unused,
3779137609 .unused,
......@@ -37817,7 +37635,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3781737635 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3781837636 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
3781937637 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
37820 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
37638 .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
3782137639 .unused,
3782237640 .unused,
3782337641 .unused,
......@@ -37852,7 +37670,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3785237670 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3785337671 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
3785437672 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
37855 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
37673 .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
3785637674 .unused,
3785737675 .unused,
3785837676 .unused,
......@@ -37887,7 +37705,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3788737705 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3788837706 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
3788937707 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
37890 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
37708 .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
3789137709 .unused,
3789237710 .unused,
3789337711 .unused,
......@@ -37923,7 +37741,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3792337741 .extra_temps = .{
3792437742 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
3792537743 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
37926 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
37744 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
3792737745 .unused,
3792837746 .unused,
3792937747 .unused,
......@@ -37956,7 +37774,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3795637774 .extra_temps = .{
3795737775 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
3795837776 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
37959 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
37777 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
3796037778 .unused,
3796137779 .unused,
3796237780 .unused,
......@@ -37989,7 +37807,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3798937807 .extra_temps = .{
3799037808 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
3799137809 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
37992 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
37810 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
3799337811 .unused,
3799437812 .unused,
3799537813 .unused,
......@@ -38023,7 +37841,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3802337841 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3802437842 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
3802537843 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
38026 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
37844 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
3802737845 .unused,
3802837846 .unused,
3802937847 .unused,
......@@ -38061,7 +37879,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3806137879 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3806237880 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
3806337881 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
38064 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
37882 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
3806537883 .unused,
3806637884 .unused,
3806737885 .unused,
......@@ -38099,7 +37917,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3809937917 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3810037918 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
3810137919 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
38102 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
37920 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
3810337921 .unused,
3810437922 .unused,
3810537923 .unused,
......@@ -38134,7 +37952,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3813437952 },
3813537953 .call_frame = .{ .alignment = .@"16" },
3813637954 .extra_temps = .{
38137 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
37955 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
3813837956 .unused,
3813937957 .unused,
3814037958 .unused,
......@@ -38166,7 +37984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3816637984 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3816737985 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3816837986 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
38169 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
37987 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
3817037988 .unused,
3817137989 .unused,
3817237990 .unused,
......@@ -38201,7 +38019,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3820138019 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3820238020 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3820338021 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
38204 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
38022 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
3820538023 .unused,
3820638024 .unused,
3820738025 .unused,
......@@ -38236,7 +38054,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3823638054 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3823738055 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
3823838056 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
38239 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
38057 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
3824038058 .unused,
3824138059 .unused,
3824238060 .unused,
......@@ -38571,7 +38389,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3857138389 .call_frame = .{ .alignment = .@"16" },
3857238390 .extra_temps = .{
3857338391 .{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
38574 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modti3" } } },
38392 .{ .type = .usize, .kind = .{ .extern_func = "__modti3" } },
3857538393 .{ .type = .i64, .kind = .{ .rc = .general_purpose } },
3857638394 .unused,
3857738395 .unused,
......@@ -38610,7 +38428,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3861038428 .call_frame = .{ .alignment = .@"16" },
3861138429 .extra_temps = .{
3861238430 .{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
38613 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modti3" } } },
38431 .{ .type = .usize, .kind = .{ .extern_func = "__modti3" } },
3861438432 .unused,
3861538433 .unused,
3861638434 .unused,
......@@ -38650,7 +38468,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3865038468 },
3865138469 .call_frame = .{ .alignment = .@"16" },
3865238470 .extra_temps = .{
38653 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodti3" } } },
38471 .{ .type = .usize, .kind = .{ .extern_func = "__umodti3" } },
3865438472 .unused,
3865538473 .unused,
3865638474 .unused,
......@@ -38684,7 +38502,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3868438502 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
3868538503 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
3868638504 .{ .type = .i64, .kind = .{ .rc = .general_purpose } },
38687 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modei4" } } },
38505 .{ .type = .usize, .kind = .{ .extern_func = "__modei4" } },
3868838506 .unused,
3868938507 .unused,
3869038508 .unused,
......@@ -38741,7 +38559,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3874138559 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
3874238560 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
3874338561 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
38744 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodei4" } } },
38562 .{ .type = .usize, .kind = .{ .extern_func = "__umodei4" } },
3874538563 .unused,
3874638564 .unused,
3874738565 .unused,
......@@ -38771,7 +38589,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3877138589 .call_frame = .{ .alignment = .@"16" },
3877238590 .extra_temps = .{
3877338591 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
38774 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
38592 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3877538593 .{ .type = .f16, .kind = .{ .reg = .dx } },
3877638594 .{ .type = .f16, .kind = .{ .reg = .ax } },
3877738595 .unused,
......@@ -38812,7 +38630,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3881238630 .call_frame = .{ .alignment = .@"16" },
3881338631 .extra_temps = .{
3881438632 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
38815 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
38633 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3881638634 .{ .type = .f16, .kind = .{ .reg = .dx } },
3881738635 .{ .type = .f16, .kind = .{ .reg = .ax } },
3881838636 .unused,
......@@ -38853,10 +38671,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3885338671 .call_frame = .{ .alignment = .@"16" },
3885438672 .extra_temps = .{
3885538673 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
38856 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
38674 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3885738675 .{ .type = .f16, .kind = .{ .reg = .dx } },
3885838676 .{ .type = .f16, .kind = .{ .reg = .ax } },
38859 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
38677 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3886038678 .unused,
3886138679 .unused,
3886238680 .unused,
......@@ -38891,10 +38709,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3889138709 .call_frame = .{ .alignment = .@"16" },
3889238710 .extra_temps = .{
3889338711 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
38894 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
38712 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3889538713 .{ .type = .f16, .kind = .{ .reg = .dx } },
3889638714 .{ .type = .f16, .kind = .{ .reg = .ax } },
38897 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
38715 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3889838716 .unused,
3889938717 .unused,
3890038718 .unused,
......@@ -38929,10 +38747,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3892938747 .call_frame = .{ .alignment = .@"16" },
3893038748 .extra_temps = .{
3893138749 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
38932 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
38750 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3893338751 .{ .type = .f16, .kind = .{ .reg = .dx } },
3893438752 .{ .type = .f16, .kind = .{ .reg = .ax } },
38935 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
38753 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3893638754 .unused,
3893738755 .unused,
3893838756 .unused,
......@@ -38967,10 +38785,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3896738785 .call_frame = .{ .alignment = .@"16" },
3896838786 .extra_temps = .{
3896938787 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
38970 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
38788 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3897138789 .{ .type = .f16, .kind = .{ .reg = .dx } },
3897238790 .{ .type = .f16, .kind = .{ .reg = .ax } },
38973 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
38791 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3897438792 .unused,
3897538793 .unused,
3897638794 .unused,
......@@ -39005,10 +38823,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3900538823 .call_frame = .{ .alignment = .@"16" },
3900638824 .extra_temps = .{
3900738825 .{ .type = .f32, .kind = .mem },
39008 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
38826 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3900938827 .{ .type = .f32, .kind = .mem },
3901038828 .{ .type = .f16, .kind = .{ .reg = .ax } },
39011 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
38829 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3901238830 .unused,
3901338831 .unused,
3901438832 .unused,
......@@ -39043,10 +38861,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3904338861 .call_frame = .{ .alignment = .@"16" },
3904438862 .extra_temps = .{
3904538863 .{ .type = .f32, .kind = .mem },
39046 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
38864 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3904738865 .{ .type = .f32, .kind = .mem },
3904838866 .{ .type = .f16, .kind = .{ .reg = .ax } },
39049 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
38867 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3905038868 .unused,
3905138869 .unused,
3905238870 .unused,
......@@ -39084,7 +38902,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3908438902 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3908538903 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
3908638904 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
39087 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
38905 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3908838906 .{ .type = .f16, .kind = .{ .reg = .dx } },
3908938907 .{ .type = .f16, .kind = .{ .reg = .ax } },
3909038908 .unused,
......@@ -39132,7 +38950,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3913238950 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3913338951 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
3913438952 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
39135 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
38953 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3913638954 .{ .type = .f16, .kind = .{ .reg = .dx } },
3913738955 .{ .type = .f16, .kind = .{ .reg = .ax } },
3913838956 .unused,
......@@ -39180,10 +38998,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3918038998 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3918138999 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
3918239000 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
39183 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
39001 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3918439002 .{ .type = .f16, .kind = .{ .reg = .dx } },
3918539003 .{ .type = .f16, .kind = .{ .reg = .ax } },
39186 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
39004 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3918739005 .unused,
3918839006 .unused,
3918939007 .unused,
......@@ -39225,10 +39043,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3922539043 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3922639044 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
3922739045 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
39228 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
39046 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3922939047 .{ .type = .f16, .kind = .{ .reg = .dx } },
3923039048 .{ .type = .f16, .kind = .{ .reg = .ax } },
39231 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
39049 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3923239050 .unused,
3923339051 .unused,
3923439052 .unused,
......@@ -39270,10 +39088,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3927039088 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3927139089 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
3927239090 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
39273 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
39091 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3927439092 .{ .type = .f16, .kind = .{ .reg = .dx } },
3927539093 .{ .type = .f16, .kind = .{ .reg = .ax } },
39276 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
39094 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3927739095 .unused,
3927839096 .unused,
3927939097 .unused,
......@@ -39315,10 +39133,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3931539133 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3931639134 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
3931739135 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
39318 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
39136 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3931939137 .{ .type = .f16, .kind = .{ .reg = .dx } },
3932039138 .{ .type = .f16, .kind = .{ .reg = .ax } },
39321 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
39139 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3932239140 .unused,
3932339141 .unused,
3932439142 .unused,
......@@ -39360,10 +39178,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3936039178 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3936139179 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
3936239180 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
39363 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
39181 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3936439182 .{ .type = .f16, .kind = .{ .reg = .dx } },
3936539183 .{ .type = .f16, .kind = .{ .reg = .ax } },
39366 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
39184 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3936739185 .unused,
3936839186 .unused,
3936939187 .unused,
......@@ -39406,10 +39224,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3940639224 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3940739225 .{ .type = .f16, .kind = .{ .rc = .general_purpose } },
3940839226 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
39409 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
39227 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3941039228 .{ .type = .f16, .kind = .{ .reg = .dx } },
3941139229 .{ .type = .f16, .kind = .{ .reg = .ax } },
39412 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
39230 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3941339231 .unused,
3941439232 .unused,
3941539233 .unused,
......@@ -39453,9 +39271,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3945339271 .{ .type = .f32, .kind = .mem },
3945439272 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3945539273 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
39456 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
39274 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3945739275 .{ .type = .f32, .kind = .mem },
39458 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
39276 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3945939277 .unused,
3946039278 .unused,
3946139279 .unused,
......@@ -39502,9 +39320,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3950239320 .{ .type = .f32, .kind = .mem },
3950339321 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
3950439322 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
39505 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
39323 .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
3950639324 .{ .type = .f32, .kind = .mem },
39507 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
39325 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
3950839326 .unused,
3950939327 .unused,
3951039328 .unused,
......@@ -39547,7 +39365,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3954739365 .call_frame = .{ .alignment = .@"16" },
3954839366 .extra_temps = .{
3954939367 .{ .type = .f32, .kind = .{ .rc = .general_purpose } },
39550 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
39368 .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
3955139369 .{ .type = .f32, .kind = .{ .reg = .edx } },
3955239370 .{ .type = .f32, .kind = .{ .reg = .eax } },
3955339371 .unused,
......@@ -39585,7 +39403,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3958539403 .call_frame = .{ .alignment = .@"16" },
3958639404 .extra_temps = .{
3958739405 .{ .type = .f32, .kind = .{ .rc = .general_purpose } },
39588 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
39406 .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
3958939407 .{ .type = .f32, .kind = .{ .reg = .edx } },
3959039408 .{ .type = .f32, .kind = .{ .reg = .eax } },
3959139409 .unused,
......@@ -39623,7 +39441,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3962339441 .call_frame = .{ .alignment = .@"16" },
3962439442 .extra_temps = .{
3962539443 .{ .type = .f32, .kind = .mem },
39626 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
39444 .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
3962739445 .{ .type = .f32, .kind = .mem },
3962839446 .{ .type = .f32, .kind = .{ .reg = .eax } },
3962939447 .unused,
......@@ -39663,7 +39481,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3966339481 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
3966439482 .{ .type = .f32, .kind = .{ .reg = .xmm1 } },
3966539483 .{ .type = .f32, .kind = .{ .rc = .general_purpose } },
39666 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
39484 .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
3966739485 .{ .type = .f32, .kind = .{ .reg = .edx } },
3966839486 .{ .type = .f32, .kind = .{ .reg = .eax } },
3966939487 .unused,
......@@ -39707,7 +39525,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3970739525 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
3970839526 .{ .type = .f32, .kind = .{ .reg = .xmm1 } },
3970939527 .{ .type = .f32, .kind = .{ .rc = .general_purpose } },
39710 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
39528 .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
3971139529 .{ .type = .f32, .kind = .{ .reg = .edx } },
3971239530 .{ .type = .f32, .kind = .{ .reg = .eax } },
3971339531 .unused,
......@@ -39750,7 +39568,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3975039568 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
3975139569 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
3975239570 .{ .type = .f32, .kind = .{ .reg = .xmm1 } },
39753 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
39571 .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
3975439572 .{ .type = .f32, .kind = .mem },
3975539573 .{ .type = .f32, .kind = .{ .reg = .eax } },
3975639574 .unused,
......@@ -39790,7 +39608,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3979039608 .call_frame = .{ .alignment = .@"16" },
3979139609 .extra_temps = .{
3979239610 .{ .type = .f64, .kind = .{ .rc = .general_purpose } },
39793 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
39611 .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
3979439612 .{ .type = .f64, .kind = .{ .reg = .rcx } },
3979539613 .{ .type = .f64, .kind = .{ .reg = .rdx } },
3979639614 .{ .type = .f64, .kind = .{ .reg = .rax } },
......@@ -39829,7 +39647,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3982939647 .call_frame = .{ .alignment = .@"16" },
3983039648 .extra_temps = .{
3983139649 .{ .type = .f64, .kind = .{ .rc = .general_purpose } },
39832 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
39650 .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
3983339651 .{ .type = .f64, .kind = .{ .reg = .rcx } },
3983439652 .{ .type = .f64, .kind = .{ .reg = .rdx } },
3983539653 .{ .type = .f64, .kind = .{ .reg = .rax } },
......@@ -39868,7 +39686,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3986839686 .call_frame = .{ .alignment = .@"16" },
3986939687 .extra_temps = .{
3987039688 .{ .type = .f64, .kind = .mem },
39871 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
39689 .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
3987239690 .{ .type = .f64, .kind = .mem },
3987339691 .{ .type = .f64, .kind = .{ .reg = .rdx } },
3987439692 .{ .type = .f64, .kind = .{ .reg = .rax } },
......@@ -39913,7 +39731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3991339731 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
3991439732 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
3991539733 .{ .type = .f64, .kind = .{ .rc = .general_purpose } },
39916 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
39734 .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
3991739735 .{ .type = .f64, .kind = .{ .reg = .rcx } },
3991839736 .{ .type = .f64, .kind = .{ .reg = .rdx } },
3991939737 .{ .type = .f64, .kind = .{ .reg = .rax } },
......@@ -39958,7 +39776,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3995839776 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
3995939777 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
3996039778 .{ .type = .f64, .kind = .{ .rc = .general_purpose } },
39961 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
39779 .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
3996239780 .{ .type = .f64, .kind = .{ .reg = .rcx } },
3996339781 .{ .type = .f64, .kind = .{ .reg = .rdx } },
3996439782 .{ .type = .f64, .kind = .{ .reg = .rax } },
......@@ -40002,7 +39820,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4000239820 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4000339821 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
4000439822 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
40005 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
39823 .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
4000639824 .{ .type = .f64, .kind = .{ .reg = .rdx } },
4000739825 .{ .type = .f64, .kind = .mem },
4000839826 .{ .type = .f64, .kind = .{ .reg = .rax } },
......@@ -40050,7 +39868,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4005039868 .extra_temps = .{
4005139869 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
4005239870 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
40053 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
39871 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
4005439872 .{ .type = .f80, .kind = .{ .reg = .st7 } },
4005539873 .{ .type = .f80, .kind = .{ .reg = .rax } },
4005639874 .unused,
......@@ -40093,7 +39911,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4009339911 .extra_temps = .{
4009439912 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
4009539913 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
40096 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
39914 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
4009739915 .{ .type = .f80, .kind = .{ .reg = .st7 } },
4009839916 .{ .type = .f80, .kind = .{ .reg = .rax } },
4009939917 .unused,
......@@ -40136,7 +39954,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4013639954 .extra_temps = .{
4013739955 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
4013839956 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
40139 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
39957 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
4014039958 .{ .type = .f80, .kind = .{ .reg = .st7 } },
4014139959 .{ .type = .f80, .kind = .{ .reg = .rax } },
4014239960 .unused,
......@@ -40179,7 +39997,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4017939997 .extra_temps = .{
4018039998 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
4018139999 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
40182 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
40000 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
4018340001 .{ .type = .f80, .kind = .{ .reg = .st7 } },
4018440002 .{ .type = .f80, .kind = .{ .reg = .rax } },
4018540003 .unused,
......@@ -40222,7 +40040,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4022240040 .extra_temps = .{
4022340041 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
4022440042 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
40225 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
40043 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
4022640044 .{ .type = .f80, .kind = .{ .reg = .st7 } },
4022740045 .{ .type = .f80, .kind = .{ .reg = .rax } },
4022840046 .unused,
......@@ -40265,7 +40083,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4026540083 .extra_temps = .{
4026640084 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
4026740085 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
40268 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
40086 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
4026940087 .{ .type = .f80, .kind = .{ .reg = .st7 } },
4027040088 .{ .type = .f80, .kind = .{ .reg = .rax } },
4027140089 .unused,
......@@ -40309,7 +40127,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4030940127 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4031040128 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
4031140129 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
40312 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
40130 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
4031340131 .{ .type = .f80, .kind = .{ .reg = .st7 } },
4031440132 .{ .type = .f80, .kind = .{ .reg = .rax } },
4031540133 .unused,
......@@ -40357,7 +40175,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4035740175 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4035840176 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
4035940177 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
40360 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
40178 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
4036140179 .{ .type = .f80, .kind = .{ .reg = .st7 } },
4036240180 .{ .type = .f80, .kind = .{ .reg = .rax } },
4036340181 .unused,
......@@ -40405,7 +40223,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4040540223 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4040640224 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
4040740225 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
40408 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
40226 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
4040940227 .{ .type = .f80, .kind = .{ .reg = .st7 } },
4041040228 .{ .type = .f80, .kind = .{ .reg = .rax } },
4041140229 .unused,
......@@ -40453,7 +40271,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4045340271 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4045440272 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
4045540273 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
40456 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
40274 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
4045740275 .{ .type = .f80, .kind = .{ .reg = .st7 } },
4045840276 .{ .type = .f80, .kind = .{ .reg = .rax } },
4045940277 .unused,
......@@ -40501,7 +40319,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4050140319 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4050240320 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
4050340321 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
40504 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
40322 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
4050540323 .{ .type = .f80, .kind = .{ .reg = .st7 } },
4050640324 .{ .type = .f80, .kind = .{ .reg = .rax } },
4050740325 .unused,
......@@ -40549,7 +40367,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4054940367 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4055040368 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
4055140369 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
40552 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
40370 .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
4055340371 .{ .type = .f80, .kind = .{ .reg = .st7 } },
4055440372 .{ .type = .f80, .kind = .{ .reg = .rax } },
4055540373 .unused,
......@@ -40595,11 +40413,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4059540413 .call_frame = .{ .alignment = .@"16" },
4059640414 .extra_temps = .{
4059740415 .{ .type = .f128, .kind = .mem },
40598 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
40416 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
4059940417 .{ .type = .f128, .kind = .{ .reg = .rcx } },
4060040418 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4060140419 .{ .type = .f128, .kind = .{ .reg = .rax } },
40602 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
40420 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
4060340421 .unused,
4060440422 .unused,
4060540423 .unused,
......@@ -40636,11 +40454,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4063640454 .call_frame = .{ .alignment = .@"16" },
4063740455 .extra_temps = .{
4063840456 .{ .type = .f128, .kind = .mem },
40639 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
40457 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
4064040458 .{ .type = .f128, .kind = .{ .reg = .rcx } },
4064140459 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4064240460 .{ .type = .f128, .kind = .{ .reg = .rax } },
40643 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
40461 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
4064440462 .unused,
4064540463 .unused,
4064640464 .unused,
......@@ -40677,11 +40495,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4067740495 .call_frame = .{ .alignment = .@"16" },
4067840496 .extra_temps = .{
4067940497 .{ .type = .f128, .kind = .mem },
40680 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
40498 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
4068140499 .{ .type = .f128, .kind = .{ .reg = .rcx } },
4068240500 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4068340501 .{ .type = .f128, .kind = .{ .reg = .rax } },
40684 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
40502 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
4068540503 .unused,
4068640504 .unused,
4068740505 .unused,
......@@ -40719,11 +40537,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4071940537 .call_frame = .{ .alignment = .@"16" },
4072040538 .extra_temps = .{
4072140539 .{ .type = .f128, .kind = .mem },
40722 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
40540 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
4072340541 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4072440542 .{ .type = .f128, .kind = .mem },
4072540543 .{ .type = .f128, .kind = .{ .reg = .rax } },
40726 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
40544 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
4072740545 .unused,
4072840546 .unused,
4072940547 .unused,
......@@ -40761,11 +40579,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4076140579 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4076240580 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
4076340581 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
40764 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
40582 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
4076540583 .{ .type = .f128, .kind = .{ .reg = .rcx } },
4076640584 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4076740585 .{ .type = .f128, .kind = .{ .reg = .rax } },
40768 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
40586 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
4076940587 .unused,
4077040588 .unused,
4077140589 .unused,
......@@ -40807,11 +40625,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4080740625 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4080840626 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
4080940627 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
40810 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
40628 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
4081140629 .{ .type = .f128, .kind = .{ .reg = .rcx } },
4081240630 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4081340631 .{ .type = .f128, .kind = .{ .reg = .rax } },
40814 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
40632 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
4081540633 .unused,
4081640634 .unused,
4081740635 .unused,
......@@ -40853,11 +40671,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4085340671 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4085440672 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
4085540673 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
40856 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
40674 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
4085740675 .{ .type = .f128, .kind = .{ .reg = .rcx } },
4085840676 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4085940677 .{ .type = .f128, .kind = .{ .reg = .rax } },
40860 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
40678 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
4086140679 .unused,
4086240680 .unused,
4086340681 .unused,
......@@ -40900,11 +40718,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4090040718 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4090140719 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
4090240720 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
40903 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
40721 .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
4090440722 .{ .type = .f128, .kind = .{ .reg = .rdx } },
4090540723 .{ .type = .f128, .kind = .mem },
4090640724 .{ .type = .f128, .kind = .{ .reg = .rax } },
40907 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
40725 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
4090840726 .unused,
4090940727 .unused,
4091040728 .unused,
......@@ -43994,7 +43812,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4399443812 },
4399543813 .call_frame = .{ .alignment = .@"16" },
4399643814 .extra_temps = .{
43997 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
43815 .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
4399843816 .unused,
4399943817 .unused,
4400043818 .unused,
......@@ -44132,7 +43950,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4413243950 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4413343951 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
4413443952 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
44135 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
43953 .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
4413643954 .unused,
4413743955 .unused,
4413843956 .unused,
......@@ -44168,7 +43986,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4416843986 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4416943987 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
4417043988 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
44171 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
43989 .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
4417243990 .unused,
4417343991 .unused,
4417443992 .unused,
......@@ -44205,7 +44023,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4420544023 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4420644024 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
4420744025 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
44208 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
44026 .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
4420944027 .{ .type = .f16, .kind = .{ .reg = .ax } },
4421044028 .unused,
4421144029 .unused,
......@@ -44245,7 +44063,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4424544063 .{ .type = .f32, .kind = .mem },
4424644064 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
4424744065 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
44248 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
44066 .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
4424944067 .unused,
4425044068 .unused,
4425144069 .unused,
......@@ -44660,7 +44478,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4466044478 },
4466144479 .call_frame = .{ .alignment = .@"16" },
4466244480 .extra_temps = .{
44663 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmax" } } },
44481 .{ .type = .usize, .kind = .{ .extern_func = "fmax" } },
4466444482 .unused,
4466544483 .unused,
4466644484 .unused,
......@@ -44915,7 +44733,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4491544733 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4491644734 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
4491744735 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
44918 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmax" } } },
44736 .{ .type = .usize, .kind = .{ .extern_func = "fmax" } },
4491944737 .unused,
4492044738 .unused,
4492144739 .unused,
......@@ -45204,7 +45022,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4520445022 },
4520545023 .call_frame = .{ .alignment = .@"16" },
4520645024 .extra_temps = .{
45207 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
45025 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
4520845026 .unused,
4520945027 .unused,
4521045028 .unused,
......@@ -45236,7 +45054,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4523645054 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4523745055 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
4523845056 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
45239 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
45057 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
4524045058 .unused,
4524145059 .unused,
4524245060 .unused,
......@@ -45271,7 +45089,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4527145089 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4527245090 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
4527345091 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
45274 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
45092 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
4527545093 .unused,
4527645094 .unused,
4527745095 .unused,
......@@ -45306,7 +45124,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4530645124 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4530745125 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
4530845126 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
45309 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
45127 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
4531045128 .unused,
4531145129 .unused,
4531245130 .unused,
......@@ -48153,7 +47971,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4815347971 },
4815447972 .call_frame = .{ .alignment = .@"16" },
4815547973 .extra_temps = .{
48156 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
47974 .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
4815747975 .unused,
4815847976 .unused,
4815947977 .unused,
......@@ -48291,7 +48109,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4829148109 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4829248110 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
4829348111 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
48294 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
48112 .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
4829548113 .unused,
4829648114 .unused,
4829748115 .unused,
......@@ -48327,7 +48145,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4832748145 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4832848146 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
4832948147 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
48330 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
48148 .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
4833148149 .unused,
4833248150 .unused,
4833348151 .unused,
......@@ -48364,7 +48182,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4836448182 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4836548183 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
4836648184 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
48367 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
48185 .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
4836848186 .{ .type = .f16, .kind = .{ .reg = .ax } },
4836948187 .unused,
4837048188 .unused,
......@@ -48404,7 +48222,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4840448222 .{ .type = .f32, .kind = .mem },
4840548223 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
4840648224 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
48407 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
48225 .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
4840848226 .unused,
4840948227 .unused,
4841048228 .unused,
......@@ -48819,7 +48637,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4881948637 },
4882048638 .call_frame = .{ .alignment = .@"16" },
4882148639 .extra_temps = .{
48822 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmin" } } },
48640 .{ .type = .usize, .kind = .{ .extern_func = "fmin" } },
4882348641 .unused,
4882448642 .unused,
4882548643 .unused,
......@@ -49074,7 +48892,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4907448892 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4907548893 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
4907648894 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
49077 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmin" } } },
48895 .{ .type = .usize, .kind = .{ .extern_func = "fmin" } },
4907848896 .unused,
4907948897 .unused,
4908048898 .unused,
......@@ -49351,7 +49169,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4935149169 },
4935249170 .call_frame = .{ .alignment = .@"16" },
4935349171 .extra_temps = .{
49354 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
49172 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
4935549173 .unused,
4935649174 .unused,
4935749175 .unused,
......@@ -49383,7 +49201,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4938349201 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4938449202 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
4938549203 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
49386 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
49204 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
4938749205 .unused,
4938849206 .unused,
4938949207 .unused,
......@@ -49418,7 +49236,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4941849236 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4941949237 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
4942049238 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
49421 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
49239 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
4942249240 .unused,
4942349241 .unused,
4942449242 .unused,
......@@ -49453,7 +49271,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4945349271 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
4945449272 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
4945549273 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
49456 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
49274 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
4945749275 .unused,
4945849276 .unused,
4945949277 .unused,
......@@ -64179,9 +63997,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
6417963997 .block => {
6418063998 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
6418163999 const block = cg.air.extraData(Air.Block, ty_pl.payload);
64182 if (cg.debug_output != .none) try cg.asmPseudo(.pseudo_dbg_enter_block_none);
64000 if (!cg.mod.strip) try cg.asmPseudo(.pseudo_dbg_enter_block_none);
6418364001 try cg.lowerBlock(inst, @ptrCast(cg.air.extra.items[block.end..][0..block.data.body_len]));
64184 if (cg.debug_output != .none) try cg.asmPseudo(.pseudo_dbg_leave_block_none);
64002 if (!cg.mod.strip) try cg.asmPseudo(.pseudo_dbg_leave_block_none);
6418564003 },
6418664004 .loop => if (use_old) try cg.airLoop(inst) else {
6418764005 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
......@@ -72393,7 +72211,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7239372211 },
7239472212 .call_frame = .{ .alignment = .@"16" },
7239572213 .extra_temps = .{
72396 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__sqrth" } } },
72214 .{ .type = .usize, .kind = .{ .extern_func = "__sqrth" } },
7239772215 .unused,
7239872216 .unused,
7239972217 .unused,
......@@ -72475,7 +72293,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7247572293 .extra_temps = .{
7247672294 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7247772295 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
72478 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__sqrth" } } },
72296 .{ .type = .usize, .kind = .{ .extern_func = "__sqrth" } },
7247972297 .unused,
7248072298 .unused,
7248172299 .unused,
......@@ -72506,7 +72324,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7250672324 .extra_temps = .{
7250772325 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7250872326 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
72509 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__sqrth" } } },
72327 .{ .type = .usize, .kind = .{ .extern_func = "__sqrth" } },
7251072328 .unused,
7251172329 .unused,
7251272330 .unused,
......@@ -72537,7 +72355,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7253772355 .extra_temps = .{
7253872356 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7253972357 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
72540 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__sqrth" } } },
72358 .{ .type = .usize, .kind = .{ .extern_func = "__sqrth" } },
7254172359 .{ .type = .f16, .kind = .{ .reg = .ax } },
7254272360 .unused,
7254372361 .unused,
......@@ -72571,7 +72389,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7257172389 .{ .type = .f16, .kind = .{ .reg = .ax } },
7257272390 .{ .type = .f32, .kind = .mem },
7257372391 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
72574 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__sqrth" } } },
72392 .{ .type = .usize, .kind = .{ .extern_func = "__sqrth" } },
7257572393 .unused,
7257672394 .unused,
7257772395 .unused,
......@@ -72643,7 +72461,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7264372461 },
7264472462 .call_frame = .{ .alignment = .@"16" },
7264572463 .extra_temps = .{
72646 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtf" } } },
72464 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf" } },
7264772465 .unused,
7264872466 .unused,
7264972467 .unused,
......@@ -72759,7 +72577,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7275972577 .extra_temps = .{
7276072578 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7276172579 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
72762 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtf" } } },
72580 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf" } },
7276372581 .unused,
7276472582 .unused,
7276572583 .unused,
......@@ -72789,7 +72607,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7278972607 .extra_temps = .{
7279072608 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7279172609 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
72792 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtf" } } },
72610 .{ .type = .usize, .kind = .{ .extern_func = "sqrtf" } },
7279372611 .unused,
7279472612 .unused,
7279572613 .unused,
......@@ -72859,7 +72677,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7285972677 },
7286072678 .call_frame = .{ .alignment = .@"16" },
7286172679 .extra_temps = .{
72862 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrt" } } },
72680 .{ .type = .usize, .kind = .{ .extern_func = "sqrt" } },
7286372681 .unused,
7286472682 .unused,
7286572683 .unused,
......@@ -72975,7 +72793,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7297572793 .extra_temps = .{
7297672794 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7297772795 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
72978 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrt" } } },
72796 .{ .type = .usize, .kind = .{ .extern_func = "sqrt" } },
7297972797 .unused,
7298072798 .unused,
7298172799 .unused,
......@@ -73005,7 +72823,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7300572823 .extra_temps = .{
7300672824 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7300772825 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
73008 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrt" } } },
72826 .{ .type = .usize, .kind = .{ .extern_func = "sqrt" } },
7300972827 .unused,
7301072828 .unused,
7301172829 .unused,
......@@ -73035,7 +72853,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7303572853 .extra_temps = .{
7303672854 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7303772855 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
73038 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrt" } } },
72856 .{ .type = .usize, .kind = .{ .extern_func = "sqrt" } },
7303972857 .unused,
7304072858 .unused,
7304172859 .unused,
......@@ -73119,7 +72937,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7311972937 },
7312072938 .call_frame = .{ .alignment = .@"16" },
7312172939 .extra_temps = .{
73122 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtq" } } },
72940 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
7312372941 .unused,
7312472942 .unused,
7312572943 .unused,
......@@ -73146,7 +72964,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7314672964 .extra_temps = .{
7314772965 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7314872966 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
73149 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtq" } } },
72967 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
7315072968 .unused,
7315172969 .unused,
7315272970 .unused,
......@@ -73176,7 +72994,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7317672994 .extra_temps = .{
7317772995 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7317872996 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
73179 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtq" } } },
72997 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
7318072998 .unused,
7318172999 .unused,
7318273000 .unused,
......@@ -73206,7 +73024,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7320673024 .extra_temps = .{
7320773025 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7320873026 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
73209 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtq" } } },
73027 .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
7321073028 .unused,
7321173029 .unused,
7321273030 .unused,
......@@ -73250,7 +73068,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7325073068 },
7325173069 .call_frame = .{ .alignment = .@"16" },
7325273070 .extra_temps = .{
73253 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "h" } } },
73071 .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "h" } },
7325473072 .unused,
7325573073 .unused,
7325673074 .unused,
......@@ -73277,7 +73095,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7327773095 .extra_temps = .{
7327873096 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7327973097 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
73280 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "h" } } },
73098 .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "h" } },
7328173099 .unused,
7328273100 .unused,
7328373101 .unused,
......@@ -73308,7 +73126,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7330873126 .extra_temps = .{
7330973127 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7331073128 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
73311 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "h" } } },
73129 .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "h" } },
7331273130 .unused,
7331373131 .unused,
7331473132 .unused,
......@@ -73339,7 +73157,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7333973157 .extra_temps = .{
7334073158 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7334173159 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
73342 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "h" } } },
73160 .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "h" } },
7334373161 .{ .type = .f16, .kind = .{ .reg = .ax } },
7334473162 .unused,
7334573163 .unused,
......@@ -73373,7 +73191,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7337373191 .{ .type = .f16, .kind = .{ .reg = .ax } },
7337473192 .{ .type = .f32, .kind = .mem },
7337573193 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
73376 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "h" } } },
73194 .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "h" } },
7337773195 .unused,
7337873196 .unused,
7337973197 .unused,
......@@ -73403,7 +73221,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7340373221 },
7340473222 .call_frame = .{ .alignment = .@"16" },
7340573223 .extra_temps = .{
73406 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "f" } } },
73224 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f" } },
7340773225 .unused,
7340873226 .unused,
7340973227 .unused,
......@@ -73430,7 +73248,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7343073248 .extra_temps = .{
7343173249 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7343273250 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
73433 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "f" } } },
73251 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f" } },
7343473252 .unused,
7343573253 .unused,
7343673254 .unused,
......@@ -73460,7 +73278,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7346073278 .extra_temps = .{
7346173279 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7346273280 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
73463 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "f" } } },
73281 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f" } },
7346473282 .unused,
7346573283 .unused,
7346673284 .unused,
......@@ -73488,7 +73306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7348873306 },
7348973307 .call_frame = .{ .alignment = .@"16" },
7349073308 .extra_temps = .{
73491 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) } } },
73309 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) } },
7349273310 .unused,
7349373311 .unused,
7349473312 .unused,
......@@ -73515,7 +73333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7351573333 .extra_temps = .{
7351673334 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7351773335 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
73518 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) } } },
73336 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) } },
7351973337 .unused,
7352073338 .unused,
7352173339 .unused,
......@@ -73545,7 +73363,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7354573363 .extra_temps = .{
7354673364 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7354773365 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
73548 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) } } },
73366 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) } },
7354973367 .unused,
7355073368 .unused,
7355173369 .unused,
......@@ -73575,7 +73393,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7357573393 .extra_temps = .{
7357673394 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7357773395 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
73578 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) } } },
73396 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) } },
7357973397 .unused,
7358073398 .unused,
7358173399 .unused,
......@@ -73606,7 +73424,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7360673424 .extra_temps = .{
7360773425 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
7360873426 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
73609 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "x" } } },
73427 .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "x" } },
7361073428 .unused,
7361173429 .unused,
7361273430 .unused,
......@@ -73633,7 +73451,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7363373451 .extra_temps = .{
7363473452 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
7363573453 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
73636 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "x" } } },
73454 .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "x" } },
7363773455 .unused,
7363873456 .unused,
7363973457 .unused,
......@@ -73660,7 +73478,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7366073478 .extra_temps = .{
7366173479 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
7366273480 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
73663 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "x" } } },
73481 .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "x" } },
7366473482 .unused,
7366573483 .unused,
7366673484 .unused,
......@@ -73688,7 +73506,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7368873506 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7368973507 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
7369073508 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
73691 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "x" } } },
73509 .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "x" } },
7369273510 .unused,
7369373511 .unused,
7369473512 .unused,
......@@ -73720,7 +73538,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7372073538 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7372173539 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
7372273540 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
73723 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "x" } } },
73541 .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "x" } },
7372473542 .unused,
7372573543 .unused,
7372673544 .unused,
......@@ -73752,7 +73570,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7375273570 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7375373571 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
7375473572 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
73755 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "x" } } },
73573 .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "x" } },
7375673574 .unused,
7375773575 .unused,
7375873576 .unused,
......@@ -73781,7 +73599,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7378173599 },
7378273600 .call_frame = .{ .alignment = .@"16" },
7378373601 .extra_temps = .{
73784 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "q" } } },
73602 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
7378573603 .unused,
7378673604 .unused,
7378773605 .unused,
......@@ -73808,7 +73626,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7380873626 .extra_temps = .{
7380973627 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7381073628 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
73811 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "q" } } },
73629 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
7381273630 .unused,
7381373631 .unused,
7381473632 .unused,
......@@ -73838,7 +73656,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7383873656 .extra_temps = .{
7383973657 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7384073658 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
73841 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "q" } } },
73659 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
7384273660 .unused,
7384373661 .unused,
7384473662 .unused,
......@@ -73868,7 +73686,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7386873686 .extra_temps = .{
7386973687 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7387073688 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
73871 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "q" } } },
73689 .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
7387273690 .unused,
7387373691 .unused,
7387473692 .unused,
......@@ -75486,12 +75304,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7548675304 },
7548775305 .call_frame = .{ .alignment = .@"16" },
7548875306 .extra_temps = .{
75489 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
75307 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7549075308 else => unreachable,
7549175309 .down => "__floorh",
7549275310 .up => "__ceilh",
7549375311 .zero => "__trunch",
75494 } } } },
75312 } } },
7549575313 .unused,
7549675314 .unused,
7549775315 .unused,
......@@ -75573,12 +75391,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7557375391 .extra_temps = .{
7557475392 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7557575393 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
75576 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
75394 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7557775395 else => unreachable,
7557875396 .down => "__floorh",
7557975397 .up => "__ceilh",
7558075398 .zero => "__trunch",
75581 } } } },
75399 } } },
7558275400 .unused,
7558375401 .unused,
7558475402 .unused,
......@@ -75609,12 +75427,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7560975427 .extra_temps = .{
7561075428 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7561175429 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
75612 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
75430 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7561375431 else => unreachable,
7561475432 .down => "__floorh",
7561575433 .up => "__ceilh",
7561675434 .zero => "__trunch",
75617 } } } },
75435 } } },
7561875436 .unused,
7561975437 .unused,
7562075438 .unused,
......@@ -75645,12 +75463,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7564575463 .extra_temps = .{
7564675464 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7564775465 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
75648 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
75466 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7564975467 else => unreachable,
7565075468 .down => "__floorh",
7565175469 .up => "__ceilh",
7565275470 .zero => "__trunch",
75653 } } } },
75471 } } },
7565475472 .{ .type = .f16, .kind = .{ .reg = .ax } },
7565575473 .unused,
7565675474 .unused,
......@@ -75684,12 +75502,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7568475502 .{ .type = .f16, .kind = .{ .reg = .ax } },
7568575503 .{ .type = .f32, .kind = .mem },
7568675504 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
75687 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
75505 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7568875506 else => unreachable,
7568975507 .down => "__floorh",
7569075508 .up => "__ceilh",
7569175509 .zero => "__trunch",
75692 } } } },
75510 } } },
7569375511 .unused,
7569475512 .unused,
7569575513 .unused,
......@@ -75761,12 +75579,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7576175579 },
7576275580 .call_frame = .{ .alignment = .@"16" },
7576375581 .extra_temps = .{
75764 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
75582 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7576575583 else => unreachable,
7576675584 .down => "floorf",
7576775585 .up => "ceilf",
7576875586 .zero => "truncf",
75769 } } } },
75587 } } },
7577075588 .unused,
7577175589 .unused,
7577275590 .unused,
......@@ -75888,12 +75706,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7588875706 .extra_temps = .{
7588975707 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7589075708 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
75891 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
75709 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7589275710 else => unreachable,
7589375711 .down => "floorf",
7589475712 .up => "ceilf",
7589575713 .zero => "truncf",
75896 } } } },
75714 } } },
7589775715 .unused,
7589875716 .unused,
7589975717 .unused,
......@@ -75923,12 +75741,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7592375741 .extra_temps = .{
7592475742 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7592575743 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
75926 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
75744 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7592775745 else => unreachable,
7592875746 .down => "floorf",
7592975747 .up => "ceilf",
7593075748 .zero => "truncf",
75931 } } } },
75749 } } },
7593275750 .unused,
7593375751 .unused,
7593475752 .unused,
......@@ -75998,12 +75816,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7599875816 },
7599975817 .call_frame = .{ .alignment = .@"16" },
7600075818 .extra_temps = .{
76001 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
75819 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7600275820 else => unreachable,
7600375821 .down => "floor",
7600475822 .up => "ceil",
7600575823 .zero => "trunc",
76006 } } } },
75824 } } },
7600775825 .unused,
7600875826 .unused,
7600975827 .unused,
......@@ -76125,12 +75943,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7612575943 .extra_temps = .{
7612675944 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7612775945 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
76128 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
75946 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7612975947 else => unreachable,
7613075948 .down => "floor",
7613175949 .up => "ceil",
7613275950 .zero => "trunc",
76133 } } } },
75951 } } },
7613475952 .unused,
7613575953 .unused,
7613675954 .unused,
......@@ -76160,12 +75978,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7616075978 .extra_temps = .{
7616175979 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7616275980 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
76163 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
75981 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7616475982 else => unreachable,
7616575983 .down => "floor",
7616675984 .up => "ceil",
7616775985 .zero => "trunc",
76168 } } } },
75986 } } },
7616975987 .unused,
7617075988 .unused,
7617175989 .unused,
......@@ -76195,12 +76013,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7619576013 .extra_temps = .{
7619676014 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7619776015 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
76198 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
76016 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7619976017 else => unreachable,
7620076018 .down => "floor",
7620176019 .up => "ceil",
7620276020 .zero => "trunc",
76203 } } } },
76021 } } },
7620476022 .unused,
7620576023 .unused,
7620676024 .unused,
......@@ -76231,12 +76049,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7623176049 .extra_temps = .{
7623276050 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
7623376051 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
76234 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
76052 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7623576053 else => unreachable,
7623676054 .down => "__floorx",
7623776055 .up => "__ceilx",
7623876056 .zero => "__truncx",
76239 } } } },
76057 } } },
7624076058 .unused,
7624176059 .unused,
7624276060 .unused,
......@@ -76263,12 +76081,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7626376081 .extra_temps = .{
7626476082 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
7626576083 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
76266 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
76084 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7626776085 else => unreachable,
7626876086 .down => "__floorx",
7626976087 .up => "__ceilx",
7627076088 .zero => "__truncx",
76271 } } } },
76089 } } },
7627276090 .unused,
7627376091 .unused,
7627476092 .unused,
......@@ -76295,12 +76113,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7629576113 .extra_temps = .{
7629676114 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
7629776115 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
76298 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
76116 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7629976117 else => unreachable,
7630076118 .down => "__floorx",
7630176119 .up => "__ceilx",
7630276120 .zero => "__truncx",
76303 } } } },
76121 } } },
7630476122 .unused,
7630576123 .unused,
7630676124 .unused,
......@@ -76328,12 +76146,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7632876146 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7632976147 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
7633076148 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
76331 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
76149 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7633276150 else => unreachable,
7633376151 .down => "__floorx",
7633476152 .up => "__ceilx",
7633576153 .zero => "__truncx",
76336 } } } },
76154 } } },
7633776155 .unused,
7633876156 .unused,
7633976157 .unused,
......@@ -76365,12 +76183,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7636576183 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7636676184 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
7636776185 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
76368 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
76186 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7636976187 else => unreachable,
7637076188 .down => "__floorx",
7637176189 .up => "__ceilx",
7637276190 .zero => "__truncx",
76373 } } } },
76191 } } },
7637476192 .unused,
7637576193 .unused,
7637676194 .unused,
......@@ -76402,12 +76220,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7640276220 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7640376221 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
7640476222 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
76405 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
76223 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7640676224 else => unreachable,
7640776225 .down => "__floorx",
7640876226 .up => "__ceilx",
7640976227 .zero => "__truncx",
76410 } } } },
76228 } } },
7641176229 .unused,
7641276230 .unused,
7641376231 .unused,
......@@ -76436,12 +76254,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7643676254 },
7643776255 .call_frame = .{ .alignment = .@"16" },
7643876256 .extra_temps = .{
76439 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
76257 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7644076258 else => unreachable,
7644176259 .down => "floorq",
7644276260 .up => "ceilq",
7644376261 .zero => "truncq",
76444 } } } },
76262 } } },
7644576263 .unused,
7644676264 .unused,
7644776265 .unused,
......@@ -76468,12 +76286,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7646876286 .extra_temps = .{
7646976287 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7647076288 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
76471 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
76289 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7647276290 else => unreachable,
7647376291 .down => "floorq",
7647476292 .up => "ceilq",
7647576293 .zero => "truncq",
76476 } } } },
76294 } } },
7647776295 .unused,
7647876296 .unused,
7647976297 .unused,
......@@ -76503,12 +76321,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7650376321 .extra_temps = .{
7650476322 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7650576323 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
76506 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
76324 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7650776325 else => unreachable,
7650876326 .down => "floorq",
7650976327 .up => "ceilq",
7651076328 .zero => "truncq",
76511 } } } },
76329 } } },
7651276330 .unused,
7651376331 .unused,
7651476332 .unused,
......@@ -76538,12 +76356,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7653876356 .extra_temps = .{
7653976357 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
7654076358 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
76541 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
76359 .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
7654276360 else => unreachable,
7654376361 .down => "floorq",
7654476362 .up => "ceilq",
7654576363 .zero => "truncq",
76546 } } } },
76364 } } },
7654776365 .unused,
7654876366 .unused,
7654976367 .unused,
......@@ -77175,7 +76993,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7717576993 },
7717676994 .call_frame = .{ .alignment = .@"16" },
7717776995 .extra_temps = .{
77178 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
76996 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7717976997 .{ .type = .i32, .kind = .{ .reg = .eax } },
7718076998 .unused,
7718176999 .unused,
......@@ -77518,7 +77336,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7751877336 },
7751977337 .call_frame = .{ .alignment = .@"16" },
7752077338 .extra_temps = .{
77521 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
77339 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
7752277340 .{ .type = .i32, .kind = .{ .reg = .eax } },
7752377341 .unused,
7752477342 .unused,
......@@ -77679,7 +77497,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7767977497 },
7768077498 .call_frame = .{ .alignment = .@"16" },
7768177499 .extra_temps = .{
77682 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
77500 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7768377501 .{ .type = .i32, .kind = .{ .reg = .eax } },
7768477502 .unused,
7768577503 .unused,
......@@ -78046,7 +77864,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7804677864 },
7804777865 .call_frame = .{ .alignment = .@"16" },
7804877866 .extra_temps = .{
78049 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
77867 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
7805077868 .{ .type = .i32, .kind = .{ .reg = .eax } },
7805177869 .unused,
7805277870 .unused,
......@@ -78715,7 +78533,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7871578533 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7871678534 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
7871778535 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
78718 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
78536 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7871978537 .{ .type = .i32, .kind = .{ .reg = .eax } },
7872078538 .{ .type = .u8, .kind = .{ .reg = .cl } },
7872178539 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -78759,7 +78577,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7875978577 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7876078578 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
7876178579 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
78762 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
78580 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7876378581 .{ .type = .i32, .kind = .{ .reg = .eax } },
7876478582 .{ .type = .u8, .kind = .{ .reg = .cl } },
7876578583 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -78803,7 +78621,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7880378621 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7880478622 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
7880578623 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
78806 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
78624 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7880778625 .{ .type = .i32, .kind = .{ .reg = .eax } },
7880878626 .{ .type = .u8, .kind = .{ .reg = .cl } },
7880978627 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -78848,7 +78666,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7884878666 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7884978667 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
7885078668 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
78851 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
78669 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7885278670 .{ .type = .i32, .kind = .{ .reg = .eax } },
7885378671 .{ .type = .u8, .kind = .{ .reg = .cl } },
7885478672 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -78893,7 +78711,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7889378711 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7889478712 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
7889578713 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
78896 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
78714 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7889778715 .{ .type = .i32, .kind = .{ .reg = .eax } },
7889878716 .{ .type = .u8, .kind = .{ .reg = .cl } },
7889978717 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -78940,7 +78758,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7894078758 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
7894178759 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
7894278760 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
78943 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
78761 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7894478762 .{ .type = .i32, .kind = .{ .reg = .eax } },
7894578763 .{ .type = .u8, .kind = .{ .reg = .cl } },
7894678764 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -78987,7 +78805,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7898778805 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
7898878806 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
7898978807 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
78990 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
78808 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7899178809 .{ .type = .i32, .kind = .{ .reg = .eax } },
7899278810 .{ .type = .u8, .kind = .{ .reg = .cl } },
7899378811 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -79040,7 +78858,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7904078858 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
7904178859 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
7904278860 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
79043 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
78861 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7904478862 .{ .type = .i32, .kind = .{ .reg = .eax } },
7904578863 .{ .type = .u8, .kind = .{ .reg = .cl } },
7904678864 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -79093,7 +78911,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7909378911 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
7909478912 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
7909578913 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
79096 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
78914 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7909778915 .{ .type = .i32, .kind = .{ .reg = .eax } },
7909878916 .{ .type = .u8, .kind = .{ .reg = .cl } },
7909978917 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -79147,7 +78965,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7914778965 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
7914878966 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
7914978967 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
79150 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
78968 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7915178969 .{ .type = .i32, .kind = .{ .reg = .eax } },
7915278970 .{ .type = .u8, .kind = .{ .reg = .cl } },
7915378971 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -79201,7 +79019,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7920179019 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
7920279020 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
7920379021 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
79204 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
79022 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7920579023 .{ .type = .i32, .kind = .{ .reg = .eax } },
7920679024 .{ .type = .u8, .kind = .{ .reg = .cl } },
7920779025 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -79257,7 +79075,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
7925779075 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
7925879076 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
7925979077 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
79260 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
79078 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
7926179079 .{ .type = .i32, .kind = .{ .reg = .eax } },
7926279080 .{ .type = .u8, .kind = .{ .reg = .cl } },
7926379081 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -80084,7 +79902,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8008479902 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8008579903 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8008679904 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
80087 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
79905 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8008879906 .{ .type = .i32, .kind = .{ .reg = .eax } },
8008979907 .{ .type = .u8, .kind = .{ .reg = .cl } },
8009079908 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -80128,7 +79946,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8012879946 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8012979947 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8013079948 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
80131 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
79949 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8013279950 .{ .type = .i32, .kind = .{ .reg = .eax } },
8013379951 .{ .type = .u8, .kind = .{ .reg = .cl } },
8013479952 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -80172,7 +79990,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8017279990 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8017379991 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8017479992 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
80175 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
79993 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8017679994 .{ .type = .i32, .kind = .{ .reg = .eax } },
8017779995 .{ .type = .u8, .kind = .{ .reg = .cl } },
8017879996 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -80216,7 +80034,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8021680034 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8021780035 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8021880036 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
80219 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
80037 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8022080038 .{ .type = .i32, .kind = .{ .reg = .eax } },
8022180039 .{ .type = .u8, .kind = .{ .reg = .cl } },
8022280040 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -80260,7 +80078,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8026080078 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8026180079 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8026280080 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
80263 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
80081 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8026480082 .{ .type = .i32, .kind = .{ .reg = .eax } },
8026580083 .{ .type = .u8, .kind = .{ .reg = .cl } },
8026680084 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -80304,7 +80122,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8030480122 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8030580123 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8030680124 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
80307 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
80125 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8030880126 .{ .type = .i32, .kind = .{ .reg = .eax } },
8030980127 .{ .type = .u8, .kind = .{ .reg = .cl } },
8031080128 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -80348,7 +80166,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8034880166 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8034980167 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8035080168 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
80351 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
80169 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8035280170 .{ .type = .i32, .kind = .{ .reg = .eax } },
8035380171 .{ .type = .u8, .kind = .{ .reg = .cl } },
8035480172 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -80401,7 +80219,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8040180219 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8040280220 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8040380221 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
80404 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
80222 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8040580223 .{ .type = .i32, .kind = .{ .reg = .eax } },
8040680224 .{ .type = .u8, .kind = .{ .reg = .cl } },
8040780225 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -80454,7 +80272,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8045480272 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8045580273 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8045680274 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
80457 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
80275 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8045880276 .{ .type = .i32, .kind = .{ .reg = .eax } },
8045980277 .{ .type = .u8, .kind = .{ .reg = .cl } },
8046080278 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -80507,7 +80325,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8050780325 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8050880326 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8050980327 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
80510 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
80328 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8051180329 .{ .type = .i32, .kind = .{ .reg = .eax } },
8051280330 .{ .type = .u8, .kind = .{ .reg = .cl } },
8051380331 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -80560,7 +80378,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8056080378 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8056180379 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8056280380 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
80563 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
80381 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8056480382 .{ .type = .i32, .kind = .{ .reg = .eax } },
8056580383 .{ .type = .u8, .kind = .{ .reg = .cl } },
8056680384 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -80613,7 +80431,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8061380431 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8061480432 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8061580433 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
80616 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
80434 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8061780435 .{ .type = .i32, .kind = .{ .reg = .eax } },
8061880436 .{ .type = .u8, .kind = .{ .reg = .cl } },
8061980437 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -83223,7 +83041,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8322383041 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8322483042 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
8322583043 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
83226 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
83044 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
8322783045 .{ .type = .i32, .kind = .{ .reg = .eax } },
8322883046 .{ .type = .u8, .kind = .{ .reg = .cl } },
8322983047 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -83267,7 +83085,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8326783085 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8326883086 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
8326983087 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
83270 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
83088 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
8327183089 .{ .type = .i32, .kind = .{ .reg = .eax } },
8327283090 .{ .type = .u8, .kind = .{ .reg = .cl } },
8327383091 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -83311,7 +83129,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8331183129 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8331283130 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
8331383131 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
83314 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
83132 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
8331583133 .{ .type = .i32, .kind = .{ .reg = .eax } },
8331683134 .{ .type = .u8, .kind = .{ .reg = .cl } },
8331783135 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -83356,7 +83174,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8335683174 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8335783175 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
8335883176 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
83359 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
83177 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
8336083178 .{ .type = .i32, .kind = .{ .reg = .eax } },
8336183179 .{ .type = .u8, .kind = .{ .reg = .cl } },
8336283180 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -83401,7 +83219,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8340183219 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8340283220 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
8340383221 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
83404 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
83222 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
8340583223 .{ .type = .i32, .kind = .{ .reg = .eax } },
8340683224 .{ .type = .u8, .kind = .{ .reg = .cl } },
8340783225 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -83448,7 +83266,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8344883266 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8344983267 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
8345083268 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
83451 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
83269 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
8345283270 .{ .type = .i32, .kind = .{ .reg = .eax } },
8345383271 .{ .type = .u8, .kind = .{ .reg = .cl } },
8345483272 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -83495,7 +83313,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8349583313 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8349683314 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
8349783315 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
83498 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
83316 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
8349983317 .{ .type = .i32, .kind = .{ .reg = .eax } },
8350083318 .{ .type = .u8, .kind = .{ .reg = .cl } },
8350183319 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -83548,7 +83366,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8354883366 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8354983367 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
8355083368 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
83551 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
83369 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
8355283370 .{ .type = .i32, .kind = .{ .reg = .eax } },
8355383371 .{ .type = .u8, .kind = .{ .reg = .cl } },
8355483372 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -83601,7 +83419,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8360183419 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8360283420 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
8360383421 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
83604 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
83422 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
8360583423 .{ .type = .i32, .kind = .{ .reg = .eax } },
8360683424 .{ .type = .u8, .kind = .{ .reg = .cl } },
8360783425 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -83655,7 +83473,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8365583473 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8365683474 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
8365783475 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
83658 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
83476 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
8365983477 .{ .type = .i32, .kind = .{ .reg = .eax } },
8366083478 .{ .type = .u8, .kind = .{ .reg = .cl } },
8366183479 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -83709,7 +83527,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8370983527 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8371083528 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
8371183529 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
83712 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
83530 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
8371383531 .{ .type = .i32, .kind = .{ .reg = .eax } },
8371483532 .{ .type = .u8, .kind = .{ .reg = .cl } },
8371583533 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -83765,7 +83583,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8376583583 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8376683584 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
8376783585 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
83768 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
83586 .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
8376983587 .{ .type = .i32, .kind = .{ .reg = .eax } },
8377083588 .{ .type = .u8, .kind = .{ .reg = .cl } },
8377183589 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -84606,7 +84424,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8460684424 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8460784425 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8460884426 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
84609 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
84427 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8461084428 .{ .type = .i32, .kind = .{ .reg = .eax } },
8461184429 .{ .type = .u8, .kind = .{ .reg = .cl } },
8461284430 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -84650,7 +84468,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8465084468 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8465184469 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8465284470 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
84653 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
84471 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8465484472 .{ .type = .i32, .kind = .{ .reg = .eax } },
8465584473 .{ .type = .u8, .kind = .{ .reg = .cl } },
8465684474 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -84694,7 +84512,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8469484512 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8469584513 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8469684514 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
84697 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
84515 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8469884516 .{ .type = .i32, .kind = .{ .reg = .eax } },
8469984517 .{ .type = .u8, .kind = .{ .reg = .cl } },
8470084518 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -84738,7 +84556,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8473884556 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8473984557 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8474084558 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
84741 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
84559 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8474284560 .{ .type = .i32, .kind = .{ .reg = .eax } },
8474384561 .{ .type = .u8, .kind = .{ .reg = .cl } },
8474484562 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -84782,7 +84600,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8478284600 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8478384601 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8478484602 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
84785 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
84603 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8478684604 .{ .type = .i32, .kind = .{ .reg = .eax } },
8478784605 .{ .type = .u8, .kind = .{ .reg = .cl } },
8478884606 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -84826,7 +84644,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8482684644 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
8482784645 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8482884646 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
84829 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
84647 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8483084648 .{ .type = .i32, .kind = .{ .reg = .eax } },
8483184649 .{ .type = .u8, .kind = .{ .reg = .cl } },
8483284650 .{ .type = .u32, .kind = .{ .reg = .edx } },
......@@ -84870,7 +84688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8487084688 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8487184689 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8487284690 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
84873 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
84691 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8487484692 .{ .type = .i32, .kind = .{ .reg = .eax } },
8487584693 .{ .type = .u8, .kind = .{ .reg = .cl } },
8487684694 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -84923,7 +84741,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8492384741 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8492484742 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8492584743 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
84926 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
84744 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8492784745 .{ .type = .i32, .kind = .{ .reg = .eax } },
8492884746 .{ .type = .u8, .kind = .{ .reg = .cl } },
8492984747 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -84976,7 +84794,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8497684794 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8497784795 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8497884796 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
84979 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
84797 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8498084798 .{ .type = .i32, .kind = .{ .reg = .eax } },
8498184799 .{ .type = .u8, .kind = .{ .reg = .cl } },
8498284800 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -85029,7 +84847,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8502984847 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8503084848 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8503184849 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
85032 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
84850 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8503384851 .{ .type = .i32, .kind = .{ .reg = .eax } },
8503484852 .{ .type = .u8, .kind = .{ .reg = .cl } },
8503584853 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -85082,7 +84900,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8508284900 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8508384901 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8508484902 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
85085 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
84903 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8508684904 .{ .type = .i32, .kind = .{ .reg = .eax } },
8508784905 .{ .type = .u8, .kind = .{ .reg = .cl } },
8508884906 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -85135,7 +84953,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8513584953 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
8513684954 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
8513784955 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
85138 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
84956 .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
8513984957 .{ .type = .i32, .kind = .{ .reg = .eax } },
8514084958 .{ .type = .u8, .kind = .{ .reg = .cl } },
8514184959 .{ .type = .u64, .kind = .{ .reg = .rdx } },
......@@ -85191,7 +85009,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8519185009 .switch_dispatch => try cg.airSwitchDispatch(inst),
8519285010 .@"try", .try_cold => try cg.airTry(inst),
8519385011 .try_ptr, .try_ptr_cold => try cg.airTryPtr(inst),
85194 .dbg_stmt => if (cg.debug_output != .none) {
85012 .dbg_stmt => if (!cg.mod.strip) {
8519585013 const dbg_stmt = air_datas[@intFromEnum(inst)].dbg_stmt;
8519685014 _ = try cg.addInst(.{
8519785015 .tag = .pseudo,
......@@ -85202,7 +85020,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8520285020 } },
8520385021 });
8520485022 },
85205 .dbg_empty_stmt => if (cg.debug_output != .none) {
85023 .dbg_empty_stmt => if (!cg.mod.strip) {
8520685024 if (cg.mir_instructions.len > 0) {
8520785025 const prev_mir_op = &cg.mir_instructions.items(.ops)[cg.mir_instructions.len - 1];
8520885026 if (prev_mir_op.* == .pseudo_dbg_line_line_column)
......@@ -85216,23 +85034,27 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8521685034 const old_inline_func = cg.inline_func;
8521785035 defer cg.inline_func = old_inline_func;
8521885036 cg.inline_func = dbg_inline_block.data.func;
85219 if (cg.debug_output != .none) _ = try cg.addInst(.{
85037 if (!cg.mod.strip) _ = try cg.addInst(.{
8522085038 .tag = .pseudo,
8522185039 .ops = .pseudo_dbg_enter_inline_func,
85222 .data = .{ .func = dbg_inline_block.data.func },
85040 .data = .{ .ip_index = dbg_inline_block.data.func },
8522385041 });
8522485042 try cg.lowerBlock(inst, @ptrCast(cg.air.extra.items[dbg_inline_block.end..][0..dbg_inline_block.data.body_len]));
85225 if (cg.debug_output != .none) _ = try cg.addInst(.{
85043 if (!cg.mod.strip) _ = try cg.addInst(.{
8522685044 .tag = .pseudo,
8522785045 .ops = .pseudo_dbg_leave_inline_func,
85228 .data = .{ .func = old_inline_func },
85046 .data = .{ .ip_index = old_inline_func },
8522985047 });
8523085048 },
85231 .dbg_var_ptr,
85232 .dbg_var_val,
85233 .dbg_arg_inline,
85234 => if (use_old) try cg.airDbgVar(inst) else if (cg.debug_output != .none) {
85049 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => |air_tag| if (use_old) try cg.airDbgVar(inst) else if (!cg.mod.strip) {
8523585050 const pl_op = air_datas[@intFromEnum(inst)].pl_op;
85051 const air_name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
85052 const op_ty = cg.typeOf(pl_op.operand);
85053 const local_ty = switch (air_tag) {
85054 else => unreachable,
85055 .dbg_var_ptr => op_ty.childType(zcu),
85056 .dbg_var_val, .dbg_arg_inline => op_ty,
85057 };
8523685058 var ops = try cg.tempsFromOperands(inst, .{pl_op.operand});
8523785059 var mcv = ops[0].tracking(cg).short;
8523885060 switch (mcv) {
......@@ -85247,7 +85069,19 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8524785069 },
8524885070 },
8524985071 }
85250 try cg.genLocalDebugInfo(inst, ops[0].tracking(cg).short);
85072
85073 try cg.mir_locals.append(cg.gpa, .{
85074 .name = switch (air_name) {
85075 .none => switch (air_tag) {
85076 else => unreachable,
85077 .dbg_arg_inline => .none,
85078 },
85079 else => try cg.addString(air_name.toSlice(cg.air)),
85080 },
85081 .type = local_ty.toIntern(),
85082 });
85083
85084 try cg.genLocalDebugInfo(air_tag, local_ty, ops[0].tracking(cg).short);
8525185085 try ops[0].die(cg);
8525285086 },
8525385087 .is_null => if (use_old) try cg.airIsNull(inst) else {
......@@ -85435,11 +85269,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8543585269 .ret => try cg.airRet(inst, false),
8543685270 .ret_safe => try cg.airRet(inst, true),
8543785271 .ret_load => try cg.airRetLoad(inst),
85438 .store, .store_safe => |air_tag| if (use_old) try cg.airStore(inst, switch (air_tag) {
85439 else => unreachable,
85440 .store => false,
85441 .store_safe => true,
85442 }) else fallback: {
85272 .store, .store_safe => |air_tag| fallback: {
8544385273 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
8544485274 const ptr_ty = cg.typeOf(bin_op.lhs);
8544585275 const ptr_info = ptr_ty.ptrInfo(zcu);
......@@ -85513,7 +85343,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8551385343 },
8551485344 .call_frame = .{ .alignment = .@"16" },
8551585345 .extra_temps = .{
85516 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncsfhf2" } } },
85346 .{ .type = .usize, .kind = .{ .extern_func = "__truncsfhf2" } },
8551785347 .unused,
8551885348 .unused,
8551985349 .unused,
......@@ -85570,7 +85400,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8557085400 .extra_temps = .{
8557185401 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8557285402 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
85573 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncsfhf2" } } },
85403 .{ .type = .usize, .kind = .{ .extern_func = "__truncsfhf2" } },
8557485404 .unused,
8557585405 .unused,
8557685406 .unused,
......@@ -85601,7 +85431,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8560185431 .extra_temps = .{
8560285432 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8560385433 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
85604 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncsfhf2" } } },
85434 .{ .type = .usize, .kind = .{ .extern_func = "__truncsfhf2" } },
8560585435 .unused,
8560685436 .unused,
8560785437 .unused,
......@@ -85632,7 +85462,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8563285462 .extra_temps = .{
8563385463 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8563485464 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
85635 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncsfhf2" } } },
85465 .{ .type = .usize, .kind = .{ .extern_func = "__truncsfhf2" } },
8563685466 .{ .type = .f16, .kind = .{ .reg = .ax } },
8563785467 .unused,
8563885468 .unused,
......@@ -85664,7 +85494,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8566485494 .extra_temps = .{
8566585495 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8566685496 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
85667 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncsfhf2" } } },
85497 .{ .type = .usize, .kind = .{ .extern_func = "__truncsfhf2" } },
8566885498 .{ .type = .f32, .kind = .mem },
8566985499 .{ .type = .f16, .kind = .{ .reg = .ax } },
8567085500 .unused,
......@@ -85695,7 +85525,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8569585525 },
8569685526 .call_frame = .{ .alignment = .@"16" },
8569785527 .extra_temps = .{
85698 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncdfhf2" } } },
85528 .{ .type = .usize, .kind = .{ .extern_func = "__truncdfhf2" } },
8569985529 .unused,
8570085530 .unused,
8570185531 .unused,
......@@ -85723,7 +85553,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8572385553 .extra_temps = .{
8572485554 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8572585555 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
85726 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncdfhf2" } } },
85556 .{ .type = .usize, .kind = .{ .extern_func = "__truncdfhf2" } },
8572785557 .unused,
8572885558 .unused,
8572985559 .unused,
......@@ -85754,7 +85584,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8575485584 .extra_temps = .{
8575585585 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8575685586 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
85757 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncdfhf2" } } },
85587 .{ .type = .usize, .kind = .{ .extern_func = "__truncdfhf2" } },
8575885588 .unused,
8575985589 .unused,
8576085590 .unused,
......@@ -85785,7 +85615,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8578585615 .extra_temps = .{
8578685616 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8578785617 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
85788 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncdfhf2" } } },
85618 .{ .type = .usize, .kind = .{ .extern_func = "__truncdfhf2" } },
8578985619 .{ .type = .f16, .kind = .{ .reg = .ax } },
8579085620 .unused,
8579185621 .unused,
......@@ -85817,7 +85647,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8581785647 .extra_temps = .{
8581885648 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8581985649 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
85820 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncdfhf2" } } },
85650 .{ .type = .usize, .kind = .{ .extern_func = "__truncdfhf2" } },
8582185651 .{ .type = .f32, .kind = .mem },
8582285652 .{ .type = .f16, .kind = .{ .reg = .ax } },
8582385653 .unused,
......@@ -86034,7 +85864,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8603485864 .call_frame = .{ .size = 16, .alignment = .@"16" },
8603585865 .extra_temps = .{
8603685866 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
86037 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
85867 .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
8603885868 .unused,
8603985869 .unused,
8604085870 .unused,
......@@ -86062,7 +85892,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8606285892 .call_frame = .{ .size = 16, .alignment = .@"16" },
8606385893 .extra_temps = .{
8606485894 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
86065 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
85895 .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
8606685896 .unused,
8606785897 .unused,
8606885898 .unused,
......@@ -86090,7 +85920,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8609085920 .call_frame = .{ .size = 16, .alignment = .@"16" },
8609185921 .extra_temps = .{
8609285922 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
86093 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
85923 .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
8609485924 .unused,
8609585925 .unused,
8609685926 .unused,
......@@ -86120,7 +85950,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8612085950 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8612185951 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
8612285952 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
86123 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
85953 .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
8612485954 .unused,
8612585955 .unused,
8612685956 .unused,
......@@ -86152,7 +85982,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8615285982 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8615385983 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
8615485984 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
86155 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
85985 .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
8615685986 .unused,
8615785987 .unused,
8615885988 .unused,
......@@ -86184,7 +86014,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8618486014 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8618586015 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
8618686016 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
86187 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
86017 .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
8618886018 .{ .type = .f16, .kind = .{ .reg = .ax } },
8618986019 .unused,
8619086020 .unused,
......@@ -86217,7 +86047,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8621786047 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8621886048 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
8621986049 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
86220 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
86050 .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
8622186051 .{ .type = .f16, .kind = .{ .reg = .ax } },
8622286052 .unused,
8622386053 .unused,
......@@ -86358,7 +86188,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8635886188 },
8635986189 .call_frame = .{ .alignment = .@"16" },
8636086190 .extra_temps = .{
86361 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfhf2" } } },
86191 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfhf2" } },
8636286192 .unused,
8636386193 .unused,
8636486194 .unused,
......@@ -86386,7 +86216,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8638686216 .extra_temps = .{
8638786217 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8638886218 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
86389 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfhf2" } } },
86219 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfhf2" } },
8639086220 .unused,
8639186221 .unused,
8639286222 .unused,
......@@ -86417,7 +86247,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8641786247 .extra_temps = .{
8641886248 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8641986249 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
86420 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfhf2" } } },
86250 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfhf2" } },
8642186251 .unused,
8642286252 .unused,
8642386253 .unused,
......@@ -86448,7 +86278,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8644886278 .extra_temps = .{
8644986279 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8645086280 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
86451 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfhf2" } } },
86281 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfhf2" } },
8645286282 .{ .type = .f16, .kind = .{ .reg = .ax } },
8645386283 .unused,
8645486284 .unused,
......@@ -86480,7 +86310,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8648086310 .extra_temps = .{
8648186311 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8648286312 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
86483 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfhf2" } } },
86313 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfhf2" } },
8648486314 .{ .type = .f32, .kind = .mem },
8648586315 .{ .type = .f16, .kind = .{ .reg = .ax } },
8648686316 .unused,
......@@ -86511,7 +86341,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8651186341 },
8651286342 .call_frame = .{ .alignment = .@"16" },
8651386343 .extra_temps = .{
86514 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfsf2" } } },
86344 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfsf2" } },
8651586345 .unused,
8651686346 .unused,
8651786347 .unused,
......@@ -86539,7 +86369,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8653986369 .extra_temps = .{
8654086370 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8654186371 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
86542 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfsf2" } } },
86372 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfsf2" } },
8654386373 .unused,
8654486374 .unused,
8654586375 .unused,
......@@ -86570,7 +86400,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8657086400 .extra_temps = .{
8657186401 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8657286402 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
86573 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfsf2" } } },
86403 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfsf2" } },
8657486404 .unused,
8657586405 .unused,
8657686406 .unused,
......@@ -86601,7 +86431,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8660186431 .extra_temps = .{
8660286432 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8660386433 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
86604 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfsf2" } } },
86434 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfsf2" } },
8660586435 .unused,
8660686436 .unused,
8660786437 .unused,
......@@ -86630,7 +86460,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8663086460 },
8663186461 .call_frame = .{ .alignment = .@"16" },
8663286462 .extra_temps = .{
86633 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfdf2" } } },
86463 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfdf2" } },
8663486464 .unused,
8663586465 .unused,
8663686466 .unused,
......@@ -86658,7 +86488,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8665886488 .extra_temps = .{
8665986489 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8666086490 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
86661 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfdf2" } } },
86491 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfdf2" } },
8666286492 .unused,
8666386493 .unused,
8666486494 .unused,
......@@ -86689,7 +86519,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8668986519 .extra_temps = .{
8669086520 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8669186521 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
86692 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfdf2" } } },
86522 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfdf2" } },
8669386523 .unused,
8669486524 .unused,
8669586525 .unused,
......@@ -86720,7 +86550,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8672086550 .extra_temps = .{
8672186551 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8672286552 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
86723 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfdf2" } } },
86553 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfdf2" } },
8672486554 .unused,
8672586555 .unused,
8672686556 .unused,
......@@ -86749,7 +86579,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8674986579 },
8675086580 .call_frame = .{ .alignment = .@"16" },
8675186581 .extra_temps = .{
86752 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfxf2" } } },
86582 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfxf2" } },
8675386583 .unused,
8675486584 .unused,
8675586585 .unused,
......@@ -86777,7 +86607,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8677786607 .extra_temps = .{
8677886608 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8677986609 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
86780 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfxf2" } } },
86610 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfxf2" } },
8678186611 .unused,
8678286612 .unused,
8678386613 .unused,
......@@ -86809,7 +86639,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8680986639 .extra_temps = .{
8681086640 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8681186641 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
86812 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfxf2" } } },
86642 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfxf2" } },
8681386643 .unused,
8681486644 .unused,
8681586645 .unused,
......@@ -86841,7 +86671,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8684186671 .extra_temps = .{
8684286672 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8684386673 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
86844 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfxf2" } } },
86674 .{ .type = .usize, .kind = .{ .extern_func = "__trunctfxf2" } },
8684586675 .unused,
8684686676 .unused,
8684786677 .unused,
......@@ -86921,7 +86751,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8692186751 },
8692286752 .call_frame = .{ .alignment = .@"16" },
8692386753 .extra_temps = .{
86924 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfsf2" } } },
86754 .{ .type = .usize, .kind = .{ .extern_func = "__extendhfsf2" } },
8692586755 .unused,
8692686756 .unused,
8692786757 .unused,
......@@ -86978,7 +86808,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8697886808 .extra_temps = .{
8697986809 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8698086810 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
86981 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfsf2" } } },
86811 .{ .type = .usize, .kind = .{ .extern_func = "__extendhfsf2" } },
8698286812 .unused,
8698386813 .unused,
8698486814 .unused,
......@@ -87010,7 +86840,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8701086840 .extra_temps = .{
8701186841 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8701286842 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
87013 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfsf2" } } },
86843 .{ .type = .usize, .kind = .{ .extern_func = "__extendhfsf2" } },
8701486844 .unused,
8701586845 .unused,
8701686846 .unused,
......@@ -87044,7 +86874,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8704486874 .{ .type = .f16, .kind = .{ .reg = .ax } },
8704586875 .{ .type = .f32, .kind = .mem },
8704686876 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
87047 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfsf2" } } },
86877 .{ .type = .usize, .kind = .{ .extern_func = "__extendhfsf2" } },
8704886878 .unused,
8704986879 .unused,
8705086880 .unused,
......@@ -87141,7 +86971,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8714186971 },
8714286972 .call_frame = .{ .alignment = .@"16" },
8714386973 .extra_temps = .{
87144 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfdf2" } } },
86974 .{ .type = .usize, .kind = .{ .extern_func = "__extendhfdf2" } },
8714586975 .unused,
8714686976 .unused,
8714786977 .unused,
......@@ -87202,7 +87032,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8720287032 .extra_temps = .{
8720387033 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8720487034 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
87205 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfdf2" } } },
87035 .{ .type = .usize, .kind = .{ .extern_func = "__extendhfdf2" } },
8720687036 .unused,
8720787037 .unused,
8720887038 .unused,
......@@ -87234,7 +87064,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8723487064 .extra_temps = .{
8723587065 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8723687066 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
87237 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfdf2" } } },
87067 .{ .type = .usize, .kind = .{ .extern_func = "__extendhfdf2" } },
8723887068 .unused,
8723987069 .unused,
8724087070 .unused,
......@@ -87268,7 +87098,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8726887098 .{ .type = .f16, .kind = .{ .reg = .ax } },
8726987099 .{ .type = .f32, .kind = .mem },
8727087100 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
87271 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfdf2" } } },
87101 .{ .type = .usize, .kind = .{ .extern_func = "__extendhfdf2" } },
8727287102 .unused,
8727387103 .unused,
8727487104 .unused,
......@@ -87324,7 +87154,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8732487154 },
8732587155 .call_frame = .{ .alignment = .@"16" },
8732687156 .extra_temps = .{
87327 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfxf2" } } },
87157 .{ .type = .usize, .kind = .{ .extern_func = "__extendhfxf2" } },
8732887158 .unused,
8732987159 .unused,
8733087160 .unused,
......@@ -87352,7 +87182,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8735287182 .extra_temps = .{
8735387183 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8735487184 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
87355 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfxf2" } } },
87185 .{ .type = .usize, .kind = .{ .extern_func = "__extendhfxf2" } },
8735687186 .unused,
8735787187 .unused,
8735887188 .unused,
......@@ -87385,7 +87215,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8738587215 .extra_temps = .{
8738687216 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8738787217 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
87388 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfxf2" } } },
87218 .{ .type = .usize, .kind = .{ .extern_func = "__extendhfxf2" } },
8738987219 .unused,
8739087220 .unused,
8739187221 .unused,
......@@ -87420,7 +87250,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8742087250 .{ .type = .f16, .kind = .{ .reg = .ax } },
8742187251 .{ .type = .f32, .kind = .mem },
8742287252 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
87423 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfxf2" } } },
87253 .{ .type = .usize, .kind = .{ .extern_func = "__extendhfxf2" } },
8742487254 .unused,
8742587255 .unused,
8742687256 .unused,
......@@ -87450,7 +87280,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8745087280 },
8745187281 .call_frame = .{ .alignment = .@"16" },
8745287282 .extra_temps = .{
87453 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhftf2" } } },
87283 .{ .type = .usize, .kind = .{ .extern_func = "__extendhftf2" } },
8745487284 .unused,
8745587285 .unused,
8745687286 .unused,
......@@ -87478,7 +87308,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8747887308 .extra_temps = .{
8747987309 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8748087310 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
87481 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhftf2" } } },
87311 .{ .type = .usize, .kind = .{ .extern_func = "__extendhftf2" } },
8748287312 .unused,
8748387313 .unused,
8748487314 .unused,
......@@ -87510,7 +87340,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8751087340 .extra_temps = .{
8751187341 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8751287342 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
87513 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhftf2" } } },
87343 .{ .type = .usize, .kind = .{ .extern_func = "__extendhftf2" } },
8751487344 .unused,
8751587345 .unused,
8751687346 .unused,
......@@ -87544,7 +87374,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8754487374 .{ .type = .f16, .kind = .{ .reg = .ax } },
8754587375 .{ .type = .f32, .kind = .mem },
8754687376 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
87547 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhftf2" } } },
87377 .{ .type = .usize, .kind = .{ .extern_func = "__extendhftf2" } },
8754887378 .unused,
8754987379 .unused,
8755087380 .unused,
......@@ -87811,7 +87641,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8781187641 },
8781287642 .call_frame = .{ .alignment = .@"16" },
8781387643 .extra_temps = .{
87814 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendsftf2" } } },
87644 .{ .type = .usize, .kind = .{ .extern_func = "__extendsftf2" } },
8781587645 .unused,
8781687646 .unused,
8781787647 .unused,
......@@ -87839,7 +87669,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8783987669 .extra_temps = .{
8784087670 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8784187671 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
87842 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendsftf2" } } },
87672 .{ .type = .usize, .kind = .{ .extern_func = "__extendsftf2" } },
8784387673 .unused,
8784487674 .unused,
8784587675 .unused,
......@@ -87870,7 +87700,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8787087700 .extra_temps = .{
8787187701 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8787287702 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
87873 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendsftf2" } } },
87703 .{ .type = .usize, .kind = .{ .extern_func = "__extendsftf2" } },
8787487704 .unused,
8787587705 .unused,
8787687706 .unused,
......@@ -87901,7 +87731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8790187731 .extra_temps = .{
8790287732 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8790387733 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
87904 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendsftf2" } } },
87734 .{ .type = .usize, .kind = .{ .extern_func = "__extendsftf2" } },
8790587735 .unused,
8790687736 .unused,
8790787737 .unused,
......@@ -87984,7 +87814,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8798487814 },
8798587815 .call_frame = .{ .alignment = .@"16" },
8798687816 .extra_temps = .{
87987 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extenddftf2" } } },
87817 .{ .type = .usize, .kind = .{ .extern_func = "__extenddftf2" } },
8798887818 .unused,
8798987819 .unused,
8799087820 .unused,
......@@ -88012,7 +87842,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8801287842 .extra_temps = .{
8801387843 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8801487844 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
88015 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extenddftf2" } } },
87845 .{ .type = .usize, .kind = .{ .extern_func = "__extenddftf2" } },
8801687846 .unused,
8801787847 .unused,
8801887848 .unused,
......@@ -88043,7 +87873,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8804387873 .extra_temps = .{
8804487874 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8804587875 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
88046 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extenddftf2" } } },
87876 .{ .type = .usize, .kind = .{ .extern_func = "__extenddftf2" } },
8804787877 .unused,
8804887878 .unused,
8804987879 .unused,
......@@ -88074,7 +87904,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8807487904 .extra_temps = .{
8807587905 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8807687906 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
88077 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extenddftf2" } } },
87907 .{ .type = .usize, .kind = .{ .extern_func = "__extenddftf2" } },
8807887908 .unused,
8807987909 .unused,
8808087910 .unused,
......@@ -88105,7 +87935,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8810587935 .call_frame = .{ .size = 16, .alignment = .@"16" },
8810687936 .extra_temps = .{
8810787937 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
88108 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendxftf2" } } },
87938 .{ .type = .usize, .kind = .{ .extern_func = "__extendxftf2" } },
8810987939 .unused,
8811087940 .unused,
8811187941 .unused,
......@@ -88133,7 +87963,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8813387963 .call_frame = .{ .size = 16, .alignment = .@"16" },
8813487964 .extra_temps = .{
8813587965 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
88136 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendxftf2" } } },
87966 .{ .type = .usize, .kind = .{ .extern_func = "__extendxftf2" } },
8813787967 .unused,
8813887968 .unused,
8813987969 .unused,
......@@ -88161,7 +87991,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8816187991 .call_frame = .{ .size = 16, .alignment = .@"16" },
8816287992 .extra_temps = .{
8816387993 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
88164 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendxftf2" } } },
87994 .{ .type = .usize, .kind = .{ .extern_func = "__extendxftf2" } },
8816587995 .unused,
8816687996 .unused,
8816787997 .unused,
......@@ -88191,7 +88021,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8819188021 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8819288022 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
8819388023 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
88194 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendxftf2" } } },
88024 .{ .type = .usize, .kind = .{ .extern_func = "__extendxftf2" } },
8819588025 .unused,
8819688026 .unused,
8819788027 .unused,
......@@ -88223,7 +88053,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8822388053 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8822488054 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
8822588055 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
88226 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendxftf2" } } },
88056 .{ .type = .usize, .kind = .{ .extern_func = "__extendxftf2" } },
8822788057 .unused,
8822888058 .unused,
8822988059 .unused,
......@@ -88255,7 +88085,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8825588085 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
8825688086 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
8825788087 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
88258 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendxftf2" } } },
88088 .{ .type = .usize, .kind = .{ .extern_func = "__extendxftf2" } },
8825988089 .unused,
8826088090 .unused,
8826188091 .unused,
......@@ -99006,9 +98836,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9900698836 } }) catch |err| switch (err) {
9900798837 error.SelectFailed => {
9900898838 const elem_size = res_ty.abiSize(zcu);
99009 const base = try cg.tempAllocReg(.usize, abi.RegisterClass.gp);
98839 var base = try cg.tempAllocReg(.usize, abi.RegisterClass.gp);
9901098840 while (try ops[0].toBase(false, cg) or
99011 try ops[1].toRegClass(true, .general_purpose, cg))
98841 try ops[1].toRegClass(true, .general_purpose, cg) or
98842 try base.toRegClass(true, .general_purpose, cg))
9901298843 {}
9901398844 const base_reg = base.tracking(cg).short.register.to64();
9901498845 const rhs_reg = ops[1].tracking(cg).short.register.to64();
......@@ -99449,7 +99280,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9944999280 },
9945099281 .call_frame = .{ .alignment = .@"16" },
9945199282 .extra_temps = .{
99452 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
99283 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
9945399284 .unused,
9945499285 .unused,
9945599286 .unused,
......@@ -99475,7 +99306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9947599306 },
9947699307 .call_frame = .{ .alignment = .@"16" },
9947799308 .extra_temps = .{
99478 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfsi" } } },
99309 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfsi" } },
9947999310 .unused,
9948099311 .unused,
9948199312 .unused,
......@@ -99501,7 +99332,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9950199332 },
9950299333 .call_frame = .{ .alignment = .@"16" },
9950399334 .extra_temps = .{
99504 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfdi" } } },
99335 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfdi" } },
9950599336 .unused,
9950699337 .unused,
9950799338 .unused,
......@@ -99527,7 +99358,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9952799358 },
9952899359 .call_frame = .{ .alignment = .@"16" },
9952999360 .extra_temps = .{
99530 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfdi" } } },
99361 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfdi" } },
9953199362 .unused,
9953299363 .unused,
9953399364 .unused,
......@@ -99553,7 +99384,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9955399384 },
9955499385 .call_frame = .{ .alignment = .@"16" },
9955599386 .extra_temps = .{
99556 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfti" } } },
99387 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfti" } },
9955799388 .unused,
9955899389 .unused,
9955999390 .unused,
......@@ -99579,7 +99410,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9957999410 },
9958099411 .call_frame = .{ .alignment = .@"16" },
9958199412 .extra_temps = .{
99582 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfti" } } },
99413 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfti" } },
9958399414 .unused,
9958499415 .unused,
9958599416 .unused,
......@@ -99605,7 +99436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9960599436 },
9960699437 .call_frame = .{ .alignment = .@"16" },
9960799438 .extra_temps = .{
99608 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfdi" } } },
99439 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfdi" } },
9960999440 .{ .type = .i64, .kind = .{ .reg = .rax } },
9961099441 .{ .type = .usize, .kind = .{ .reg = .rdi } },
9961199442 .{ .type = .u32, .kind = .{ .reg = .ecx } },
......@@ -99636,7 +99467,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9963699467 },
9963799468 .call_frame = .{ .alignment = .@"16" },
9963899469 .extra_temps = .{
99639 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfdi" } } },
99470 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfdi" } },
9964099471 .{ .type = .i64, .kind = .{ .reg = .rax } },
9964199472 .{ .type = .usize, .kind = .{ .reg = .rdi } },
9964299473 .{ .type = .u32, .kind = .{ .reg = .ecx } },
......@@ -99730,7 +99561,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9973099561 .extra_temps = .{
9973199562 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
9973299563 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
99733 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
99564 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
9973499565 .{ .type = .i32, .kind = .{ .reg = .eax } },
9973599566 .unused,
9973699567 .unused,
......@@ -99762,7 +99593,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9976299593 .extra_temps = .{
9976399594 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
9976499595 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
99765 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
99596 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
9976699597 .{ .type = .i32, .kind = .{ .reg = .eax } },
9976799598 .unused,
9976899599 .unused,
......@@ -99794,7 +99625,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9979499625 .extra_temps = .{
9979599626 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
9979699627 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
99797 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
99628 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
9979899629 .{ .type = .i32, .kind = .{ .reg = .eax } },
9979999630 .unused,
9980099631 .unused,
......@@ -99826,7 +99657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9982699657 .extra_temps = .{
9982799658 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
9982899659 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
99829 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
99660 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
9983099661 .{ .type = .i32, .kind = .{ .reg = .eax } },
9983199662 .unused,
9983299663 .unused,
......@@ -99860,7 +99691,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9986099691 .{ .type = .i32, .kind = .{ .reg = .eax } },
9986199692 .{ .type = .f32, .kind = .mem },
9986299693 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
99863 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
99694 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
9986499695 .unused,
9986599696 .unused,
9986699697 .unused,
......@@ -99893,7 +99724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9989399724 .{ .type = .i32, .kind = .{ .reg = .eax } },
9989499725 .{ .type = .f32, .kind = .mem },
9989599726 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
99896 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
99727 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
9989799728 .unused,
9989899729 .unused,
9989999730 .unused,
......@@ -100014,7 +99845,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
10001499845 .extra_temps = .{
10001599846 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
10001699847 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100017 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
99848 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
10001899849 .{ .type = .i32, .kind = .{ .reg = .eax } },
10001999850 .unused,
10002099851 .unused,
......@@ -100046,7 +99877,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
10004699877 .extra_temps = .{
10004799878 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
10004899879 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100049 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
99880 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
10005099881 .{ .type = .i32, .kind = .{ .reg = .eax } },
10005199882 .unused,
10005299883 .unused,
......@@ -100080,7 +99911,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
10008099911 .{ .type = .i32, .kind = .{ .reg = .eax } },
10008199912 .{ .type = .f32, .kind = .mem },
10008299913 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100083 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
99914 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
10008499915 .unused,
10008599916 .unused,
10008699917 .unused,
......@@ -100173,7 +100004,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100173100004 .extra_temps = .{
100174100005 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
100175100006 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100176 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
100007 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
100177100008 .{ .type = .i32, .kind = .{ .reg = .eax } },
100178100009 .unused,
100179100010 .unused,
......@@ -100205,7 +100036,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100205100036 .extra_temps = .{
100206100037 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
100207100038 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100208 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfsi" } } },
100039 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfsi" } },
100209100040 .{ .type = .u32, .kind = .{ .reg = .eax } },
100210100041 .unused,
100211100042 .unused,
......@@ -100237,7 +100068,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100237100068 .extra_temps = .{
100238100069 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
100239100070 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100240 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
100071 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
100241100072 .{ .type = .i32, .kind = .{ .reg = .eax } },
100242100073 .unused,
100243100074 .unused,
......@@ -100269,7 +100100,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100269100100 .extra_temps = .{
100270100101 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
100271100102 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100272 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfsi" } } },
100103 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfsi" } },
100273100104 .{ .type = .u32, .kind = .{ .reg = .eax } },
100274100105 .unused,
100275100106 .unused,
......@@ -100303,7 +100134,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100303100134 .{ .type = .i32, .kind = .{ .reg = .eax } },
100304100135 .{ .type = .f32, .kind = .mem },
100305100136 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100306 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
100137 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
100307100138 .unused,
100308100139 .unused,
100309100140 .unused,
......@@ -100336,7 +100167,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100336100167 .{ .type = .u32, .kind = .{ .reg = .eax } },
100337100168 .{ .type = .f32, .kind = .mem },
100338100169 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100339 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfsi" } } },
100170 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfsi" } },
100340100171 .unused,
100341100172 .unused,
100342100173 .unused,
......@@ -100399,7 +100230,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100399100230 .extra_temps = .{
100400100231 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
100401100232 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100402 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfdi" } } },
100233 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfdi" } },
100403100234 .{ .type = .i64, .kind = .{ .reg = .rax } },
100404100235 .unused,
100405100236 .unused,
......@@ -100431,7 +100262,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100431100262 .extra_temps = .{
100432100263 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
100433100264 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100434 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfdi" } } },
100265 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfdi" } },
100435100266 .{ .type = .u64, .kind = .{ .reg = .rax } },
100436100267 .unused,
100437100268 .unused,
......@@ -100463,7 +100294,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100463100294 .extra_temps = .{
100464100295 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
100465100296 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100466 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfdi" } } },
100297 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfdi" } },
100467100298 .{ .type = .i64, .kind = .{ .reg = .rax } },
100468100299 .unused,
100469100300 .unused,
......@@ -100495,7 +100326,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100495100326 .extra_temps = .{
100496100327 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
100497100328 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100498 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfdi" } } },
100329 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfdi" } },
100499100330 .{ .type = .u64, .kind = .{ .reg = .rax } },
100500100331 .unused,
100501100332 .unused,
......@@ -100529,7 +100360,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100529100360 .{ .type = .i64, .kind = .{ .reg = .rax } },
100530100361 .{ .type = .f32, .kind = .mem },
100531100362 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100532 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfdi" } } },
100363 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfdi" } },
100533100364 .unused,
100534100365 .unused,
100535100366 .unused,
......@@ -100562,7 +100393,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100562100393 .{ .type = .u64, .kind = .{ .reg = .rax } },
100563100394 .{ .type = .f32, .kind = .mem },
100564100395 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100565 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfdi" } } },
100396 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfdi" } },
100566100397 .unused,
100567100398 .unused,
100568100399 .unused,
......@@ -100593,7 +100424,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100593100424 .extra_temps = .{
100594100425 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
100595100426 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100596 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfti" } } },
100427 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfti" } },
100597100428 .{ .type = .u64, .kind = .{ .reg = .rax } },
100598100429 .{ .type = .i64, .kind = .{ .reg = .rdx } },
100599100430 .unused,
......@@ -100626,7 +100457,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100626100457 .extra_temps = .{
100627100458 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
100628100459 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100629 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfti" } } },
100460 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfti" } },
100630100461 .{ .type = .u64, .kind = .{ .reg = .rax } },
100631100462 .{ .type = .u64, .kind = .{ .reg = .rdx } },
100632100463 .unused,
......@@ -100659,7 +100490,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100659100490 .extra_temps = .{
100660100491 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
100661100492 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100662 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfti" } } },
100493 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfti" } },
100663100494 .{ .type = .u64, .kind = .{ .reg = .rax } },
100664100495 .{ .type = .i64, .kind = .{ .reg = .rdx } },
100665100496 .unused,
......@@ -100692,7 +100523,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100692100523 .extra_temps = .{
100693100524 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
100694100525 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100695 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfti" } } },
100526 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfti" } },
100696100527 .{ .type = .u64, .kind = .{ .reg = .rax } },
100697100528 .{ .type = .u64, .kind = .{ .reg = .rdx } },
100698100529 .unused,
......@@ -100727,7 +100558,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100727100558 .{ .type = .u64, .kind = .{ .reg = .rax } },
100728100559 .{ .type = .f32, .kind = .mem },
100729100560 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100730 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfti" } } },
100561 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfti" } },
100731100562 .{ .type = .i64, .kind = .{ .reg = .rdx } },
100732100563 .unused,
100733100564 .unused,
......@@ -100761,7 +100592,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100761100592 .{ .type = .u64, .kind = .{ .reg = .rax } },
100762100593 .{ .type = .f32, .kind = .mem },
100763100594 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100764 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfti" } } },
100595 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfti" } },
100765100596 .{ .type = .u64, .kind = .{ .reg = .rdx } },
100766100597 .unused,
100767100598 .unused,
......@@ -100796,7 +100627,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100796100627 .{ .type = .usize, .kind = .{ .reg = .rdi } },
100797100628 .{ .type = .usize, .kind = .{ .reg = .rsi } },
100798100629 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100799 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfei" } } },
100630 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfei" } },
100800100631 .unused,
100801100632 .unused,
100802100633 .unused,
......@@ -100831,7 +100662,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100831100662 .{ .type = .usize, .kind = .{ .reg = .rdi } },
100832100663 .{ .type = .usize, .kind = .{ .reg = .rsi } },
100833100664 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100834 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfei" } } },
100665 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfei" } },
100835100666 .unused,
100836100667 .unused,
100837100668 .unused,
......@@ -100866,7 +100697,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100866100697 .{ .type = .usize, .kind = .{ .reg = .rdi } },
100867100698 .{ .type = .usize, .kind = .{ .reg = .rsi } },
100868100699 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100869 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfei" } } },
100700 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfei" } },
100870100701 .unused,
100871100702 .unused,
100872100703 .unused,
......@@ -100901,7 +100732,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100901100732 .{ .type = .usize, .kind = .{ .reg = .rdi } },
100902100733 .{ .type = .usize, .kind = .{ .reg = .rsi } },
100903100734 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100904 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfei" } } },
100735 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfei" } },
100905100736 .unused,
100906100737 .unused,
100907100738 .unused,
......@@ -100937,7 +100768,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100937100768 .{ .type = .usize, .kind = .{ .reg = .rsi } },
100938100769 .{ .type = .f32, .kind = .mem },
100939100770 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100940 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfei" } } },
100771 .{ .type = .usize, .kind = .{ .extern_func = "__fixhfei" } },
100941100772 .unused,
100942100773 .unused,
100943100774 .unused,
......@@ -100973,7 +100804,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100973100804 .{ .type = .usize, .kind = .{ .reg = .rsi } },
100974100805 .{ .type = .f32, .kind = .mem },
100975100806 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
100976 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfei" } } },
100807 .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfei" } },
100977100808 .unused,
100978100809 .unused,
100979100810 .unused,
......@@ -101115,7 +100946,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101115100946 },
101116100947 .call_frame = .{ .alignment = .@"16" },
101117100948 .extra_temps = .{
101118 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfti" } } },
100949 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfti" } },
101119100950 .unused,
101120100951 .unused,
101121100952 .unused,
......@@ -101141,7 +100972,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101141100972 },
101142100973 .call_frame = .{ .alignment = .@"16" },
101143100974 .extra_temps = .{
101144 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
100975 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
101145100976 .unused,
101146100977 .unused,
101147100978 .unused,
......@@ -101170,7 +101001,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101170101001 .{ .type = .i64, .kind = .{ .rc = .general_purpose } },
101171101002 .{ .type = .i64, .kind = .{ .reg = .rax } },
101172101003 .{ .type = .vector_4_f32, .kind = .{ .smax_mem = .{} } },
101173 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
101004 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
101174101005 .{ .type = .i64, .kind = .{ .reg = .rdx } },
101175101006 .{ .type = .usize, .kind = .{ .reg = .rdi } },
101176101007 .{ .type = .u32, .kind = .{ .reg = .ecx } },
......@@ -101211,7 +101042,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101211101042 .{ .type = .i64, .kind = .{ .rc = .general_purpose } },
101212101043 .{ .type = .i64, .kind = .{ .reg = .rax } },
101213101044 .{ .type = .vector_4_f32, .kind = .{ .smax_mem = .{} } },
101214 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
101045 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
101215101046 .{ .type = .i64, .kind = .{ .reg = .rdx } },
101216101047 .{ .type = .usize, .kind = .{ .reg = .rdi } },
101217101048 .{ .type = .u32, .kind = .{ .reg = .ecx } },
......@@ -101252,7 +101083,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101252101083 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
101253101084 .{ .type = .i64, .kind = .{ .reg = .rax } },
101254101085 .{ .type = .vector_4_f32, .kind = .{ .smax_mem = .{} } },
101255 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
101086 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
101256101087 .{ .type = .u32, .kind = .{ .reg = .ecx } },
101257101088 .{ .type = .i64, .kind = .{ .reg = .rdx } },
101258101089 .{ .type = .usize, .kind = .{ .reg = .rdi } },
......@@ -101290,7 +101121,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101290101121 },
101291101122 .call_frame = .{ .alignment = .@"16" },
101292101123 .extra_temps = .{
101293 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
101124 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
101294101125 .{ .type = .i64, .kind = .{ .reg = .rax } },
101295101126 .{ .type = .i64, .kind = .{ .reg = .rdx } },
101296101127 .{ .type = .usize, .kind = .{ .reg = .rdi } },
......@@ -101500,7 +101331,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101500101331 .extra_temps = .{
101501101332 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
101502101333 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
101503 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
101334 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
101504101335 .{ .type = .i32, .kind = .{ .reg = .eax } },
101505101336 .unused,
101506101337 .unused,
......@@ -101531,7 +101362,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101531101362 .extra_temps = .{
101532101363 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
101533101364 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
101534 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
101365 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
101535101366 .{ .type = .i32, .kind = .{ .reg = .eax } },
101536101367 .unused,
101537101368 .unused,
......@@ -101562,7 +101393,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101562101393 .extra_temps = .{
101563101394 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
101564101395 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
101565 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
101396 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
101566101397 .{ .type = .i32, .kind = .{ .reg = .eax } },
101567101398 .unused,
101568101399 .unused,
......@@ -101593,7 +101424,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101593101424 .extra_temps = .{
101594101425 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
101595101426 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
101596 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
101427 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
101597101428 .{ .type = .i32, .kind = .{ .reg = .eax } },
101598101429 .unused,
101599101430 .unused,
......@@ -101796,7 +101627,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101796101627 .extra_temps = .{
101797101628 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
101798101629 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
101799 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
101630 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
101800101631 .{ .type = .i32, .kind = .{ .reg = .eax } },
101801101632 .unused,
101802101633 .unused,
......@@ -101827,7 +101658,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101827101658 .extra_temps = .{
101828101659 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
101829101660 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
101830 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
101661 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
101831101662 .{ .type = .i32, .kind = .{ .reg = .eax } },
101832101663 .unused,
101833101664 .unused,
......@@ -101940,7 +101771,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101940101771 .extra_temps = .{
101941101772 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
101942101773 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
101943 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
101774 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
101944101775 .{ .type = .i32, .kind = .{ .reg = .eax } },
101945101776 .unused,
101946101777 .unused,
......@@ -101971,7 +101802,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
101971101802 .extra_temps = .{
101972101803 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
101973101804 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
101974 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfsi" } } },
101805 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfsi" } },
101975101806 .{ .type = .u32, .kind = .{ .reg = .eax } },
101976101807 .unused,
101977101808 .unused,
......@@ -102002,7 +101833,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102002101833 .extra_temps = .{
102003101834 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
102004101835 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102005 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
101836 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
102006101837 .{ .type = .i32, .kind = .{ .reg = .eax } },
102007101838 .unused,
102008101839 .unused,
......@@ -102033,7 +101864,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102033101864 .extra_temps = .{
102034101865 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
102035101866 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102036 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfsi" } } },
101867 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfsi" } },
102037101868 .{ .type = .u32, .kind = .{ .reg = .eax } },
102038101869 .unused,
102039101870 .unused,
......@@ -102122,7 +101953,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102122101953 .extra_temps = .{
102123101954 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
102124101955 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102125 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfdi" } } },
101956 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfdi" } },
102126101957 .{ .type = .i64, .kind = .{ .reg = .rax } },
102127101958 .unused,
102128101959 .unused,
......@@ -102153,7 +101984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102153101984 .extra_temps = .{
102154101985 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
102155101986 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102156 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfdi" } } },
101987 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfdi" } },
102157101988 .{ .type = .u64, .kind = .{ .reg = .rax } },
102158101989 .unused,
102159101990 .unused,
......@@ -102184,7 +102015,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102184102015 .extra_temps = .{
102185102016 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
102186102017 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102187 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfdi" } } },
102018 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfdi" } },
102188102019 .{ .type = .i64, .kind = .{ .reg = .rax } },
102189102020 .unused,
102190102021 .unused,
......@@ -102215,7 +102046,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102215102046 .extra_temps = .{
102216102047 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
102217102048 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102218 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfdi" } } },
102049 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfdi" } },
102219102050 .{ .type = .u64, .kind = .{ .reg = .rax } },
102220102051 .unused,
102221102052 .unused,
......@@ -102246,7 +102077,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102246102077 .extra_temps = .{
102247102078 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
102248102079 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102249 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfti" } } },
102080 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfti" } },
102250102081 .{ .type = .u64, .kind = .{ .reg = .rax } },
102251102082 .{ .type = .i64, .kind = .{ .reg = .rdx } },
102252102083 .unused,
......@@ -102278,7 +102109,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102278102109 .extra_temps = .{
102279102110 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
102280102111 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102281 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
102112 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
102282102113 .{ .type = .u64, .kind = .{ .reg = .rax } },
102283102114 .{ .type = .u64, .kind = .{ .reg = .rdx } },
102284102115 .unused,
......@@ -102310,7 +102141,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102310102141 .extra_temps = .{
102311102142 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
102312102143 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102313 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfti" } } },
102144 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfti" } },
102314102145 .{ .type = .u64, .kind = .{ .reg = .rax } },
102315102146 .{ .type = .i64, .kind = .{ .reg = .rdx } },
102316102147 .unused,
......@@ -102342,7 +102173,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102342102173 .extra_temps = .{
102343102174 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
102344102175 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102345 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
102176 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
102346102177 .{ .type = .u64, .kind = .{ .reg = .rax } },
102347102178 .{ .type = .u64, .kind = .{ .reg = .rdx } },
102348102179 .unused,
......@@ -102377,7 +102208,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102377102208 .{ .type = .usize, .kind = .{ .reg = .rdi } },
102378102209 .{ .type = .usize, .kind = .{ .reg = .rsi } },
102379102210 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102380 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfei" } } },
102211 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfei" } },
102381102212 .unused,
102382102213 .unused,
102383102214 .unused,
......@@ -102411,7 +102242,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102411102242 .{ .type = .usize, .kind = .{ .reg = .rdi } },
102412102243 .{ .type = .usize, .kind = .{ .reg = .rsi } },
102413102244 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102414 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfei" } } },
102245 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfei" } },
102415102246 .unused,
102416102247 .unused,
102417102248 .unused,
......@@ -102445,7 +102276,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102445102276 .{ .type = .usize, .kind = .{ .reg = .rdi } },
102446102277 .{ .type = .usize, .kind = .{ .reg = .rsi } },
102447102278 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102448 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfei" } } },
102279 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfei" } },
102449102280 .unused,
102450102281 .unused,
102451102282 .unused,
......@@ -102479,7 +102310,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102479102310 .{ .type = .usize, .kind = .{ .reg = .rdi } },
102480102311 .{ .type = .usize, .kind = .{ .reg = .rsi } },
102481102312 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
102482 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfei" } } },
102313 .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfei" } },
102483102314 .unused,
102484102315 .unused,
102485102316 .unused,
......@@ -102818,7 +102649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102818102649 },
102819102650 .call_frame = .{ .alignment = .@"16" },
102820102651 .extra_temps = .{
102821 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfti" } } },
102652 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfti" } },
102822102653 .unused,
102823102654 .unused,
102824102655 .unused,
......@@ -102844,7 +102675,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102844102675 },
102845102676 .call_frame = .{ .alignment = .@"16" },
102846102677 .extra_temps = .{
102847 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfti" } } },
102678 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfti" } },
102848102679 .unused,
102849102680 .unused,
102850102681 .unused,
......@@ -102872,7 +102703,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102872102703 .extra_temps = .{
102873102704 .{ .type = .usize, .kind = .{ .reg = .rdi } },
102874102705 .{ .type = .usize, .kind = .{ .reg = .rsi } },
102875 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfei" } } },
102706 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfei" } },
102876102707 .unused,
102877102708 .unused,
102878102709 .unused,
......@@ -102900,7 +102731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
102900102731 .extra_temps = .{
102901102732 .{ .type = .usize, .kind = .{ .reg = .rdi } },
102902102733 .{ .type = .usize, .kind = .{ .reg = .rsi } },
102903 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfei" } } },
102734 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfei" } },
102904102735 .unused,
102905102736 .unused,
102906102737 .unused,
......@@ -103205,7 +103036,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
103205103036 .extra_temps = .{
103206103037 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
103207103038 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
103208 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
103039 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
103209103040 .{ .type = .i32, .kind = .{ .reg = .eax } },
103210103041 .unused,
103211103042 .unused,
......@@ -103236,7 +103067,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
103236103067 .extra_temps = .{
103237103068 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
103238103069 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
103239 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
103070 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
103240103071 .{ .type = .i32, .kind = .{ .reg = .eax } },
103241103072 .unused,
103242103073 .unused,
......@@ -103267,7 +103098,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
103267103098 .extra_temps = .{
103268103099 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
103269103100 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
103270 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
103101 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
103271103102 .{ .type = .i32, .kind = .{ .reg = .eax } },
103272103103 .unused,
103273103104 .unused,
......@@ -103298,7 +103129,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
103298103129 .extra_temps = .{
103299103130 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
103300103131 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
103301 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
103132 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
103302103133 .{ .type = .i32, .kind = .{ .reg = .eax } },
103303103134 .unused,
103304103135 .unused,
......@@ -103329,7 +103160,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
103329103160 .extra_temps = .{
103330103161 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
103331103162 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
103332 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
103163 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
103333103164 .{ .type = .i32, .kind = .{ .reg = .eax } },
103334103165 .unused,
103335103166 .unused,
......@@ -103361,7 +103192,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
103361103192 .extra_temps = .{
103362103193 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
103363103194 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
103364 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
103195 .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
103365103196 .{ .type = .i32, .kind = .{ .reg = .eax } },
103366103197 .unused,
103367103198 .unused,
......@@ -103692,7 +103523,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
103692103523 .extra_temps = .{
103693103524 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
103694103525 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
103695 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
103526 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
103696103527 .{ .type = .i32, .kind = .{ .reg = .eax } },
103697103528 .unused,
103698103529 .unused,
......@@ -103723,7 +103554,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
103723103554 .extra_temps = .{
103724103555 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
103725103556 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
103726 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
103557 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
103727103558 .{ .type = .i32, .kind = .{ .reg = .eax } },
103728103559 .unused,
103729103560 .unused,
......@@ -103754,7 +103585,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
103754103585 .extra_temps = .{
103755103586 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
103756103587 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
103757 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
103588 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
103758103589 .{ .type = .i32, .kind = .{ .reg = .eax } },
103759103590 .unused,
103760103591 .unused,
......@@ -103952,7 +103783,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
103952103783 .extra_temps = .{
103953103784 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
103954103785 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
103955 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
103786 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
103956103787 .{ .type = .i32, .kind = .{ .reg = .eax } },
103957103788 .unused,
103958103789 .unused,
......@@ -103983,7 +103814,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
103983103814 .extra_temps = .{
103984103815 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
103985103816 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
103986 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfsi" } } },
103817 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfsi" } },
103987103818 .{ .type = .u32, .kind = .{ .reg = .eax } },
103988103819 .unused,
103989103820 .unused,
......@@ -104014,7 +103845,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104014103845 .extra_temps = .{
104015103846 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104016103847 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104017 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
103848 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
104018103849 .{ .type = .i32, .kind = .{ .reg = .eax } },
104019103850 .unused,
104020103851 .unused,
......@@ -104045,7 +103876,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104045103876 .extra_temps = .{
104046103877 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104047103878 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104048 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfsi" } } },
103879 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfsi" } },
104049103880 .{ .type = .u32, .kind = .{ .reg = .eax } },
104050103881 .unused,
104051103882 .unused,
......@@ -104076,7 +103907,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104076103907 .extra_temps = .{
104077103908 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104078103909 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104079 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
103910 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
104080103911 .{ .type = .i32, .kind = .{ .reg = .eax } },
104081103912 .unused,
104082103913 .unused,
......@@ -104108,7 +103939,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104108103939 .extra_temps = .{
104109103940 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104110103941 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104111 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfsi" } } },
103942 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfsi" } },
104112103943 .{ .type = .u32, .kind = .{ .reg = .eax } },
104113103944 .unused,
104114103945 .unused,
......@@ -104233,7 +104064,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104233104064 .extra_temps = .{
104234104065 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104235104066 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104236 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfdi" } } },
104067 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfdi" } },
104237104068 .{ .type = .i64, .kind = .{ .reg = .rax } },
104238104069 .unused,
104239104070 .unused,
......@@ -104264,7 +104095,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104264104095 .extra_temps = .{
104265104096 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104266104097 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104267 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfdi" } } },
104098 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfdi" } },
104268104099 .{ .type = .u64, .kind = .{ .reg = .rax } },
104269104100 .unused,
104270104101 .unused,
......@@ -104295,7 +104126,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104295104126 .extra_temps = .{
104296104127 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104297104128 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104298 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfdi" } } },
104129 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfdi" } },
104299104130 .{ .type = .i64, .kind = .{ .reg = .rax } },
104300104131 .unused,
104301104132 .unused,
......@@ -104326,7 +104157,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104326104157 .extra_temps = .{
104327104158 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104328104159 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104329 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfdi" } } },
104160 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfdi" } },
104330104161 .{ .type = .u64, .kind = .{ .reg = .rax } },
104331104162 .unused,
104332104163 .unused,
......@@ -104357,7 +104188,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104357104188 .extra_temps = .{
104358104189 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104359104190 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104360 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfdi" } } },
104191 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfdi" } },
104361104192 .{ .type = .i64, .kind = .{ .reg = .rax } },
104362104193 .unused,
104363104194 .unused,
......@@ -104389,7 +104220,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104389104220 .extra_temps = .{
104390104221 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104391104222 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104392 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfdi" } } },
104223 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfdi" } },
104393104224 .{ .type = .u64, .kind = .{ .reg = .rax } },
104394104225 .unused,
104395104226 .unused,
......@@ -104421,7 +104252,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104421104252 .extra_temps = .{
104422104253 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104423104254 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104424 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfti" } } },
104255 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfti" } },
104425104256 .{ .type = .u64, .kind = .{ .reg = .rax } },
104426104257 .{ .type = .i64, .kind = .{ .reg = .rdx } },
104427104258 .unused,
......@@ -104453,7 +104284,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104453104284 .extra_temps = .{
104454104285 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104455104286 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104456 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfti" } } },
104287 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfti" } },
104457104288 .{ .type = .u64, .kind = .{ .reg = .rax } },
104458104289 .{ .type = .u64, .kind = .{ .reg = .rdx } },
104459104290 .unused,
......@@ -104485,7 +104316,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104485104316 .extra_temps = .{
104486104317 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104487104318 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104488 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfti" } } },
104319 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfti" } },
104489104320 .{ .type = .u64, .kind = .{ .reg = .rax } },
104490104321 .{ .type = .i64, .kind = .{ .reg = .rdx } },
104491104322 .unused,
......@@ -104517,7 +104348,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104517104348 .extra_temps = .{
104518104349 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104519104350 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104520 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfti" } } },
104351 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfti" } },
104521104352 .{ .type = .u64, .kind = .{ .reg = .rax } },
104522104353 .{ .type = .u64, .kind = .{ .reg = .rdx } },
104523104354 .unused,
......@@ -104549,7 +104380,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104549104380 .extra_temps = .{
104550104381 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104551104382 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104552 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfti" } } },
104383 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfti" } },
104553104384 .{ .type = .u64, .kind = .{ .reg = .rax } },
104554104385 .{ .type = .i64, .kind = .{ .reg = .rdx } },
104555104386 .unused,
......@@ -104582,7 +104413,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104582104413 .extra_temps = .{
104583104414 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
104584104415 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104585 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfti" } } },
104416 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfti" } },
104586104417 .{ .type = .u64, .kind = .{ .reg = .rax } },
104587104418 .{ .type = .u64, .kind = .{ .reg = .rdx } },
104588104419 .unused,
......@@ -104618,7 +104449,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104618104449 .{ .type = .usize, .kind = .{ .reg = .rdi } },
104619104450 .{ .type = .usize, .kind = .{ .reg = .rsi } },
104620104451 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104621 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfei" } } },
104452 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfei" } },
104622104453 .unused,
104623104454 .unused,
104624104455 .unused,
......@@ -104652,7 +104483,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104652104483 .{ .type = .usize, .kind = .{ .reg = .rdi } },
104653104484 .{ .type = .usize, .kind = .{ .reg = .rsi } },
104654104485 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104655 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfei" } } },
104486 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfei" } },
104656104487 .unused,
104657104488 .unused,
104658104489 .unused,
......@@ -104686,7 +104517,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104686104517 .{ .type = .usize, .kind = .{ .reg = .rdi } },
104687104518 .{ .type = .usize, .kind = .{ .reg = .rsi } },
104688104519 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104689 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfei" } } },
104520 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfei" } },
104690104521 .unused,
104691104522 .unused,
104692104523 .unused,
......@@ -104720,7 +104551,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104720104551 .{ .type = .usize, .kind = .{ .reg = .rdi } },
104721104552 .{ .type = .usize, .kind = .{ .reg = .rsi } },
104722104553 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104723 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfei" } } },
104554 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfei" } },
104724104555 .unused,
104725104556 .unused,
104726104557 .unused,
......@@ -104754,7 +104585,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104754104585 .{ .type = .usize, .kind = .{ .reg = .rdi } },
104755104586 .{ .type = .usize, .kind = .{ .reg = .rsi } },
104756104587 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104757 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfei" } } },
104588 .{ .type = .usize, .kind = .{ .extern_func = "__fixdfei" } },
104758104589 .unused,
104759104590 .unused,
104760104591 .unused,
......@@ -104789,7 +104620,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104789104620 .{ .type = .usize, .kind = .{ .reg = .rdi } },
104790104621 .{ .type = .usize, .kind = .{ .reg = .rsi } },
104791104622 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
104792 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfei" } } },
104623 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfei" } },
104793104624 .unused,
104794104625 .unused,
104795104626 .unused,
......@@ -105810,7 +105641,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
105810105641 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
105811105642 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
105812105643 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
105813 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
105644 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
105814105645 .{ .type = .u64, .kind = .{ .reg = .rax } },
105815105646 .unused,
105816105647 .unused,
......@@ -105842,7 +105673,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
105842105673 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
105843105674 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
105844105675 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
105845 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
105676 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
105846105677 .{ .type = .u64, .kind = .{ .reg = .rax } },
105847105678 .unused,
105848105679 .unused,
......@@ -105874,7 +105705,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
105874105705 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
105875105706 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
105876105707 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
105877 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
105708 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
105878105709 .{ .type = .u64, .kind = .{ .reg = .rax } },
105879105710 .unused,
105880105711 .unused,
......@@ -105905,7 +105736,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
105905105736 .extra_temps = .{
105906105737 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
105907105738 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
105908 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfti" } } },
105739 .{ .type = .usize, .kind = .{ .extern_func = "__fixxfti" } },
105909105740 .unused,
105910105741 .unused,
105911105742 .unused,
......@@ -105933,7 +105764,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
105933105764 .extra_temps = .{
105934105765 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
105935105766 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
105936 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
105767 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
105937105768 .unused,
105938105769 .unused,
105939105770 .unused,
......@@ -105961,7 +105792,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
105961105792 .extra_temps = .{
105962105793 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
105963105794 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
105964 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfti" } } },
105795 .{ .type = .usize, .kind = .{ .extern_func = "__fixxfti" } },
105965105796 .unused,
105966105797 .unused,
105967105798 .unused,
......@@ -105989,7 +105820,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
105989105820 .extra_temps = .{
105990105821 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
105991105822 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
105992 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
105823 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
105993105824 .unused,
105994105825 .unused,
105995105826 .unused,
......@@ -106017,7 +105848,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106017105848 .extra_temps = .{
106018105849 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106019105850 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106020 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfti" } } },
105851 .{ .type = .usize, .kind = .{ .extern_func = "__fixxfti" } },
106021105852 .unused,
106022105853 .unused,
106023105854 .unused,
......@@ -106045,7 +105876,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106045105876 .extra_temps = .{
106046105877 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106047105878 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106048 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
105879 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
106049105880 .unused,
106050105881 .unused,
106051105882 .unused,
......@@ -106074,7 +105905,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106074105905 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106075105906 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106076105907 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106077 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfti" } } },
105908 .{ .type = .usize, .kind = .{ .extern_func = "__fixxfti" } },
106078105909 .{ .type = .u64, .kind = .{ .reg = .rax } },
106079105910 .{ .type = .i64, .kind = .{ .reg = .rdx } },
106080105911 .unused,
......@@ -106107,7 +105938,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106107105938 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106108105939 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106109105940 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106110 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
105941 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
106111105942 .{ .type = .u64, .kind = .{ .reg = .rax } },
106112105943 .{ .type = .u64, .kind = .{ .reg = .rdx } },
106113105944 .unused,
......@@ -106140,7 +105971,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106140105971 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106141105972 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106142105973 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106143 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfti" } } },
105974 .{ .type = .usize, .kind = .{ .extern_func = "__fixxfti" } },
106144105975 .{ .type = .u64, .kind = .{ .reg = .rax } },
106145105976 .{ .type = .i64, .kind = .{ .reg = .rdx } },
106146105977 .unused,
......@@ -106173,7 +106004,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106173106004 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106174106005 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106175106006 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106176 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
106007 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
106177106008 .{ .type = .u64, .kind = .{ .reg = .rax } },
106178106009 .{ .type = .u64, .kind = .{ .reg = .rdx } },
106179106010 .unused,
......@@ -106206,7 +106037,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106206106037 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106207106038 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106208106039 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106209 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfti" } } },
106040 .{ .type = .usize, .kind = .{ .extern_func = "__fixxfti" } },
106210106041 .{ .type = .u64, .kind = .{ .reg = .rax } },
106211106042 .{ .type = .i64, .kind = .{ .reg = .rdx } },
106212106043 .unused,
......@@ -106239,7 +106070,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106239106070 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106240106071 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106241106072 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106242 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
106073 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
106243106074 .{ .type = .u64, .kind = .{ .reg = .rax } },
106244106075 .{ .type = .u64, .kind = .{ .reg = .rdx } },
106245106076 .unused,
......@@ -106273,7 +106104,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106273106104 .{ .type = .usize, .kind = .{ .reg = .rsi } },
106274106105 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106275106106 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106276 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfei" } } },
106107 .{ .type = .usize, .kind = .{ .extern_func = "__fixxfei" } },
106277106108 .unused,
106278106109 .unused,
106279106110 .unused,
......@@ -106303,7 +106134,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106303106134 .{ .type = .usize, .kind = .{ .reg = .rsi } },
106304106135 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106305106136 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106306 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfei" } } },
106137 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfei" } },
106307106138 .unused,
106308106139 .unused,
106309106140 .unused,
......@@ -106333,7 +106164,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106333106164 .{ .type = .usize, .kind = .{ .reg = .rsi } },
106334106165 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106335106166 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106336 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfei" } } },
106167 .{ .type = .usize, .kind = .{ .extern_func = "__fixxfei" } },
106337106168 .unused,
106338106169 .unused,
106339106170 .unused,
......@@ -106363,7 +106194,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106363106194 .{ .type = .usize, .kind = .{ .reg = .rsi } },
106364106195 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106365106196 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106366 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfei" } } },
106197 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfei" } },
106367106198 .unused,
106368106199 .unused,
106369106200 .unused,
......@@ -106393,7 +106224,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106393106224 .{ .type = .usize, .kind = .{ .reg = .rsi } },
106394106225 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106395106226 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106396 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfei" } } },
106227 .{ .type = .usize, .kind = .{ .extern_func = "__fixxfei" } },
106397106228 .unused,
106398106229 .unused,
106399106230 .unused,
......@@ -106423,7 +106254,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106423106254 .{ .type = .usize, .kind = .{ .reg = .rsi } },
106424106255 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106425106256 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106426 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfei" } } },
106257 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfei" } },
106427106258 .unused,
106428106259 .unused,
106429106260 .unused,
......@@ -106455,7 +106286,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106455106286 .{ .type = .usize, .kind = .{ .reg = .rsi } },
106456106287 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106457106288 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106458 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfei" } } },
106289 .{ .type = .usize, .kind = .{ .extern_func = "__fixxfei" } },
106459106290 .unused,
106460106291 .unused,
106461106292 .unused,
......@@ -106490,7 +106321,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106490106321 .{ .type = .usize, .kind = .{ .reg = .rsi } },
106491106322 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106492106323 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106493 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfei" } } },
106324 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfei" } },
106494106325 .unused,
106495106326 .unused,
106496106327 .unused,
......@@ -106525,7 +106356,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106525106356 .{ .type = .usize, .kind = .{ .reg = .rsi } },
106526106357 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106527106358 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106528 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfei" } } },
106359 .{ .type = .usize, .kind = .{ .extern_func = "__fixxfei" } },
106529106360 .unused,
106530106361 .unused,
106531106362 .unused,
......@@ -106560,7 +106391,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106560106391 .{ .type = .usize, .kind = .{ .reg = .rsi } },
106561106392 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106562106393 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106563 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfei" } } },
106394 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfei" } },
106564106395 .unused,
106565106396 .unused,
106566106397 .unused,
......@@ -106595,7 +106426,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106595106426 .{ .type = .usize, .kind = .{ .reg = .rsi } },
106596106427 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106597106428 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106598 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfei" } } },
106429 .{ .type = .usize, .kind = .{ .extern_func = "__fixxfei" } },
106599106430 .unused,
106600106431 .unused,
106601106432 .unused,
......@@ -106630,7 +106461,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106630106461 .{ .type = .usize, .kind = .{ .reg = .rsi } },
106631106462 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
106632106463 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
106633 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfei" } } },
106464 .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfei" } },
106634106465 .unused,
106635106466 .unused,
106636106467 .unused,
......@@ -106662,7 +106493,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106662106493 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
106663106494 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106664106495 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
106665 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106496 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
106666106497 .{ .type = .i32, .kind = .{ .reg = .eax } },
106667106498 .unused,
106668106499 .unused,
......@@ -106695,7 +106526,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106695106526 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
106696106527 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106697106528 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
106698 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106529 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
106699106530 .{ .type = .i32, .kind = .{ .reg = .eax } },
106700106531 .unused,
106701106532 .unused,
......@@ -106728,7 +106559,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106728106559 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
106729106560 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106730106561 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
106731 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106562 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
106732106563 .{ .type = .i32, .kind = .{ .reg = .eax } },
106733106564 .unused,
106734106565 .unused,
......@@ -106761,7 +106592,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106761106592 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
106762106593 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106763106594 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
106764 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106595 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
106765106596 .{ .type = .i32, .kind = .{ .reg = .eax } },
106766106597 .unused,
106767106598 .unused,
......@@ -106794,7 +106625,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106794106625 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
106795106626 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106796106627 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
106797 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106628 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
106798106629 .{ .type = .i32, .kind = .{ .reg = .eax } },
106799106630 .unused,
106800106631 .unused,
......@@ -106827,7 +106658,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106827106658 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
106828106659 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106829106660 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
106830 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106661 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
106831106662 .{ .type = .i32, .kind = .{ .reg = .eax } },
106832106663 .unused,
106833106664 .unused,
......@@ -106859,7 +106690,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106859106690 .extra_temps = .{
106860106691 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106861106692 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
106862 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106693 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
106863106694 .{ .type = .i32, .kind = .{ .reg = .eax } },
106864106695 .unused,
106865106696 .unused,
......@@ -106890,7 +106721,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106890106721 .extra_temps = .{
106891106722 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106892106723 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
106893 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106724 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
106894106725 .{ .type = .i32, .kind = .{ .reg = .eax } },
106895106726 .unused,
106896106727 .unused,
......@@ -106921,7 +106752,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106921106752 .extra_temps = .{
106922106753 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
106923106754 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
106924 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106755 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
106925106756 .{ .type = .i32, .kind = .{ .reg = .eax } },
106926106757 .unused,
106927106758 .unused,
......@@ -106950,7 +106781,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106950106781 },
106951106782 .call_frame = .{ .alignment = .@"16" },
106952106783 .extra_temps = .{
106953 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106784 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
106954106785 .unused,
106955106786 .unused,
106956106787 .unused,
......@@ -106976,7 +106807,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
106976106807 },
106977106808 .call_frame = .{ .alignment = .@"16" },
106978106809 .extra_temps = .{
106979 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfsi" } } },
106810 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfsi" } },
106980106811 .unused,
106981106812 .unused,
106982106813 .unused,
......@@ -107004,7 +106835,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107004106835 .extra_temps = .{
107005106836 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107006106837 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107007 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106838 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
107008106839 .{ .type = .i32, .kind = .{ .reg = .eax } },
107009106840 .unused,
107010106841 .unused,
......@@ -107035,7 +106866,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107035106866 .extra_temps = .{
107036106867 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107037106868 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107038 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfsi" } } },
106869 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfsi" } },
107039106870 .{ .type = .u32, .kind = .{ .reg = .eax } },
107040106871 .unused,
107041106872 .unused,
......@@ -107066,7 +106897,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107066106897 .extra_temps = .{
107067106898 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107068106899 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107069 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106900 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
107070106901 .{ .type = .i32, .kind = .{ .reg = .eax } },
107071106902 .unused,
107072106903 .unused,
......@@ -107097,7 +106928,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107097106928 .extra_temps = .{
107098106929 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107099106930 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107100 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfsi" } } },
106931 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfsi" } },
107101106932 .{ .type = .u32, .kind = .{ .reg = .eax } },
107102106933 .unused,
107103106934 .unused,
......@@ -107128,7 +106959,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107128106959 .extra_temps = .{
107129106960 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107130106961 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107131 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
106962 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
107132106963 .{ .type = .i32, .kind = .{ .reg = .eax } },
107133106964 .unused,
107134106965 .unused,
......@@ -107159,7 +106990,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107159106990 .extra_temps = .{
107160106991 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107161106992 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107162 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfsi" } } },
106993 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfsi" } },
107163106994 .{ .type = .u32, .kind = .{ .reg = .eax } },
107164106995 .unused,
107165106996 .unused,
......@@ -107188,7 +107019,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107188107019 },
107189107020 .call_frame = .{ .alignment = .@"16" },
107190107021 .extra_temps = .{
107191 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfdi" } } },
107022 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfdi" } },
107192107023 .unused,
107193107024 .unused,
107194107025 .unused,
......@@ -107214,7 +107045,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107214107045 },
107215107046 .call_frame = .{ .alignment = .@"16" },
107216107047 .extra_temps = .{
107217 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfdi" } } },
107048 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfdi" } },
107218107049 .unused,
107219107050 .unused,
107220107051 .unused,
......@@ -107242,7 +107073,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107242107073 .extra_temps = .{
107243107074 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107244107075 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107245 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfdi" } } },
107076 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfdi" } },
107246107077 .{ .type = .i64, .kind = .{ .reg = .rax } },
107247107078 .unused,
107248107079 .unused,
......@@ -107273,7 +107104,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107273107104 .extra_temps = .{
107274107105 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107275107106 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107276 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfdi" } } },
107107 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfdi" } },
107277107108 .{ .type = .u64, .kind = .{ .reg = .rax } },
107278107109 .unused,
107279107110 .unused,
......@@ -107304,7 +107135,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107304107135 .extra_temps = .{
107305107136 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107306107137 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107307 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfdi" } } },
107138 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfdi" } },
107308107139 .{ .type = .i64, .kind = .{ .reg = .rax } },
107309107140 .unused,
107310107141 .unused,
......@@ -107335,7 +107166,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107335107166 .extra_temps = .{
107336107167 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107337107168 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107338 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfdi" } } },
107169 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfdi" } },
107339107170 .{ .type = .u64, .kind = .{ .reg = .rax } },
107340107171 .unused,
107341107172 .unused,
......@@ -107366,7 +107197,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107366107197 .extra_temps = .{
107367107198 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107368107199 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107369 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfdi" } } },
107200 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfdi" } },
107370107201 .{ .type = .i64, .kind = .{ .reg = .rax } },
107371107202 .unused,
107372107203 .unused,
......@@ -107397,7 +107228,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107397107228 .extra_temps = .{
107398107229 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107399107230 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107400 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfdi" } } },
107231 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfdi" } },
107401107232 .{ .type = .u64, .kind = .{ .reg = .rax } },
107402107233 .unused,
107403107234 .unused,
......@@ -107426,7 +107257,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107426107257 },
107427107258 .call_frame = .{ .alignment = .@"16" },
107428107259 .extra_temps = .{
107429 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfti" } } },
107260 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfti" } },
107430107261 .unused,
107431107262 .unused,
107432107263 .unused,
......@@ -107452,7 +107283,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107452107283 },
107453107284 .call_frame = .{ .alignment = .@"16" },
107454107285 .extra_temps = .{
107455 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfti" } } },
107286 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfti" } },
107456107287 .unused,
107457107288 .unused,
107458107289 .unused,
......@@ -107480,7 +107311,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107480107311 .extra_temps = .{
107481107312 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107482107313 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107483 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfti" } } },
107314 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfti" } },
107484107315 .{ .type = .u64, .kind = .{ .reg = .rax } },
107485107316 .{ .type = .i64, .kind = .{ .reg = .rdx } },
107486107317 .unused,
......@@ -107512,7 +107343,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107512107343 .extra_temps = .{
107513107344 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107514107345 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107515 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfti" } } },
107346 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfti" } },
107516107347 .{ .type = .u64, .kind = .{ .reg = .rax } },
107517107348 .{ .type = .u64, .kind = .{ .reg = .rdx } },
107518107349 .unused,
......@@ -107544,7 +107375,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107544107375 .extra_temps = .{
107545107376 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107546107377 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107547 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfti" } } },
107378 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfti" } },
107548107379 .{ .type = .u64, .kind = .{ .reg = .rax } },
107549107380 .{ .type = .i64, .kind = .{ .reg = .rdx } },
107550107381 .unused,
......@@ -107576,7 +107407,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107576107407 .extra_temps = .{
107577107408 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107578107409 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107579 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfti" } } },
107410 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfti" } },
107580107411 .{ .type = .u64, .kind = .{ .reg = .rax } },
107581107412 .{ .type = .u64, .kind = .{ .reg = .rdx } },
107582107413 .unused,
......@@ -107608,7 +107439,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107608107439 .extra_temps = .{
107609107440 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107610107441 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107611 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfti" } } },
107442 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfti" } },
107612107443 .{ .type = .u64, .kind = .{ .reg = .rax } },
107613107444 .{ .type = .i64, .kind = .{ .reg = .rdx } },
107614107445 .unused,
......@@ -107640,7 +107471,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107640107471 .extra_temps = .{
107641107472 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
107642107473 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107643 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfti" } } },
107474 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfti" } },
107644107475 .{ .type = .u64, .kind = .{ .reg = .rax } },
107645107476 .{ .type = .u64, .kind = .{ .reg = .rdx } },
107646107477 .unused,
......@@ -107672,7 +107503,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107672107503 .extra_temps = .{
107673107504 .{ .type = .usize, .kind = .{ .reg = .rdi } },
107674107505 .{ .type = .usize, .kind = .{ .reg = .rsi } },
107675 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfei" } } },
107506 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfei" } },
107676107507 .unused,
107677107508 .unused,
107678107509 .unused,
......@@ -107700,7 +107531,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107700107531 .extra_temps = .{
107701107532 .{ .type = .usize, .kind = .{ .reg = .rdi } },
107702107533 .{ .type = .usize, .kind = .{ .reg = .rsi } },
107703 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfei" } } },
107534 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfei" } },
107704107535 .unused,
107705107536 .unused,
107706107537 .unused,
......@@ -107731,7 +107562,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107731107562 .{ .type = .usize, .kind = .{ .reg = .rdi } },
107732107563 .{ .type = .usize, .kind = .{ .reg = .rsi } },
107733107564 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107734 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfei" } } },
107565 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfei" } },
107735107566 .unused,
107736107567 .unused,
107737107568 .unused,
......@@ -107765,7 +107596,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107765107596 .{ .type = .usize, .kind = .{ .reg = .rdi } },
107766107597 .{ .type = .usize, .kind = .{ .reg = .rsi } },
107767107598 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107768 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfei" } } },
107599 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfei" } },
107769107600 .unused,
107770107601 .unused,
107771107602 .unused,
......@@ -107799,7 +107630,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107799107630 .{ .type = .usize, .kind = .{ .reg = .rdi } },
107800107631 .{ .type = .usize, .kind = .{ .reg = .rsi } },
107801107632 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107802 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfei" } } },
107633 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfei" } },
107803107634 .unused,
107804107635 .unused,
107805107636 .unused,
......@@ -107833,7 +107664,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107833107664 .{ .type = .usize, .kind = .{ .reg = .rdi } },
107834107665 .{ .type = .usize, .kind = .{ .reg = .rsi } },
107835107666 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107836 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfei" } } },
107667 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfei" } },
107837107668 .unused,
107838107669 .unused,
107839107670 .unused,
......@@ -107867,7 +107698,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107867107698 .{ .type = .usize, .kind = .{ .reg = .rdi } },
107868107699 .{ .type = .usize, .kind = .{ .reg = .rsi } },
107869107700 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107870 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfei" } } },
107701 .{ .type = .usize, .kind = .{ .extern_func = "__fixtfei" } },
107871107702 .unused,
107872107703 .unused,
107873107704 .unused,
......@@ -107901,7 +107732,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
107901107732 .{ .type = .usize, .kind = .{ .reg = .rdi } },
107902107733 .{ .type = .usize, .kind = .{ .reg = .rsi } },
107903107734 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
107904 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfei" } } },
107735 .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfei" } },
107905107736 .unused,
107906107737 .unused,
107907107738 .unused,
......@@ -108149,7 +107980,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108149107980 },
108150107981 .call_frame = .{ .alignment = .@"16" },
108151107982 .extra_temps = .{
108152 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
107983 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
108153107984 .unused,
108154107985 .unused,
108155107986 .unused,
......@@ -108176,7 +108007,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108176108007 },
108177108008 .call_frame = .{ .alignment = .@"16" },
108178108009 .extra_temps = .{
108179 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
108010 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
108180108011 .unused,
108181108012 .unused,
108182108013 .unused,
......@@ -108203,7 +108034,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108203108034 },
108204108035 .call_frame = .{ .alignment = .@"16" },
108205108036 .extra_temps = .{
108206 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
108037 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
108207108038 .unused,
108208108039 .unused,
108209108040 .unused,
......@@ -108230,7 +108061,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108230108061 },
108231108062 .call_frame = .{ .alignment = .@"16" },
108232108063 .extra_temps = .{
108233 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
108064 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
108234108065 .unused,
108235108066 .unused,
108236108067 .unused,
......@@ -108257,7 +108088,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108257108088 },
108258108089 .call_frame = .{ .alignment = .@"16" },
108259108090 .extra_temps = .{
108260 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
108091 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
108261108092 .unused,
108262108093 .unused,
108263108094 .unused,
......@@ -108283,7 +108114,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108283108114 },
108284108115 .call_frame = .{ .alignment = .@"16" },
108285108116 .extra_temps = .{
108286 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
108117 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
108287108118 .unused,
108288108119 .unused,
108289108120 .unused,
......@@ -108309,7 +108140,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108309108140 },
108310108141 .call_frame = .{ .alignment = .@"16" },
108311108142 .extra_temps = .{
108312 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdihf" } } },
108143 .{ .type = .usize, .kind = .{ .extern_func = "__floatdihf" } },
108313108144 .unused,
108314108145 .unused,
108315108146 .unused,
......@@ -108335,7 +108166,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108335108166 },
108336108167 .call_frame = .{ .alignment = .@"16" },
108337108168 .extra_temps = .{
108338 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundihf" } } },
108169 .{ .type = .usize, .kind = .{ .extern_func = "__floatundihf" } },
108339108170 .unused,
108340108171 .unused,
108341108172 .unused,
......@@ -108361,7 +108192,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108361108192 },
108362108193 .call_frame = .{ .alignment = .@"16" },
108363108194 .extra_temps = .{
108364 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattihf" } } },
108195 .{ .type = .usize, .kind = .{ .extern_func = "__floattihf" } },
108365108196 .unused,
108366108197 .unused,
108367108198 .unused,
......@@ -108387,7 +108218,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108387108218 },
108388108219 .call_frame = .{ .alignment = .@"16" },
108389108220 .extra_temps = .{
108390 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntihf" } } },
108221 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntihf" } },
108391108222 .unused,
108392108223 .unused,
108393108224 .unused,
......@@ -108415,7 +108246,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108415108246 .extra_temps = .{
108416108247 .{ .type = .usize, .kind = .{ .reg = .rdi } },
108417108248 .{ .type = .usize, .kind = .{ .reg = .rsi } },
108418 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateihf" } } },
108249 .{ .type = .usize, .kind = .{ .extern_func = "__floateihf" } },
108419108250 .unused,
108420108251 .unused,
108421108252 .unused,
......@@ -108443,7 +108274,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108443108274 .extra_temps = .{
108444108275 .{ .type = .usize, .kind = .{ .reg = .rdi } },
108445108276 .{ .type = .usize, .kind = .{ .reg = .rsi } },
108446 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneihf" } } },
108277 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneihf" } },
108447108278 .unused,
108448108279 .unused,
108449108280 .unused,
......@@ -108647,7 +108478,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108647108478 .extra_temps = .{
108648108479 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
108649108480 .{ .type = .i32, .kind = .{ .reg = .edi } },
108650 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
108481 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
108651108482 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
108652108483 .unused,
108653108484 .unused,
......@@ -108678,7 +108509,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108678108509 .extra_temps = .{
108679108510 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
108680108511 .{ .type = .i32, .kind = .{ .reg = .edi } },
108681 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
108512 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
108682108513 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
108683108514 .unused,
108684108515 .unused,
......@@ -108709,7 +108540,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108709108540 .extra_temps = .{
108710108541 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
108711108542 .{ .type = .i32, .kind = .{ .reg = .edi } },
108712 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
108543 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
108713108544 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
108714108545 .unused,
108715108546 .unused,
......@@ -108740,7 +108571,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108740108571 .extra_temps = .{
108741108572 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
108742108573 .{ .type = .i32, .kind = .{ .reg = .edi } },
108743 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
108574 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
108744108575 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
108745108576 .unused,
108746108577 .unused,
......@@ -108771,7 +108602,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108771108602 .extra_temps = .{
108772108603 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
108773108604 .{ .type = .i32, .kind = .{ .reg = .edi } },
108774 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
108605 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
108775108606 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
108776108607 .unused,
108777108608 .unused,
......@@ -108803,7 +108634,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108803108634 .extra_temps = .{
108804108635 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
108805108636 .{ .type = .i32, .kind = .{ .reg = .edi } },
108806 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
108637 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
108807108638 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
108808108639 .unused,
108809108640 .unused,
......@@ -108835,7 +108666,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108835108666 .extra_temps = .{
108836108667 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
108837108668 .{ .type = .i32, .kind = .{ .reg = .edi } },
108838 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
108669 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
108839108670 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
108840108671 .{ .type = .f32, .kind = .mem },
108841108672 .unused,
......@@ -108868,7 +108699,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108868108699 .extra_temps = .{
108869108700 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
108870108701 .{ .type = .i32, .kind = .{ .reg = .edi } },
108871 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
108702 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
108872108703 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
108873108704 .{ .type = .f32, .kind = .mem },
108874108705 .unused,
......@@ -108901,7 +108732,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108901108732 .extra_temps = .{
108902108733 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
108903108734 .{ .type = .u32, .kind = .{ .reg = .edi } },
108904 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
108735 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
108905108736 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
108906108737 .unused,
108907108738 .unused,
......@@ -108932,7 +108763,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108932108763 .extra_temps = .{
108933108764 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
108934108765 .{ .type = .u32, .kind = .{ .reg = .edi } },
108935 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
108766 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
108936108767 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
108937108768 .unused,
108938108769 .unused,
......@@ -108963,7 +108794,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108963108794 .extra_temps = .{
108964108795 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
108965108796 .{ .type = .u32, .kind = .{ .reg = .edi } },
108966 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
108797 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
108967108798 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
108968108799 .unused,
108969108800 .unused,
......@@ -108994,7 +108825,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
108994108825 .extra_temps = .{
108995108826 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
108996108827 .{ .type = .u32, .kind = .{ .reg = .edi } },
108997 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
108828 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
108998108829 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
108999108830 .unused,
109000108831 .unused,
......@@ -109025,7 +108856,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109025108856 .extra_temps = .{
109026108857 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109027108858 .{ .type = .u32, .kind = .{ .reg = .edi } },
109028 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
108859 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
109029108860 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109030108861 .unused,
109031108862 .unused,
......@@ -109057,7 +108888,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109057108888 .extra_temps = .{
109058108889 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109059108890 .{ .type = .u32, .kind = .{ .reg = .edi } },
109060 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
108891 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
109061108892 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109062108893 .unused,
109063108894 .unused,
......@@ -109089,7 +108920,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109089108920 .extra_temps = .{
109090108921 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109091108922 .{ .type = .u32, .kind = .{ .reg = .edi } },
109092 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
108923 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
109093108924 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109094108925 .{ .type = .f32, .kind = .mem },
109095108926 .unused,
......@@ -109122,7 +108953,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109122108953 .extra_temps = .{
109123108954 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109124108955 .{ .type = .u32, .kind = .{ .reg = .edi } },
109125 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
108956 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
109126108957 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109127108958 .{ .type = .f32, .kind = .mem },
109128108959 .unused,
......@@ -109331,7 +109162,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109331109162 .extra_temps = .{
109332109163 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109333109164 .{ .type = .i32, .kind = .{ .reg = .edi } },
109334 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
109165 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
109335109166 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109336109167 .unused,
109337109168 .unused,
......@@ -109362,7 +109193,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109362109193 .extra_temps = .{
109363109194 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109364109195 .{ .type = .i32, .kind = .{ .reg = .edi } },
109365 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
109196 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
109366109197 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109367109198 .unused,
109368109199 .unused,
......@@ -109393,7 +109224,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109393109224 .extra_temps = .{
109394109225 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109395109226 .{ .type = .i32, .kind = .{ .reg = .edi } },
109396 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
109227 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
109397109228 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109398109229 .unused,
109399109230 .unused,
......@@ -109425,7 +109256,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109425109256 .extra_temps = .{
109426109257 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109427109258 .{ .type = .i32, .kind = .{ .reg = .edi } },
109428 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
109259 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
109429109260 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109430109261 .{ .type = .f32, .kind = .mem },
109431109262 .unused,
......@@ -109458,7 +109289,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109458109289 .extra_temps = .{
109459109290 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109460109291 .{ .type = .u32, .kind = .{ .reg = .edi } },
109461 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
109292 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
109462109293 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109463109294 .unused,
109464109295 .unused,
......@@ -109489,7 +109320,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109489109320 .extra_temps = .{
109490109321 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109491109322 .{ .type = .u32, .kind = .{ .reg = .edi } },
109492 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
109323 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
109493109324 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109494109325 .unused,
109495109326 .unused,
......@@ -109520,7 +109351,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109520109351 .extra_temps = .{
109521109352 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109522109353 .{ .type = .u32, .kind = .{ .reg = .edi } },
109523 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
109354 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
109524109355 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109525109356 .unused,
109526109357 .unused,
......@@ -109552,7 +109383,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109552109383 .extra_temps = .{
109553109384 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109554109385 .{ .type = .u32, .kind = .{ .reg = .edi } },
109555 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
109386 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
109556109387 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109557109388 .{ .type = .f32, .kind = .mem },
109558109389 .unused,
......@@ -109669,7 +109500,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109669109500 .extra_temps = .{
109670109501 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109671109502 .{ .type = .i32, .kind = .{ .reg = .edi } },
109672 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
109503 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
109673109504 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109674109505 .unused,
109675109506 .unused,
......@@ -109700,7 +109531,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109700109531 .extra_temps = .{
109701109532 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109702109533 .{ .type = .i32, .kind = .{ .reg = .edi } },
109703 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
109534 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
109704109535 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109705109536 .unused,
109706109537 .unused,
......@@ -109731,7 +109562,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109731109562 .extra_temps = .{
109732109563 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109733109564 .{ .type = .i32, .kind = .{ .reg = .edi } },
109734 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
109565 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
109735109566 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109736109567 .unused,
109737109568 .unused,
......@@ -109763,7 +109594,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109763109594 .extra_temps = .{
109764109595 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109765109596 .{ .type = .i32, .kind = .{ .reg = .edi } },
109766 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
109597 .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
109767109598 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109768109599 .{ .type = .f32, .kind = .mem },
109769109600 .unused,
......@@ -109796,7 +109627,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109796109627 .extra_temps = .{
109797109628 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109798109629 .{ .type = .u32, .kind = .{ .reg = .edi } },
109799 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
109630 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
109800109631 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109801109632 .unused,
109802109633 .unused,
......@@ -109827,7 +109658,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109827109658 .extra_temps = .{
109828109659 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109829109660 .{ .type = .u32, .kind = .{ .reg = .edi } },
109830 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
109661 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
109831109662 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109832109663 .unused,
109833109664 .unused,
......@@ -109858,7 +109689,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109858109689 .extra_temps = .{
109859109690 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109860109691 .{ .type = .u32, .kind = .{ .reg = .edi } },
109861 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
109692 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
109862109693 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109863109694 .unused,
109864109695 .unused,
......@@ -109890,7 +109721,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109890109721 .extra_temps = .{
109891109722 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109892109723 .{ .type = .u32, .kind = .{ .reg = .edi } },
109893 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
109724 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
109894109725 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109895109726 .{ .type = .f32, .kind = .mem },
109896109727 .unused,
......@@ -109954,7 +109785,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109954109785 .extra_temps = .{
109955109786 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109956109787 .{ .type = .i64, .kind = .{ .reg = .rdi } },
109957 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdihf" } } },
109788 .{ .type = .usize, .kind = .{ .extern_func = "__floatdihf" } },
109958109789 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109959109790 .unused,
109960109791 .unused,
......@@ -109985,7 +109816,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
109985109816 .extra_temps = .{
109986109817 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
109987109818 .{ .type = .i64, .kind = .{ .reg = .rdi } },
109988 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdihf" } } },
109819 .{ .type = .usize, .kind = .{ .extern_func = "__floatdihf" } },
109989109820 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
109990109821 .unused,
109991109822 .unused,
......@@ -110016,7 +109847,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110016109847 .extra_temps = .{
110017109848 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110018109849 .{ .type = .i64, .kind = .{ .reg = .rdi } },
110019 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdihf" } } },
109850 .{ .type = .usize, .kind = .{ .extern_func = "__floatdihf" } },
110020109851 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110021109852 .unused,
110022109853 .unused,
......@@ -110048,7 +109879,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110048109879 .extra_temps = .{
110049109880 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110050109881 .{ .type = .i64, .kind = .{ .reg = .rdi } },
110051 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdihf" } } },
109882 .{ .type = .usize, .kind = .{ .extern_func = "__floatdihf" } },
110052109883 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110053109884 .{ .type = .f32, .kind = .mem },
110054109885 .unused,
......@@ -110081,7 +109912,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110081109912 .extra_temps = .{
110082109913 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110083109914 .{ .type = .u64, .kind = .{ .reg = .rdi } },
110084 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundihf" } } },
109915 .{ .type = .usize, .kind = .{ .extern_func = "__floatundihf" } },
110085109916 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110086109917 .unused,
110087109918 .unused,
......@@ -110112,7 +109943,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110112109943 .extra_temps = .{
110113109944 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110114109945 .{ .type = .u64, .kind = .{ .reg = .rdi } },
110115 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundihf" } } },
109946 .{ .type = .usize, .kind = .{ .extern_func = "__floatundihf" } },
110116109947 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110117109948 .unused,
110118109949 .unused,
......@@ -110143,7 +109974,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110143109974 .extra_temps = .{
110144109975 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110145109976 .{ .type = .u64, .kind = .{ .reg = .rdi } },
110146 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundihf" } } },
109977 .{ .type = .usize, .kind = .{ .extern_func = "__floatundihf" } },
110147109978 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110148109979 .unused,
110149109980 .unused,
......@@ -110175,7 +110006,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110175110006 .extra_temps = .{
110176110007 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110177110008 .{ .type = .u64, .kind = .{ .reg = .rdi } },
110178 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundihf" } } },
110009 .{ .type = .usize, .kind = .{ .extern_func = "__floatundihf" } },
110179110010 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110180110011 .{ .type = .f32, .kind = .mem },
110181110012 .unused,
......@@ -110209,7 +110040,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110209110040 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110210110041 .{ .type = .u64, .kind = .{ .reg = .rdi } },
110211110042 .{ .type = .i64, .kind = .{ .reg = .rsi } },
110212 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattihf" } } },
110043 .{ .type = .usize, .kind = .{ .extern_func = "__floattihf" } },
110213110044 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110214110045 .unused,
110215110046 .unused,
......@@ -110241,7 +110072,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110241110072 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110242110073 .{ .type = .u64, .kind = .{ .reg = .rdi } },
110243110074 .{ .type = .i64, .kind = .{ .reg = .rsi } },
110244 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattihf" } } },
110075 .{ .type = .usize, .kind = .{ .extern_func = "__floattihf" } },
110245110076 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110246110077 .unused,
110247110078 .unused,
......@@ -110273,7 +110104,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110273110104 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110274110105 .{ .type = .u64, .kind = .{ .reg = .rdi } },
110275110106 .{ .type = .i64, .kind = .{ .reg = .rsi } },
110276 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattihf" } } },
110107 .{ .type = .usize, .kind = .{ .extern_func = "__floattihf" } },
110277110108 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110278110109 .unused,
110279110110 .unused,
......@@ -110306,7 +110137,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110306110137 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110307110138 .{ .type = .u64, .kind = .{ .reg = .rdi } },
110308110139 .{ .type = .i64, .kind = .{ .reg = .rsi } },
110309 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattihf" } } },
110140 .{ .type = .usize, .kind = .{ .extern_func = "__floattihf" } },
110310110141 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110311110142 .{ .type = .f32, .kind = .mem },
110312110143 .unused,
......@@ -110340,7 +110171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110340110171 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110341110172 .{ .type = .u64, .kind = .{ .reg = .rdi } },
110342110173 .{ .type = .u64, .kind = .{ .reg = .rsi } },
110343 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntihf" } } },
110174 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntihf" } },
110344110175 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110345110176 .unused,
110346110177 .unused,
......@@ -110372,7 +110203,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110372110203 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110373110204 .{ .type = .u64, .kind = .{ .reg = .rdi } },
110374110205 .{ .type = .u64, .kind = .{ .reg = .rsi } },
110375 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntihf" } } },
110206 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntihf" } },
110376110207 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110377110208 .unused,
110378110209 .unused,
......@@ -110404,7 +110235,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110404110235 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110405110236 .{ .type = .u64, .kind = .{ .reg = .rdi } },
110406110237 .{ .type = .u64, .kind = .{ .reg = .rsi } },
110407 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntihf" } } },
110238 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntihf" } },
110408110239 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110409110240 .unused,
110410110241 .unused,
......@@ -110437,7 +110268,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110437110268 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110438110269 .{ .type = .u64, .kind = .{ .reg = .rdi } },
110439110270 .{ .type = .u64, .kind = .{ .reg = .rsi } },
110440 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntihf" } } },
110271 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntihf" } },
110441110272 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110442110273 .{ .type = .f32, .kind = .mem },
110443110274 .unused,
......@@ -110472,7 +110303,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110472110303 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110473110304 .{ .type = .usize, .kind = .{ .reg = .rdi } },
110474110305 .{ .type = .usize, .kind = .{ .reg = .rsi } },
110475 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateihf" } } },
110306 .{ .type = .usize, .kind = .{ .extern_func = "__floateihf" } },
110476110307 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110477110308 .unused,
110478110309 .unused,
......@@ -110506,7 +110337,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110506110337 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110507110338 .{ .type = .usize, .kind = .{ .reg = .rdi } },
110508110339 .{ .type = .usize, .kind = .{ .reg = .rsi } },
110509 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateihf" } } },
110340 .{ .type = .usize, .kind = .{ .extern_func = "__floateihf" } },
110510110341 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110511110342 .unused,
110512110343 .unused,
......@@ -110540,7 +110371,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110540110371 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110541110372 .{ .type = .usize, .kind = .{ .reg = .rdi } },
110542110373 .{ .type = .usize, .kind = .{ .reg = .rsi } },
110543 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateihf" } } },
110374 .{ .type = .usize, .kind = .{ .extern_func = "__floateihf" } },
110544110375 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110545110376 .unused,
110546110377 .unused,
......@@ -110575,7 +110406,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110575110406 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110576110407 .{ .type = .usize, .kind = .{ .reg = .rdi } },
110577110408 .{ .type = .usize, .kind = .{ .reg = .rsi } },
110578 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateihf" } } },
110409 .{ .type = .usize, .kind = .{ .extern_func = "__floateihf" } },
110579110410 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110580110411 .{ .type = .f32, .kind = .mem },
110581110412 .unused,
......@@ -110611,7 +110442,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110611110442 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110612110443 .{ .type = .usize, .kind = .{ .reg = .rdi } },
110613110444 .{ .type = .usize, .kind = .{ .reg = .rsi } },
110614 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneihf" } } },
110445 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneihf" } },
110615110446 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110616110447 .unused,
110617110448 .unused,
......@@ -110645,7 +110476,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110645110476 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110646110477 .{ .type = .usize, .kind = .{ .reg = .rdi } },
110647110478 .{ .type = .usize, .kind = .{ .reg = .rsi } },
110648 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneihf" } } },
110479 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneihf" } },
110649110480 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110650110481 .unused,
110651110482 .unused,
......@@ -110679,7 +110510,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110679110510 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110680110511 .{ .type = .usize, .kind = .{ .reg = .rdi } },
110681110512 .{ .type = .usize, .kind = .{ .reg = .rsi } },
110682 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneihf" } } },
110513 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneihf" } },
110683110514 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110684110515 .unused,
110685110516 .unused,
......@@ -110714,7 +110545,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
110714110545 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
110715110546 .{ .type = .usize, .kind = .{ .reg = .rdi } },
110716110547 .{ .type = .usize, .kind = .{ .reg = .rsi } },
110717 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneihf" } } },
110548 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneihf" } },
110718110549 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
110719110550 .{ .type = .f32, .kind = .mem },
110720110551 .unused,
......@@ -111138,7 +110969,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111138110969 },
111139110970 .call_frame = .{ .alignment = .@"16" },
111140110971 .extra_temps = .{
111141 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattisf" } } },
110972 .{ .type = .usize, .kind = .{ .extern_func = "__floattisf" } },
111142110973 .unused,
111143110974 .unused,
111144110975 .unused,
......@@ -111164,7 +110995,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111164110995 },
111165110996 .call_frame = .{ .alignment = .@"16" },
111166110997 .extra_temps = .{
111167 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntisf" } } },
110998 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntisf" } },
111168110999 .unused,
111169111000 .unused,
111170111001 .unused,
......@@ -111192,7 +111023,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111192111023 .extra_temps = .{
111193111024 .{ .type = .usize, .kind = .{ .reg = .rdi } },
111194111025 .{ .type = .usize, .kind = .{ .reg = .rsi } },
111195 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateisf" } } },
111026 .{ .type = .usize, .kind = .{ .extern_func = "__floateisf" } },
111196111027 .unused,
111197111028 .unused,
111198111029 .unused,
......@@ -111220,7 +111051,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111220111051 .extra_temps = .{
111221111052 .{ .type = .usize, .kind = .{ .reg = .rdi } },
111222111053 .{ .type = .usize, .kind = .{ .reg = .rsi } },
111223 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneisf" } } },
111054 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneisf" } },
111224111055 .unused,
111225111056 .unused,
111226111057 .unused,
......@@ -111506,7 +111337,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111506111337 .extra_temps = .{
111507111338 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
111508111339 .{ .type = .i32, .kind = .{ .reg = .edi } },
111509 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
111340 .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
111510111341 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
111511111342 .unused,
111512111343 .unused,
......@@ -111537,7 +111368,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111537111368 .extra_temps = .{
111538111369 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
111539111370 .{ .type = .i32, .kind = .{ .reg = .edi } },
111540 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
111371 .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
111541111372 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
111542111373 .unused,
111543111374 .unused,
......@@ -111568,7 +111399,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111568111399 .extra_temps = .{
111569111400 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
111570111401 .{ .type = .i32, .kind = .{ .reg = .edi } },
111571 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
111402 .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
111572111403 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
111573111404 .unused,
111574111405 .unused,
......@@ -111599,7 +111430,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111599111430 .extra_temps = .{
111600111431 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
111601111432 .{ .type = .i32, .kind = .{ .reg = .edi } },
111602 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
111433 .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
111603111434 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
111604111435 .unused,
111605111436 .unused,
......@@ -111630,7 +111461,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111630111461 .extra_temps = .{
111631111462 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
111632111463 .{ .type = .u32, .kind = .{ .reg = .edi } },
111633 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
111464 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
111634111465 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
111635111466 .unused,
111636111467 .unused,
......@@ -111661,7 +111492,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111661111492 .extra_temps = .{
111662111493 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
111663111494 .{ .type = .u32, .kind = .{ .reg = .edi } },
111664 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
111495 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
111665111496 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
111666111497 .unused,
111667111498 .unused,
......@@ -111692,7 +111523,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111692111523 .extra_temps = .{
111693111524 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
111694111525 .{ .type = .u32, .kind = .{ .reg = .edi } },
111695 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
111526 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
111696111527 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
111697111528 .unused,
111698111529 .unused,
......@@ -111723,7 +111554,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111723111554 .extra_temps = .{
111724111555 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
111725111556 .{ .type = .u32, .kind = .{ .reg = .edi } },
111726 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
111557 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
111727111558 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
111728111559 .unused,
111729111560 .unused,
......@@ -112012,7 +111843,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112012111843 .extra_temps = .{
112013111844 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112014111845 .{ .type = .i32, .kind = .{ .reg = .edi } },
112015 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
111846 .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
112016111847 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112017111848 .unused,
112018111849 .unused,
......@@ -112043,7 +111874,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112043111874 .extra_temps = .{
112044111875 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112045111876 .{ .type = .i32, .kind = .{ .reg = .edi } },
112046 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
111877 .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
112047111878 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112048111879 .unused,
112049111880 .unused,
......@@ -112074,7 +111905,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112074111905 .extra_temps = .{
112075111906 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112076111907 .{ .type = .u32, .kind = .{ .reg = .edi } },
112077 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
111908 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
112078111909 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112079111910 .unused,
112080111911 .unused,
......@@ -112105,7 +111936,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112105111936 .extra_temps = .{
112106111937 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112107111938 .{ .type = .u32, .kind = .{ .reg = .edi } },
112108 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
111939 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
112109111940 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112110111941 .unused,
112111111942 .unused,
......@@ -112288,7 +112119,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112288112119 .extra_temps = .{
112289112120 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112290112121 .{ .type = .i32, .kind = .{ .reg = .edi } },
112291 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
112122 .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
112292112123 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112293112124 .unused,
112294112125 .unused,
......@@ -112319,7 +112150,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112319112150 .extra_temps = .{
112320112151 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112321112152 .{ .type = .i32, .kind = .{ .reg = .edi } },
112322 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
112153 .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
112323112154 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112324112155 .unused,
112325112156 .unused,
......@@ -112350,7 +112181,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112350112181 .extra_temps = .{
112351112182 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112352112183 .{ .type = .u32, .kind = .{ .reg = .edi } },
112353 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
112184 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
112354112185 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112355112186 .unused,
112356112187 .unused,
......@@ -112381,7 +112212,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112381112212 .extra_temps = .{
112382112213 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112383112214 .{ .type = .u32, .kind = .{ .reg = .edi } },
112384 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
112215 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
112385112216 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112386112217 .unused,
112387112218 .unused,
......@@ -112472,7 +112303,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112472112303 .extra_temps = .{
112473112304 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112474112305 .{ .type = .i64, .kind = .{ .reg = .rdi } },
112475 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdisf" } } },
112306 .{ .type = .usize, .kind = .{ .extern_func = "__floatdisf" } },
112476112307 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112477112308 .unused,
112478112309 .unused,
......@@ -112503,7 +112334,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112503112334 .extra_temps = .{
112504112335 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112505112336 .{ .type = .i64, .kind = .{ .reg = .rdi } },
112506 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdisf" } } },
112337 .{ .type = .usize, .kind = .{ .extern_func = "__floatdisf" } },
112507112338 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112508112339 .unused,
112509112340 .unused,
......@@ -112534,7 +112365,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112534112365 .extra_temps = .{
112535112366 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112536112367 .{ .type = .u64, .kind = .{ .reg = .rdi } },
112537 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundisf" } } },
112368 .{ .type = .usize, .kind = .{ .extern_func = "__floatundisf" } },
112538112369 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112539112370 .unused,
112540112371 .unused,
......@@ -112565,7 +112396,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112565112396 .extra_temps = .{
112566112397 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112567112398 .{ .type = .u64, .kind = .{ .reg = .rdi } },
112568 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundisf" } } },
112399 .{ .type = .usize, .kind = .{ .extern_func = "__floatundisf" } },
112569112400 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112570112401 .unused,
112571112402 .unused,
......@@ -112597,7 +112428,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112597112428 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112598112429 .{ .type = .u64, .kind = .{ .reg = .rdi } },
112599112430 .{ .type = .i64, .kind = .{ .reg = .rsi } },
112600 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattisf" } } },
112431 .{ .type = .usize, .kind = .{ .extern_func = "__floattisf" } },
112601112432 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112602112433 .unused,
112603112434 .unused,
......@@ -112629,7 +112460,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112629112460 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112630112461 .{ .type = .u64, .kind = .{ .reg = .rdi } },
112631112462 .{ .type = .i64, .kind = .{ .reg = .rsi } },
112632 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattisf" } } },
112463 .{ .type = .usize, .kind = .{ .extern_func = "__floattisf" } },
112633112464 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112634112465 .unused,
112635112466 .unused,
......@@ -112661,7 +112492,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112661112492 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112662112493 .{ .type = .u64, .kind = .{ .reg = .rdi } },
112663112494 .{ .type = .u64, .kind = .{ .reg = .rsi } },
112664 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntisf" } } },
112495 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntisf" } },
112665112496 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112666112497 .unused,
112667112498 .unused,
......@@ -112693,7 +112524,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112693112524 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112694112525 .{ .type = .u64, .kind = .{ .reg = .rdi } },
112695112526 .{ .type = .u64, .kind = .{ .reg = .rsi } },
112696 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntisf" } } },
112527 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntisf" } },
112697112528 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112698112529 .unused,
112699112530 .unused,
......@@ -112726,7 +112557,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112726112557 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112727112558 .{ .type = .usize, .kind = .{ .reg = .rdi } },
112728112559 .{ .type = .usize, .kind = .{ .reg = .rsi } },
112729 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateisf" } } },
112560 .{ .type = .usize, .kind = .{ .extern_func = "__floateisf" } },
112730112561 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112731112562 .unused,
112732112563 .unused,
......@@ -112760,7 +112591,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112760112591 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112761112592 .{ .type = .usize, .kind = .{ .reg = .rdi } },
112762112593 .{ .type = .usize, .kind = .{ .reg = .rsi } },
112763 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateisf" } } },
112594 .{ .type = .usize, .kind = .{ .extern_func = "__floateisf" } },
112764112595 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112765112596 .unused,
112766112597 .unused,
......@@ -112794,7 +112625,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112794112625 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112795112626 .{ .type = .usize, .kind = .{ .reg = .rdi } },
112796112627 .{ .type = .usize, .kind = .{ .reg = .rsi } },
112797 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneisf" } } },
112628 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneisf" } },
112798112629 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112799112630 .unused,
112800112631 .unused,
......@@ -112828,7 +112659,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
112828112659 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
112829112660 .{ .type = .usize, .kind = .{ .reg = .rdi } },
112830112661 .{ .type = .usize, .kind = .{ .reg = .rsi } },
112831 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneisf" } } },
112662 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneisf" } },
112832112663 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
112833112664 .unused,
112834112665 .unused,
......@@ -113468,7 +113299,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
113468113299 },
113469113300 .call_frame = .{ .alignment = .@"16" },
113470113301 .extra_temps = .{
113471 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattidf" } } },
113302 .{ .type = .usize, .kind = .{ .extern_func = "__floattidf" } },
113472113303 .unused,
113473113304 .unused,
113474113305 .unused,
......@@ -113494,7 +113325,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
113494113325 },
113495113326 .call_frame = .{ .alignment = .@"16" },
113496113327 .extra_temps = .{
113497 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntidf" } } },
113328 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntidf" } },
113498113329 .unused,
113499113330 .unused,
113500113331 .unused,
......@@ -113522,7 +113353,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
113522113353 .extra_temps = .{
113523113354 .{ .type = .usize, .kind = .{ .reg = .rdi } },
113524113355 .{ .type = .usize, .kind = .{ .reg = .rsi } },
113525 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateidf" } } },
113356 .{ .type = .usize, .kind = .{ .extern_func = "__floateidf" } },
113526113357 .unused,
113527113358 .unused,
113528113359 .unused,
......@@ -113550,7 +113381,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
113550113381 .extra_temps = .{
113551113382 .{ .type = .usize, .kind = .{ .reg = .rdi } },
113552113383 .{ .type = .usize, .kind = .{ .reg = .rsi } },
113553 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneidf" } } },
113384 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneidf" } },
113554113385 .unused,
113555113386 .unused,
113556113387 .unused,
......@@ -113844,7 +113675,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
113844113675 .extra_temps = .{
113845113676 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
113846113677 .{ .type = .i32, .kind = .{ .reg = .edi } },
113847 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
113678 .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
113848113679 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
113849113680 .unused,
113850113681 .unused,
......@@ -113875,7 +113706,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
113875113706 .extra_temps = .{
113876113707 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
113877113708 .{ .type = .i32, .kind = .{ .reg = .edi } },
113878 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
113709 .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
113879113710 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
113880113711 .unused,
113881113712 .unused,
......@@ -113906,7 +113737,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
113906113737 .extra_temps = .{
113907113738 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
113908113739 .{ .type = .i32, .kind = .{ .reg = .edi } },
113909 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
113740 .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
113910113741 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
113911113742 .unused,
113912113743 .unused,
......@@ -113937,7 +113768,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
113937113768 .extra_temps = .{
113938113769 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
113939113770 .{ .type = .i32, .kind = .{ .reg = .edi } },
113940 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
113771 .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
113941113772 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
113942113773 .unused,
113943113774 .unused,
......@@ -113968,7 +113799,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
113968113799 .extra_temps = .{
113969113800 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
113970113801 .{ .type = .i32, .kind = .{ .reg = .edi } },
113971 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
113802 .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
113972113803 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
113973113804 .unused,
113974113805 .unused,
......@@ -113999,7 +113830,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
113999113830 .extra_temps = .{
114000113831 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114001113832 .{ .type = .i32, .kind = .{ .reg = .edi } },
114002 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
113833 .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
114003113834 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114004113835 .unused,
114005113836 .unused,
......@@ -114030,7 +113861,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114030113861 .extra_temps = .{
114031113862 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114032113863 .{ .type = .u32, .kind = .{ .reg = .edi } },
114033 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
113864 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
114034113865 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114035113866 .unused,
114036113867 .unused,
......@@ -114061,7 +113892,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114061113892 .extra_temps = .{
114062113893 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114063113894 .{ .type = .u32, .kind = .{ .reg = .edi } },
114064 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
113895 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
114065113896 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114066113897 .unused,
114067113898 .unused,
......@@ -114092,7 +113923,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114092113923 .extra_temps = .{
114093113924 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114094113925 .{ .type = .u32, .kind = .{ .reg = .edi } },
114095 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
113926 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
114096113927 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114097113928 .unused,
114098113929 .unused,
......@@ -114123,7 +113954,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114123113954 .extra_temps = .{
114124113955 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114125113956 .{ .type = .u32, .kind = .{ .reg = .edi } },
114126 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
113957 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
114127113958 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114128113959 .unused,
114129113960 .unused,
......@@ -114154,7 +113985,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114154113985 .extra_temps = .{
114155113986 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114156113987 .{ .type = .u32, .kind = .{ .reg = .edi } },
114157 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
113988 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
114158113989 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114159113990 .unused,
114160113991 .unused,
......@@ -114185,7 +114016,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114185114016 .extra_temps = .{
114186114017 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114187114018 .{ .type = .u32, .kind = .{ .reg = .edi } },
114188 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
114019 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
114189114020 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114190114021 .unused,
114191114022 .unused,
......@@ -114478,7 +114309,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114478114309 .extra_temps = .{
114479114310 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114480114311 .{ .type = .i32, .kind = .{ .reg = .edi } },
114481 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
114312 .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
114482114313 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114483114314 .unused,
114484114315 .unused,
......@@ -114509,7 +114340,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114509114340 .extra_temps = .{
114510114341 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114511114342 .{ .type = .i32, .kind = .{ .reg = .edi } },
114512 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
114343 .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
114513114344 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114514114345 .unused,
114515114346 .unused,
......@@ -114540,7 +114371,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114540114371 .extra_temps = .{
114541114372 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114542114373 .{ .type = .i32, .kind = .{ .reg = .edi } },
114543 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
114374 .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
114544114375 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114545114376 .unused,
114546114377 .unused,
......@@ -114571,7 +114402,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114571114402 .extra_temps = .{
114572114403 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114573114404 .{ .type = .u32, .kind = .{ .reg = .edi } },
114574 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
114405 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
114575114406 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114576114407 .unused,
114577114408 .unused,
......@@ -114602,7 +114433,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114602114433 .extra_temps = .{
114603114434 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114604114435 .{ .type = .u32, .kind = .{ .reg = .edi } },
114605 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
114436 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
114606114437 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114607114438 .unused,
114608114439 .unused,
......@@ -114633,7 +114464,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114633114464 .extra_temps = .{
114634114465 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114635114466 .{ .type = .u32, .kind = .{ .reg = .edi } },
114636 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
114467 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
114637114468 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114638114469 .unused,
114639114470 .unused,
......@@ -114787,7 +114618,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114787114618 .extra_temps = .{
114788114619 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114789114620 .{ .type = .i32, .kind = .{ .reg = .edi } },
114790 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
114621 .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
114791114622 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114792114623 .unused,
114793114624 .unused,
......@@ -114818,7 +114649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114818114649 .extra_temps = .{
114819114650 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114820114651 .{ .type = .i32, .kind = .{ .reg = .edi } },
114821 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
114652 .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
114822114653 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114823114654 .unused,
114824114655 .unused,
......@@ -114849,7 +114680,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114849114680 .extra_temps = .{
114850114681 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114851114682 .{ .type = .i32, .kind = .{ .reg = .edi } },
114852 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
114683 .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
114853114684 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114854114685 .unused,
114855114686 .unused,
......@@ -114880,7 +114711,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114880114711 .extra_temps = .{
114881114712 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114882114713 .{ .type = .u32, .kind = .{ .reg = .edi } },
114883 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
114714 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
114884114715 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114885114716 .unused,
114886114717 .unused,
......@@ -114911,7 +114742,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114911114742 .extra_temps = .{
114912114743 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114913114744 .{ .type = .u32, .kind = .{ .reg = .edi } },
114914 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
114745 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
114915114746 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114916114747 .unused,
114917114748 .unused,
......@@ -114942,7 +114773,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
114942114773 .extra_temps = .{
114943114774 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
114944114775 .{ .type = .u32, .kind = .{ .reg = .edi } },
114945 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
114776 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
114946114777 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
114947114778 .unused,
114948114779 .unused,
......@@ -115033,7 +114864,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115033114864 .extra_temps = .{
115034114865 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115035114866 .{ .type = .i64, .kind = .{ .reg = .rdi } },
115036 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdidf" } } },
114867 .{ .type = .usize, .kind = .{ .extern_func = "__floatdidf" } },
115037114868 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115038114869 .unused,
115039114870 .unused,
......@@ -115064,7 +114895,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115064114895 .extra_temps = .{
115065114896 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115066114897 .{ .type = .i64, .kind = .{ .reg = .rdi } },
115067 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdidf" } } },
114898 .{ .type = .usize, .kind = .{ .extern_func = "__floatdidf" } },
115068114899 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115069114900 .unused,
115070114901 .unused,
......@@ -115095,7 +114926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115095114926 .extra_temps = .{
115096114927 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115097114928 .{ .type = .i64, .kind = .{ .reg = .rdi } },
115098 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdidf" } } },
114929 .{ .type = .usize, .kind = .{ .extern_func = "__floatdidf" } },
115099114930 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115100114931 .unused,
115101114932 .unused,
......@@ -115126,7 +114957,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115126114957 .extra_temps = .{
115127114958 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115128114959 .{ .type = .u64, .kind = .{ .reg = .rdi } },
115129 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundidf" } } },
114960 .{ .type = .usize, .kind = .{ .extern_func = "__floatundidf" } },
115130114961 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115131114962 .unused,
115132114963 .unused,
......@@ -115157,7 +114988,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115157114988 .extra_temps = .{
115158114989 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115159114990 .{ .type = .u64, .kind = .{ .reg = .rdi } },
115160 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundidf" } } },
114991 .{ .type = .usize, .kind = .{ .extern_func = "__floatundidf" } },
115161114992 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115162114993 .unused,
115163114994 .unused,
......@@ -115188,7 +115019,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115188115019 .extra_temps = .{
115189115020 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115190115021 .{ .type = .u64, .kind = .{ .reg = .rdi } },
115191 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundidf" } } },
115022 .{ .type = .usize, .kind = .{ .extern_func = "__floatundidf" } },
115192115023 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115193115024 .unused,
115194115025 .unused,
......@@ -115220,7 +115051,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115220115051 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115221115052 .{ .type = .u64, .kind = .{ .reg = .rdi } },
115222115053 .{ .type = .i64, .kind = .{ .reg = .rsi } },
115223 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattidf" } } },
115054 .{ .type = .usize, .kind = .{ .extern_func = "__floattidf" } },
115224115055 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115225115056 .unused,
115226115057 .unused,
......@@ -115252,7 +115083,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115252115083 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115253115084 .{ .type = .u64, .kind = .{ .reg = .rdi } },
115254115085 .{ .type = .i64, .kind = .{ .reg = .rsi } },
115255 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattidf" } } },
115086 .{ .type = .usize, .kind = .{ .extern_func = "__floattidf" } },
115256115087 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115257115088 .unused,
115258115089 .unused,
......@@ -115284,7 +115115,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115284115115 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115285115116 .{ .type = .u64, .kind = .{ .reg = .rdi } },
115286115117 .{ .type = .i64, .kind = .{ .reg = .rsi } },
115287 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattidf" } } },
115118 .{ .type = .usize, .kind = .{ .extern_func = "__floattidf" } },
115288115119 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115289115120 .unused,
115290115121 .unused,
......@@ -115316,7 +115147,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115316115147 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115317115148 .{ .type = .u64, .kind = .{ .reg = .rdi } },
115318115149 .{ .type = .u64, .kind = .{ .reg = .rsi } },
115319 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntidf" } } },
115150 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntidf" } },
115320115151 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115321115152 .unused,
115322115153 .unused,
......@@ -115348,7 +115179,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115348115179 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115349115180 .{ .type = .u64, .kind = .{ .reg = .rdi } },
115350115181 .{ .type = .u64, .kind = .{ .reg = .rsi } },
115351 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntidf" } } },
115182 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntidf" } },
115352115183 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115353115184 .unused,
115354115185 .unused,
......@@ -115380,7 +115211,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115380115211 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115381115212 .{ .type = .u64, .kind = .{ .reg = .rdi } },
115382115213 .{ .type = .u64, .kind = .{ .reg = .rsi } },
115383 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntidf" } } },
115214 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntidf" } },
115384115215 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115385115216 .unused,
115386115217 .unused,
......@@ -115413,7 +115244,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115413115244 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115414115245 .{ .type = .usize, .kind = .{ .reg = .rdi } },
115415115246 .{ .type = .usize, .kind = .{ .reg = .rsi } },
115416 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateidf" } } },
115247 .{ .type = .usize, .kind = .{ .extern_func = "__floateidf" } },
115417115248 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115418115249 .unused,
115419115250 .unused,
......@@ -115447,7 +115278,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115447115278 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115448115279 .{ .type = .usize, .kind = .{ .reg = .rdi } },
115449115280 .{ .type = .usize, .kind = .{ .reg = .rsi } },
115450 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateidf" } } },
115281 .{ .type = .usize, .kind = .{ .extern_func = "__floateidf" } },
115451115282 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115452115283 .unused,
115453115284 .unused,
......@@ -115481,7 +115312,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115481115312 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115482115313 .{ .type = .usize, .kind = .{ .reg = .rdi } },
115483115314 .{ .type = .usize, .kind = .{ .reg = .rsi } },
115484 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateidf" } } },
115315 .{ .type = .usize, .kind = .{ .extern_func = "__floateidf" } },
115485115316 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115486115317 .unused,
115487115318 .unused,
......@@ -115515,7 +115346,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115515115346 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115516115347 .{ .type = .usize, .kind = .{ .reg = .rdi } },
115517115348 .{ .type = .usize, .kind = .{ .reg = .rsi } },
115518 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneidf" } } },
115349 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneidf" } },
115519115350 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115520115351 .unused,
115521115352 .unused,
......@@ -115549,7 +115380,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115549115380 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115550115381 .{ .type = .usize, .kind = .{ .reg = .rdi } },
115551115382 .{ .type = .usize, .kind = .{ .reg = .rsi } },
115552 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneidf" } } },
115383 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneidf" } },
115553115384 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115554115385 .unused,
115555115386 .unused,
......@@ -115583,7 +115414,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115583115414 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
115584115415 .{ .type = .usize, .kind = .{ .reg = .rdi } },
115585115416 .{ .type = .usize, .kind = .{ .reg = .rsi } },
115586 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneidf" } } },
115417 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneidf" } },
115587115418 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
115588115419 .unused,
115589115420 .unused,
......@@ -115830,7 +115661,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115830115661 },
115831115662 .call_frame = .{ .alignment = .@"16" },
115832115663 .extra_temps = .{
115833 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattixf" } } },
115664 .{ .type = .usize, .kind = .{ .extern_func = "__floattixf" } },
115834115665 .unused,
115835115666 .unused,
115836115667 .unused,
......@@ -115856,7 +115687,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115856115687 },
115857115688 .call_frame = .{ .alignment = .@"16" },
115858115689 .extra_temps = .{
115859 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntixf" } } },
115690 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntixf" } },
115860115691 .unused,
115861115692 .unused,
115862115693 .unused,
......@@ -115884,7 +115715,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115884115715 .extra_temps = .{
115885115716 .{ .type = .usize, .kind = .{ .reg = .rdi } },
115886115717 .{ .type = .usize, .kind = .{ .reg = .rsi } },
115887 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateixf" } } },
115718 .{ .type = .usize, .kind = .{ .extern_func = "__floateixf" } },
115888115719 .unused,
115889115720 .unused,
115890115721 .unused,
......@@ -115912,7 +115743,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
115912115743 .extra_temps = .{
115913115744 .{ .type = .usize, .kind = .{ .reg = .rdi } },
115914115745 .{ .type = .usize, .kind = .{ .reg = .rsi } },
115915 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneixf" } } },
115746 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneixf" } },
115916115747 .unused,
115917115748 .unused,
115918115749 .unused,
......@@ -116073,7 +115904,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116073115904 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116074115905 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
116075115906 .{ .type = .i32, .kind = .{ .reg = .edi } },
116076 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsixf" } } },
115907 .{ .type = .usize, .kind = .{ .extern_func = "__floatsixf" } },
116077115908 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116078115909 .unused,
116079115910 .unused,
......@@ -116107,7 +115938,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116107115938 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116108115939 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
116109115940 .{ .type = .i32, .kind = .{ .reg = .edi } },
116110 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsixf" } } },
115941 .{ .type = .usize, .kind = .{ .extern_func = "__floatsixf" } },
116111115942 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116112115943 .unused,
116113115944 .unused,
......@@ -116141,7 +115972,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116141115972 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116142115973 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
116143115974 .{ .type = .u32, .kind = .{ .reg = .edi } },
116144 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsixf" } } },
115975 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsixf" } },
116145115976 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116146115977 .unused,
116147115978 .unused,
......@@ -116175,7 +116006,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116175116006 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116176116007 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
116177116008 .{ .type = .u32, .kind = .{ .reg = .edi } },
116178 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsixf" } } },
116009 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsixf" } },
116179116010 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116180116011 .unused,
116181116012 .unused,
......@@ -116237,7 +116068,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116237116068 .extra_temps = .{
116238116069 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116239116070 .{ .type = .i32, .kind = .{ .reg = .edi } },
116240 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsixf" } } },
116071 .{ .type = .usize, .kind = .{ .extern_func = "__floatsixf" } },
116241116072 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116242116073 .unused,
116243116074 .unused,
......@@ -116269,7 +116100,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116269116100 .extra_temps = .{
116270116101 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116271116102 .{ .type = .u32, .kind = .{ .reg = .edi } },
116272 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsixf" } } },
116103 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsixf" } },
116273116104 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116274116105 .unused,
116275116106 .unused,
......@@ -116330,7 +116161,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116330116161 .extra_temps = .{
116331116162 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116332116163 .{ .type = .i32, .kind = .{ .reg = .edi } },
116333 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsixf" } } },
116164 .{ .type = .usize, .kind = .{ .extern_func = "__floatsixf" } },
116334116165 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116335116166 .unused,
116336116167 .unused,
......@@ -116362,7 +116193,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116362116193 .extra_temps = .{
116363116194 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116364116195 .{ .type = .u32, .kind = .{ .reg = .edi } },
116365 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsixf" } } },
116196 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsixf" } },
116366116197 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116367116198 .unused,
116368116199 .unused,
......@@ -116423,7 +116254,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116423116254 .extra_temps = .{
116424116255 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116425116256 .{ .type = .i64, .kind = .{ .reg = .rdi } },
116426 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdixf" } } },
116257 .{ .type = .usize, .kind = .{ .extern_func = "__floatdixf" } },
116427116258 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116428116259 .unused,
116429116260 .unused,
......@@ -116455,7 +116286,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116455116286 .extra_temps = .{
116456116287 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116457116288 .{ .type = .u64, .kind = .{ .reg = .rdi } },
116458 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundixf" } } },
116289 .{ .type = .usize, .kind = .{ .extern_func = "__floatundixf" } },
116459116290 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116460116291 .unused,
116461116292 .unused,
......@@ -116488,7 +116319,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116488116319 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116489116320 .{ .type = .u64, .kind = .{ .reg = .rdi } },
116490116321 .{ .type = .i64, .kind = .{ .reg = .rsi } },
116491 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattixf" } } },
116322 .{ .type = .usize, .kind = .{ .extern_func = "__floattixf" } },
116492116323 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116493116324 .unused,
116494116325 .unused,
......@@ -116521,7 +116352,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116521116352 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116522116353 .{ .type = .u64, .kind = .{ .reg = .rdi } },
116523116354 .{ .type = .u64, .kind = .{ .reg = .rsi } },
116524 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntixf" } } },
116355 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntixf" } },
116525116356 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116526116357 .unused,
116527116358 .unused,
......@@ -116555,7 +116386,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116555116386 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116556116387 .{ .type = .usize, .kind = .{ .reg = .rdi } },
116557116388 .{ .type = .usize, .kind = .{ .reg = .rsi } },
116558 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateixf" } } },
116389 .{ .type = .usize, .kind = .{ .extern_func = "__floateixf" } },
116559116390 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116560116391 .unused,
116561116392 .unused,
......@@ -116590,7 +116421,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116590116421 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116591116422 .{ .type = .usize, .kind = .{ .reg = .rdi } },
116592116423 .{ .type = .usize, .kind = .{ .reg = .rsi } },
116593 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneixf" } } },
116424 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneixf" } },
116594116425 .{ .type = .f80, .kind = .{ .reg = .st7 } },
116595116426 .unused,
116596116427 .unused,
......@@ -116623,7 +116454,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116623116454 .call_frame = .{ .alignment = .@"16" },
116624116455 .extra_temps = .{
116625116456 .{ .type = .i32, .kind = .{ .reg = .edi } },
116626 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
116457 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
116627116458 .unused,
116628116459 .unused,
116629116460 .unused,
......@@ -116651,7 +116482,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116651116482 .call_frame = .{ .alignment = .@"16" },
116652116483 .extra_temps = .{
116653116484 .{ .type = .u32, .kind = .{ .reg = .edi } },
116654 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
116485 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
116655116486 .unused,
116656116487 .unused,
116657116488 .unused,
......@@ -116679,7 +116510,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116679116510 .call_frame = .{ .alignment = .@"16" },
116680116511 .extra_temps = .{
116681116512 .{ .type = .i32, .kind = .{ .reg = .edi } },
116682 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
116513 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
116683116514 .unused,
116684116515 .unused,
116685116516 .unused,
......@@ -116707,7 +116538,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116707116538 .call_frame = .{ .alignment = .@"16" },
116708116539 .extra_temps = .{
116709116540 .{ .type = .u32, .kind = .{ .reg = .edi } },
116710 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
116541 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
116711116542 .unused,
116712116543 .unused,
116713116544 .unused,
......@@ -116733,7 +116564,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116733116564 },
116734116565 .call_frame = .{ .alignment = .@"16" },
116735116566 .extra_temps = .{
116736 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
116567 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
116737116568 .unused,
116738116569 .unused,
116739116570 .unused,
......@@ -116759,7 +116590,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116759116590 },
116760116591 .call_frame = .{ .alignment = .@"16" },
116761116592 .extra_temps = .{
116762 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
116593 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
116763116594 .unused,
116764116595 .unused,
116765116596 .unused,
......@@ -116785,7 +116616,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116785116616 },
116786116617 .call_frame = .{ .alignment = .@"16" },
116787116618 .extra_temps = .{
116788 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatditf" } } },
116619 .{ .type = .usize, .kind = .{ .extern_func = "__floatditf" } },
116789116620 .unused,
116790116621 .unused,
116791116622 .unused,
......@@ -116811,7 +116642,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116811116642 },
116812116643 .call_frame = .{ .alignment = .@"16" },
116813116644 .extra_temps = .{
116814 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunditf" } } },
116645 .{ .type = .usize, .kind = .{ .extern_func = "__floatunditf" } },
116815116646 .unused,
116816116647 .unused,
116817116648 .unused,
......@@ -116837,7 +116668,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116837116668 },
116838116669 .call_frame = .{ .alignment = .@"16" },
116839116670 .extra_temps = .{
116840 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattitf" } } },
116671 .{ .type = .usize, .kind = .{ .extern_func = "__floattitf" } },
116841116672 .unused,
116842116673 .unused,
116843116674 .unused,
......@@ -116863,7 +116694,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116863116694 },
116864116695 .call_frame = .{ .alignment = .@"16" },
116865116696 .extra_temps = .{
116866 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntitf" } } },
116697 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
116867116698 .unused,
116868116699 .unused,
116869116700 .unused,
......@@ -116891,7 +116722,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116891116722 .extra_temps = .{
116892116723 .{ .type = .usize, .kind = .{ .reg = .rdi } },
116893116724 .{ .type = .usize, .kind = .{ .reg = .rsi } },
116894 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateitf" } } },
116725 .{ .type = .usize, .kind = .{ .extern_func = "__floateitf" } },
116895116726 .unused,
116896116727 .unused,
116897116728 .unused,
......@@ -116919,7 +116750,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116919116750 .extra_temps = .{
116920116751 .{ .type = .usize, .kind = .{ .reg = .rdi } },
116921116752 .{ .type = .usize, .kind = .{ .reg = .rsi } },
116922 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneitf" } } },
116753 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneitf" } },
116923116754 .unused,
116924116755 .unused,
116925116756 .unused,
......@@ -116948,7 +116779,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116948116779 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116949116780 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
116950116781 .{ .type = .i32, .kind = .{ .reg = .edi } },
116951 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
116782 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
116952116783 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
116953116784 .unused,
116954116785 .unused,
......@@ -116981,7 +116812,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
116981116812 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
116982116813 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
116983116814 .{ .type = .i32, .kind = .{ .reg = .edi } },
116984 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
116815 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
116985116816 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
116986116817 .unused,
116987116818 .unused,
......@@ -117014,7 +116845,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117014116845 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117015116846 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
117016116847 .{ .type = .i32, .kind = .{ .reg = .edi } },
117017 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
116848 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
117018116849 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117019116850 .unused,
117020116851 .unused,
......@@ -117047,7 +116878,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117047116878 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117048116879 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
117049116880 .{ .type = .i32, .kind = .{ .reg = .edi } },
117050 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
116881 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
117051116882 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117052116883 .unused,
117053116884 .unused,
......@@ -117080,7 +116911,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117080116911 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117081116912 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
117082116913 .{ .type = .i32, .kind = .{ .reg = .edi } },
117083 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
116914 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
117084116915 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117085116916 .unused,
117086116917 .unused,
......@@ -117113,7 +116944,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117113116944 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117114116945 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
117115116946 .{ .type = .i32, .kind = .{ .reg = .edi } },
117116 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
116947 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
117117116948 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117118116949 .unused,
117119116950 .unused,
......@@ -117146,7 +116977,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117146116977 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117147116978 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
117148116979 .{ .type = .u32, .kind = .{ .reg = .edi } },
117149 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
116980 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
117150116981 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117151116982 .unused,
117152116983 .unused,
......@@ -117179,7 +117010,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117179117010 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117180117011 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
117181117012 .{ .type = .u32, .kind = .{ .reg = .edi } },
117182 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
117013 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
117183117014 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117184117015 .unused,
117185117016 .unused,
......@@ -117212,7 +117043,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117212117043 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117213117044 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
117214117045 .{ .type = .u32, .kind = .{ .reg = .edi } },
117215 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
117046 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
117216117047 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117217117048 .unused,
117218117049 .unused,
......@@ -117245,7 +117076,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117245117076 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117246117077 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
117247117078 .{ .type = .u32, .kind = .{ .reg = .edi } },
117248 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
117079 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
117249117080 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117250117081 .unused,
117251117082 .unused,
......@@ -117278,7 +117109,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117278117109 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117279117110 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
117280117111 .{ .type = .u32, .kind = .{ .reg = .edi } },
117281 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
117112 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
117282117113 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117283117114 .unused,
117284117115 .unused,
......@@ -117311,7 +117142,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117311117142 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117312117143 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
117313117144 .{ .type = .u32, .kind = .{ .reg = .edi } },
117314 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
117145 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
117315117146 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117316117147 .unused,
117317117148 .unused,
......@@ -117343,7 +117174,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117343117174 .extra_temps = .{
117344117175 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117345117176 .{ .type = .i32, .kind = .{ .reg = .edi } },
117346 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
117177 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
117347117178 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117348117179 .unused,
117349117180 .unused,
......@@ -117374,7 +117205,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117374117205 .extra_temps = .{
117375117206 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117376117207 .{ .type = .i32, .kind = .{ .reg = .edi } },
117377 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
117208 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
117378117209 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117379117210 .unused,
117380117211 .unused,
......@@ -117405,7 +117236,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117405117236 .extra_temps = .{
117406117237 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117407117238 .{ .type = .i32, .kind = .{ .reg = .edi } },
117408 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
117239 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
117409117240 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117410117241 .unused,
117411117242 .unused,
......@@ -117436,7 +117267,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117436117267 .extra_temps = .{
117437117268 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117438117269 .{ .type = .u32, .kind = .{ .reg = .edi } },
117439 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
117270 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
117440117271 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117441117272 .unused,
117442117273 .unused,
......@@ -117467,7 +117298,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117467117298 .extra_temps = .{
117468117299 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117469117300 .{ .type = .u32, .kind = .{ .reg = .edi } },
117470 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
117301 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
117471117302 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117472117303 .unused,
117473117304 .unused,
......@@ -117498,7 +117329,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117498117329 .extra_temps = .{
117499117330 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117500117331 .{ .type = .u32, .kind = .{ .reg = .edi } },
117501 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
117332 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
117502117333 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117503117334 .unused,
117504117335 .unused,
......@@ -117529,7 +117360,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117529117360 .extra_temps = .{
117530117361 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117531117362 .{ .type = .i32, .kind = .{ .reg = .edi } },
117532 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
117363 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
117533117364 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117534117365 .unused,
117535117366 .unused,
......@@ -117560,7 +117391,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117560117391 .extra_temps = .{
117561117392 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117562117393 .{ .type = .i32, .kind = .{ .reg = .edi } },
117563 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
117394 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
117564117395 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117565117396 .unused,
117566117397 .unused,
......@@ -117591,7 +117422,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117591117422 .extra_temps = .{
117592117423 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117593117424 .{ .type = .i32, .kind = .{ .reg = .edi } },
117594 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
117425 .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
117595117426 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117596117427 .unused,
117597117428 .unused,
......@@ -117622,7 +117453,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117622117453 .extra_temps = .{
117623117454 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117624117455 .{ .type = .u32, .kind = .{ .reg = .edi } },
117625 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
117456 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
117626117457 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117627117458 .unused,
117628117459 .unused,
......@@ -117653,7 +117484,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117653117484 .extra_temps = .{
117654117485 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117655117486 .{ .type = .u32, .kind = .{ .reg = .edi } },
117656 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
117487 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
117657117488 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117658117489 .unused,
117659117490 .unused,
......@@ -117684,7 +117515,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117684117515 .extra_temps = .{
117685117516 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117686117517 .{ .type = .u32, .kind = .{ .reg = .edi } },
117687 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
117518 .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
117688117519 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117689117520 .unused,
117690117521 .unused,
......@@ -117715,7 +117546,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117715117546 .extra_temps = .{
117716117547 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117717117548 .{ .type = .i64, .kind = .{ .reg = .rdi } },
117718 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatditf" } } },
117549 .{ .type = .usize, .kind = .{ .extern_func = "__floatditf" } },
117719117550 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117720117551 .unused,
117721117552 .unused,
......@@ -117746,7 +117577,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117746117577 .extra_temps = .{
117747117578 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117748117579 .{ .type = .i64, .kind = .{ .reg = .rdi } },
117749 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatditf" } } },
117580 .{ .type = .usize, .kind = .{ .extern_func = "__floatditf" } },
117750117581 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117751117582 .unused,
117752117583 .unused,
......@@ -117777,7 +117608,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117777117608 .extra_temps = .{
117778117609 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117779117610 .{ .type = .i64, .kind = .{ .reg = .rdi } },
117780 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatditf" } } },
117611 .{ .type = .usize, .kind = .{ .extern_func = "__floatditf" } },
117781117612 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117782117613 .unused,
117783117614 .unused,
......@@ -117808,7 +117639,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117808117639 .extra_temps = .{
117809117640 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117810117641 .{ .type = .u64, .kind = .{ .reg = .rdi } },
117811 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunditf" } } },
117642 .{ .type = .usize, .kind = .{ .extern_func = "__floatunditf" } },
117812117643 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117813117644 .unused,
117814117645 .unused,
......@@ -117839,7 +117670,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117839117670 .extra_temps = .{
117840117671 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117841117672 .{ .type = .u64, .kind = .{ .reg = .rdi } },
117842 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunditf" } } },
117673 .{ .type = .usize, .kind = .{ .extern_func = "__floatunditf" } },
117843117674 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117844117675 .unused,
117845117676 .unused,
......@@ -117870,7 +117701,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117870117701 .extra_temps = .{
117871117702 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117872117703 .{ .type = .u64, .kind = .{ .reg = .rdi } },
117873 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunditf" } } },
117704 .{ .type = .usize, .kind = .{ .extern_func = "__floatunditf" } },
117874117705 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117875117706 .unused,
117876117707 .unused,
......@@ -117902,7 +117733,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117902117733 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117903117734 .{ .type = .u64, .kind = .{ .reg = .rdi } },
117904117735 .{ .type = .i64, .kind = .{ .reg = .rsi } },
117905 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattitf" } } },
117736 .{ .type = .usize, .kind = .{ .extern_func = "__floattitf" } },
117906117737 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117907117738 .unused,
117908117739 .unused,
......@@ -117934,7 +117765,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117934117765 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117935117766 .{ .type = .u64, .kind = .{ .reg = .rdi } },
117936117767 .{ .type = .i64, .kind = .{ .reg = .rsi } },
117937 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattitf" } } },
117768 .{ .type = .usize, .kind = .{ .extern_func = "__floattitf" } },
117938117769 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117939117770 .unused,
117940117771 .unused,
......@@ -117966,7 +117797,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117966117797 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117967117798 .{ .type = .u64, .kind = .{ .reg = .rdi } },
117968117799 .{ .type = .i64, .kind = .{ .reg = .rsi } },
117969 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattitf" } } },
117800 .{ .type = .usize, .kind = .{ .extern_func = "__floattitf" } },
117970117801 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
117971117802 .unused,
117972117803 .unused,
......@@ -117998,7 +117829,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
117998117829 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
117999117830 .{ .type = .u64, .kind = .{ .reg = .rdi } },
118000117831 .{ .type = .u64, .kind = .{ .reg = .rsi } },
118001 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntitf" } } },
117832 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
118002117833 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
118003117834 .unused,
118004117835 .unused,
......@@ -118030,7 +117861,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
118030117861 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
118031117862 .{ .type = .u64, .kind = .{ .reg = .rdi } },
118032117863 .{ .type = .u64, .kind = .{ .reg = .rsi } },
118033 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntitf" } } },
117864 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
118034117865 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
118035117866 .unused,
118036117867 .unused,
......@@ -118062,7 +117893,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
118062117893 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
118063117894 .{ .type = .u64, .kind = .{ .reg = .rdi } },
118064117895 .{ .type = .u64, .kind = .{ .reg = .rsi } },
118065 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntitf" } } },
117896 .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
118066117897 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
118067117898 .unused,
118068117899 .unused,
......@@ -118095,7 +117926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
118095117926 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
118096117927 .{ .type = .usize, .kind = .{ .reg = .rdi } },
118097117928 .{ .type = .usize, .kind = .{ .reg = .rsi } },
118098 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateitf" } } },
117929 .{ .type = .usize, .kind = .{ .extern_func = "__floateitf" } },
118099117930 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
118100117931 .unused,
118101117932 .unused,
......@@ -118129,7 +117960,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
118129117960 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
118130117961 .{ .type = .usize, .kind = .{ .reg = .rdi } },
118131117962 .{ .type = .usize, .kind = .{ .reg = .rsi } },
118132 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateitf" } } },
117963 .{ .type = .usize, .kind = .{ .extern_func = "__floateitf" } },
118133117964 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
118134117965 .unused,
118135117966 .unused,
......@@ -118163,7 +117994,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
118163117994 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
118164117995 .{ .type = .usize, .kind = .{ .reg = .rdi } },
118165117996 .{ .type = .usize, .kind = .{ .reg = .rsi } },
118166 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateitf" } } },
117997 .{ .type = .usize, .kind = .{ .extern_func = "__floateitf" } },
118167117998 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
118168117999 .unused,
118169118000 .unused,
......@@ -118197,7 +118028,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
118197118028 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
118198118029 .{ .type = .usize, .kind = .{ .reg = .rdi } },
118199118030 .{ .type = .usize, .kind = .{ .reg = .rsi } },
118200 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneitf" } } },
118031 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneitf" } },
118201118032 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
118202118033 .unused,
118203118034 .unused,
......@@ -118231,7 +118062,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
118231118062 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
118232118063 .{ .type = .usize, .kind = .{ .reg = .rdi } },
118233118064 .{ .type = .usize, .kind = .{ .reg = .rsi } },
118234 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneitf" } } },
118065 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneitf" } },
118235118066 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
118236118067 .unused,
118237118068 .unused,
......@@ -118265,7 +118096,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
118265118096 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
118266118097 .{ .type = .usize, .kind = .{ .reg = .rdi } },
118267118098 .{ .type = .usize, .kind = .{ .reg = .rsi } },
118268 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneitf" } } },
118099 .{ .type = .usize, .kind = .{ .extern_func = "__floatuneitf" } },
118269118100 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
118270118101 .unused,
118271118102 .unused,
......@@ -131980,7 +131811,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
131980131811 .extra_temps = .{
131981131812 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
131982131813 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
131983 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
131814 .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
131984131815 .unused,
131985131816 .unused,
131986131817 .unused,
......@@ -132013,7 +131844,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
132013131844 .extra_temps = .{
132014131845 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
132015131846 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
132016 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
131847 .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
132017131848 .unused,
132018131849 .unused,
132019131850 .unused,
......@@ -132048,7 +131879,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
132048131879 .{ .type = .f16, .kind = .{ .reg = .ax } },
132049131880 .{ .type = .f32, .kind = .mem },
132050131881 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
132051 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
131882 .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
132052131883 .unused,
132053131884 .unused,
132054131885 .unused,
......@@ -133648,7 +133479,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
133648133479 .extra_temps = .{
133649133480 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
133650133481 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
133651 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
133482 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
133652133483 .unused,
133653133484 .unused,
133654133485 .unused,
......@@ -133679,7 +133510,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
133679133510 .extra_temps = .{
133680133511 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
133681133512 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
133682 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
133513 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
133683133514 .unused,
133684133515 .unused,
133685133516 .unused,
......@@ -133710,7 +133541,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
133710133541 .extra_temps = .{
133711133542 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
133712133543 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
133713 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
133544 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
133714133545 .unused,
133715133546 .unused,
133716133547 .unused,
......@@ -142100,7 +141931,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142100141931 .extra_temps = .{
142101141932 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142102141933 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
142103 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
141934 .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
142104141935 .unused,
142105141936 .unused,
142106141937 .unused,
......@@ -142133,7 +141964,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142133141964 .extra_temps = .{
142134141965 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
142135141966 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
142136 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
141967 .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
142137141968 .unused,
142138141969 .unused,
142139141970 .unused,
......@@ -142168,7 +141999,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
142168141999 .{ .type = .f16, .kind = .{ .reg = .ax } },
142169142000 .{ .type = .f32, .kind = .mem },
142170142001 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
142171 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
142002 .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
142172142003 .unused,
142173142004 .unused,
142174142005 .unused,
......@@ -143776,7 +143607,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
143776143607 .extra_temps = .{
143777143608 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
143778143609 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
143779 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
143610 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
143780143611 .unused,
143781143612 .unused,
143782143613 .unused,
......@@ -143807,7 +143638,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
143807143638 .extra_temps = .{
143808143639 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
143809143640 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
143810 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
143641 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
143811143642 .unused,
143812143643 .unused,
143813143644 .unused,
......@@ -143838,7 +143669,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
143838143669 .extra_temps = .{
143839143670 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
143840143671 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
143841 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
143672 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
143842143673 .unused,
143843143674 .unused,
143844143675 .unused,
......@@ -147771,7 +147602,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
147771147602 .extra_temps = .{
147772147603 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
147773147604 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
147774 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
147605 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
147775147606 .unused,
147776147607 .unused,
147777147608 .unused,
......@@ -147804,7 +147635,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
147804147635 .extra_temps = .{
147805147636 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
147806147637 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
147807 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
147638 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
147808147639 .unused,
147809147640 .unused,
147810147641 .unused,
......@@ -147839,7 +147670,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
147839147670 .{ .type = .f16, .kind = .{ .reg = .ax } },
147840147671 .{ .type = .f32, .kind = .mem },
147841147672 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
147842 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
147673 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
147843147674 .unused,
147844147675 .unused,
147845147676 .unused,
......@@ -148356,7 +148187,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
148356148187 .extra_temps = .{
148357148188 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
148358148189 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
148359 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
148190 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
148360148191 .unused,
148361148192 .unused,
148362148193 .unused,
......@@ -148387,7 +148218,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
148387148218 .extra_temps = .{
148388148219 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
148389148220 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
148390 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
148221 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
148391148222 .unused,
148392148223 .unused,
148393148224 .unused,
......@@ -148418,7 +148249,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
148418148249 .extra_temps = .{
148419148250 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
148420148251 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
148421 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
148252 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
148422148253 .unused,
148423148254 .unused,
148424148255 .unused,
......@@ -151430,7 +151261,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
151430151261 .extra_temps = .{
151431151262 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
151432151263 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
151433 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
151264 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
151434151265 .unused,
151435151266 .unused,
151436151267 .unused,
......@@ -151463,7 +151294,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
151463151294 .extra_temps = .{
151464151295 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
151465151296 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
151466 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
151297 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
151467151298 .unused,
151468151299 .unused,
151469151300 .unused,
......@@ -151498,7 +151329,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
151498151329 .{ .type = .f16, .kind = .{ .reg = .ax } },
151499151330 .{ .type = .f32, .kind = .mem },
151500151331 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
151501 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
151332 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
151502151333 .unused,
151503151334 .unused,
151504151335 .unused,
......@@ -151895,7 +151726,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
151895151726 .extra_temps = .{
151896151727 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
151897151728 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
151898 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
151729 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
151899151730 .unused,
151900151731 .unused,
151901151732 .unused,
......@@ -151926,7 +151757,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
151926151757 .extra_temps = .{
151927151758 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
151928151759 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
151929 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
151760 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
151930151761 .unused,
151931151762 .unused,
151932151763 .unused,
......@@ -151957,7 +151788,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
151957151788 .extra_temps = .{
151958151789 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
151959151790 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
151960 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
151791 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
151961151792 .unused,
151962151793 .unused,
151963151794 .unused,
......@@ -152469,7 +152300,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152469152300 .extra_temps = .{
152470152301 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152471152302 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
152472 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
152303 .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
152473152304 .unused,
152474152305 .unused,
152475152306 .unused,
......@@ -152502,7 +152333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152502152333 .extra_temps = .{
152503152334 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
152504152335 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
152505 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
152336 .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
152506152337 .unused,
152507152338 .unused,
152508152339 .unused,
......@@ -152537,7 +152368,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
152537152368 .{ .type = .f16, .kind = .{ .reg = .ax } },
152538152369 .{ .type = .f32, .kind = .mem },
152539152370 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
152540 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
152371 .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
152541152372 .unused,
152542152373 .unused,
152543152374 .unused,
......@@ -153617,7 +153448,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
153617153448 .extra_temps = .{
153618153449 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
153619153450 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
153620 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
153451 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
153621153452 .unused,
153622153453 .unused,
153623153454 .unused,
......@@ -153648,7 +153479,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
153648153479 .extra_temps = .{
153649153480 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
153650153481 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
153651 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
153482 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
153652153483 .unused,
153653153484 .unused,
153654153485 .unused,
......@@ -153679,7 +153510,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
153679153510 .extra_temps = .{
153680153511 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
153681153512 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
153682 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
153513 .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
153683153514 .unused,
153684153515 .unused,
153685153516 .unused,
......@@ -154161,7 +153992,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
154161153992 .extra_temps = .{
154162153993 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
154163153994 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
154164 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
153995 .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
154165153996 .unused,
154166153997 .unused,
154167153998 .unused,
......@@ -154194,7 +154025,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
154194154025 .extra_temps = .{
154195154026 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
154196154027 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
154197 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
154028 .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
154198154029 .unused,
154199154030 .unused,
154200154031 .unused,
......@@ -154229,7 +154060,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
154229154060 .{ .type = .f16, .kind = .{ .reg = .ax } },
154230154061 .{ .type = .f32, .kind = .mem },
154231154062 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
154232 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
154063 .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
154233154064 .unused,
154234154065 .unused,
154235154066 .unused,
......@@ -155309,7 +155140,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
155309155140 .extra_temps = .{
155310155141 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
155311155142 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
155312 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
155143 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
155313155144 .unused,
155314155145 .unused,
155315155146 .unused,
......@@ -155340,7 +155171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
155340155171 .extra_temps = .{
155341155172 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
155342155173 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
155343 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
155174 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
155344155175 .unused,
155345155176 .unused,
155346155177 .unused,
......@@ -155371,7 +155202,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
155371155202 .extra_temps = .{
155372155203 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
155373155204 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
155374 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
155205 .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
155375155206 .unused,
155376155207 .unused,
155377155208 .unused,
......@@ -156102,7 +155933,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
156102155933 .extra_temps = .{
156103155934 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
156104155935 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
156105 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
155936 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
156106155937 .unused,
156107155938 .unused,
156108155939 .unused,
......@@ -156135,7 +155966,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
156135155966 .extra_temps = .{
156136155967 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
156137155968 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
156138 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
155969 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
156139155970 .unused,
156140155971 .unused,
156141155972 .unused,
......@@ -156170,7 +156001,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
156170156001 .{ .type = .f16, .kind = .{ .reg = .ax } },
156171156002 .{ .type = .f32, .kind = .mem },
156172156003 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
156173 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
156004 .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
156174156005 .unused,
156175156006 .unused,
156176156007 .unused,
......@@ -157568,7 +157399,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
157568157399 .extra_temps = .{
157569157400 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
157570157401 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
157571 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
157402 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
157572157403 .unused,
157573157404 .unused,
157574157405 .unused,
......@@ -157599,7 +157430,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
157599157430 .extra_temps = .{
157600157431 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
157601157432 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
157602 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
157433 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
157603157434 .unused,
157604157435 .unused,
157605157436 .unused,
......@@ -157630,7 +157461,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
157630157461 .extra_temps = .{
157631157462 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
157632157463 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
157633 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
157464 .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
157634157465 .unused,
157635157466 .unused,
157636157467 .unused,
......@@ -158112,7 +157943,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
158112157943 .extra_temps = .{
158113157944 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
158114157945 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
158115 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
157946 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
158116157947 .unused,
158117157948 .unused,
158118157949 .unused,
......@@ -158145,7 +157976,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
158145157976 .extra_temps = .{
158146157977 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
158147157978 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
158148 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
157979 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
158149157980 .unused,
158150157981 .unused,
158151157982 .unused,
......@@ -158180,7 +158011,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
158180158011 .{ .type = .f16, .kind = .{ .reg = .ax } },
158181158012 .{ .type = .f32, .kind = .mem },
158182158013 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
158183 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
158014 .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
158184158015 .unused,
158185158016 .unused,
158186158017 .unused,
......@@ -159111,7 +158942,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
159111158942 .extra_temps = .{
159112158943 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
159113158944 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
159114 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
158945 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
159115158946 .unused,
159116158947 .unused,
159117158948 .unused,
......@@ -159142,7 +158973,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
159142158973 .extra_temps = .{
159143158974 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
159144158975 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
159145 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
158976 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
159146158977 .unused,
159147158978 .unused,
159148158979 .unused,
......@@ -159173,7 +159004,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
159173159004 .extra_temps = .{
159174159005 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
159175159006 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
159176 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
159007 .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
159177159008 .unused,
159178159009 .unused,
159179159010 .unused,
......@@ -161054,7 +160885,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161054160885 },
161055160886 .call_frame = .{ .alignment = .@"16" },
161056160887 .extra_temps = .{
161057 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(symbol) } } },
160888 .{ .type = .usize, .kind = .{ .extern_func = @tagName(symbol) } },
161058160889 .unused,
161059160890 .unused,
161060160891 .unused,
......@@ -161103,7 +160934,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161103160934 },
161104160935 .call_frame = .{ .alignment = .@"32" },
161105160936 .extra_temps = .{
161106 .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src0 } } },
160937 .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src0 } } },
161107160938 .unused,
161108160939 .unused,
161109160940 .unused,
......@@ -161129,7 +160960,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161129160960 },
161130160961 .call_frame = .{ .alignment = .@"16" },
161131160962 .extra_temps = .{
161132 .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src0 } } },
160963 .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src0 } } },
161133160964 .unused,
161134160965 .unused,
161135160966 .unused,
......@@ -161154,7 +160985,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161154160985 },
161155160986 .call_frame = .{ .alignment = .@"8" },
161156160987 .extra_temps = .{
161157 .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src0 } } },
160988 .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src0 } } },
161158160989 .unused,
161159160990 .unused,
161160160991 .unused,
......@@ -161194,7 +161025,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161194161025 },
161195161026 .call_frame = .{ .alignment = .@"32" },
161196161027 .extra_temps = .{
161197 .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src0 } } },
161028 .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src0 } } },
161198161029 .unused,
161199161030 .unused,
161200161031 .unused,
......@@ -161219,7 +161050,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161219161050 },
161220161051 .call_frame = .{ .alignment = .@"16" },
161221161052 .extra_temps = .{
161222 .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src0 } } },
161053 .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src0 } } },
161223161054 .unused,
161224161055 .unused,
161225161056 .unused,
......@@ -161243,7 +161074,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161243161074 },
161244161075 .call_frame = .{ .alignment = .@"8" },
161245161076 .extra_temps = .{
161246 .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src0 } } },
161077 .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src0 } } },
161247161078 .unused,
161248161079 .unused,
161249161080 .unused,
......@@ -161282,7 +161113,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161282161113 .{ .src = .{ .to_gpr, .none, .none } },
161283161114 },
161284161115 .extra_temps = .{
161285 .{ .type = .anyerror, .kind = .{ .lazy_symbol = .{ .kind = .const_data } } },
161116 .{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
161286161117 .{ .type = .u32, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } } },
161287161118 .unused,
161288161119 .unused,
......@@ -161311,7 +161142,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161311161142 .{ .src = .{ .to_gpr, .none, .none } },
161312161143 },
161313161144 .extra_temps = .{
161314 .{ .type = .anyerror, .kind = .{ .lazy_symbol = .{ .kind = .const_data } } },
161145 .{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
161315161146 .{ .type = .u32, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } } },
161316161147 .unused,
161317161148 .unused,
......@@ -161340,7 +161171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161340161171 .{ .src = .{ .to_gpr, .none, .none } },
161341161172 },
161342161173 .extra_temps = .{
161343 .{ .type = .anyerror, .kind = .{ .lazy_symbol = .{ .kind = .const_data } } },
161174 .{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
161344161175 .{ .type = .u32, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } } },
161345161176 .unused,
161346161177 .unused,
......@@ -161391,7 +161222,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161391161222 },
161392161223 .call_frame = .{ .alignment = .@"32" },
161393161224 .extra_temps = .{
161394 .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src1 } } },
161225 .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src1 } } },
161395161226 .unused,
161396161227 .unused,
161397161228 .unused,
......@@ -161417,7 +161248,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161417161248 },
161418161249 .call_frame = .{ .alignment = .@"16" },
161419161250 .extra_temps = .{
161420 .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src1 } } },
161251 .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src1 } } },
161421161252 .unused,
161422161253 .unused,
161423161254 .unused,
......@@ -161442,7 +161273,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161442161273 },
161443161274 .call_frame = .{ .alignment = .@"8" },
161444161275 .extra_temps = .{
161445 .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src1 } } },
161276 .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src1 } } },
161446161277 .unused,
161447161278 .unused,
161448161279 .unused,
......@@ -161638,7 +161469,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161638161469 },
161639161470 .call_frame = .{ .alignment = .@"16" },
161640161471 .extra_temps = .{
161641 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmah" } } },
161472 .{ .type = .usize, .kind = .{ .extern_func = "__fmah" } },
161642161473 .unused,
161643161474 .unused,
161644161475 .unused,
......@@ -161781,7 +161612,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161781161612 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
161782161613 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
161783161614 .{ .type = .f16, .kind = .{ .reg = .xmm2 } },
161784 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmah" } } },
161615 .{ .type = .usize, .kind = .{ .extern_func = "__fmah" } },
161785161616 .unused,
161786161617 .unused,
161787161618 .unused,
......@@ -161818,7 +161649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161818161649 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
161819161650 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
161820161651 .{ .type = .f16, .kind = .{ .reg = .xmm2 } },
161821 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmah" } } },
161652 .{ .type = .usize, .kind = .{ .extern_func = "__fmah" } },
161822161653 .unused,
161823161654 .unused,
161824161655 .unused,
......@@ -161857,7 +161688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161857161688 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
161858161689 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
161859161690 .{ .type = .f16, .kind = .{ .reg = .xmm2 } },
161860 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmah" } } },
161691 .{ .type = .usize, .kind = .{ .extern_func = "__fmah" } },
161861161692 .{ .type = .f16, .kind = .{ .reg = .ax } },
161862161693 .unused,
161863161694 .unused,
......@@ -161899,7 +161730,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161899161730 .{ .type = .f16, .kind = .{ .reg = .xmm0 } },
161900161731 .{ .type = .f16, .kind = .{ .reg = .xmm1 } },
161901161732 .{ .type = .f16, .kind = .{ .reg = .xmm2 } },
161902 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmah" } } },
161733 .{ .type = .usize, .kind = .{ .extern_func = "__fmah" } },
161903161734 .unused,
161904161735 .unused,
161905161736 .unused,
......@@ -161987,7 +161818,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
161987161818 },
161988161819 .call_frame = .{ .alignment = .@"16" },
161989161820 .extra_temps = .{
161990 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaf" } } },
161821 .{ .type = .usize, .kind = .{ .extern_func = "fmaf" } },
161991161822 .unused,
161992161823 .unused,
161993161824 .unused,
......@@ -162153,7 +161984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162153161984 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
162154161985 .{ .type = .f32, .kind = .{ .reg = .xmm1 } },
162155161986 .{ .type = .f32, .kind = .{ .reg = .xmm2 } },
162156 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaf" } } },
161987 .{ .type = .usize, .kind = .{ .extern_func = "fmaf" } },
162157161988 .unused,
162158161989 .unused,
162159161990 .unused,
......@@ -162189,7 +162020,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162189162020 .{ .type = .f32, .kind = .{ .reg = .xmm0 } },
162190162021 .{ .type = .f32, .kind = .{ .reg = .xmm1 } },
162191162022 .{ .type = .f32, .kind = .{ .reg = .xmm2 } },
162192 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaf" } } },
162023 .{ .type = .usize, .kind = .{ .extern_func = "fmaf" } },
162193162024 .unused,
162194162025 .unused,
162195162026 .unused,
......@@ -162271,7 +162102,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162271162102 },
162272162103 .call_frame = .{ .alignment = .@"16" },
162273162104 .extra_temps = .{
162274 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fma" } } },
162105 .{ .type = .usize, .kind = .{ .extern_func = "fma" } },
162275162106 .unused,
162276162107 .unused,
162277162108 .unused,
......@@ -162437,7 +162268,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162437162268 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
162438162269 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
162439162270 .{ .type = .f64, .kind = .{ .reg = .xmm2 } },
162440 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fma" } } },
162271 .{ .type = .usize, .kind = .{ .extern_func = "fma" } },
162441162272 .unused,
162442162273 .unused,
162443162274 .unused,
......@@ -162473,7 +162304,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162473162304 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
162474162305 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
162475162306 .{ .type = .f64, .kind = .{ .reg = .xmm2 } },
162476 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fma" } } },
162307 .{ .type = .usize, .kind = .{ .extern_func = "fma" } },
162477162308 .unused,
162478162309 .unused,
162479162310 .unused,
......@@ -162509,7 +162340,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162509162340 .{ .type = .f64, .kind = .{ .reg = .xmm0 } },
162510162341 .{ .type = .f64, .kind = .{ .reg = .xmm1 } },
162511162342 .{ .type = .f64, .kind = .{ .reg = .xmm2 } },
162512 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fma" } } },
162343 .{ .type = .usize, .kind = .{ .extern_func = "fma" } },
162513162344 .unused,
162514162345 .unused,
162515162346 .unused,
......@@ -162546,7 +162377,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162546162377 .extra_temps = .{
162547162378 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
162548162379 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
162549 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmax" } } },
162380 .{ .type = .usize, .kind = .{ .extern_func = "__fmax" } },
162550162381 .unused,
162551162382 .unused,
162552162383 .unused,
......@@ -162582,7 +162413,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162582162413 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
162583162414 .{ .type = .f80, .kind = .{ .reg = .xmm0 } },
162584162415 .{ .type = .f80, .kind = .{ .frame = .call_frame } },
162585 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmax" } } },
162416 .{ .type = .usize, .kind = .{ .extern_func = "__fmax" } },
162586162417 .unused,
162587162418 .unused,
162588162419 .unused,
......@@ -162619,7 +162450,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162619162450 },
162620162451 .call_frame = .{ .alignment = .@"16" },
162621162452 .extra_temps = .{
162622 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaq" } } },
162453 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
162623162454 .unused,
162624162455 .unused,
162625162456 .unused,
......@@ -162652,7 +162483,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162652162483 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
162653162484 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
162654162485 .{ .type = .f128, .kind = .{ .reg = .xmm2 } },
162655 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaq" } } },
162486 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
162656162487 .unused,
162657162488 .unused,
162658162489 .unused,
......@@ -162688,7 +162519,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162688162519 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
162689162520 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
162690162521 .{ .type = .f128, .kind = .{ .reg = .xmm2 } },
162691 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaq" } } },
162522 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
162692162523 .unused,
162693162524 .unused,
162694162525 .unused,
......@@ -162724,7 +162555,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162724162555 .{ .type = .f128, .kind = .{ .reg = .xmm0 } },
162725162556 .{ .type = .f128, .kind = .{ .reg = .xmm1 } },
162726162557 .{ .type = .f128, .kind = .{ .reg = .xmm2 } },
162727 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaq" } } },
162558 .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
162728162559 .unused,
162729162560 .unused,
162730162561 .unused,
......@@ -162778,7 +162609,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162778162609 .{ .src = .{ .to_gpr, .none, .none } },
162779162610 },
162780162611 .extra_temps = .{
162781 .{ .type = .anyerror, .kind = .{ .lazy_symbol = .{ .kind = .const_data } } },
162612 .{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
162782162613 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
162783162614 .unused,
162784162615 .unused,
......@@ -162802,7 +162633,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162802162633 .{ .src = .{ .to_gpr, .none, .none } },
162803162634 },
162804162635 .extra_temps = .{
162805 .{ .type = .anyerror, .kind = .{ .lazy_symbol = .{ .kind = .const_data } } },
162636 .{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
162806162637 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
162807162638 .unused,
162808162639 .unused,
......@@ -162826,7 +162657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
162826162657 .{ .src = .{ .to_gpr, .none, .none } },
162827162658 },
162828162659 .extra_temps = .{
162829 .{ .type = .anyerror, .kind = .{ .lazy_symbol = .{ .kind = .const_data } } },
162660 .{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
162830162661 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
162831162662 .unused,
162832162663 .unused,
......@@ -163517,65 +163348,18 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163517163348 };
163518163349 for (ops) |op| try op.die(cg);
163519163350 },
163520 .runtime_nav_ptr => switch (cg.bin_file.tag) {
163521 .elf, .macho => {
163522 const ty_nav = air_datas[@intFromEnum(inst)].ty_nav;
163523
163524 const nav = ip.getNav(ty_nav.nav);
163525 const sym_index, const relocation = sym: {
163526 if (cg.bin_file.cast(.elf)) |elf_file| {
163527 const zo = elf_file.zigObjectPtr().?;
163528 if (nav.getExtern(ip)) |e| {
163529 const sym = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip));
163530 linkage: switch (e.linkage) {
163531 .internal => {},
163532 .strong => switch (e.visibility) {
163533 .default => zo.symbol(sym).flags.is_extern_ptr = true,
163534 .hidden, .protected => {},
163535 },
163536 .weak => {
163537 zo.symbol(sym).flags.weak = true;
163538 continue :linkage .strong;
163539 },
163540 .link_once => unreachable,
163541 }
163542 break :sym .{ sym, e.relocation };
163543 } else break :sym .{ try zo.getOrCreateMetadataForNav(zcu, ty_nav.nav), .any };
163544 } else if (cg.bin_file.cast(.macho)) |macho_file| {
163545 const zo = macho_file.getZigObject().?;
163546 if (nav.getExtern(ip)) |e| {
163547 const sym = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip));
163548 linkage: switch (e.linkage) {
163549 .internal => {},
163550 .strong => switch (e.visibility) {
163551 .default => zo.symbols.items[sym].flags.is_extern_ptr = true,
163552 .hidden, .protected => {},
163553 },
163554 .weak => {
163555 zo.symbols.items[sym].flags.weak = true;
163556 continue :linkage .strong;
163557 },
163558 .link_once => unreachable,
163559 }
163560 break :sym .{ sym, e.relocation };
163561 } else break :sym .{ try zo.getOrCreateMetadataForNav(macho_file, ty_nav.nav), .any };
163562 } else unreachable;
163563 };
163564
163565 if (cg.mod.pic) {
163566 try cg.spillRegisters(&.{ .rdi, .rax });
163567 } else {
163568 try cg.spillRegisters(&.{.rax});
163569 }
163570
163571 var slot = try cg.tempInit(.usize, switch (relocation) {
163572 .any => .{ .lea_symbol = .{ .sym_index = sym_index } },
163573 .pcrel => .{ .lea_pcrel = .{ .sym_index = sym_index } },
163574 });
163575 while (try slot.toRegClass(true, .general_purpose, cg)) {}
163576 try slot.finish(inst, &.{}, &.{}, cg);
163577 },
163578 else => return cg.fail("TODO implement runtime_nav_ptr on {}", .{cg.bin_file.tag}),
163351 .runtime_nav_ptr => {
163352 const ty_nav = air_datas[@intFromEnum(inst)].ty_nav;
163353 const nav = ip.getNav(ty_nav.nav);
163354 const is_threadlocal = zcu.comp.config.any_non_single_threaded and nav.isThreadlocal(ip);
163355 if (is_threadlocal) if (cg.mod.pic) {
163356 try cg.spillRegisters(&.{ .rdi, .rax });
163357 } else {
163358 try cg.spillRegisters(&.{.rax});
163359 };
163360 var res = try cg.tempInit(.fromInterned(ty_nav.ty), .{ .lea_nav = ty_nav.nav });
163361 if (is_threadlocal) while (try res.toRegClass(true, .general_purpose, cg)) {};
163362 try res.finish(inst, &.{}, &.{}, cg);
163579163363 },
163580163364 .c_va_arg => try cg.airVaArg(inst),
163581163365 .c_va_copy => try cg.airVaCopy(inst),
......@@ -164231,11 +164015,11 @@ fn airFptrunc(self: *CodeGen, inst: Air.Inst.Index) !void {
164231164015 },
164232164016 else => unreachable,
164233164017 }) {
164234 var callee_buf: ["__trunc?f?f2".len]u8 = undefined;
164235 break :result try self.genCall(.{ .lib = .{
164018 var sym_buf: ["__trunc?f?f2".len]u8 = undefined;
164019 break :result try self.genCall(.{ .extern_func = .{
164236164020 .return_type = self.floatCompilerRtAbiType(dst_ty, src_ty).toIntern(),
164237164021 .param_types = &.{self.floatCompilerRtAbiType(src_ty, dst_ty).toIntern()},
164238 .callee = std.fmt.bufPrint(&callee_buf, "__trunc{c}f{c}f2", .{
164022 .sym = std.fmt.bufPrint(&sym_buf, "__trunc{c}f{c}f2", .{
164239164023 floatCompilerRtAbiName(src_bits),
164240164024 floatCompilerRtAbiName(dst_bits),
164241164025 }) catch unreachable,
......@@ -164335,11 +164119,11 @@ fn airFpext(self: *CodeGen, inst: Air.Inst.Index) !void {
164335164119 else => unreachable,
164336164120 }) {
164337164121 if (dst_ty.isVector(zcu)) break :result null;
164338 var callee_buf: ["__extend?f?f2".len]u8 = undefined;
164339 break :result try self.genCall(.{ .lib = .{
164122 var sym_buf: ["__extend?f?f2".len]u8 = undefined;
164123 break :result try self.genCall(.{ .extern_func = .{
164340164124 .return_type = self.floatCompilerRtAbiType(dst_scalar_ty, src_scalar_ty).toIntern(),
164341164125 .param_types = &.{self.floatCompilerRtAbiType(src_scalar_ty, dst_scalar_ty).toIntern()},
164342 .callee = std.fmt.bufPrint(&callee_buf, "__extend{c}f{c}f2", .{
164126 .sym = std.fmt.bufPrint(&sym_buf, "__extend{c}f{c}f2", .{
164343164127 floatCompilerRtAbiName(src_bits),
164344164128 floatCompilerRtAbiName(dst_bits),
164345164129 }) catch unreachable,
......@@ -164776,7 +164560,7 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void {
164776164560 .storage = .{ .repeated_elem = mask_val.ip_index },
164777164561 } });
164778164562
164779 const splat_mcv = try self.genTypedValue(.fromInterned(splat_val));
164563 const splat_mcv = try self.lowerValue(.fromInterned(splat_val));
164780164564 const splat_addr_mcv: MCValue = switch (splat_mcv) {
164781164565 .memory, .indirect, .load_frame => splat_mcv.address(),
164782164566 else => .{ .register = try self.copyToTmpRegister(.usize, splat_mcv.address()) },
......@@ -164975,7 +164759,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
164975164759 .mul, .mul_wrap => {},
164976164760 .div_trunc, .div_floor, .div_exact, .rem, .mod => {
164977164761 const signed = dst_ty.isSignedInt(zcu);
164978 var callee_buf: ["__udiv?i3".len]u8 = undefined;
164762 var sym_buf: ["__udiv?i3".len]u8 = undefined;
164979164763 const signed_div_floor_state: struct {
164980164764 frame_index: FrameIndex,
164981164765 state: State,
......@@ -164994,7 +164778,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
164994164778
164995164779 const lhs_mcv = try self.resolveInst(bin_op.lhs);
164996164780 const mat_lhs_mcv = switch (lhs_mcv) {
164997 .load_symbol => mat_lhs_mcv: {
164781 .load_nav, .load_uav, .load_lazy_sym => mat_lhs_mcv: {
164998164782 // TODO clean this up!
164999164783 const addr_reg = try self.copyToTmpRegister(.usize, lhs_mcv.address());
165000164784 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
......@@ -165018,7 +164802,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
165018164802
165019164803 const rhs_mcv = try self.resolveInst(bin_op.rhs);
165020164804 const mat_rhs_mcv = switch (rhs_mcv) {
165021 .load_symbol => mat_rhs_mcv: {
164805 .load_nav, .load_uav, .load_lazy_sym => mat_rhs_mcv: {
165022164806 // TODO clean this up!
165023164807 const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
165024164808 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
......@@ -165045,10 +164829,10 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
165045164829 break :state .{ .frame_index = frame_index, .state = state, .reloc = reloc };
165046164830 } else undefined;
165047164831 const call_mcv = try self.genCall(
165048 .{ .lib = .{
164832 .{ .extern_func = .{
165049164833 .return_type = dst_ty.toIntern(),
165050164834 .param_types = &.{ src_ty.toIntern(), src_ty.toIntern() },
165051 .callee = std.fmt.bufPrint(&callee_buf, "__{s}{s}{c}i3", .{
164835 .sym = std.fmt.bufPrint(&sym_buf, "__{s}{s}{c}i3", .{
165052164836 if (signed) "" else "u",
165053164837 switch (tag) {
165054164838 .div_trunc, .div_exact => "div",
......@@ -165082,10 +164866,10 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
165082164866 });
165083164867 self.performReloc(signed_div_floor_state.reloc);
165084164868 const dst_mcv = try self.genCall(
165085 .{ .lib = .{
164869 .{ .extern_func = .{
165086164870 .return_type = dst_ty.toIntern(),
165087164871 .param_types = &.{ src_ty.toIntern(), src_ty.toIntern() },
165088 .callee = std.fmt.bufPrint(&callee_buf, "__div{c}i3", .{
164872 .sym = std.fmt.bufPrint(&sym_buf, "__div{c}i3", .{
165089164873 intCompilerRtAbiName(@intCast(dst_ty.bitSize(zcu))),
165090164874 }) catch unreachable,
165091164875 } },
......@@ -165119,7 +164903,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
165119164903
165120164904 const rhs_mcv = try self.resolveInst(bin_op.rhs);
165121164905 const mat_rhs_mcv = switch (rhs_mcv) {
165122 .load_symbol => mat_rhs_mcv: {
164906 .load_nav, .load_uav, .load_lazy_sym => mat_rhs_mcv: {
165123164907 // TODO clean this up!
165124164908 const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
165125164909 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
......@@ -165333,10 +165117,10 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {
165333165117 const ptr_c_int = try pt.singleMutPtrType(.c_int);
165334165118 const overflow = try self.allocTempRegOrMem(.c_int, false);
165335165119
165336 const dst_mcv = try self.genCall(.{ .lib = .{
165120 const dst_mcv = try self.genCall(.{ .extern_func = .{
165337165121 .return_type = .i128_type,
165338165122 .param_types = &.{ .i128_type, .i128_type, ptr_c_int.toIntern() },
165339 .callee = "__muloti4",
165123 .sym = "__muloti4",
165340165124 } }, &.{ .i128, .i128, ptr_c_int }, &.{
165341165125 .{ .air_ref = bin_op.lhs },
165342165126 .{ .air_ref = bin_op.rhs },
......@@ -165351,7 +165135,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {
165351165135
165352165136 const lhs_mcv = try self.resolveInst(bin_op.lhs);
165353165137 const mat_lhs_mcv = switch (lhs_mcv) {
165354 .load_symbol => mat_lhs_mcv: {
165138 .load_nav, .load_uav, .load_lazy_sym => mat_lhs_mcv: {
165355165139 // TODO clean this up!
165356165140 const addr_reg = try self.copyToTmpRegister(.usize, lhs_mcv.address());
165357165141 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
......@@ -165375,7 +165159,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {
165375165159
165376165160 const rhs_mcv = try self.resolveInst(bin_op.rhs);
165377165161 const mat_rhs_mcv = switch (rhs_mcv) {
165378 .load_symbol => mat_rhs_mcv: {
165162 .load_nav, .load_uav, .load_lazy_sym => mat_rhs_mcv: {
165379165163 // TODO clean this up!
165380165164 const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
165381165165 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
......@@ -165849,10 +165633,10 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
165849165633 .signed => {
165850165634 const ptr_c_int = try pt.singleMutPtrType(.c_int);
165851165635 const overflow = try self.allocTempRegOrMem(.c_int, false);
165852 const result = try self.genCall(.{ .lib = .{
165636 const result = try self.genCall(.{ .extern_func = .{
165853165637 .return_type = .i128_type,
165854165638 .param_types = &.{ .i128_type, .i128_type, ptr_c_int.toIntern() },
165855 .callee = "__muloti4",
165639 .sym = "__muloti4",
165856165640 } }, &.{ .i128, .i128, ptr_c_int }, &.{
165857165641 .{ .air_ref = bin_op.lhs },
165858165642 .{ .air_ref = bin_op.rhs },
......@@ -165906,7 +165690,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
165906165690 break :mat_lhs_mcv mat_lhs_mcv;
165907165691 },
165908165692 },
165909 .load_symbol => {
165693 .load_nav, .load_uav, .load_lazy_sym => {
165910165694 // TODO clean this up!
165911165695 const addr_reg = try self.copyToTmpRegister(.usize, lhs_mcv.address());
165912165696 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
......@@ -165930,7 +165714,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
165930165714 break :mat_rhs_mcv mat_rhs_mcv;
165931165715 },
165932165716 },
165933 .load_symbol => {
165717 .load_nav, .load_uav, .load_lazy_sym => {
165934165718 // TODO clean this up!
165935165719 const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
165936165720 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
......@@ -166406,7 +166190,7 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {
166406166190 defer self.register_manager.unlockReg(shift_lock);
166407166191
166408166192 const mask_ty = try pt.vectorType(.{ .len = 16, .child = .u8_type });
166409 const mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
166193 const mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
166410166194 .ty = mask_ty.toIntern(),
166411166195 .storage = .{ .elems = &([1]InternPool.Index{
166412166196 (try rhs_ty.childType(zcu).maxIntScalar(pt, .u8)).toIntern(),
......@@ -166547,7 +166331,7 @@ fn airShlSat(self: *CodeGen, inst: Air.Inst.Index) !void {
166547166331 // if lhs is negative, it is min
166548166332 switch (lhs_ty.intInfo(zcu).signedness) {
166549166333 .unsigned => {
166550 const bound_mcv = try self.genTypedValue(try lhs_ty.maxIntScalar(self.pt, lhs_ty));
166334 const bound_mcv = try self.lowerValue(try lhs_ty.maxIntScalar(self.pt, lhs_ty));
166551166335 try self.genCopy(lhs_ty, dst_mcv, bound_mcv, .{});
166552166336 },
166553166337 .signed => {
......@@ -166556,7 +166340,7 @@ fn airShlSat(self: *CodeGen, inst: Air.Inst.Index) !void {
166556166340 // we only need the highest bit so shifting the highest part of lhs_mcv
166557166341 // is enough to check the signedness. other parts can be skipped here.
166558166342 var lhs_temp2 = try self.tempInit(lhs_ty, lhs_mcv);
166559 var zero_temp = try self.tempInit(lhs_ty, try self.genTypedValue(try self.pt.intValue(lhs_ty, 0)));
166343 var zero_temp = try self.tempInit(lhs_ty, try self.lowerValue(try self.pt.intValue(lhs_ty, 0)));
166560166344 const sign_cc_temp = lhs_temp2.cmpInts(.lt, &zero_temp, self) catch |err| switch (err) {
166561166345 error.SelectFailed => unreachable,
166562166346 else => |e| return e,
......@@ -166567,13 +166351,13 @@ fn airShlSat(self: *CodeGen, inst: Air.Inst.Index) !void {
166567166351 try sign_cc_temp.die(self);
166568166352
166569166353 // if it is negative
166570 const min_mcv = try self.genTypedValue(try lhs_ty.minIntScalar(self.pt, lhs_ty));
166354 const min_mcv = try self.lowerValue(try lhs_ty.minIntScalar(self.pt, lhs_ty));
166571166355 try self.genCopy(lhs_ty, dst_mcv, min_mcv, .{});
166572166356 const sign_reloc_br = try self.asmJmpReloc(undefined);
166573166357 self.performReloc(sign_reloc_condbr);
166574166358
166575166359 // if it is positive
166576 const max_mcv = try self.genTypedValue(try lhs_ty.maxIntScalar(self.pt, lhs_ty));
166360 const max_mcv = try self.lowerValue(try lhs_ty.maxIntScalar(self.pt, lhs_ty));
166577166361 try self.genCopy(lhs_ty, dst_mcv, max_mcv, .{});
166578166362 self.performReloc(sign_reloc_br);
166579166363 },
......@@ -167294,7 +167078,12 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
167294167078 }.to64(),
167295167079 ),
167296167080 },
167297 .memory, .load_symbol, .load_direct, .load_got => switch (index_mcv) {
167081 .memory,
167082 .load_nav,
167083 .load_uav,
167084 .load_lazy_sym,
167085 .load_extern_func,
167086 => switch (index_mcv) {
167298167087 .immediate => |index_imm| try self.asmMemoryImmediate(
167299167088 .{ ._, .bt },
167300167089 .{
......@@ -167356,11 +167145,15 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
167356167145 },
167357167146 ),
167358167147 .memory,
167359 .load_symbol,
167360 .load_direct,
167361 .load_got,
167148 .load_nav,
167149 .lea_nav,
167150 .load_uav,
167151 .lea_uav,
167152 .load_lazy_sym,
167153 .lea_lazy_sym,
167154 .load_extern_func,
167155 .lea_extern_func,
167362167156 => try self.genSetReg(addr_reg, .usize, array_mcv.address(), .{}),
167363 .lea_symbol, .lea_direct => unreachable,
167364167157 else => return self.fail("TODO airArrayElemVal_val for {s} of {}", .{
167365167158 @tagName(array_mcv), array_ty.fmt(pt),
167366167159 }),
......@@ -168461,7 +168254,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A
168461168254 .child = (try pt.intType(.signed, scalar_bits)).ip_index,
168462168255 });
168463168256
168464 const sign_mcv = try self.genTypedValue(switch (tag) {
168257 const sign_mcv = try self.lowerValue(switch (tag) {
168465168258 .neg => try vec_ty.minInt(pt, vec_ty),
168466168259 .abs => try vec_ty.maxInt(pt, vec_ty),
168467168260 else => unreachable,
......@@ -168603,11 +168396,11 @@ fn genRoundLibcall(self: *CodeGen, ty: Type, src_mcv: MCValue, mode: bits.RoundM
168603168396 if (ty.zigTypeTag(zcu) != .float)
168604168397 return self.fail("TODO implement genRound for {}", .{ty.fmt(pt)});
168605168398
168606 var callee_buf: ["__trunc?".len]u8 = undefined;
168607 return try self.genCall(.{ .lib = .{
168399 var sym_buf: ["__trunc?".len]u8 = undefined;
168400 return try self.genCall(.{ .extern_func = .{
168608168401 .return_type = ty.toIntern(),
168609168402 .param_types = &.{ty.toIntern()},
168610 .callee = std.fmt.bufPrint(&callee_buf, "{s}{s}{s}", .{
168403 .sym = std.fmt.bufPrint(&sym_buf, "{s}{s}{s}", .{
168611168404 floatLibcAbiPrefix(ty),
168612168405 switch (mode.direction) {
168613168406 .down => "floor",
......@@ -168880,11 +168673,11 @@ fn airSqrt(self: *CodeGen, inst: Air.Inst.Index) !void {
168880168673 80, 128 => true,
168881168674 else => unreachable,
168882168675 }) {
168883 var callee_buf: ["__sqrt?".len]u8 = undefined;
168884 break :result try self.genCall(.{ .lib = .{
168676 var sym_buf: ["__sqrt?".len]u8 = undefined;
168677 break :result try self.genCall(.{ .extern_func = .{
168885168678 .return_type = ty.toIntern(),
168886168679 .param_types = &.{ty.toIntern()},
168887 .callee = std.fmt.bufPrint(&callee_buf, "{s}sqrt{s}", .{
168680 .sym = std.fmt.bufPrint(&sym_buf, "{s}sqrt{s}", .{
168888168681 floatLibcAbiPrefix(ty),
168889168682 floatLibcAbiSuffix(ty),
168890168683 }) catch unreachable,
......@@ -169033,11 +168826,11 @@ fn airSqrt(self: *CodeGen, inst: Air.Inst.Index) !void {
169033168826fn airUnaryMath(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
169034168827 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
169035168828 const ty = self.typeOf(un_op);
169036 var callee_buf: ["__round?".len]u8 = undefined;
169037 const result = try self.genCall(.{ .lib = .{
168829 var sym_buf: ["__round?".len]u8 = undefined;
168830 const result = try self.genCall(.{ .extern_func = .{
169038168831 .return_type = ty.toIntern(),
169039168832 .param_types = &.{ty.toIntern()},
169040 .callee = std.fmt.bufPrint(&callee_buf, "{s}{s}{s}", .{
168833 .sym = std.fmt.bufPrint(&sym_buf, "{s}{s}{s}", .{
169041168834 floatLibcAbiPrefix(ty),
169042168835 switch (tag) {
169043168836 .sin,
......@@ -169237,19 +169030,19 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE
169237169030 .immediate,
169238169031 .register,
169239169032 .register_offset,
169240 .lea_symbol,
169241 .lea_pcrel,
169242 .lea_direct,
169243 .lea_got,
169244169033 .lea_frame,
169034 .lea_nav,
169035 .lea_uav,
169036 .lea_lazy_sym,
169037 .lea_extern_func,
169245169038 => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref(), .{}),
169246169039 .memory,
169247169040 .indirect,
169248 .load_symbol,
169249 .load_pcrel,
169250 .load_direct,
169251 .load_got,
169252169041 .load_frame,
169042 .load_nav,
169043 .load_uav,
169044 .load_lazy_sym,
169045 .load_extern_func,
169253169046 => {
169254169047 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv);
169255169048 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
......@@ -169457,19 +169250,19 @@ fn store(
169457169250 .immediate,
169458169251 .register,
169459169252 .register_offset,
169460 .lea_symbol,
169461 .lea_pcrel,
169462 .lea_direct,
169463 .lea_got,
169464169253 .lea_frame,
169254 .lea_nav,
169255 .lea_uav,
169256 .lea_lazy_sym,
169257 .lea_extern_func,
169465169258 => try self.genCopy(src_ty, ptr_mcv.deref(), src_mcv, opts),
169466169259 .memory,
169467169260 .indirect,
169468 .load_symbol,
169469 .load_pcrel,
169470 .load_direct,
169471 .load_got,
169472169261 .load_frame,
169262 .load_nav,
169263 .load_uav,
169264 .load_lazy_sym,
169265 .load_extern_func,
169473169266 => {
169474169267 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv);
169475169268 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
......@@ -169935,18 +169728,18 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv:
169935169728 .eflags,
169936169729 .register_overflow,
169937169730 .register_mask,
169938 .lea_symbol,
169939 .lea_pcrel,
169940 .lea_direct,
169941 .lea_got,
169942169731 .lea_frame,
169732 .lea_nav,
169733 .lea_uav,
169734 .lea_lazy_sym,
169735 .lea_extern_func,
169943169736 .elementwise_args,
169944169737 .reserved_frame,
169945169738 .air_ref,
169946169739 => unreachable, // unmodifiable destination
169947169740 .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)),
169948169741 .register_pair, .register_triple, .register_quadruple => unreachable, // unimplemented
169949 .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => {
169742 .memory, .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {
169950169743 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
169951169744 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
169952169745 defer self.register_manager.unlockReg(addr_reg_lock);
......@@ -170706,7 +170499,7 @@ fn genMulDivBinOp(
170706170499 defer for (reg_locks) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);
170707170500
170708170501 const mat_lhs_mcv = switch (lhs_mcv) {
170709 .load_symbol => mat_lhs_mcv: {
170502 .load_nav, .load_uav, .load_lazy_sym => mat_lhs_mcv: {
170710170503 // TODO clean this up!
170711170504 const addr_reg = try self.copyToTmpRegister(.usize, lhs_mcv.address());
170712170505 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
......@@ -170719,7 +170512,7 @@ fn genMulDivBinOp(
170719170512 };
170720170513 defer if (mat_lhs_lock) |lock| self.register_manager.unlockReg(lock);
170721170514 const mat_rhs_mcv = switch (rhs_mcv) {
170722 .load_symbol => mat_rhs_mcv: {
170515 .load_nav, .load_uav, .load_lazy_sym => mat_rhs_mcv: {
170723170516 // TODO clean this up!
170724170517 const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
170725170518 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
......@@ -170887,7 +170680,7 @@ fn genMulDivBinOp(
170887170680 .is_const = true,
170888170681 },
170889170682 });
170890 _ = try self.genCall(.{ .lib = .{
170683 _ = try self.genCall(.{ .extern_func = .{
170891170684 .return_type = .void_type,
170892170685 .param_types = &.{
170893170686 manyptr_u32_ty.toIntern(),
......@@ -170895,7 +170688,7 @@ fn genMulDivBinOp(
170895170688 manyptr_const_u32_ty.toIntern(),
170896170689 .usize_type,
170897170690 },
170898 .callee = switch (tag) {
170691 .sym = switch (tag) {
170899170692 .div_trunc,
170900170693 .div_floor,
170901170694 .div_exact,
......@@ -171118,8 +170911,8 @@ fn genBinOp(
171118170911 .rem, .mod => {},
171119170912 else => if (!type_needs_libcall) break :libcall,
171120170913 }
171121 var callee_buf: ["__mod?f3".len]u8 = undefined;
171122 const callee = switch (air_tag) {
170914 var sym_buf: ["__mod?f3".len]u8 = undefined;
170915 const sym = switch (air_tag) {
171123170916 .add,
171124170917 .sub,
171125170918 .mul,
......@@ -171127,11 +170920,11 @@ fn genBinOp(
171127170920 .div_trunc,
171128170921 .div_floor,
171129170922 .div_exact,
171130 => std.fmt.bufPrint(&callee_buf, "__{s}{c}f3", .{
170923 => std.fmt.bufPrint(&sym_buf, "__{s}{c}f3", .{
171131170924 @tagName(air_tag)[0..3],
171132170925 floatCompilerRtAbiName(float_bits),
171133170926 }),
171134 .rem, .mod, .min, .max => std.fmt.bufPrint(&callee_buf, "{s}f{s}{s}", .{
170927 .rem, .mod, .min, .max => std.fmt.bufPrint(&sym_buf, "{s}f{s}{s}", .{
171135170928 floatLibcAbiPrefix(lhs_ty),
171136170929 switch (air_tag) {
171137170930 .rem, .mod => "mod",
......@@ -171145,22 +170938,22 @@ fn genBinOp(
171145170938 @tagName(air_tag), lhs_ty.fmt(pt),
171146170939 }),
171147170940 } catch unreachable;
171148 const result = try self.genCall(.{ .lib = .{
170941 const result = try self.genCall(.{ .extern_func = .{
171149170942 .return_type = lhs_ty.toIntern(),
171150170943 .param_types = &.{ lhs_ty.toIntern(), rhs_ty.toIntern() },
171151 .callee = callee,
170944 .sym = sym,
171152170945 } }, &.{ lhs_ty, rhs_ty }, &.{ .{ .air_ref = lhs_air }, .{ .air_ref = rhs_air } }, .{});
171153170946 return switch (air_tag) {
171154170947 .mod => result: {
171155170948 const adjusted: MCValue = if (type_needs_libcall) adjusted: {
171156 var add_callee_buf: ["__add?f3".len]u8 = undefined;
171157 break :adjusted try self.genCall(.{ .lib = .{
170949 var add_sym_buf: ["__add?f3".len]u8 = undefined;
170950 break :adjusted try self.genCall(.{ .extern_func = .{
171158170951 .return_type = lhs_ty.toIntern(),
171159170952 .param_types = &.{
171160170953 lhs_ty.toIntern(),
171161170954 rhs_ty.toIntern(),
171162170955 },
171163 .callee = std.fmt.bufPrint(&add_callee_buf, "__add{c}f3", .{
170956 .sym = std.fmt.bufPrint(&add_sym_buf, "__add{c}f3", .{
171164170957 floatCompilerRtAbiName(float_bits),
171165170958 }) catch unreachable,
171166170959 } }, &.{ lhs_ty, rhs_ty }, &.{ result, .{ .air_ref = rhs_air } }, .{});
......@@ -171259,10 +171052,10 @@ fn genBinOp(
171259171052 }),
171260171053 else => unreachable,
171261171054 };
171262 break :result try self.genCall(.{ .lib = .{
171055 break :result try self.genCall(.{ .extern_func = .{
171263171056 .return_type = lhs_ty.toIntern(),
171264171057 .param_types = &.{ lhs_ty.toIntern(), rhs_ty.toIntern() },
171265 .callee = callee,
171058 .sym = sym,
171266171059 } }, &.{ lhs_ty, rhs_ty }, &.{ adjusted, .{ .air_ref = rhs_air } }, .{});
171267171060 },
171268171061 .div_trunc, .div_floor => try self.genRoundLibcall(lhs_ty, result, .{
......@@ -171545,13 +171338,15 @@ fn genBinOp(
171545171338 .immediate,
171546171339 .eflags,
171547171340 .register_offset,
171548 .load_symbol,
171549 .lea_symbol,
171550 .load_direct,
171551 .lea_direct,
171552 .load_got,
171553 .lea_got,
171554171341 .lea_frame,
171342 .load_nav,
171343 .lea_nav,
171344 .load_uav,
171345 .lea_uav,
171346 .load_lazy_sym,
171347 .lea_lazy_sym,
171348 .load_extern_func,
171349 .lea_extern_func,
171555171350 => true,
171556171351 .memory => |addr| std.math.cast(i32, @as(i64, @bitCast(addr))) == null,
171557171352 else => false,
......@@ -171604,15 +171399,15 @@ fn genBinOp(
171604171399 .register_offset,
171605171400 .register_overflow,
171606171401 .register_mask,
171607 .load_symbol,
171608 .lea_symbol,
171609 .load_pcrel,
171610 .lea_pcrel,
171611 .load_direct,
171612 .lea_direct,
171613 .load_got,
171614 .lea_got,
171615171402 .lea_frame,
171403 .load_nav,
171404 .lea_nav,
171405 .load_uav,
171406 .lea_uav,
171407 .load_lazy_sym,
171408 .lea_lazy_sym,
171409 .load_extern_func,
171410 .lea_extern_func,
171616171411 .elementwise_args,
171617171412 .reserved_frame,
171618171413 .air_ref,
......@@ -172710,7 +172505,7 @@ fn genBinOp(
172710172505 .cmp_neq,
172711172506 => {
172712172507 const unsigned_ty = try lhs_ty.toUnsigned(pt);
172713 const not_mcv = try self.genTypedValue(try unsigned_ty.maxInt(pt, unsigned_ty));
172508 const not_mcv = try self.lowerValue(try unsigned_ty.maxInt(pt, unsigned_ty));
172714172509 const not_mem: Memory = if (not_mcv.isBase())
172715172510 try not_mcv.mem(self, .{ .size = .fromSize(abi_size) })
172716172511 else
......@@ -172792,11 +172587,11 @@ fn genBinOpMir(
172792172587 .eflags,
172793172588 .register_overflow,
172794172589 .register_mask,
172795 .lea_direct,
172796 .lea_got,
172797172590 .lea_frame,
172798 .lea_symbol,
172799 .lea_pcrel,
172591 .lea_nav,
172592 .lea_uav,
172593 .lea_lazy_sym,
172594 .lea_extern_func,
172800172595 .elementwise_args,
172801172596 .reserved_frame,
172802172597 .air_ref,
......@@ -172886,16 +172681,16 @@ fn genBinOpMir(
172886172681 .register_offset,
172887172682 .memory,
172888172683 .indirect,
172889 .load_symbol,
172890 .lea_symbol,
172891 .load_pcrel,
172892 .lea_pcrel,
172893 .load_direct,
172894 .lea_direct,
172895 .load_got,
172896 .lea_got,
172897172684 .load_frame,
172898172685 .lea_frame,
172686 .load_nav,
172687 .lea_nav,
172688 .load_uav,
172689 .lea_uav,
172690 .load_lazy_sym,
172691 .lea_lazy_sym,
172692 .load_extern_func,
172693 .lea_extern_func,
172899172694 => {
172900172695 direct: {
172901172696 try self.asmRegisterMemory(mir_limb_tag, dst_alias, switch (src_mcv) {
......@@ -172928,10 +172723,11 @@ fn genBinOpMir(
172928172723 switch (src_mcv) {
172929172724 .eflags,
172930172725 .register_offset,
172931 .lea_symbol,
172932 .lea_direct,
172933 .lea_got,
172934172726 .lea_frame,
172727 .lea_nav,
172728 .lea_uav,
172729 .lea_lazy_sym,
172730 .lea_extern_func,
172935172731 => {
172936172732 assert(off == 0);
172937172733 const reg = try self.copyToTmpRegister(ty, src_mcv);
......@@ -172943,9 +172739,10 @@ fn genBinOpMir(
172943172739 );
172944172740 },
172945172741 .memory,
172946 .load_symbol,
172947 .load_direct,
172948 .load_got,
172742 .load_nav,
172743 .load_uav,
172744 .load_lazy_sym,
172745 .load_extern_func,
172949172746 => {
172950172747 const ptr_ty = try pt.singleConstPtrType(ty);
172951172748 const addr_reg = try self.copyToTmpRegister(ptr_ty, src_mcv.address());
......@@ -172965,13 +172762,20 @@ fn genBinOpMir(
172965172762 }
172966172763 }
172967172764 },
172968 .memory, .indirect, .load_symbol, .load_pcrel, .load_got, .load_direct, .load_frame => {
172765 .memory,
172766 .indirect,
172767 .load_frame,
172768 .load_nav,
172769 .load_uav,
172770 .load_lazy_sym,
172771 .load_extern_func,
172772 => {
172969172773 const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock };
172970172774 const limb_abi_size: u32 = @min(abi_size, 8);
172971172775
172972172776 const dst_info: OpInfo = switch (dst_mcv) {
172973172777 else => unreachable,
172974 .memory, .load_symbol, .load_got, .load_direct => dst: {
172778 .memory, .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => dst: {
172975172779 const dst_addr_reg =
172976172780 (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
172977172781 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
......@@ -173007,19 +172811,24 @@ fn genBinOpMir(
173007172811 .register_quadruple,
173008172812 .register_offset,
173009172813 .indirect,
173010 .lea_direct,
173011 .lea_got,
173012172814 .load_frame,
173013172815 .lea_frame,
173014 .lea_symbol,
173015 .lea_pcrel,
172816 .lea_nav,
172817 .lea_uav,
172818 .lea_lazy_sym,
172819 .lea_extern_func,
173016172820 => null,
173017 .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => src: {
172821 .memory,
172822 .load_nav,
172823 .load_uav,
172824 .load_lazy_sym,
172825 .load_extern_func,
172826 => src: {
173018172827 switch (resolved_src_mcv) {
173019172828 .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr))) != null and
173020172829 std.math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null)
173021172830 break :src null,
173022 .load_symbol, .load_got, .load_direct => {},
172831 .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {},
173023172832 else => unreachable,
173024172833 }
173025172834
......@@ -173059,9 +172868,10 @@ fn genBinOpMir(
173059172868 };
173060172869 const dst_limb_mem: Memory = switch (dst_mcv) {
173061172870 .memory,
173062 .load_symbol,
173063 .load_got,
173064 .load_direct,
172871 .load_nav,
172872 .load_uav,
172873 .load_lazy_sym,
172874 .load_extern_func,
173065172875 => .{
173066172876 .base = .{ .reg = dst_info.?.addr_reg },
173067172877 .mod = .{ .rm = .{
......@@ -173151,16 +172961,16 @@ fn genBinOpMir(
173151172961 .eflags,
173152172962 .memory,
173153172963 .indirect,
173154 .load_symbol,
173155 .lea_symbol,
173156 .load_pcrel,
173157 .lea_pcrel,
173158 .load_direct,
173159 .lea_direct,
173160 .load_got,
173161 .lea_got,
173162172964 .load_frame,
173163172965 .lea_frame,
172966 .load_nav,
172967 .lea_nav,
172968 .load_uav,
172969 .lea_uav,
172970 .load_lazy_sym,
172971 .lea_lazy_sym,
172972 .load_extern_func,
172973 .lea_extern_func,
173164172974 => {
173165172975 const src_limb_mcv: MCValue = if (src_info) |info| .{
173166172976 .indirect = .{ .reg = info.addr_reg, .off = off },
......@@ -173170,10 +172980,11 @@ fn genBinOpMir(
173170172980 },
173171172981 .eflags,
173172172982 .register_offset,
173173 .lea_symbol,
173174 .lea_direct,
173175 .lea_got,
173176172983 .lea_frame,
172984 .lea_nav,
172985 .lea_uav,
172986 .lea_lazy_sym,
172987 .lea_extern_func,
173177172988 => switch (limb_i) {
173178172989 0 => resolved_src_mcv,
173179172990 else => .{ .immediate = 0 },
......@@ -173221,11 +173032,11 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv
173221173032 .register_offset,
173222173033 .register_overflow,
173223173034 .register_mask,
173224 .lea_symbol,
173225 .lea_pcrel,
173226 .lea_direct,
173227 .lea_got,
173228173035 .lea_frame,
173036 .lea_nav,
173037 .lea_uav,
173038 .lea_lazy_sym,
173039 .lea_extern_func,
173229173040 .elementwise_args,
173230173041 .reserved_frame,
173231173042 .air_ref,
......@@ -173283,15 +173094,15 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv
173283173094 },
173284173095 .register_offset,
173285173096 .eflags,
173286 .load_symbol,
173287 .lea_symbol,
173288 .load_pcrel,
173289 .lea_pcrel,
173290 .load_direct,
173291 .lea_direct,
173292 .load_got,
173293 .lea_got,
173294173097 .lea_frame,
173098 .load_nav,
173099 .lea_nav,
173100 .load_uav,
173101 .lea_uav,
173102 .load_lazy_sym,
173103 .lea_lazy_sym,
173104 .load_extern_func,
173105 .lea_extern_func,
173295173106 => {
173296173107 const src_reg = try self.copyToTmpRegister(dst_ty, resolved_src_mcv);
173297173108 switch (abi_size) {
......@@ -173346,7 +173157,14 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv
173346173157 }
173347173158 },
173348173159 .register_pair, .register_triple, .register_quadruple => unreachable, // unimplemented
173349 .memory, .indirect, .load_symbol, .load_pcrel, .load_direct, .load_got, .load_frame => {
173160 .memory,
173161 .indirect,
173162 .load_frame,
173163 .load_nav,
173164 .load_uav,
173165 .load_lazy_sym,
173166 .load_extern_func,
173167 => {
173350173168 const tmp_reg = try self.copyToTmpRegister(dst_ty, dst_mcv);
173351173169 const tmp_mcv = MCValue{ .register = tmp_reg };
173352173170 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
......@@ -173359,16 +173177,14 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv
173359173177}
173360173178
173361173179fn airArg(self: *CodeGen, inst: Air.Inst.Index) !void {
173362 const pt = self.pt;
173363 const zcu = pt.zcu;
173364 // skip zero-bit arguments as they don't have a corresponding arg instruction
173365 var arg_index = self.arg_index;
173366 while (self.args[arg_index] == .none) arg_index += 1;
173367 self.arg_index = arg_index + 1;
173368
173369 const result: MCValue = if (self.debug_output == .none and self.liveness.isUnused(inst)) .unreach else result: {
173180 const zcu = self.pt.zcu;
173181 const arg_index = for (self.args, 0..) |arg, arg_index| {
173182 if (arg != .none) break arg_index;
173183 } else unreachable;
173184 const src_mcv = self.args[arg_index];
173185 self.args = self.args[arg_index + 1 ..];
173186 const result: MCValue = if (self.mod.strip and self.liveness.isUnused(inst)) .unreach else result: {
173370173187 const arg_ty = self.typeOfIndex(inst);
173371 const src_mcv = self.args[arg_index];
173372173188 switch (src_mcv) {
173373173189 .register, .register_pair, .load_frame => {
173374173190 for (src_mcv.getRegs()) |reg| self.register_manager.getRegAssumeFree(reg, inst);
......@@ -173467,68 +173283,115 @@ fn airArg(self: *CodeGen, inst: Air.Inst.Index) !void {
173467173283 return self.finishAir(inst, result, .{ .none, .none, .none });
173468173284}
173469173285
173470fn airDbgVarArgs(self: *CodeGen) !void {
173471 if (self.debug_output == .none) return;
173472 if (!self.pt.zcu.typeToFunc(self.fn_type).?.is_var_args) return;
173473 try self.asmPseudo(.pseudo_dbg_var_args_none);
173474}
173475
173476fn genLocalDebugInfo(
173477 self: *CodeGen,
173478 inst: Air.Inst.Index,
173479 mcv: MCValue,
173480) !void {
173481 if (self.debug_output == .none) return;
173482 switch (self.air.instructions.items(.tag)[@intFromEnum(inst)]) {
173286fn genLocalDebugInfo(cg: *CodeGen, air_tag: Air.Inst.Tag, ty: Type, mcv: MCValue) !void {
173287 assert(!cg.mod.strip);
173288 _ = switch (air_tag) {
173483173289 else => unreachable,
173484 .arg, .dbg_arg_inline, .dbg_var_val => |tag| {
173485 switch (mcv) {
173486 .none => try self.asmAir(.dbg_local, inst),
173487 .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
173488 .immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, .u(imm)),
173489 .lea_frame => |frame_addr| try self.asmAirFrameAddress(.dbg_local, inst, frame_addr),
173490 .lea_symbol => |sym_off| try self.asmAirImmediate(.dbg_local, inst, .rel(sym_off)),
173491 else => {
173492 const ty = switch (tag) {
173493 else => unreachable,
173494 .arg => self.typeOfIndex(inst),
173495 .dbg_arg_inline, .dbg_var_val => self.typeOf(
173496 self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op.operand,
173497 ),
173498 };
173499 const frame_index = try self.allocFrameIndex(.initSpill(ty, self.pt.zcu));
173500 try self.genSetMem(.{ .frame = frame_index }, 0, ty, mcv, .{});
173501 try self.asmAirMemory(.dbg_local, inst, .{
173502 .base = .{ .frame = frame_index },
173503 .mod = .{ .rm = .{ .size = .qword } },
173504 });
173290 .arg, .dbg_var_val, .dbg_arg_inline => switch (mcv) {
173291 .none, .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
173292 .immediate => |imm| if (std.math.cast(u32, imm)) |small| try cg.addInst(.{
173293 .tag = .pseudo,
173294 .ops = switch (air_tag) {
173295 else => unreachable,
173296 .arg, .dbg_arg_inline => .pseudo_dbg_arg_i_u,
173297 .dbg_var_val => .pseudo_dbg_var_i_u,
173505173298 },
173506 }
173299 .data = .{ .i = .{ .i = small } },
173300 }) else try cg.addInst(.{
173301 .tag = .pseudo,
173302 .ops = switch (air_tag) {
173303 else => unreachable,
173304 .arg, .dbg_arg_inline => .pseudo_dbg_arg_i_64,
173305 .dbg_var_val => .pseudo_dbg_var_i_64,
173306 },
173307 .data = .{ .i64 = imm },
173308 }),
173309 .lea_frame => |frame_addr| try cg.addInst(.{
173310 .tag = .pseudo,
173311 .ops = switch (air_tag) {
173312 else => unreachable,
173313 .arg, .dbg_arg_inline => .pseudo_dbg_arg_fa,
173314 .dbg_var_val => .pseudo_dbg_var_fa,
173315 },
173316 .data = .{ .fa = frame_addr },
173317 }),
173318 else => {
173319 const frame_index = try cg.allocFrameIndex(.initSpill(ty, cg.pt.zcu));
173320 try cg.genSetMem(.{ .frame = frame_index }, 0, ty, mcv, .{});
173321 _ = try cg.addInst(.{
173322 .tag = .pseudo,
173323 .ops = switch (air_tag) {
173324 else => unreachable,
173325 .arg, .dbg_arg_inline => .pseudo_dbg_arg_m,
173326 .dbg_var_val => .pseudo_dbg_var_m,
173327 },
173328 .data = .{ .x = .{
173329 .payload = try cg.addExtra(Mir.Memory.encode(.{
173330 .base = .{ .frame = frame_index },
173331 .mod = .{ .rm = .{ .size = .qword } },
173332 })),
173333 } },
173334 });
173335 },
173507173336 },
173508173337 .dbg_var_ptr => switch (mcv) {
173509173338 else => unreachable,
173510 .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
173511 .lea_frame => |frame_addr| try self.asmAirMemory(.dbg_local, inst, .{
173512 .base = .{ .frame = frame_addr.index },
173513 .mod = .{ .rm = .{
173514 .size = .qword,
173515 .disp = frame_addr.off,
173339 .none, .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
173340 .lea_frame => |frame_addr| try cg.addInst(.{
173341 .tag = .pseudo,
173342 .ops = .pseudo_dbg_var_m,
173343 .data = .{ .x = .{
173344 .payload = try cg.addExtra(Mir.Memory.encode(.{
173345 .base = .{ .frame = frame_addr.index },
173346 .mod = .{ .rm = .{
173347 .size = .qword,
173348 .disp = frame_addr.off,
173349 } },
173350 })),
173516173351 } },
173517173352 }),
173518 // debug info should explicitly ignore pcrel requirements
173519 .lea_symbol, .lea_pcrel => |sym_off| try self.asmAirMemory(.dbg_local, inst, .{
173520 .base = .{ .reloc = sym_off.sym_index },
173521 .mod = .{ .rm = .{
173522 .size = .qword,
173523 .disp = sym_off.off,
173353 .lea_nav => |nav| try cg.addInst(.{
173354 .tag = .pseudo,
173355 .ops = .pseudo_dbg_var_m,
173356 .data = .{ .x = .{
173357 .payload = try cg.addExtra(Mir.Memory.encode(.{
173358 .base = .{ .nav = nav },
173359 .mod = .{ .rm = .{ .size = .qword } },
173360 })),
173361 } },
173362 }),
173363 .lea_uav => |uav| try cg.addInst(.{
173364 .tag = .pseudo,
173365 .ops = .pseudo_dbg_var_m,
173366 .data = .{ .x = .{
173367 .payload = try cg.addExtra(Mir.Memory.encode(.{
173368 .base = .{ .uav = uav },
173369 .mod = .{ .rm = .{ .size = .qword } },
173370 })),
173524173371 } },
173525173372 }),
173526 .lea_direct, .lea_got => |sym_index| try self.asmAirMemory(.dbg_local, inst, .{
173527 .base = .{ .reloc = sym_index },
173528 .mod = .{ .rm = .{ .size = .qword } },
173373 .lea_lazy_sym => |lazy_sym| try cg.addInst(.{
173374 .tag = .pseudo,
173375 .ops = .pseudo_dbg_var_m,
173376 .data = .{ .x = .{
173377 .payload = try cg.addExtra(Mir.Memory.encode(.{
173378 .base = .{ .lazy_sym = lazy_sym },
173379 .mod = .{ .rm = .{ .size = .qword } },
173380 })),
173381 } },
173382 }),
173383 .lea_extern_func => |extern_func| try cg.addInst(.{
173384 .tag = .pseudo,
173385 .ops = .pseudo_dbg_var_m,
173386 .data = .{ .x = .{
173387 .payload = try cg.addExtra(Mir.Memory.encode(.{
173388 .base = .{ .extern_func = extern_func },
173389 .mod = .{ .rm = .{ .size = .qword } },
173390 })),
173391 } },
173529173392 }),
173530173393 },
173531 }
173394 };
173532173395}
173533173396
173534173397fn airRetAddr(self: *CodeGen, inst: Air.Inst.Index) !void {
......@@ -173552,8 +173415,8 @@ fn airCall(self: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
173552173415 @ptrCast(self.air.extra.items[extra.end..][0..extra.data.args_len]);
173553173416
173554173417 const ExpectedContents = extern struct {
173555 tys: [16][@sizeOf(Type)]u8 align(@alignOf(Type)),
173556 vals: [16][@sizeOf(MCValue)]u8 align(@alignOf(MCValue)),
173418 tys: [32][@sizeOf(Type)]u8 align(@alignOf(Type)),
173419 vals: [32][@sizeOf(MCValue)]u8 align(@alignOf(MCValue)),
173557173420 };
173558173421 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
173559173422 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
......@@ -173579,11 +173442,10 @@ fn airCall(self: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
173579173442
173580173443fn genCall(self: *CodeGen, info: union(enum) {
173581173444 air: Air.Inst.Ref,
173582 lib: struct {
173445 extern_func: struct {
173583173446 return_type: InternPool.Index,
173584173447 param_types: []const InternPool.Index,
173585 lib: ?[]const u8 = null,
173586 callee: []const u8,
173448 sym: []const u8,
173587173449 },
173588173450}, arg_types: []const Type, args: []const MCValue, opts: CopyOptions) !MCValue {
173589173451 const pt = self.pt;
......@@ -173599,18 +173461,18 @@ fn genCall(self: *CodeGen, info: union(enum) {
173599173461 else => unreachable,
173600173462 };
173601173463 },
173602 .lib => |lib| try pt.funcType(.{
173603 .param_types = lib.param_types,
173604 .return_type = lib.return_type,
173464 .extern_func => |extern_func| try pt.funcType(.{
173465 .param_types = extern_func.param_types,
173466 .return_type = extern_func.return_type,
173605173467 .cc = self.target.cCallingConvention().?,
173606173468 }),
173607173469 };
173608173470 const fn_info = zcu.typeToFunc(fn_ty).?;
173609173471
173610173472 const ExpectedContents = extern struct {
173611 var_args: [16][@sizeOf(Type)]u8 align(@alignOf(Type)),
173612 frame_indices: [16]FrameIndex,
173613 reg_locks: [16][@sizeOf(?RegisterLock)]u8 align(@alignOf(?RegisterLock)),
173473 var_args: [32][@sizeOf(Type)]u8 align(@alignOf(Type)),
173474 frame_indices: [32]FrameIndex,
173475 reg_locks: [32][@sizeOf(?RegisterLock)]u8 align(@alignOf(?RegisterLock)),
173614173476 };
173615173477 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
173616173478 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
......@@ -173830,52 +173692,9 @@ fn genCall(self: *CodeGen, info: union(enum) {
173830173692 else => func_key,
173831173693 } else func_key,
173832173694 }) {
173833 .func => |func| {
173834 if (self.bin_file.cast(.elf)) |elf_file| {
173835 const zo = elf_file.zigObjectPtr().?;
173836 const sym_index = try zo.getOrCreateMetadataForNav(zcu, func.owner_nav);
173837 try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = sym_index }));
173838 } else if (self.bin_file.cast(.coff)) |coff_file| {
173839 const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
173840 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
173841 const scratch_reg = abi.getCAbiLinkerScratchReg(fn_info.cc);
173842 try self.genSetReg(scratch_reg, .usize, .{ .lea_got = sym_index }, .{});
173843 try self.asmRegister(.{ ._, .call }, scratch_reg);
173844 } else if (self.bin_file.cast(.macho)) |macho_file| {
173845 const zo = macho_file.getZigObject().?;
173846 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);
173847 const sym = zo.symbols.items[sym_index];
173848 try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = sym.nlist_idx }));
173849 } else if (self.bin_file.cast(.plan9)) |p9| {
173850 const atom_index = try p9.seeNav(pt, func.owner_nav);
173851 const atom = p9.getAtom(atom_index);
173852 try self.asmMemory(.{ ._, .call }, .{
173853 .base = .{ .reg = .ds },
173854 .mod = .{ .rm = .{
173855 .size = .qword,
173856 .disp = @intCast(atom.getOffsetTableAddress(p9)),
173857 } },
173858 });
173859 } else unreachable;
173860 },
173861 .@"extern" => |@"extern"| if (self.bin_file.cast(.elf)) |elf_file| {
173862 const target_sym_index = try elf_file.getGlobalSymbol(
173863 @"extern".name.toSlice(ip),
173864 @"extern".lib_name.toSlice(ip),
173865 );
173866 try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
173867 } else if (self.bin_file.cast(.macho)) |macho_file| {
173868 const target_sym_index = try macho_file.getGlobalSymbol(
173869 @"extern".name.toSlice(ip),
173870 @"extern".lib_name.toSlice(ip),
173871 );
173872 try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
173873 } else try self.genExternSymbolRef(
173874 .call,
173875 @"extern".lib_name.toSlice(ip),
173876 @"extern".name.toSlice(ip),
173877 ),
173878 else => return self.fail("TODO implement calling bitcasted functions", .{}),
173695 else => unreachable,
173696 .func => |func| try self.asmImmediate(.{ ._, .call }, .{ .nav = .{ .index = func.owner_nav } }),
173697 .@"extern" => |@"extern"| try self.asmImmediate(.{ ._, .call }, .{ .nav = .{ .index = @"extern".owner_nav } }),
173879173698 }
173880173699 } else {
173881173700 assert(self.typeOf(callee).zigTypeTag(zcu) == .pointer);
......@@ -173883,13 +173702,7 @@ fn genCall(self: *CodeGen, info: union(enum) {
173883173702 try self.genSetReg(scratch_reg, .usize, .{ .air_ref = callee }, .{});
173884173703 try self.asmRegister(.{ ._, .call }, scratch_reg);
173885173704 },
173886 .lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {
173887 const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);
173888 try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
173889 } else if (self.bin_file.cast(.macho)) |macho_file| {
173890 const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);
173891 try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
173892 } else try self.genExternSymbolRef(.call, lib.lib, lib.callee),
173705 .extern_func => |extern_func| try self.asmImmediate(.{ ._, .call }, .{ .extern_func = try self.addString(extern_func.sym) }),
173893173706 }
173894173707 return call_info.return_value.short;
173895173708}
......@@ -174023,11 +173836,11 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
174023173836 80, 128 => false,
174024173837 else => unreachable,
174025173838 }) {
174026 var callee_buf: ["__???f2".len]u8 = undefined;
174027 const ret = try self.genCall(.{ .lib = .{
173839 var sym_buf: ["__???f2".len]u8 = undefined;
173840 const ret = try self.genCall(.{ .extern_func = .{
174028173841 .return_type = .i32_type,
174029173842 .param_types = &.{ ty.toIntern(), ty.toIntern() },
174030 .callee = std.fmt.bufPrint(&callee_buf, "__{s}{c}f2", .{
173843 .sym = std.fmt.bufPrint(&sym_buf, "__{s}{c}f2", .{
174031173844 switch (op) {
174032173845 .eq => "eq",
174033173846 .neq => "ne",
......@@ -174170,17 +173983,27 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
174170173983 .register_overflow,
174171173984 .register_mask,
174172173985 .indirect,
174173 .lea_direct,
174174 .lea_got,
174175173986 .lea_frame,
174176 .lea_symbol,
174177 .lea_pcrel,
173987 .lea_nav,
173988 .lea_uav,
173989 .lea_lazy_sym,
173990 .lea_extern_func,
174178173991 .elementwise_args,
174179173992 .reserved_frame,
174180173993 .air_ref,
174181173994 => unreachable,
174182 .register, .register_pair, .register_triple, .register_quadruple, .load_frame => null,
174183 .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => dst: {
173995 .register,
173996 .register_pair,
173997 .register_triple,
173998 .register_quadruple,
173999 .load_frame,
174000 => null,
174001 .memory,
174002 .load_nav,
174003 .load_uav,
174004 .load_lazy_sym,
174005 .load_extern_func,
174006 => dst: {
174184174007 switch (resolved_dst_mcv) {
174185174008 .memory => |addr| if (std.math.cast(
174186174009 i32,
......@@ -174189,7 +174012,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
174189174012 i32,
174190174013 @as(i64, @bitCast(addr)) + abi_size - 8,
174191174014 ) != null) break :dst null,
174192 .load_symbol, .load_pcrel, .load_got, .load_direct => {},
174015 .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {},
174193174016 else => unreachable,
174194174017 }
174195174018
......@@ -174226,17 +174049,26 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
174226174049 .register_overflow,
174227174050 .register_mask,
174228174051 .indirect,
174229 .lea_symbol,
174230 .lea_pcrel,
174231 .lea_direct,
174232 .lea_got,
174233174052 .lea_frame,
174053 .lea_nav,
174054 .lea_uav,
174055 .lea_lazy_sym,
174056 .lea_extern_func,
174234174057 .elementwise_args,
174235174058 .reserved_frame,
174236174059 .air_ref,
174237174060 => unreachable,
174238 .register_pair, .register_triple, .register_quadruple, .load_frame => null,
174239 .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => src: {
174061 .register_pair,
174062 .register_triple,
174063 .register_quadruple,
174064 .load_frame,
174065 => null,
174066 .memory,
174067 .load_nav,
174068 .load_uav,
174069 .load_lazy_sym,
174070 .load_extern_func,
174071 => src: {
174240174072 switch (resolved_src_mcv) {
174241174073 .memory => |addr| if (std.math.cast(
174242174074 i32,
......@@ -174245,7 +174077,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
174245174077 i32,
174246174078 @as(i64, @bitCast(addr)) + abi_size - 8,
174247174079 ) != null) break :src null,
174248 .load_symbol, .load_pcrel, .load_got, .load_direct => {},
174080 .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {},
174249174081 else => unreachable,
174250174082 }
174251174083
......@@ -174526,10 +174358,31 @@ fn genTry(
174526174358 return result;
174527174359}
174528174360
174529fn airDbgVar(self: *CodeGen, inst: Air.Inst.Index) !void {
174530 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
174531 try self.genLocalDebugInfo(inst, try self.resolveInst(pl_op.operand));
174532 return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none });
174361fn airDbgVar(cg: *CodeGen, inst: Air.Inst.Index) !void {
174362 if (cg.mod.strip) return;
174363 const air_tag = cg.air.instructions.items(.tag)[@intFromEnum(inst)];
174364 const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
174365 const air_name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
174366 const op_ty = cg.typeOf(pl_op.operand);
174367 const local_ty = switch (air_tag) {
174368 else => unreachable,
174369 .dbg_var_ptr => op_ty.childType(cg.pt.zcu),
174370 .dbg_var_val, .dbg_arg_inline => op_ty,
174371 };
174372
174373 try cg.mir_locals.append(cg.gpa, .{
174374 .name = switch (air_name) {
174375 .none => switch (air_tag) {
174376 else => unreachable,
174377 .dbg_arg_inline => .none,
174378 },
174379 else => try cg.addString(air_name.toSlice(cg.air)),
174380 },
174381 .type = local_ty.toIntern(),
174382 });
174383
174384 try cg.genLocalDebugInfo(air_tag, local_ty, try cg.resolveInst(pl_op.operand));
174385 return cg.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none });
174533174386}
174534174387
174535174388fn genCondBrMir(self: *CodeGen, ty: Type, mcv: MCValue) !Mir.Inst.Index {
......@@ -174633,10 +174486,10 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue)
174633174486 .register_offset,
174634174487 .register_overflow,
174635174488 .register_mask,
174636 .lea_direct,
174637 .lea_got,
174638 .lea_symbol,
174639 .lea_pcrel,
174489 .lea_nav,
174490 .lea_uav,
174491 .lea_lazy_sym,
174492 .lea_extern_func,
174640174493 .elementwise_args,
174641174494 .reserved_frame,
174642174495 .air_ref,
......@@ -174684,10 +174537,10 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue)
174684174537 },
174685174538
174686174539 .memory,
174687 .load_symbol,
174688 .load_pcrel,
174689 .load_got,
174690 .load_direct,
174540 .load_nav,
174541 .load_uav,
174542 .load_lazy_sym,
174543 .load_extern_func,
174691174544 => {
174692174545 const addr_reg = (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
174693174546 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
......@@ -175721,7 +175574,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
175721175574 .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |_|
175722175575 break :arg input_mcv,
175723175576 .indirect, .load_frame => break :arg input_mcv,
175724 .load_symbol, .load_direct, .load_got => {},
175577 .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {},
175725175578 else => {
175726175579 const temp_mcv = try self.allocTempRegOrMem(ty, false);
175727175580 try self.genCopy(ty, temp_mcv, input_mcv, .{});
......@@ -176000,12 +175853,20 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
176000175853 } }
176001175854 else
176002175855 return self.fail("invalid modifier: '{s}'", .{modifier}),
176003 .lea_got => |sym_index| if (std.mem.eql(u8, modifier, "P"))
176004 .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_got = sym_index }) }
175856 .lea_nav => |nav| if (std.mem.eql(u8, modifier, "P"))
175857 .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_nav = nav }) }
175858 else
175859 return self.fail("invalid modifier: '{s}'", .{modifier}),
175860 .lea_uav => |uav| if (std.mem.eql(u8, modifier, "P"))
175861 .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_uav = uav }) }
175862 else
175863 return self.fail("invalid modifier: '{s}'", .{modifier}),
175864 .lea_lazy_sym => |lazy_sym| if (std.mem.eql(u8, modifier, "P"))
175865 .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_lazy_sym = lazy_sym }) }
176005175866 else
176006175867 return self.fail("invalid modifier: '{s}'", .{modifier}),
176007 .lea_symbol => |sym_off| if (std.mem.eql(u8, modifier, "P"))
176008 .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_symbol = sym_off }) }
175868 .lea_extern_func => |extern_func| if (std.mem.eql(u8, modifier, "P"))
175869 .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_extern_func = extern_func }) }
176009175870 else
176010175871 return self.fail("invalid modifier: '{s}'", .{modifier}),
176011175872 else => return self.fail("invalid constraint: '{s}'", .{op_str}),
......@@ -176689,11 +176550,11 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
176689176550 .eflags,
176690176551 .register_overflow,
176691176552 .register_mask,
176692 .lea_direct,
176693 .lea_got,
176694176553 .lea_frame,
176695 .lea_symbol,
176696 .lea_pcrel,
176554 .lea_nav,
176555 .lea_uav,
176556 .lea_lazy_sym,
176557 .lea_extern_func,
176697176558 .elementwise_args,
176698176559 .reserved_frame,
176699176560 .air_ref,
......@@ -176788,7 +176649,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
176788176649 }
176789176650 return;
176790176651 },
176791 .load_symbol, .load_pcrel, .load_direct, .load_got => {
176652 .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {
176792176653 const src_addr_reg =
176793176654 (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
176794176655 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
......@@ -176821,7 +176682,11 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
176821176682 .undef => if (opts.safety and part_i > 0) .{ .register = dst_regs[0] } else .undef,
176822176683 dst_tag => |src_regs| .{ .register = src_regs[part_i] },
176823176684 .memory, .indirect, .load_frame => src_mcv.address().offset(part_disp).deref(),
176824 .load_symbol, .load_pcrel, .load_direct, .load_got => .{ .indirect = .{
176685 .load_nav,
176686 .load_uav,
176687 .load_lazy_sym,
176688 .load_extern_func,
176689 => .{ .indirect = .{
176825176690 .reg = src_info.?.addr_reg,
176826176691 .off = part_disp,
176827176692 } },
......@@ -176842,11 +176707,11 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
176842176707 src_mcv,
176843176708 opts,
176844176709 ),
176845 .memory, .load_symbol, .load_pcrel, .load_direct, .load_got => {
176710 .memory => {
176846176711 switch (dst_mcv) {
176847176712 .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
176848176713 return self.genSetMem(.{ .reg = .ds }, small_addr, ty, src_mcv, opts),
176849 .load_symbol, .load_pcrel, .load_direct, .load_got => {},
176714 .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {},
176850176715 else => unreachable,
176851176716 }
176852176717
......@@ -176863,6 +176728,10 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
176863176728 src_mcv,
176864176729 opts,
176865176730 ),
176731 .load_nav => |nav| try self.genSetMem(.{ .nav = nav }, 0, ty, src_mcv, opts),
176732 .load_uav => |uav| try self.genSetMem(.{ .uav = uav }, 0, ty, src_mcv, opts),
176733 .load_lazy_sym => |lazy_sym| try self.genSetMem(.{ .lazy_sym = lazy_sym }, 0, ty, src_mcv, opts),
176734 .load_extern_func => |extern_func| try self.genSetMem(.{ .extern_func = extern_func }, 0, ty, src_mcv, opts),
176866176735 }
176867176736}
176868176737
......@@ -176907,14 +176776,14 @@ fn genSetReg(
176907176776 .len = self.vectorSize(.float),
176908176777 .child = .u8_type,
176909176778 });
176910 try self.genSetReg(dst_reg, full_ty, try self.genTypedValue(
176779 try self.genSetReg(dst_reg, full_ty, try self.lowerValue(
176911176780 .fromInterned(try pt.intern(.{ .aggregate = .{
176912176781 .ty = full_ty.toIntern(),
176913176782 .storage = .{ .repeated_elem = (try pt.intValue(.u8, 0xaa)).toIntern() },
176914176783 } })),
176915176784 ), opts);
176916176785 },
176917 .x87 => try self.genSetReg(dst_reg, .f80, try self.genTypedValue(
176786 .x87 => try self.genSetReg(dst_reg, .f80, try self.lowerValue(
176918176787 try pt.floatValue(.f80, @as(f80, @bitCast(@as(u80, 0xaaaaaaaaaaaaaaaaaaaa)))),
176919176788 ), opts),
176920176789 .ip, .cr, .dr => unreachable,
......@@ -176944,12 +176813,24 @@ fn genSetReg(
176944176813 }
176945176814 },
176946176815 .register => |src_reg| if (dst_reg.id() != src_reg.id()) switch (dst_reg.class()) {
176947 .general_purpose, .gphi => switch (src_reg.class()) {
176948 .general_purpose, .gphi => try self.asmRegisterRegister(
176816 .general_purpose => switch (src_reg.class()) {
176817 .general_purpose => try self.asmRegisterRegister(
176949176818 .{ ._, .mov },
176950176819 dst_alias,
176951176820 registerAlias(src_reg, abi_size),
176952176821 ),
176822 .gphi => if (dst_reg.isClass(.gphi)) try self.asmRegisterRegister(
176823 .{ ._, .mov },
176824 dst_alias,
176825 registerAlias(src_reg, abi_size),
176826 ) else {
176827 const src_lock = self.register_manager.lockReg(src_reg);
176828 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
176829 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gphi);
176830
176831 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg.to8(), src_reg);
176832 try self.asmRegisterRegister(.{ ._, .mov }, dst_alias, tmp_reg.to8());
176833 },
176953176834 .segment => try self.asmRegisterRegister(
176954176835 .{ ._, .mov },
176955176836 dst_alias,
......@@ -176985,6 +176866,26 @@ fn genSetReg(
176985176866 });
176986176867 },
176987176868 },
176869 .gphi => switch (src_reg.class()) {
176870 .general_purpose => if (src_reg.isClass(.gphi)) try self.asmRegisterRegister(
176871 .{ ._, .mov },
176872 dst_alias,
176873 registerAlias(src_reg, abi_size),
176874 ) else {
176875 const dst_lock = self.register_manager.lockReg(dst_reg);
176876 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
176877 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gphi);
176878
176879 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg.to8(), src_reg.to8());
176880 try self.asmRegisterRegister(.{ ._, .mov }, dst_reg, tmp_reg.to8());
176881 },
176882 .gphi => try self.asmRegisterRegister(
176883 .{ ._, .mov },
176884 dst_alias,
176885 registerAlias(src_reg, abi_size),
176886 ),
176887 .segment, .x87, .mmx, .ip, .cr, .dr, .sse => unreachable,
176888 },
176988176889 .segment => try self.asmRegisterRegister(
176989176890 .{ ._, .mov },
176990176891 dst_reg,
......@@ -177303,7 +177204,7 @@ fn genSetReg(
177303177204 if (src_reg_mask.info.inverted) try self.asmRegister(.{ ._, .not }, registerAlias(bits_reg, abi_size));
177304177205 try self.genSetReg(dst_reg, ty, .{ .register = bits_reg }, .{});
177305177206 },
177306 .memory, .load_symbol, .load_pcrel, .load_direct, .load_got => {
177207 .memory, .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {
177307177208 switch (src_mcv) {
177308177209 .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
177309177210 return (try self.moveStrategy(
......@@ -177317,52 +177218,50 @@ fn genSetReg(
177317177218 .disp = small_addr,
177318177219 } },
177319177220 }),
177320 .load_symbol => |sym_off| switch (dst_reg.class()) {
177221 .load_nav => |nav| switch (dst_reg.class()) {
177321177222 .general_purpose, .gphi => {
177322 assert(sym_off.off == 0);
177323177223 try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
177324 .base = .{ .reloc = sym_off.sym_index },
177325 .mod = .{ .rm = .{
177326 .size = self.memSize(ty),
177327 .disp = sym_off.off,
177328 } },
177224 .base = .{ .nav = nav },
177225 .mod = .{ .rm = .{ .size = self.memSize(ty) } },
177329177226 });
177330177227 return;
177331177228 },
177332177229 .segment, .mmx, .ip, .cr, .dr => unreachable,
177333177230 .x87, .sse => {},
177334177231 },
177335 .load_pcrel => |sym_off| switch (dst_reg.class()) {
177232 .load_uav => |uav| switch (dst_reg.class()) {
177336177233 .general_purpose, .gphi => {
177337 assert(sym_off.off == 0);
177338177234 try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
177339 .base = .{ .pcrel = sym_off.sym_index },
177340 .mod = .{ .rm = .{
177341 .size = self.memSize(ty),
177342 .disp = sym_off.off,
177343 } },
177235 .base = .{ .uav = uav },
177236 .mod = .{ .rm = .{ .size = self.memSize(ty) } },
177344177237 });
177345177238 return;
177346177239 },
177347177240 .segment, .mmx, .ip, .cr, .dr => unreachable,
177348177241 .x87, .sse => {},
177349177242 },
177350 .load_direct => |sym_index| switch (dst_reg.class()) {
177243 .load_lazy_sym => |lazy_sym| switch (dst_reg.class()) {
177351177244 .general_purpose, .gphi => {
177352 _ = try self.addInst(.{
177353 .tag = .mov,
177354 .ops = .direct_reloc,
177355 .data = .{ .rx = .{
177356 .r1 = dst_alias,
177357 .payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
177358 } },
177245 try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
177246 .base = .{ .lazy_sym = lazy_sym },
177247 .mod = .{ .rm = .{ .size = self.memSize(ty) } },
177248 });
177249 return;
177250 },
177251 .segment, .mmx, .ip, .cr, .dr => unreachable,
177252 .x87, .sse => {},
177253 },
177254 .load_extern_func => |extern_func| switch (dst_reg.class()) {
177255 .general_purpose, .gphi => {
177256 try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
177257 .base = .{ .extern_func = extern_func },
177258 .mod = .{ .rm = .{ .size = self.memSize(ty) } },
177359177259 });
177360177260 return;
177361177261 },
177362177262 .segment, .mmx, .ip, .cr, .dr => unreachable,
177363177263 .x87, .sse => {},
177364177264 },
177365 .load_got => {},
177366177265 else => unreachable,
177367177266 }
177368177267
......@@ -177375,65 +177274,17 @@ fn genSetReg(
177375177274 .mod = .{ .rm = .{ .size = self.memSize(ty) } },
177376177275 });
177377177276 },
177378 .lea_symbol => |sym_off| switch (self.bin_file.tag) {
177379 .elf, .macho => {
177380 try self.asmRegisterMemory(
177381 .{ ._, .lea },
177382 dst_reg.to64(),
177383 .{
177384 .base = .{ .reloc = sym_off.sym_index },
177385 },
177386 );
177387 if (sym_off.off != 0) try self.asmRegisterMemory(
177388 .{ ._, .lea },
177389 dst_reg.to64(),
177390 .{
177391 .base = .{ .reg = dst_reg.to64() },
177392 .mod = .{ .rm = .{ .disp = sym_off.off } },
177393 },
177394 );
177395 },
177396 else => return self.fail("TODO emit symbol sequence on {s}", .{
177397 @tagName(self.bin_file.tag),
177398 }),
177399 },
177400 .lea_pcrel => |sym_off| switch (self.bin_file.tag) {
177401 .elf, .macho => {
177402 try self.asmRegisterMemory(
177403 .{ ._, .lea },
177404 dst_reg.to64(),
177405 .{
177406 .base = .{ .pcrel = sym_off.sym_index },
177407 },
177408 );
177409 if (sym_off.off != 0) try self.asmRegisterMemory(
177410 .{ ._, .lea },
177411 dst_reg.to64(),
177412 .{
177413 .base = .{ .reg = dst_reg.to64() },
177414 .mod = .{ .rm = .{ .disp = sym_off.off } },
177415 },
177416 );
177417 },
177418 else => return self.fail("TODO emit symbol sequence on {s}", .{
177419 @tagName(self.bin_file.tag),
177420 }),
177421 },
177422 .lea_direct, .lea_got => |sym_index| _ = try self.addInst(.{
177423 .tag = switch (src_mcv) {
177424 .lea_direct => .lea,
177425 .lea_got => .mov,
177426 else => unreachable,
177427 },
177428 .ops = switch (src_mcv) {
177429 .lea_direct => .direct_reloc,
177430 .lea_got => .got_reloc,
177431 else => unreachable,
177432 },
177433 .data = .{ .rx = .{
177434 .r1 = dst_reg.to64(),
177435 .payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
177436 } },
177277 .lea_nav => |nav| try self.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
177278 .base = .{ .nav = nav },
177279 }),
177280 .lea_uav => |uav| try self.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
177281 .base = .{ .uav = uav },
177282 }),
177283 .lea_lazy_sym => |lazy_sym| try self.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
177284 .base = .{ .lazy_sym = lazy_sym },
177285 }),
177286 .lea_extern_func => |lazy_sym| try self.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
177287 .base = .{ .extern_func = lazy_sym },
177437177288 }),
177438177289 .air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref), opts),
177439177290 }
......@@ -177454,9 +177305,10 @@ fn genSetMem(
177454177305 .none => .{ .immediate = @bitCast(@as(i64, disp)) },
177455177306 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
177456177307 .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },
177457 .table, .rip_inst => unreachable,
177458 .reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } },
177459 .pcrel => |sym_index| .{ .lea_pcrel = .{ .sym_index = sym_index, .off = disp } },
177308 .table, .rip_inst, .lazy_sym => unreachable,
177309 .nav => |nav| .{ .lea_nav = nav },
177310 .uav => |uav| .{ .lea_uav = uav },
177311 .extern_func => |extern_func| .{ .lea_extern_func = extern_func },
177460177312 };
177461177313 switch (src_mcv) {
177462177314 .none,
......@@ -177519,6 +177371,7 @@ fn genSetMem(
177519177371 .rm = .{ .size = .byte, .disp = disp },
177520177372 } }),
177521177373 .register => |src_reg| {
177374 const ip = &zcu.intern_pool;
177522177375 const mem_size = switch (base) {
177523177376 .frame => |base_fi| mem_size: {
177524177377 assert(disp >= 0);
......@@ -177572,8 +177425,9 @@ fn genSetMem(
177572177425 .index = frame_index,
177573177426 .off = disp,
177574177427 }).compare(.gte, src_align),
177575 .table, .rip_inst => unreachable,
177576 .reloc, .pcrel => false,
177428 .table, .rip_inst, .lazy_sym, .extern_func => unreachable,
177429 .nav => |nav| ip.getNav(nav).getAlignment().compare(.gte, src_align),
177430 .uav => |uav| Type.fromInterned(uav.orig_ty).ptrAlignment(zcu).compare(.gte, src_align),
177577177431 })).write(
177578177432 self,
177579177433 .{ .base = base, .mod = .{ .rm = .{
......@@ -177656,16 +177510,16 @@ fn genSetMem(
177656177510 },
177657177511 .memory,
177658177512 .indirect,
177659 .load_direct,
177660 .lea_direct,
177661 .load_got,
177662 .lea_got,
177663177513 .load_frame,
177664177514 .lea_frame,
177665 .load_symbol,
177666 .lea_symbol,
177667 .load_pcrel,
177668 .lea_pcrel,
177515 .load_nav,
177516 .lea_nav,
177517 .load_uav,
177518 .lea_uav,
177519 .load_lazy_sym,
177520 .lea_lazy_sym,
177521 .load_extern_func,
177522 .lea_extern_func,
177669177523 => switch (abi_size) {
177670177524 0 => {},
177671177525 1, 2, 4, 8 => {
......@@ -177759,119 +177613,19 @@ fn genInlineMemset(
177759177613 try self.asmOpOnly(.{ .@"rep _sb", .sto });
177760177614}
177761177615
177762fn genExternSymbolRef(
177763 self: *CodeGen,
177764 comptime tag: Mir.Inst.Tag,
177765 lib: ?[]const u8,
177766 callee: []const u8,
177767) InnerError!void {
177768 if (self.bin_file.cast(.coff)) |coff_file| {
177769 const global_index = try coff_file.getGlobalSymbol(callee, lib);
177770 const scratch_reg = abi.getCAbiLinkerScratchReg(self.target.cCallingConvention().?);
177771 _ = try self.addInst(.{
177772 .tag = .mov,
177773 .ops = .import_reloc,
177774 .data = .{ .rx = .{
177775 .r1 = scratch_reg,
177776 .payload = try self.addExtra(bits.SymbolOffset{
177777 .sym_index = link.File.Coff.global_symbol_bit | global_index,
177778 }),
177779 } },
177780 });
177781 switch (tag) {
177782 .mov => {},
177783 .call => try self.asmRegister(.{ ._, .call }, scratch_reg),
177784 else => unreachable,
177785 }
177786 } else return self.fail("TODO implement calling extern functions", .{});
177787}
177788
177789177616fn genLazySymbolRef(
177790177617 self: *CodeGen,
177791177618 comptime tag: Mir.Inst.Tag,
177792177619 reg: Register,
177793177620 lazy_sym: link.File.LazySymbol,
177794177621) InnerError!void {
177795 const pt = self.pt;
177796 if (self.bin_file.cast(.elf)) |elf_file| {
177797 const zo = elf_file.zigObjectPtr().?;
177798 const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
177799 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
177800 if (self.mod.pic) {
177801 switch (tag) {
177802 .lea, .call => try self.genSetReg(reg, .usize, .{
177803 .lea_symbol = .{ .sym_index = sym_index },
177804 }, .{}),
177805 .mov => try self.genSetReg(reg, .usize, .{
177806 .load_symbol = .{ .sym_index = sym_index },
177807 }, .{}),
177808 else => unreachable,
177809 }
177810 switch (tag) {
177811 .lea, .mov => {},
177812 .call => try self.asmRegister(.{ ._, .call }, reg),
177813 else => unreachable,
177814 }
177815 } else switch (tag) {
177816 .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
177817 .base = .{ .reloc = sym_index },
177818 .mod = .{ .rm = .{ .size = .qword } },
177819 }),
177820 .call => try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = sym_index })),
177821 else => unreachable,
177822 }
177823 } else if (self.bin_file.cast(.plan9)) |p9_file| {
177824 const atom_index = p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
177825 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
177826 var atom = p9_file.getAtom(atom_index);
177827 _ = atom.getOrCreateOffsetTableEntry(p9_file);
177828 const got_addr = atom.getOffsetTableAddress(p9_file);
177829 const got_mem: Memory = .{
177830 .base = .{ .reg = .ds },
177831 .mod = .{ .rm = .{
177832 .size = .qword,
177833 .disp = @intCast(got_addr),
177834 } },
177835 };
177836 switch (tag) {
177837 .lea, .mov => try self.asmRegisterMemory(.{ ._, .mov }, reg.to64(), got_mem),
177838 .call => try self.asmMemory(.{ ._, .call }, got_mem),
177839 else => unreachable,
177840 }
177841 switch (tag) {
177842 .lea, .call => {},
177843 .mov => try self.asmRegisterMemory(
177844 .{ ._, tag },
177845 reg.to64(),
177846 .initSib(.qword, .{ .base = .{ .reg = reg.to64() } }),
177847 ),
177848 else => unreachable,
177849 }
177850 } else if (self.bin_file.cast(.coff)) |coff_file| {
177851 const atom_index = coff_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
177852 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
177853 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
177854 switch (tag) {
177855 .lea, .call => try self.genSetReg(reg, .usize, .{ .lea_got = sym_index }, .{}),
177856 .mov => try self.genSetReg(reg, .usize, .{ .load_got = sym_index }, .{}),
177857 else => unreachable,
177858 }
177859 switch (tag) {
177860 .lea, .mov => {},
177861 .call => try self.asmRegister(.{ ._, .call }, reg),
177862 else => unreachable,
177863 }
177864 } else if (self.bin_file.cast(.macho)) |macho_file| {
177865 const zo = macho_file.getZigObject().?;
177866 const sym_index = zo.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym) catch |err|
177867 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
177868 const sym = zo.symbols.items[sym_index];
177622 if (self.mod.pic) {
177869177623 switch (tag) {
177870177624 .lea, .call => try self.genSetReg(reg, .usize, .{
177871 .lea_symbol = .{ .sym_index = sym.nlist_idx },
177625 .lea_lazy_sym = lazy_sym,
177872177626 }, .{}),
177873177627 .mov => try self.genSetReg(reg, .usize, .{
177874 .load_symbol = .{ .sym_index = sym.nlist_idx },
177628 .lea_lazy_sym = lazy_sym,
177875177629 }, .{}),
177876177630 else => unreachable,
177877177631 }
......@@ -177880,8 +177634,13 @@ fn genLazySymbolRef(
177880177634 .call => try self.asmRegister(.{ ._, .call }, reg),
177881177635 else => unreachable,
177882177636 }
177883 } else {
177884 return self.fail("TODO implement genLazySymbol for x86_64 {s}", .{@tagName(self.bin_file.tag)});
177637 } else switch (tag) {
177638 .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
177639 .base = .{ .lazy_sym = lazy_sym },
177640 .mod = .{ .rm = .{ .size = .qword } },
177641 }),
177642 .call => try self.asmImmediate(.{ ._, .call }, .{ .lazy_sym = lazy_sym }),
177643 else => unreachable,
177885177644 }
177886177645}
177887177646
......@@ -178034,11 +177793,11 @@ fn airFloatFromInt(self: *CodeGen, inst: Air.Inst.Index) !void {
178034177793 src_ty.fmt(pt), dst_ty.fmt(pt),
178035177794 });
178036177795
178037 var callee_buf: ["__floatun?i?f".len]u8 = undefined;
178038 break :result try self.genCall(.{ .lib = .{
177796 var sym_buf: ["__floatun?i?f".len]u8 = undefined;
177797 break :result try self.genCall(.{ .extern_func = .{
178039177798 .return_type = dst_ty.toIntern(),
178040177799 .param_types = &.{src_ty.toIntern()},
178041 .callee = std.fmt.bufPrint(&callee_buf, "__float{s}{c}i{c}f", .{
177800 .sym = std.fmt.bufPrint(&sym_buf, "__float{s}{c}i{c}f", .{
178042177801 switch (src_signedness) {
178043177802 .signed => "",
178044177803 .unsigned => "un",
......@@ -178114,11 +177873,11 @@ fn airIntFromFloat(self: *CodeGen, inst: Air.Inst.Index) !void {
178114177873 src_ty.fmt(pt), dst_ty.fmt(pt),
178115177874 });
178116177875
178117 var callee_buf: ["__fixuns?f?i".len]u8 = undefined;
178118 break :result try self.genCall(.{ .lib = .{
177876 var sym_buf: ["__fixuns?f?i".len]u8 = undefined;
177877 break :result try self.genCall(.{ .extern_func = .{
178119177878 .return_type = dst_ty.toIntern(),
178120177879 .param_types = &.{src_ty.toIntern()},
178121 .callee = std.fmt.bufPrint(&callee_buf, "__fix{s}{c}f{c}i", .{
177880 .sym = std.fmt.bufPrint(&sym_buf, "__fix{s}{c}f{c}i", .{
178122177881 switch (dst_signedness) {
178123177882 .signed => "",
178124177883 .unsigned => "uns",
......@@ -178219,9 +177978,9 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void {
178219177978 .off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}),
178220177979 }
178221177980 const ptr_lock = switch (ptr_mem.base) {
178222 .none, .frame, .reloc, .pcrel => null,
177981 .none, .frame, .nav, .uav => null,
178223177982 .reg => |reg| self.register_manager.lockReg(reg),
178224 .table, .rip_inst => unreachable,
177983 .table, .rip_inst, .lazy_sym, .extern_func => unreachable,
178225177984 };
178226177985 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
178227177986
......@@ -178302,9 +178061,9 @@ fn atomicOp(
178302178061 .off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}),
178303178062 }
178304178063 const mem_lock = switch (ptr_mem.base) {
178305 .none, .frame, .reloc, .pcrel => null,
178064 .none, .frame, .nav, .uav => null,
178306178065 .reg => |reg| self.register_manager.lockReg(reg),
178307 .table, .rip_inst => unreachable,
178066 .table, .rip_inst, .lazy_sym, .extern_func => unreachable,
178308178067 };
178309178068 defer if (mem_lock) |lock| self.register_manager.unlockReg(lock);
178310178069
......@@ -179693,7 +179452,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
179693179452 var mask_elems_buf: [32]u8 = undefined;
179694179453 const mask_elems = mask_elems_buf[0..mask_len];
179695179454 for (mask_elems, 0..) |*elem, bit| elem.* = @intCast(bit / elem_bits);
179696 const mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
179455 const mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
179697179456 .ty = mask_ty.toIntern(),
179698179457 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, mask_elems, .maybe_embedded_nulls) },
179699179458 } })));
......@@ -179721,7 +179480,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
179721179480 mask_elem_ty,
179722179481 @as(u8, 1) << @truncate(bit),
179723179482 )).toIntern();
179724 const mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
179483 const mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
179725179484 .ty = mask_ty.toIntern(),
179726179485 .storage = .{ .elems = mask_elems },
179727179486 } })));
......@@ -180452,7 +180211,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {
180452180211 else
180453180212 try select_mask_elem_ty.minIntScalar(pt, select_mask_elem_ty)).toIntern();
180454180213 }
180455 const select_mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
180214 const select_mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
180456180215 .ty = select_mask_ty.toIntern(),
180457180216 .storage = .{ .elems = select_mask_elems[0..mask_elems.len] },
180458180217 } })));
......@@ -180597,7 +180356,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {
180597180356 })).toIntern();
180598180357 }
180599180358 const lhs_mask_ty = try pt.vectorType(.{ .len = max_abi_size, .child = .u8_type });
180600 const lhs_mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
180359 const lhs_mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
180601180360 .ty = lhs_mask_ty.toIntern(),
180602180361 .storage = .{ .elems = lhs_mask_elems[0..max_abi_size] },
180603180362 } })));
......@@ -180628,7 +180387,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {
180628180387 })).toIntern();
180629180388 }
180630180389 const rhs_mask_ty = try pt.vectorType(.{ .len = max_abi_size, .child = .u8_type });
180631 const rhs_mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
180390 const rhs_mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
180632180391 .ty = rhs_mask_ty.toIntern(),
180633180392 .storage = .{ .elems = rhs_mask_elems[0..max_abi_size] },
180634180393 } })));
......@@ -180962,7 +180721,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {
180962180721 .{ .frame = frame_index },
180963180722 @intCast(elem_size * elements.len),
180964180723 elem_ty,
180965 try self.genTypedValue(sentinel),
180724 try self.lowerValue(sentinel),
180966180725 .{},
180967180726 );
180968180727 break :result .{ .load_frame = .{ .index = frame_index } };
......@@ -181046,11 +180805,11 @@ fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void {
181046180805 ty.fmt(pt),
181047180806 });
181048180807
181049 var callee_buf: ["__fma?".len]u8 = undefined;
181050 break :result try self.genCall(.{ .lib = .{
180808 var sym_buf: ["__fma?".len]u8 = undefined;
180809 break :result try self.genCall(.{ .extern_func = .{
181051180810 .return_type = ty.toIntern(),
181052180811 .param_types = &.{ ty.toIntern(), ty.toIntern(), ty.toIntern() },
181053 .callee = std.fmt.bufPrint(&callee_buf, "{s}fma{s}", .{
180812 .sym = std.fmt.bufPrint(&sym_buf, "{s}fma{s}", .{
181054180813 floatLibcAbiPrefix(ty),
181055180814 floatLibcAbiSuffix(ty),
181056180815 }) catch unreachable,
......@@ -181450,7 +181209,7 @@ fn resolveInst(self: *CodeGen, ref: Air.Inst.Ref) InnerError!MCValue {
181450181209 const mcv: MCValue = if (ref.toIndex()) |inst| mcv: {
181451181210 break :mcv self.inst_tracking.getPtr(inst).?.short;
181452181211 } else mcv: {
181453 break :mcv try self.genTypedValue(.fromInterned(ref.toInterned().?));
181212 break :mcv try self.lowerValue(.fromInterned(ref.toInterned().?));
181454181213 };
181455181214
181456181215 switch (mcv) {
......@@ -181488,33 +181247,20 @@ fn limitImmediateType(self: *CodeGen, operand: Air.Inst.Ref, comptime T: type) !
181488181247 return mcv;
181489181248}
181490181249
181491fn genResult(self: *CodeGen, res: codegen.GenResult) InnerError!MCValue {
181492 return switch (res) {
181493 .mcv => |mcv| switch (mcv) {
181494 .none => .none,
181495 .undef => .undef,
181496 .immediate => |imm| .{ .immediate = imm },
181497 .memory => |addr| .{ .memory = addr },
181498 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym_index = sym_index } },
181499 .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index } },
181500 .load_direct => |sym_index| .{ .load_direct = sym_index },
181501 .lea_direct => |sym_index| .{ .lea_direct = sym_index },
181502 .load_got => |sym_index| .{ .lea_got = sym_index },
181503 },
181504 .fail => |msg| return self.failMsg(msg),
181250fn lowerValue(cg: *CodeGen, val: Value) Allocator.Error!MCValue {
181251 return switch (try codegen.lowerValue(cg.pt, val, cg.target)) {
181252 .none => .none,
181253 .undef => .undef,
181254 .immediate => |imm| .{ .immediate = imm },
181255 .lea_nav => |nav| .{ .lea_nav = nav },
181256 .lea_uav => |uav| .{ .lea_uav = uav },
181257 .load_uav => |uav| .{ .load_uav = uav },
181505181258 };
181506181259}
181507181260
181508fn genTypedValue(self: *CodeGen, val: Value) InnerError!MCValue {
181509 return self.genResult(try codegen.genTypedValue(self.bin_file, self.pt, self.src_loc, val, self.target.*));
181510}
181511
181512fn lowerUav(self: *CodeGen, val: Value, alignment: InternPool.Alignment) InnerError!MCValue {
181513 return self.genResult(try self.bin_file.lowerUav(self.pt, val.toIntern(), alignment, self.src_loc));
181514}
181515
181516181261const CallMCValues = struct {
181517181262 args: []MCValue,
181263 air_arg_count: u32,
181518181264 return_value: InstTracking,
181519181265 stack_byte_count: u31,
181520181266 stack_align: InternPool.Alignment,
......@@ -181550,13 +181296,14 @@ fn resolveCallingConventionValues(
181550181296 const param_types = try allocator.alloc(Type, fn_info.param_types.len + var_args.len);
181551181297 defer allocator.free(param_types);
181552181298
181553 for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src|
181554 dest.* = .fromInterned(src);
181299 for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*param_ty, arg_ty|
181300 param_ty.* = .fromInterned(arg_ty);
181555181301 for (param_types[fn_info.param_types.len..], var_args) |*param_ty, arg_ty|
181556181302 param_ty.* = self.promoteVarArg(arg_ty);
181557181303
181558181304 var result: CallMCValues = .{
181559181305 .args = try self.gpa.alloc(MCValue, param_types.len),
181306 .air_arg_count = 0,
181560181307 // These undefined values must be populated before returning from this function.
181561181308 .return_value = undefined,
181562181309 .stack_byte_count = 0,
......@@ -181678,6 +181425,7 @@ fn resolveCallingConventionValues(
181678181425 // Input params
181679181426 for (param_types, result.args) |ty, *arg| {
181680181427 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
181428 result.air_arg_count += 1;
181681181429 switch (cc) {
181682181430 .x86_64_sysv => {},
181683181431 .x86_64_win => {
......@@ -181850,6 +181598,7 @@ fn resolveCallingConventionValues(
181850181598 arg.* = .none;
181851181599 continue;
181852181600 }
181601 result.air_arg_count += 1;
181853181602 const param_size: u31 = @intCast(param_ty.abiSize(zcu));
181854181603 if (abi.zigcc.params_in_regs) switch (self.regClassForType(param_ty)) {
181855181604 .general_purpose, .gphi => if (param_gpr.len >= 1 and param_size <= @as(u4, switch (self.target.cpu.arch) {
......@@ -182373,16 +182122,16 @@ const Temp = struct {
182373182122 .register_offset,
182374182123 .register_mask,
182375182124 .memory,
182376 .load_symbol,
182377 .lea_symbol,
182378 .load_pcrel,
182379 .lea_pcrel,
182380182125 .indirect,
182381 .load_direct,
182382 .lea_direct,
182383 .load_got,
182384 .lea_got,
182385182126 .lea_frame,
182127 .load_nav,
182128 .lea_nav,
182129 .load_uav,
182130 .lea_uav,
182131 .load_lazy_sym,
182132 .lea_lazy_sym,
182133 .lea_extern_func,
182134 .load_extern_func,
182386182135 .elementwise_args,
182387182136 .reserved_frame,
182388182137 .air_ref,
......@@ -182425,15 +182174,11 @@ const Temp = struct {
182425182174 .mod = .{ .rm = .{ .disp = reg_off.off + off } },
182426182175 });
182427182176 },
182428 .load_symbol, .load_frame => {
182177 .load_frame, .load_nav, .lea_nav, .load_uav, .lea_uav, .load_lazy_sym, .lea_lazy_sym => {
182429182178 const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
182430182179 new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{ .reg = new_reg, .off = off } });
182431182180 try cg.genSetReg(new_reg, .usize, mcv, .{});
182432182181 },
182433 .lea_symbol => |sym_off| new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = .{
182434 .sym_index = sym_off.sym_index,
182435 .off = sym_off.off + off,
182436 } }),
182437182182 .lea_frame => |frame_addr| new_temp_index.tracking(cg).* = .init(.{ .lea_frame = .{
182438182183 .index = frame_addr.index,
182439182184 .off = frame_addr.off + off,
......@@ -182466,14 +182211,6 @@ const Temp = struct {
182466182211 } });
182467182212 return;
182468182213 },
182469 .lea_symbol => |sym_off| {
182470 assert(std.meta.eql(temp_tracking.long.lea_symbol, sym_off));
182471 temp_tracking.* = .init(.{ .lea_symbol = .{
182472 .sym_index = sym_off.sym_index,
182473 .off = sym_off.off + off,
182474 } });
182475 return;
182476 },
182477182214 .lea_frame => |frame_addr| {
182478182215 assert(std.meta.eql(temp_tracking.long.lea_frame, frame_addr));
182479182216 temp_tracking.* = .init(.{ .lea_frame = .{
......@@ -182522,53 +182259,85 @@ const Temp = struct {
182522182259 .mod = .{ .rm = .{ .disp = reg_off.off + @as(u31, limb_index) * 8 } },
182523182260 });
182524182261 },
182525 .load_symbol => |sym_off| {
182262 .load_frame => |frame_addr| {
182263 const new_reg =
182264 try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
182265 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
182266 try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
182267 .base = .{ .frame = frame_addr.index },
182268 .mod = .{ .rm = .{
182269 .size = .qword,
182270 .disp = frame_addr.off + @as(u31, limb_index) * 8,
182271 } },
182272 });
182273 },
182274 .lea_frame => |frame_addr| {
182275 assert(limb_index == 0);
182276 new_temp_index.tracking(cg).* = .init(.{ .lea_frame = frame_addr });
182277 },
182278 .load_nav => |nav| {
182526182279 const new_reg =
182527182280 try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
182528182281 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
182529182282 try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
182530 .base = .{ .reloc = sym_off.sym_index },
182283 .base = .{ .nav = nav },
182531182284 .mod = .{ .rm = .{
182532182285 .size = .qword,
182533 .disp = sym_off.off + @as(u31, limb_index) * 8,
182286 .disp = @as(u31, limb_index) * 8,
182534182287 } },
182535182288 });
182536182289 },
182537 .lea_symbol => |sym_off| {
182290 .lea_nav => |nav| {
182538182291 assert(limb_index == 0);
182539 new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = sym_off });
182292 new_temp_index.tracking(cg).* = .init(.{ .lea_nav = nav });
182540182293 },
182541 .load_pcrel => |sym_off| {
182294 .load_uav => |uav| {
182542182295 const new_reg =
182543182296 try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
182544182297 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
182545182298 try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
182546 .base = .{ .pcrel = sym_off.sym_index },
182299 .base = .{ .uav = uav },
182547182300 .mod = .{ .rm = .{
182548182301 .size = .qword,
182549 .disp = sym_off.off + @as(u31, limb_index) * 8,
182302 .disp = @as(u31, limb_index) * 8,
182550182303 } },
182551182304 });
182552182305 },
182553 .lea_pcrel => |sym_off| {
182306 .lea_uav => |uav| {
182554182307 assert(limb_index == 0);
182555 new_temp_index.tracking(cg).* = .init(.{ .lea_pcrel = sym_off });
182308 new_temp_index.tracking(cg).* = .init(.{ .lea_uav = uav });
182556182309 },
182557 .load_frame => |frame_addr| {
182310 .load_lazy_sym => |lazy_sym| {
182558182311 const new_reg =
182559182312 try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
182560182313 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
182561182314 try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
182562 .base = .{ .frame = frame_addr.index },
182315 .base = .{ .lazy_sym = lazy_sym },
182563182316 .mod = .{ .rm = .{
182564182317 .size = .qword,
182565 .disp = frame_addr.off + @as(u31, limb_index) * 8,
182318 .disp = @as(u31, limb_index) * 8,
182566182319 } },
182567182320 });
182568182321 },
182569 .lea_frame => |frame_addr| {
182322 .lea_lazy_sym => |lazy_sym| {
182570182323 assert(limb_index == 0);
182571 new_temp_index.tracking(cg).* = .init(.{ .lea_frame = frame_addr });
182324 new_temp_index.tracking(cg).* = .init(.{ .lea_lazy_sym = lazy_sym });
182325 },
182326 .load_extern_func => |extern_func| {
182327 const new_reg =
182328 try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
182329 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
182330 try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
182331 .base = .{ .extern_func = extern_func },
182332 .mod = .{ .rm = .{
182333 .size = .qword,
182334 .disp = @as(u31, limb_index) * 8,
182335 } },
182336 });
182337 },
182338 .lea_extern_func => |extern_func| {
182339 assert(limb_index == 0);
182340 new_temp_index.tracking(cg).* = .init(.{ .lea_extern_func = extern_func });
182572182341 },
182573182342 }
182574182343 cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
......@@ -182625,7 +182394,7 @@ const Temp = struct {
182625182394 const temp_tracking = temp_index.tracking(cg);
182626182395 switch (temp_tracking.short) {
182627182396 else => {},
182628 .register, .lea_symbol, .lea_frame => {
182397 .register, .lea_frame, .lea_nav, .lea_uav, .lea_lazy_sym => {
182629182398 assert(limb_index == 0);
182630182399 cg.temp_type[@intFromEnum(temp_index)] = limb_ty;
182631182400 return;
......@@ -182642,15 +182411,6 @@ const Temp = struct {
182642182411 cg.temp_type[@intFromEnum(temp_index)] = limb_ty;
182643182412 return;
182644182413 },
182645 .load_symbol => |sym_off| {
182646 assert(std.meta.eql(temp_tracking.long.load_symbol, sym_off));
182647 temp_tracking.* = .init(.{ .load_symbol = .{
182648 .sym_index = sym_off.sym_index,
182649 .off = sym_off.off + @as(u31, limb_index) * 8,
182650 } });
182651 cg.temp_type[@intFromEnum(temp_index)] = limb_ty;
182652 return;
182653 },
182654182414 .load_frame => |frame_addr| if (!frame_addr.index.isNamed()) {
182655182415 assert(std.meta.eql(temp_tracking.long.load_frame, frame_addr));
182656182416 temp_tracking.* = .init(.{ .load_frame = .{
......@@ -182841,27 +182601,20 @@ const Temp = struct {
182841182601 .immediate,
182842182602 .register,
182843182603 .register_offset,
182844 .lea_direct,
182845 .lea_got,
182846182604 .lea_frame,
182847182605 => return false,
182848182606 .memory,
182849182607 .indirect,
182850 .load_symbol,
182851 .load_pcrel,
182852 .load_direct,
182853 .load_got,
182854182608 .load_frame,
182609 .load_nav,
182610 .lea_nav,
182611 .load_uav,
182612 .lea_uav,
182613 .load_lazy_sym,
182614 .lea_lazy_sym,
182615 .load_extern_func,
182616 .lea_extern_func,
182855182617 => return temp.toRegClass(true, .general_purpose, cg),
182856 .lea_symbol, .lea_pcrel => |sym_off| {
182857 const off = sym_off.off;
182858 // hack around linker relocation bugs
182859 if (false and off == 0) return false;
182860 try temp.toOffset(-off, cg);
182861 while (try temp.toRegClass(true, .general_purpose, cg)) {}
182862 try temp.toOffset(off, cg);
182863 return true;
182864 },
182865182618 }
182866182619 }
182867182620
......@@ -182928,7 +182681,7 @@ const Temp = struct {
182928182681 ), cg),
182929182682 else => unreachable,
182930182683 },
182931 .memory, .indirect, .load_frame, .load_symbol => {
182684 .memory, .indirect, .load_frame, .load_nav, .load_uav, .load_lazy_sym => {
182932182685 var val_ptr = try cg.tempInit(.usize, val_mcv.address());
182933182686 var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });
182934182687 try val_ptr.memcpy(ptr, &len, cg);
......@@ -182966,7 +182719,11 @@ const Temp = struct {
182966182719 // hack around linker relocation bugs
182967182720 switch (ptr.tracking(cg).short) {
182968182721 else => {},
182969 .lea_symbol => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
182722 .lea_nav,
182723 .lea_uav,
182724 .lea_lazy_sym,
182725 .lea_extern_func,
182726 => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
182970182727 }
182971182728 try cg.asmMemoryImmediate(
182972182729 .{ ._, .mov },
......@@ -182980,7 +182737,11 @@ const Temp = struct {
182980182737 // hack around linker relocation bugs
182981182738 switch (ptr.tracking(cg).short) {
182982182739 else => {},
182983 .lea_symbol => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
182740 .lea_nav,
182741 .lea_uav,
182742 .lea_lazy_sym,
182743 .lea_extern_func,
182744 => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
182984182745 }
182985182746 try cg.asmSetccMemory(
182986182747 cc,
......@@ -183024,8 +182785,8 @@ const Temp = struct {
183024182785 try ptr.tracking(cg).short.deref().mem(cg, .{ .size = .byte }),
183025182786 );
183026182787 },
183027 .lea_frame, .lea_symbol => continue :val_to_gpr,
183028 .memory, .indirect, .load_frame, .load_symbol => {
182788 .lea_frame, .lea_nav, .lea_uav, .lea_lazy_sym => continue :val_to_gpr,
182789 .memory, .indirect, .load_frame, .load_nav, .load_uav, .load_lazy_sym => {
183029182790 var val_ptr = try cg.tempInit(.usize, val_mcv.address());
183030182791 var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });
183031182792 try ptr.memcpy(&val_ptr, &len, cg);
......@@ -183065,7 +182826,7 @@ const Temp = struct {
183065182826 ), cg),
183066182827 else => unreachable,
183067182828 },
183068 .memory, .indirect, .load_frame, .load_symbol => {
182829 .memory, .indirect, .load_frame, .load_nav, .load_uav, .load_lazy_sym => {
183069182830 var val_ptr = try cg.tempInit(.usize, val_mcv.address());
183070182831 var src_ptr =
183071182832 try cg.tempInit(.usize, src.tracking(cg).short.address().offset(opts.disp));
......@@ -183159,8 +182920,8 @@ const Temp = struct {
183159182920 }),
183160182921 );
183161182922 },
183162 .lea_frame, .lea_symbol => continue :val_to_gpr,
183163 .memory, .indirect, .load_frame, .load_symbol => {
182923 .lea_frame, .lea_nav, .lea_uav, .lea_lazy_sym => continue :val_to_gpr,
182924 .memory, .indirect, .load_frame, .load_nav, .load_uav, .load_lazy_sym => {
183164182925 var dst_ptr =
183165182926 try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(opts.disp));
183166182927 var val_ptr = try cg.tempInit(.usize, val_mcv.address());
......@@ -183181,7 +182942,7 @@ const Temp = struct {
183181182942 // hack around linker relocation bugs
183182182943 switch (ptr.tracking(cg).short) {
183183182944 else => {},
183184 .lea_symbol => |sym_off| if (dst_rc != .general_purpose or sym_off.off != 0)
182945 .lea_nav, .lea_uav, .lea_lazy_sym => if (dst_rc != .general_purpose)
183185182946 while (try ptr.toRegClass(false, .general_purpose, cg)) {},
183186182947 }
183187182948 try strat.read(cg, dst_reg, try ptr.tracking(cg).short.deref().mem(cg, .{
......@@ -183201,7 +182962,7 @@ const Temp = struct {
183201182962 // hack around linker relocation bugs
183202182963 switch (ptr.tracking(cg).short) {
183203182964 else => {},
183204 .lea_symbol => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
182965 .lea_nav, .lea_uav, .lea_lazy_sym => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
183205182966 }
183206182967 const strat = try cg.moveStrategy(src_ty, src_rc, false);
183207182968 try strat.write(cg, try ptr.tracking(cg).short.deref().mem(cg, .{
......@@ -186964,7 +186725,7 @@ const Temp = struct {
186964186725 },
186965186726 .call_frame = .{ .alignment = .@"16" },
186966186727 .extra_temps = .{
186967 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divti3" } } },
186728 .{ .type = .usize, .kind = .{ .extern_func = "__divti3" } },
186968186729 .unused,
186969186730 .unused,
186970186731 .unused,
......@@ -186993,7 +186754,7 @@ const Temp = struct {
186993186754 },
186994186755 .call_frame = .{ .alignment = .@"16" },
186995186756 .extra_temps = .{
186996 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__udivti3" } } },
186757 .{ .type = .usize, .kind = .{ .extern_func = "__udivti3" } },
186997186758 .unused,
186998186759 .unused,
186999186760 .unused,
......@@ -187026,7 +186787,7 @@ const Temp = struct {
187026186787 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
187027186788 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
187028186789 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
187029 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divei4" } } },
186790 .{ .type = .usize, .kind = .{ .extern_func = "__divei4" } },
187030186791 .unused,
187031186792 .unused,
187032186793 .unused,
......@@ -187059,7 +186820,7 @@ const Temp = struct {
187059186820 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
187060186821 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
187061186822 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
187062 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__udivei4" } } },
186823 .{ .type = .usize, .kind = .{ .extern_func = "__udivei4" } },
187063186824 .unused,
187064186825 .unused,
187065186826 .unused,
......@@ -187423,7 +187184,7 @@ const Temp = struct {
187423187184 .{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
187424187185 .{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
187425187186 .{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
187426 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divti3" } } },
187187 .{ .type = .usize, .kind = .{ .extern_func = "__divti3" } },
187427187188 .{ .type = .u64, .kind = .{ .ret_gpr = .{ .cc = .ccc, .at = 0 } } },
187428187189 .unused,
187429187190 .unused,
......@@ -187461,7 +187222,7 @@ const Temp = struct {
187461187222 .{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
187462187223 .{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
187463187224 .{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
187464 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__udivti3" } } },
187225 .{ .type = .usize, .kind = .{ .extern_func = "__udivti3" } },
187465187226 .{ .type = .u64, .kind = .{ .ret_gpr = .{ .cc = .ccc, .at = 0 } } },
187466187227 .unused,
187467187228 .unused,
......@@ -187499,7 +187260,7 @@ const Temp = struct {
187499187260 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
187500187261 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
187501187262 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
187502 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divei4" } } },
187263 .{ .type = .usize, .kind = .{ .extern_func = "__divei4" } },
187503187264 .unused,
187504187265 .unused,
187505187266 .unused,
......@@ -187535,7 +187296,7 @@ const Temp = struct {
187535187296 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
187536187297 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
187537187298 .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
187538 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__udivei4" } } },
187299 .{ .type = .usize, .kind = .{ .extern_func = "__udivei4" } },
187539187300 .unused,
187540187301 .unused,
187541187302 .unused,
......@@ -187590,16 +187351,16 @@ const Temp = struct {
187590187351 .register_overflow,
187591187352 .register_mask,
187592187353 .memory,
187593 .load_symbol,
187594 .lea_symbol,
187595 .load_pcrel,
187596 .lea_pcrel,
187597187354 .indirect,
187598 .load_direct,
187599 .lea_direct,
187600 .load_got,
187601 .lea_got,
187602187355 .load_frame,
187356 .load_nav,
187357 .lea_nav,
187358 .load_uav,
187359 .lea_uav,
187360 .load_lazy_sym,
187361 .lea_lazy_sym,
187362 .load_extern_func,
187363 .lea_extern_func,
187603187364 => {
187604187365 const result = try cg.allocRegOrMem(inst, true);
187605187366 try cg.genCopy(cg.typeOfIndex(inst), result, temp_mcv, .{});
......@@ -187776,7 +187537,7 @@ fn tempInit(cg: *CodeGen, ty: Type, value: MCValue) InnerError!Temp {
187776187537}
187777187538
187778187539fn tempFromValue(cg: *CodeGen, value: Value) InnerError!Temp {
187779 return cg.tempInit(value.typeOf(cg.pt.zcu), try cg.genTypedValue(value));
187540 return cg.tempInit(value.typeOf(cg.pt.zcu), try cg.lowerValue(value));
187780187541}
187781187542
187782187543fn tempMemFromValue(cg: *CodeGen, value: Value) InnerError!Temp {
......@@ -187784,13 +187545,20 @@ fn tempMemFromValue(cg: *CodeGen, value: Value) InnerError!Temp {
187784187545}
187785187546
187786187547fn tempMemFromAlignedValue(cg: *CodeGen, alignment: InternPool.Alignment, value: Value) InnerError!Temp {
187787 return cg.tempInit(value.typeOf(cg.pt.zcu), try cg.lowerUav(value, alignment));
187548 const ty = value.typeOf(cg.pt.zcu);
187549 return cg.tempInit(ty, .{ .load_uav = .{
187550 .val = value.toIntern(),
187551 .orig_ty = (try cg.pt.ptrType(.{
187552 .child = ty.toIntern(),
187553 .flags = .{
187554 .is_const = true,
187555 .alignment = alignment,
187556 },
187557 })).toIntern(),
187558 } });
187788187559}
187789187560
187790187561fn tempFromOperand(cg: *CodeGen, op_ref: Air.Inst.Ref, op_dies: bool) InnerError!Temp {
187791 const zcu = cg.pt.zcu;
187792 const ip = &zcu.intern_pool;
187793
187794187562 if (op_dies) {
187795187563 const temp_index = cg.next_temp_index;
187796187564 const temp: Temp = .{ .index = temp_index.toIndex() };
......@@ -187804,8 +187572,7 @@ fn tempFromOperand(cg: *CodeGen, op_ref: Air.Inst.Ref, op_dies: bool) InnerError
187804187572 }
187805187573
187806187574 if (op_ref.toIndex()) |op_inst| return .{ .index = op_inst };
187807 const val = op_ref.toInterned().?;
187808 return cg.tempInit(.fromInterned(ip.typeOf(val)), try cg.genTypedValue(.fromInterned(val)));
187575 return cg.tempFromValue(.fromInterned(op_ref.toInterned().?));
187809187576}
187810187577
187811187578fn tempsFromOperandsInner(
......@@ -188640,8 +188407,8 @@ const Select = struct {
188640188407 splat_int_mem: struct { ref: Select.Operand.Ref, inside: enum { umin, smin, smax } = .umin, outside: enum { smin, smax } },
188641188408 splat_float_mem: struct { ref: Select.Operand.Ref, inside: enum { zero } = .zero, outside: f16 },
188642188409 frame: FrameIndex,
188643 lazy_symbol: struct { kind: link.File.LazySymbol.Kind, ref: Select.Operand.Ref = .none },
188644 symbol: *const struct { lib: ?[]const u8 = null, name: []const u8 },
188410 lazy_sym: struct { kind: link.File.LazySymbol.Kind, ref: Select.Operand.Ref = .none },
188411 extern_func: [*:0]const u8,
188645188412
188646188413 const ConstSpec = struct {
188647188414 ref: Select.Operand.Ref = .none,
......@@ -189072,43 +188839,21 @@ const Select = struct {
189072188839 } }))), true };
189073188840 },
189074188841 .frame => |frame_index| .{ try cg.tempInit(spec.type, .{ .load_frame = .{ .index = frame_index } }), true },
189075 .lazy_symbol => |lazy_symbol_spec| {
188842 .lazy_sym => |lazy_symbol_spec| {
189076188843 const ip = &pt.zcu.intern_pool;
189077188844 const ty = if (lazy_symbol_spec.ref == .none) spec.type else lazy_symbol_spec.ref.typeOf(s);
189078 const lazy_symbol: link.File.LazySymbol = .{
188845 return .{ try cg.tempInit(.usize, .{ .lea_lazy_sym = .{
189079188846 .kind = lazy_symbol_spec.kind,
189080188847 .ty = switch (ip.indexToKey(ty.toIntern())) {
189081188848 .inferred_error_set_type => |func_index| switch (ip.funcIesResolvedUnordered(func_index)) {
189082 .none => unreachable, // unresolved inferred error set
188849 .none => unreachable,
189083188850 else => |ty_index| ty_index,
189084188851 },
189085188852 else => ty.toIntern(),
189086188853 },
189087 };
189088 return .{ try cg.tempInit(.usize, .{ .lea_symbol = .{
189089 .sym_index = if (cg.bin_file.cast(.elf)) |elf_file|
189090 elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_symbol) catch |err|
189091 return cg.fail("{s} creating lazy symbol", .{@errorName(err)})
189092 else if (cg.bin_file.cast(.macho)) |macho_file|
189093 macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_symbol) catch |err|
189094 return cg.fail("{s} creating lazy symbol", .{@errorName(err)})
189095 else if (cg.bin_file.cast(.coff)) |coff_file|
189096 coff_file.getAtom(coff_file.getOrCreateAtomForLazySymbol(pt, lazy_symbol) catch |err|
189097 return cg.fail("{s} creating lazy symbol", .{@errorName(err)})).getSymbolIndex().?
189098 else
189099 return cg.fail("external symbols unimplemented for {s}", .{@tagName(cg.bin_file.tag)}),
189100188854 } }), true };
189101188855 },
189102 .symbol => |symbol_spec| .{ try cg.tempInit(spec.type, .{ .lea_symbol = .{
189103 .sym_index = if (cg.bin_file.cast(.elf)) |elf_file|
189104 try elf_file.getGlobalSymbol(symbol_spec.name, symbol_spec.lib)
189105 else if (cg.bin_file.cast(.macho)) |macho_file|
189106 try macho_file.getGlobalSymbol(symbol_spec.name, symbol_spec.lib)
189107 else if (cg.bin_file.cast(.coff)) |coff_file|
189108 link.File.Coff.global_symbol_bit | try coff_file.getGlobalSymbol(symbol_spec.name, symbol_spec.lib)
189109 else
189110 return cg.fail("external symbols unimplemented for {s}", .{@tagName(cg.bin_file.tag)}),
189111 } }), true },
188856 .extern_func => |extern_func_spec| .{ try cg.tempInit(spec.type, .{ .lea_extern_func = try cg.addString(std.mem.span(extern_func_spec)) }), true },
189112188857 };
189113188858 }
189114188859
......@@ -190151,9 +189896,12 @@ const Select = struct {
190151189896 .register => |reg| .{ .reg = s.lowerReg(reg.toSize(op.flags.base.size, s.cg.target)) },
190152189897 .register_pair, .register_triple, .register_quadruple, .register_offset, .register_overflow => unreachable,
190153189898 .register_mask => |reg_mask| .{ .reg = s.lowerReg(reg_mask.reg.toSize(op.flags.base.size, s.cg.target)) },
189899 .lea_nav => |nav| .{ .imm = .{ .nav = .{ .index = nav } } },
189900 .lea_uav => |uav| .{ .imm = .{ .uav = uav } },
189901 .lea_lazy_sym => |lazy_sym| .{ .imm = .{ .lazy_sym = lazy_sym } },
189902 .lea_extern_func => |extern_func| .{ .imm = .{ .extern_func = extern_func } },
190154189903 else => |mcv| .{ .mem = try mcv.mem(s.cg, .{ .size = op.flags.base.size }) },
190155 .lea_symbol => |sym_off| .{ .imm = .rel(sym_off) },
190156 .load_direct, .lea_direct, .load_got, .lea_got, .lea_frame, .elementwise_args, .reserved_frame, .air_ref => unreachable,
189904 .lea_frame, .elementwise_args, .reserved_frame, .air_ref => unreachable,
190157189905 },
190158189906 1...2 => |imm| switch (op.flags.base.ref.valueOf(s)) {
190159189907 inline .register_pair, .register_triple, .register_quadruple => |regs| .{
......@@ -190167,37 +189915,20 @@ const Select = struct {
190167189915 },
190168189916 .simm => .{ .imm = .s(op.adjustedImm(i32, s)) },
190169189917 .uimm => .{ .imm = .u(@bitCast(op.adjustedImm(i64, s))) },
190170 .lea => .{ .mem = .{
190171 .base = switch (op.flags.base.ref.valueOf(s)) {
189918 .lea => .{ .mem = try op.flags.base.ref.valueOf(s).deref().mem(s.cg, .{
189919 .size = op.flags.base.size,
189920 .index = switch (op.flags.index.ref.valueOf(s)) {
190172189921 else => unreachable,
190173189922 .none => .none,
190174 .register => |base_reg| .{ .reg = base_reg.toSize(.ptr, s.cg.target) },
190175 .register_offset => |base_reg_off| .{ .reg = base_reg_off.reg.toSize(.ptr, s.cg.target) },
190176 .lea_symbol => |base_sym_off| .{ .reloc = base_sym_off.sym_index },
190177 .lea_pcrel => |base_sym_off| .{ .pcrel = base_sym_off.sym_index },
189923 .register => |index_reg| index_reg.toSize(.ptr, s.cg.target),
190178189924 },
190179 .mod = .{ .rm = .{
190180 .size = op.flags.base.size,
190181 .index = switch (op.flags.index.ref.valueOf(s)) {
190182 else => unreachable,
190183 .none => .none,
190184 .register => |index_reg| index_reg.toSize(.ptr, s.cg.target),
190185 .register_offset => |index_reg_off| index_reg_off.reg.toSize(.ptr, s.cg.target),
190186 },
190187 .scale = op.flags.index.scale,
190188 .disp = op.adjustedImm(i32, s) + switch (op.flags.base.ref.valueOf(s)) {
190189 else => unreachable,
190190 .none, .register => 0,
190191 .register_offset => |base_reg_off| base_reg_off.off,
190192 .lea_symbol => |base_sym_off| base_sym_off.off,
190193 } + switch (op.flags.index.ref.valueOf(s)) {
190194 else => unreachable,
190195 .none, .register => 0,
190196 .register_offset => |base_reg_off| base_reg_off.off,
190197 .lea_symbol => |base_sym_off| base_sym_off.off,
190198 },
190199 } },
190200 } },
189925 .scale = op.flags.index.scale,
189926 .disp = op.adjustedImm(i32, s) + switch (op.flags.index.ref.valueOf(s)) {
189927 else => unreachable,
189928 .none, .register, .lea_nav, .lea_uav, .lea_lazy_sym, .lea_extern_func => 0,
189929 .register_offset => |base_reg_off| base_reg_off.off,
189930 },
189931 }) },
190201189932 .mem => .{ .mem = try op.flags.base.ref.valueOf(s).mem(s.cg, .{
190202189933 .size = op.flags.base.size,
190203189934 .index = switch (op.flags.index.ref.valueOf(s)) {
src/arch/x86_64/Emit.zig+648-290
......@@ -1,7 +1,9 @@
11//! This file contains the functionality for emitting x86_64 MIR as machine code
22
3air: Air,
43lower: Lower,
4bin_file: *link.File,
5pt: Zcu.PerThread,
6pic: bool,
57atom_index: u32,
68debug_output: link.File.DebugInfoOutput,
79code: *std.ArrayListUnmanaged(u8),
......@@ -10,26 +12,29 @@ prev_di_loc: Loc,
1012/// Relative to the beginning of `code`.
1113prev_di_pc: usize,
1214
15code_offset_mapping: std.ArrayListUnmanaged(u32),
16relocs: std.ArrayListUnmanaged(Reloc),
17table_relocs: std.ArrayListUnmanaged(TableReloc),
18
1319pub const Error = Lower.Error || error{
1420 EmitFail,
1521} || link.File.UpdateDebugInfoError;
1622
1723pub fn emitMir(emit: *Emit) Error!void {
18 const gpa = emit.lower.bin_file.comp.gpa;
19 const code_offset_mapping = try emit.lower.allocator.alloc(u32, emit.lower.mir.instructions.len);
20 defer emit.lower.allocator.free(code_offset_mapping);
21 var relocs: std.ArrayListUnmanaged(Reloc) = .empty;
22 defer relocs.deinit(emit.lower.allocator);
23 var table_relocs: std.ArrayListUnmanaged(TableReloc) = .empty;
24 defer table_relocs.deinit(emit.lower.allocator);
24 const comp = emit.bin_file.comp;
25 const gpa = comp.gpa;
26 try emit.code_offset_mapping.resize(gpa, emit.lower.mir.instructions.len);
27 emit.relocs.clearRetainingCapacity();
28 emit.table_relocs.clearRetainingCapacity();
29 var local_index: usize = 0;
2530 for (0..emit.lower.mir.instructions.len) |mir_i| {
2631 const mir_index: Mir.Inst.Index = @intCast(mir_i);
27 code_offset_mapping[mir_index] = @intCast(emit.code.items.len);
32 emit.code_offset_mapping.items[mir_index] = @intCast(emit.code.items.len);
2833 const lowered = try emit.lower.lowerMir(mir_index);
2934 var lowered_relocs = lowered.relocs;
30 for (lowered.insts, 0..) |lowered_inst, lowered_index| {
31 const start_offset: u32 = @intCast(emit.code.items.len);
35 lowered_inst: for (lowered.insts, 0..) |lowered_inst, lowered_index| {
3236 if (lowered_inst.prefix == .directive) {
37 const start_offset: u32 = @intCast(emit.code.items.len);
3338 switch (emit.debug_output) {
3439 .dwarf => |dwarf| switch (lowered_inst.encoding.mnemonic) {
3540 .@".cfi_def_cfa" => try dwarf.genDebugFrame(start_offset, .{ .def_cfa = .{
......@@ -82,204 +87,327 @@ pub fn emitMir(emit: *Emit) Error!void {
8287 }
8388 continue;
8489 }
85 try lowered_inst.encode(emit.code.writer(gpa), .{});
86 const end_offset: u32 = @intCast(emit.code.items.len);
90 var reloc_info_buf: [2]RelocInfo = undefined;
91 var reloc_info_index: usize = 0;
8792 while (lowered_relocs.len > 0 and
8893 lowered_relocs[0].lowered_inst_index == lowered_index) : ({
8994 lowered_relocs = lowered_relocs[1..];
90 }) switch (lowered_relocs[0].target) {
91 .inst => |target| {
92 const inst_length: u4 = @intCast(end_offset - start_offset);
93 const reloc_offset, const reloc_length = reloc_offset_length: {
94 var reloc_offset = inst_length;
95 var op_index: usize = lowered_inst.ops.len;
96 while (true) {
97 op_index -= 1;
98 const op = lowered_inst.encoding.data.ops[op_index];
99 if (op == .none) continue;
100 const is_mem = op.isMemory();
101 const enc_length: u4 = if (is_mem) switch (lowered_inst.ops[op_index].mem.sib.base) {
102 .rip_inst => 4,
103 else => unreachable,
104 } else @intCast(std.math.divCeil(u7, @intCast(op.immBitSize()), 8) catch unreachable);
105 reloc_offset -= enc_length;
106 if (op_index == lowered_relocs[0].op_index) break :reloc_offset_length .{ reloc_offset, enc_length };
107 std.debug.assert(!is_mem);
108 }
109 };
110 try relocs.append(emit.lower.allocator, .{
111 .inst_offset = start_offset,
112 .inst_length = inst_length,
113 .source_offset = reloc_offset,
114 .source_length = reloc_length,
115 .target = target,
116 .target_offset = lowered_relocs[0].off,
117 });
118 },
119 .table => try table_relocs.append(emit.lower.allocator, .{
120 .source_offset = end_offset - 4,
121 .target_offset = lowered_relocs[0].off,
122 }),
123 .linker_extern_fn => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
124 // Add relocation to the decl.
125 const zo = elf_file.zigObjectPtr().?;
126 const atom_ptr = zo.symbol(emit.atom_index).atom(elf_file).?;
127 const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);
128 try atom_ptr.addReloc(gpa, .{
129 .r_offset = end_offset - 4,
130 .r_info = @as(u64, sym_index) << 32 | r_type,
131 .r_addend = lowered_relocs[0].off - 4,
132 }, zo);
133 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
134 // Add relocation to the decl.
135 const zo = macho_file.getZigObject().?;
136 const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
137 try atom.addReloc(macho_file, .{
138 .tag = .@"extern",
139 .offset = end_offset - 4,
140 .target = sym_index,
141 .addend = lowered_relocs[0].off,
142 .type = .branch,
143 .meta = .{
144 .pcrel = true,
145 .has_subtractor = false,
146 .length = 2,
147 .symbolnum = @intCast(sym_index),
95 reloc_info_index += 1;
96 }) reloc_info_buf[reloc_info_index] = .{
97 .op_index = lowered_relocs[0].op_index,
98 .off = lowered_relocs[0].off,
99 .target = target: switch (lowered_relocs[0].target) {
100 .inst => |inst| .{ .index = inst, .is_extern = false, .type = .inst },
101 .table => .{ .index = undefined, .is_extern = false, .type = .table },
102 .nav => |nav| {
103 const sym_index = switch (try codegen.genNavRef(
104 emit.bin_file,
105 emit.pt,
106 emit.lower.src_loc,
107 nav,
108 emit.lower.target.*,
109 )) {
110 .mcv => |mcv| mcv.lea_symbol,
111 .fail => |em| {
112 assert(emit.lower.err_msg == null);
113 emit.lower.err_msg = em;
114 return error.EmitFail;
115 },
116 };
117 const ip = &emit.pt.zcu.intern_pool;
118 break :target switch (ip.getNav(nav).status) {
119 .unresolved => unreachable,
120 .type_resolved => |type_resolved| .{
121 .index = sym_index,
122 .is_extern = false,
123 .type = if (type_resolved.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
124 },
125 .fully_resolved => |fully_resolved| switch (ip.indexToKey(fully_resolved.val)) {
126 .@"extern" => |@"extern"| .{
127 .index = sym_index,
128 .is_extern = switch (@"extern".visibility) {
129 .default => true,
130 .hidden, .protected => false,
131 },
132 .type = if (@"extern".is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
133 .force_pcrel_direct = switch (@"extern".relocation) {
134 .any => false,
135 .pcrel => true,
136 },
137 },
138 .variable => |variable| .{
139 .index = sym_index,
140 .is_extern = false,
141 .type = if (variable.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
142 },
143 else => .{ .index = sym_index, .is_extern = false, .type = .symbol },
144 },
145 };
146 },
147 .uav => |uav| .{
148 .index = switch (try emit.bin_file.lowerUav(
149 emit.pt,
150 uav.val,
151 Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),
152 emit.lower.src_loc,
153 )) {
154 .mcv => |mcv| mcv.load_symbol,
155 .fail => |em| {
156 assert(emit.lower.err_msg == null);
157 emit.lower.err_msg = em;
158 return error.EmitFail;
159 },
148160 },
149 });
150 } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
151 // Add relocation to the decl.
152 const atom_index = coff_file.getAtomIndexForSymbol(
153 .{ .sym_index = emit.atom_index, .file = null },
154 ).?;
155 const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
156 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
157 else
158 link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
159 try coff_file.addRelocation(atom_index, .{
160 .type = .direct,
161 .target = target,
162 .offset = end_offset - 4,
163 .addend = @intCast(lowered_relocs[0].off),
164 .pcrel = true,
165 .length = 2,
166 });
167 } else return emit.fail("TODO implement extern reloc for {s}", .{
168 @tagName(emit.lower.bin_file.tag),
169 }),
170 .linker_tlsld => |sym_index| {
171 const elf_file = emit.lower.bin_file.cast(.elf).?;
172 const zo = elf_file.zigObjectPtr().?;
173 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
174 const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);
175 try atom.addReloc(gpa, .{
176 .r_offset = end_offset - 4,
177 .r_info = @as(u64, sym_index) << 32 | r_type,
178 .r_addend = lowered_relocs[0].off - 4,
179 }, zo);
180 },
181 .linker_dtpoff => |sym_index| {
182 const elf_file = emit.lower.bin_file.cast(.elf).?;
183 const zo = elf_file.zigObjectPtr().?;
184 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
185 const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);
186 try atom.addReloc(gpa, .{
187 .r_offset = end_offset - 4,
188 .r_info = @as(u64, sym_index) << 32 | r_type,
189 .r_addend = lowered_relocs[0].off,
190 }, zo);
191 },
192 .linker_reloc, .linker_pcrel => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
193 const zo = elf_file.zigObjectPtr().?;
194 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
195 const sym = zo.symbol(sym_index);
196 if (emit.lower.pic) {
197 const r_type: u32 = if (sym.flags.is_extern_ptr and lowered_relocs[0].target != .linker_pcrel)
198 @intFromEnum(std.elf.R_X86_64.GOTPCREL)
161 .is_extern = false,
162 .type = .symbol,
163 },
164 .lazy_sym => |lazy_sym| .{
165 .index = if (emit.bin_file.cast(.elf)) |elf_file|
166 elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, emit.pt, lazy_sym) catch |err|
167 return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
168 else if (emit.bin_file.cast(.macho)) |macho_file|
169 macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err|
170 return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
171 else if (emit.bin_file.cast(.coff)) |coff_file| sym_index: {
172 const atom = coff_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err|
173 return emit.fail("{s} creating lazy symbol", .{@errorName(err)});
174 break :sym_index coff_file.getAtom(atom).getSymbolIndex().?;
175 } else if (emit.bin_file.cast(.plan9)) |p9_file|
176 p9_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err|
177 return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
199178 else
200 @intFromEnum(std.elf.R_X86_64.PC32);
201 try atom.addReloc(gpa, .{
202 .r_offset = end_offset - 4,
203 .r_info = @as(u64, sym_index) << 32 | r_type,
204 .r_addend = lowered_relocs[0].off - 4,
205 }, zo);
206 } else {
207 const r_type: u32 = if (sym.flags.is_tls)
208 @intFromEnum(std.elf.R_X86_64.TPOFF32)
179 return emit.fail("lazy symbols unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
180 .is_extern = false,
181 .type = .symbol,
182 },
183 .extern_func => |extern_func| .{
184 .index = if (emit.bin_file.cast(.elf)) |elf_file|
185 try elf_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null)
186 else if (emit.bin_file.cast(.macho)) |macho_file|
187 try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null)
188 else if (emit.bin_file.cast(.coff)) |coff_file|
189 link.File.Coff.global_symbol_bit | try coff_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null)
209190 else
210 @intFromEnum(std.elf.R_X86_64.@"32");
211 try atom.addReloc(gpa, .{
212 .r_offset = end_offset - 4,
213 .r_info = @as(u64, sym_index) << 32 | r_type,
214 .r_addend = lowered_relocs[0].off,
215 }, zo);
216 }
217 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
218 const zo = macho_file.getZigObject().?;
219 const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
220 const sym = &zo.symbols.items[sym_index];
221 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr and lowered_relocs[0].target != .linker_pcrel)
222 .got_load
223 else if (sym.flags.tlv)
224 .tlv
225 else
226 .signed;
227 try atom.addReloc(macho_file, .{
228 .tag = .@"extern",
229 .offset = @intCast(end_offset - 4),
230 .target = sym_index,
231 .addend = lowered_relocs[0].off,
232 .type = @"type",
233 .meta = .{
234 .pcrel = true,
235 .has_subtractor = false,
236 .length = 2,
237 .symbolnum = @intCast(sym_index),
191 return emit.fail("external symbols unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
192 .is_extern = true,
193 .type = .symbol,
194 },
195 },
196 };
197 const reloc_info = reloc_info_buf[0..reloc_info_index];
198 for (reloc_info) |*reloc| switch (reloc.target.type) {
199 .inst, .table => {},
200 .symbol => {
201 switch (lowered_inst.encoding.mnemonic) {
202 .call => {
203 reloc.target.type = .branch;
204 if (emit.bin_file.cast(.coff)) |_| try emit.encodeInst(try .new(.none, .call, &.{
205 .{ .mem = .initRip(.ptr, 0) },
206 }, emit.lower.target), reloc_info) else try emit.encodeInst(lowered_inst, reloc_info);
207 continue :lowered_inst;
238208 },
209 else => {},
210 }
211 if (emit.bin_file.cast(.elf)) |_| {
212 if (!emit.pic) switch (lowered_inst.encoding.mnemonic) {
213 .lea => try emit.encodeInst(try .new(.none, .mov, &.{
214 lowered_inst.ops[0],
215 .{ .imm = .s(0) },
216 }, emit.lower.target), reloc_info),
217 .mov => try emit.encodeInst(try .new(.none, .mov, &.{
218 lowered_inst.ops[0],
219 .{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{
220 .base = .{ .reg = .ds },
221 }) },
222 }, emit.lower.target), reloc_info),
223 else => unreachable,
224 } else if (reloc.target.is_extern) switch (lowered_inst.encoding.mnemonic) {
225 .lea => try emit.encodeInst(try .new(.none, .mov, &.{
226 lowered_inst.ops[0],
227 .{ .mem = .initRip(.ptr, 0) },
228 }, emit.lower.target), reloc_info),
229 .mov => {
230 try emit.encodeInst(try .new(.none, .mov, &.{
231 lowered_inst.ops[0],
232 .{ .mem = .initRip(.ptr, 0) },
233 }, emit.lower.target), reloc_info);
234 try emit.encodeInst(try .new(.none, .mov, &.{
235 lowered_inst.ops[0],
236 .{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{ .base = .{
237 .reg = lowered_inst.ops[0].reg.to64(),
238 } }) },
239 }, emit.lower.target), &.{});
240 },
241 else => unreachable,
242 } else switch (lowered_inst.encoding.mnemonic) {
243 .lea => try emit.encodeInst(try .new(.none, .lea, &.{
244 lowered_inst.ops[0],
245 .{ .mem = .initRip(.none, 0) },
246 }, emit.lower.target), reloc_info),
247 .mov => try emit.encodeInst(try .new(.none, .mov, &.{
248 lowered_inst.ops[0],
249 .{ .mem = .initRip(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, 0) },
250 }, emit.lower.target), reloc_info),
251 else => unreachable,
252 }
253 } else if (emit.bin_file.cast(.macho)) |_| {
254 if (reloc.target.is_extern) switch (lowered_inst.encoding.mnemonic) {
255 .lea => try emit.encodeInst(try .new(.none, .mov, &.{
256 lowered_inst.ops[0],
257 .{ .mem = .initRip(.ptr, 0) },
258 }, emit.lower.target), reloc_info),
259 .mov => {
260 try emit.encodeInst(try .new(.none, .mov, &.{
261 lowered_inst.ops[0],
262 .{ .mem = .initRip(.ptr, 0) },
263 }, emit.lower.target), reloc_info);
264 try emit.encodeInst(try .new(.none, .mov, &.{
265 lowered_inst.ops[0],
266 .{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{ .base = .{
267 .reg = lowered_inst.ops[0].reg.to64(),
268 } }) },
269 }, emit.lower.target), &.{});
270 },
271 else => unreachable,
272 } else switch (lowered_inst.encoding.mnemonic) {
273 .lea => try emit.encodeInst(try .new(.none, .lea, &.{
274 lowered_inst.ops[0],
275 .{ .mem = .initRip(.none, 0) },
276 }, emit.lower.target), reloc_info),
277 .mov => try emit.encodeInst(try .new(.none, .mov, &.{
278 lowered_inst.ops[0],
279 .{ .mem = .initRip(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, 0) },
280 }, emit.lower.target), reloc_info),
281 else => unreachable,
282 }
283 } else if (emit.bin_file.cast(.coff)) |_| {
284 if (reloc.target.is_extern) switch (lowered_inst.encoding.mnemonic) {
285 .lea => try emit.encodeInst(try .new(.none, .mov, &.{
286 lowered_inst.ops[0],
287 .{ .mem = .initRip(.ptr, 0) },
288 }, emit.lower.target), reloc_info),
289 .mov => {
290 const dst_reg = lowered_inst.ops[0].reg.to64();
291 try emit.encodeInst(try .new(.none, .mov, &.{
292 .{ .reg = dst_reg },
293 .{ .mem = .initRip(.ptr, 0) },
294 }, emit.lower.target), reloc_info);
295 try emit.encodeInst(try .new(.none, .mov, &.{
296 lowered_inst.ops[0],
297 .{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{ .base = .{
298 .reg = dst_reg,
299 } }) },
300 }, emit.lower.target), &.{});
301 },
302 else => unreachable,
303 } else switch (lowered_inst.encoding.mnemonic) {
304 .lea => try emit.encodeInst(try .new(.none, .lea, &.{
305 lowered_inst.ops[0],
306 .{ .mem = .initRip(.none, 0) },
307 }, emit.lower.target), reloc_info),
308 .mov => try emit.encodeInst(try .new(.none, .mov, &.{
309 lowered_inst.ops[0],
310 .{ .mem = .initRip(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, 0) },
311 }, emit.lower.target), reloc_info),
312 else => unreachable,
313 }
314 } else return emit.fail("TODO implement relocs for {s}", .{
315 @tagName(emit.bin_file.tag),
239316 });
240 } else unreachable,
241 .linker_got,
242 .linker_direct,
243 .linker_import,
244 => |sym_index| if (emit.lower.bin_file.cast(.elf)) |_| {
245 unreachable;
246 } else if (emit.lower.bin_file.cast(.macho)) |_| {
247 unreachable;
248 } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
249 const atom_index = coff_file.getAtomIndexForSymbol(.{
250 .sym_index = emit.atom_index,
251 .file = null,
252 }).?;
253 const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
254 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
255 else
256 link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
257 try coff_file.addRelocation(atom_index, .{
258 .type = switch (lowered_relocs[0].target) {
259 .linker_got => .got,
260 .linker_direct => .direct,
261 .linker_import => .import,
317 continue :lowered_inst;
318 },
319 .branch, .tls => unreachable,
320 .tlv => {
321 if (emit.bin_file.cast(.elf)) |elf_file| {
322 // TODO handle extern TLS vars, i.e., emit GD model
323 if (emit.pic) switch (lowered_inst.encoding.mnemonic) {
324 .lea, .mov => {
325 // Here, we currently assume local dynamic TLS vars, and so
326 // we emit LD model.
327 try emit.encodeInst(try .new(.none, .lea, &.{
328 .{ .reg = .rdi },
329 .{ .mem = .initRip(.none, 0) },
330 }, emit.lower.target), &.{.{
331 .op_index = 1,
332 .target = .{
333 .index = reloc.target.index,
334 .is_extern = false,
335 .type = .tls,
336 },
337 }});
338 try emit.encodeInst(try .new(.none, .call, &.{
339 .{ .imm = .s(0) },
340 }, emit.lower.target), &.{.{
341 .op_index = 0,
342 .target = .{
343 .index = try elf_file.getGlobalSymbol("__tls_get_addr", null),
344 .is_extern = true,
345 .type = .branch,
346 },
347 }});
348 try emit.encodeInst(try .new(.none, lowered_inst.encoding.mnemonic, &.{
349 lowered_inst.ops[0],
350 .{ .mem = .initSib(.none, .{
351 .base = .{ .reg = .rax },
352 .disp = std.math.minInt(i32),
353 }) },
354 }, emit.lower.target), reloc_info);
355 },
356 else => unreachable,
357 } else switch (lowered_inst.encoding.mnemonic) {
358 .lea, .mov => {
359 // Since we are linking statically, we emit LE model directly.
360 try emit.encodeInst(try .new(.none, .mov, &.{
361 .{ .reg = .rax },
362 .{ .mem = .initSib(.qword, .{ .base = .{ .reg = .fs } }) },
363 }, emit.lower.target), &.{});
364 try emit.encodeInst(try .new(.none, lowered_inst.encoding.mnemonic, &.{
365 lowered_inst.ops[0],
366 .{ .mem = .initSib(.none, .{
367 .base = .{ .reg = .rax },
368 .disp = std.math.minInt(i32),
369 }) },
370 }, emit.lower.target), reloc_info);
371 },
262372 else => unreachable,
373 }
374 } else if (emit.bin_file.cast(.macho)) |_| switch (lowered_inst.encoding.mnemonic) {
375 .lea => {
376 try emit.encodeInst(try .new(.none, .mov, &.{
377 .{ .reg = .rdi },
378 .{ .mem = .initRip(.ptr, 0) },
379 }, emit.lower.target), reloc_info);
380 try emit.encodeInst(try .new(.none, .call, &.{
381 .{ .mem = .initSib(.qword, .{ .base = .{ .reg = .rdi } }) },
382 }, emit.lower.target), &.{});
383 try emit.encodeInst(try .new(.none, .mov, &.{
384 lowered_inst.ops[0],
385 .{ .reg = .rax },
386 }, emit.lower.target), &.{});
263387 },
264 .target = target,
265 .offset = @intCast(end_offset - 4),
266 .addend = @intCast(lowered_relocs[0].off),
267 .pcrel = true,
268 .length = 2,
269 });
270 } else if (emit.lower.bin_file.cast(.plan9)) |p9_file| {
271 try p9_file.addReloc(emit.atom_index, .{ // TODO we may need to add a .type field to the relocs if they are .linker_got instead of just .linker_direct
272 .target = sym_index, // we set sym_index to just be the atom index
273 .offset = @intCast(end_offset - 4),
274 .addend = @intCast(lowered_relocs[0].off),
275 .type = .pcrel,
388 .mov => {
389 try emit.encodeInst(try .new(.none, .mov, &.{
390 .{ .reg = .rdi },
391 .{ .mem = .initRip(.ptr, 0) },
392 }, emit.lower.target), reloc_info);
393 try emit.encodeInst(try .new(.none, .call, &.{
394 .{ .mem = .initSib(.qword, .{ .base = .{ .reg = .rdi } }) },
395 }, emit.lower.target), &.{});
396 try emit.encodeInst(try .new(.none, .mov, &.{
397 lowered_inst.ops[0],
398 .{ .mem = .initSib(.qword, .{ .base = .{ .reg = .rax } }) },
399 }, emit.lower.target), &.{});
400 },
401 else => unreachable,
402 } else return emit.fail("TODO implement relocs for {s}", .{
403 @tagName(emit.bin_file.tag),
276404 });
277 } else return emit.fail("TODO implement linker reloc for {s}", .{
278 @tagName(emit.lower.bin_file.tag),
279 }),
405 continue :lowered_inst;
406 },
280407 };
408 try emit.encodeInst(lowered_inst, reloc_info);
281409 }
282 std.debug.assert(lowered_relocs.len == 0);
410 assert(lowered_relocs.len == 0);
283411
284412 if (lowered.insts.len == 0) {
285413 const mir_inst = emit.lower.mir.instructions.get(mir_index);
......@@ -338,7 +466,7 @@ pub fn emitMir(emit: *Emit) Error!void {
338466 log.debug("mirDbgEnterInline (line={d}, col={d})", .{
339467 emit.prev_di_loc.line, emit.prev_di_loc.column,
340468 });
341 try dwarf.enterInlineFunc(mir_inst.data.func, emit.code.items.len, emit.prev_di_loc.line, emit.prev_di_loc.column);
469 try dwarf.enterInlineFunc(mir_inst.data.ip_index, emit.code.items.len, emit.prev_di_loc.line, emit.prev_di_loc.column);
342470 },
343471 .plan9 => {},
344472 .none => {},
......@@ -348,77 +476,49 @@ pub fn emitMir(emit: *Emit) Error!void {
348476 log.debug("mirDbgLeaveInline (line={d}, col={d})", .{
349477 emit.prev_di_loc.line, emit.prev_di_loc.column,
350478 });
351 try dwarf.leaveInlineFunc(mir_inst.data.func, emit.code.items.len);
479 try dwarf.leaveInlineFunc(mir_inst.data.ip_index, emit.code.items.len);
352480 },
353481 .plan9 => {},
354482 .none => {},
355483 },
356 .pseudo_dbg_local_a,
357 .pseudo_dbg_local_ai_s,
358 .pseudo_dbg_local_ai_u,
359 .pseudo_dbg_local_ai_64,
360 .pseudo_dbg_local_as,
361 .pseudo_dbg_local_aso,
362 .pseudo_dbg_local_aro,
363 .pseudo_dbg_local_af,
364 .pseudo_dbg_local_am,
484 .pseudo_dbg_arg_none,
485 .pseudo_dbg_arg_i_s,
486 .pseudo_dbg_arg_i_u,
487 .pseudo_dbg_arg_i_64,
488 .pseudo_dbg_arg_ro,
489 .pseudo_dbg_arg_fa,
490 .pseudo_dbg_arg_m,
491 .pseudo_dbg_var_none,
492 .pseudo_dbg_var_i_s,
493 .pseudo_dbg_var_i_u,
494 .pseudo_dbg_var_i_64,
495 .pseudo_dbg_var_ro,
496 .pseudo_dbg_var_fa,
497 .pseudo_dbg_var_m,
365498 => switch (emit.debug_output) {
366499 .dwarf => |dwarf| {
367500 var loc_buf: [2]link.File.Dwarf.Loc = undefined;
368 const air_inst_index, const loc: link.File.Dwarf.Loc = switch (mir_inst.ops) {
501 const loc: link.File.Dwarf.Loc = loc: switch (mir_inst.ops) {
369502 else => unreachable,
370 .pseudo_dbg_local_a => .{ mir_inst.data.a.air_inst, .empty },
371 .pseudo_dbg_local_ai_s,
372 .pseudo_dbg_local_ai_u,
373 .pseudo_dbg_local_ai_64,
374 => .{ mir_inst.data.ai.air_inst, .{ .stack_value = stack_value: {
375 loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.ai.i)) {
503 .pseudo_dbg_arg_none, .pseudo_dbg_var_none => .empty,
504 .pseudo_dbg_arg_i_s,
505 .pseudo_dbg_arg_i_u,
506 .pseudo_dbg_var_i_s,
507 .pseudo_dbg_var_i_u,
508 => .{ .stack_value = stack_value: {
509 loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.i.i)) {
376510 .signed => |s| .{ .consts = s },
377511 .unsigned => |u| .{ .constu = u },
378512 };
379513 break :stack_value &loc_buf[0];
380 } } },
381 .pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{
382 .addr_reloc = mir_inst.data.as.sym_index,
383514 } },
384 .pseudo_dbg_local_aso => loc: {
385 const sym_off = emit.lower.mir.extraData(
386 bits.SymbolOffset,
387 mir_inst.data.ax.payload,
388 ).data;
389 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
390 sym: {
391 loc_buf[0] = .{ .addr_reloc = sym_off.sym_index };
392 break :sym &loc_buf[0];
393 },
394 off: {
395 loc_buf[1] = .{ .consts = sym_off.off };
396 break :off &loc_buf[1];
397 },
398 } } };
399 },
400 .pseudo_dbg_local_aro => loc: {
401 const air_off = emit.lower.mir.extraData(
402 Mir.AirOffset,
403 mir_inst.data.rx.payload,
404 ).data;
405 break :loc .{ air_off.air_inst, .{ .plus = .{
406 reg: {
407 loc_buf[0] = .{ .breg = mir_inst.data.rx.r1.dwarfNum() };
408 break :reg &loc_buf[0];
409 },
410 off: {
411 loc_buf[1] = .{ .consts = air_off.off };
412 break :off &loc_buf[1];
413 },
414 } } };
415 },
416 .pseudo_dbg_local_af => loc: {
417 const reg_off = emit.lower.mir.resolveFrameAddr(emit.lower.mir.extraData(
418 bits.FrameAddr,
419 mir_inst.data.ax.payload,
420 ).data);
421 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
515 .pseudo_dbg_arg_i_64, .pseudo_dbg_var_i_64 => .{ .stack_value = stack_value: {
516 loc_buf[0] = .{ .constu = mir_inst.data.i64 };
517 break :stack_value &loc_buf[0];
518 } },
519 .pseudo_dbg_arg_fa, .pseudo_dbg_var_fa => {
520 const reg_off = emit.lower.mir.resolveFrameAddr(mir_inst.data.fa);
521 break :loc .{ .plus = .{
422522 reg: {
423523 loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() };
424524 break :reg &loc_buf[0];
......@@ -427,18 +527,54 @@ pub fn emitMir(emit: *Emit) Error!void {
427527 loc_buf[1] = .{ .consts = reg_off.off };
428528 break :off &loc_buf[1];
429529 },
430 } } };
530 } };
431531 },
432 .pseudo_dbg_local_am => loc: {
433 const mem = emit.lower.mem(undefined, mir_inst.data.ax.payload);
434 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
532 .pseudo_dbg_arg_m, .pseudo_dbg_var_m => {
533 const mem = emit.lower.mir.resolveMemoryExtra(mir_inst.data.x.payload).decode();
534 break :loc .{ .plus = .{
435535 base: {
436536 loc_buf[0] = switch (mem.base()) {
437537 .none => .{ .constu = 0 },
438538 .reg => |reg| .{ .breg = reg.dwarfNum() },
439539 .frame, .table, .rip_inst => unreachable,
440 .reloc => |sym_index| .{ .addr_reloc = sym_index },
441 .pcrel => unreachable,
540 .nav => |nav| .{ .addr_reloc = switch (codegen.genNavRef(
541 emit.bin_file,
542 emit.pt,
543 emit.lower.src_loc,
544 nav,
545 emit.lower.target.*,
546 ) catch |err| switch (err) {
547 error.CodegenFail,
548 => return emit.fail("unable to codegen: {s}", .{@errorName(err)}),
549 else => |e| return e,
550 }) {
551 .mcv => |mcv| switch (mcv) {
552 else => unreachable,
553 .load_direct, .load_symbol => |sym_index| sym_index,
554 },
555 .fail => |em| {
556 assert(emit.lower.err_msg == null);
557 emit.lower.err_msg = em;
558 return error.EmitFail;
559 },
560 } },
561 .uav => |uav| .{ .addr_reloc = switch (try emit.bin_file.lowerUav(
562 emit.pt,
563 uav.val,
564 Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),
565 emit.lower.src_loc,
566 )) {
567 .mcv => |mcv| switch (mcv) {
568 else => unreachable,
569 .load_direct, .load_symbol => |sym_index| sym_index,
570 },
571 .fail => |em| {
572 assert(emit.lower.err_msg == null);
573 emit.lower.err_msg = em;
574 return error.EmitFail;
575 },
576 } },
577 .lazy_sym, .extern_func => unreachable,
442578 };
443579 break :base &loc_buf[0];
444580 },
......@@ -449,34 +585,57 @@ pub fn emitMir(emit: *Emit) Error!void {
449585 };
450586 break :disp &loc_buf[1];
451587 },
452 } } };
588 } };
453589 },
454590 };
455 const ip = &emit.lower.bin_file.comp.zcu.?.intern_pool;
456 const air_inst = emit.air.instructions.get(@intFromEnum(air_inst_index));
457 const name: Air.NullTerminatedString = switch (air_inst.tag) {
458 else => unreachable,
459 .arg => air_inst.data.arg.name,
460 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => @enumFromInt(air_inst.data.pl_op.payload),
461 };
462 try dwarf.genLocalDebugInfo(
463 switch (air_inst.tag) {
591
592 const local = &emit.lower.mir.locals[local_index];
593 local_index += 1;
594 try dwarf.genLocalVarDebugInfo(
595 switch (mir_inst.ops) {
464596 else => unreachable,
465 .arg, .dbg_arg_inline => .local_arg,
466 .dbg_var_ptr, .dbg_var_val => .local_var,
597 .pseudo_dbg_arg_none,
598 .pseudo_dbg_arg_i_s,
599 .pseudo_dbg_arg_i_u,
600 .pseudo_dbg_arg_i_64,
601 .pseudo_dbg_arg_ro,
602 .pseudo_dbg_arg_fa,
603 .pseudo_dbg_arg_m,
604 .pseudo_dbg_arg_val,
605 => .arg,
606 .pseudo_dbg_var_none,
607 .pseudo_dbg_var_i_s,
608 .pseudo_dbg_var_i_u,
609 .pseudo_dbg_var_i_64,
610 .pseudo_dbg_var_ro,
611 .pseudo_dbg_var_fa,
612 .pseudo_dbg_var_m,
613 .pseudo_dbg_var_val,
614 => .local_var,
467615 },
468 name.toSlice(emit.air),
469 switch (air_inst.tag) {
616 local.name.toSlice(&emit.lower.mir),
617 .fromInterned(local.type),
618 loc,
619 );
620 },
621 .plan9, .none => local_index += 1,
622 },
623 .pseudo_dbg_arg_val, .pseudo_dbg_var_val => switch (emit.debug_output) {
624 .dwarf => |dwarf| {
625 const local = &emit.lower.mir.locals[local_index];
626 local_index += 1;
627 try dwarf.genLocalConstDebugInfo(
628 emit.lower.src_loc,
629 switch (mir_inst.ops) {
470630 else => unreachable,
471 .arg => emit.air.typeOfIndex(air_inst_index, ip),
472 .dbg_var_ptr => emit.air.typeOf(air_inst.data.pl_op.operand, ip).childTypeIp(ip),
473 .dbg_var_val, .dbg_arg_inline => emit.air.typeOf(air_inst.data.pl_op.operand, ip),
631 .pseudo_dbg_arg_val => .comptime_arg,
632 .pseudo_dbg_var_val => .local_const,
474633 },
475 loc,
634 local.name.toSlice(&emit.lower.mir),
635 .fromInterned(mir_inst.data.ip_index),
476636 );
477637 },
478 .plan9 => {},
479 .none => {},
638 .plan9, .none => local_index += 1,
480639 },
481640 .pseudo_dbg_var_args_none => switch (emit.debug_output) {
482641 .dwarf => |dwarf| try dwarf.genVarArgsDebugInfo(),
......@@ -488,8 +647,8 @@ pub fn emitMir(emit: *Emit) Error!void {
488647 }
489648 }
490649 }
491 for (relocs.items) |reloc| {
492 const target = code_offset_mapping[reloc.target];
650 for (emit.relocs.items) |reloc| {
651 const target = emit.code_offset_mapping.items[reloc.target];
493652 const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.inst_offset + reloc.inst_length)) + reloc.target_offset;
494653 const inst_bytes = emit.code.items[reloc.inst_offset..][0..reloc.inst_length];
495654 switch (reloc.source_length) {
......@@ -503,13 +662,13 @@ pub fn emitMir(emit: *Emit) Error!void {
503662 }
504663 }
505664 if (emit.lower.mir.table.len > 0) {
506 if (emit.lower.bin_file.cast(.elf)) |elf_file| {
665 if (emit.bin_file.cast(.elf)) |elf_file| {
507666 const zo = elf_file.zigObjectPtr().?;
508667 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
509668
510669 const ptr_size = @divExact(emit.lower.target.ptrBitWidth(), 8);
511670 var table_offset = std.mem.alignForward(u32, @intCast(emit.code.items.len), ptr_size);
512 for (table_relocs.items) |table_reloc| try atom.addReloc(gpa, .{
671 for (emit.table_relocs.items) |table_reloc| try atom.addReloc(gpa, .{
513672 .r_offset = table_reloc.source_offset,
514673 .r_info = @as(u64, emit.atom_index) << 32 | @intFromEnum(std.elf.R_X86_64.@"32"),
515674 .r_addend = @as(i64, table_offset) + table_reloc.target_offset,
......@@ -518,7 +677,7 @@ pub fn emitMir(emit: *Emit) Error!void {
518677 try atom.addReloc(gpa, .{
519678 .r_offset = table_offset,
520679 .r_info = @as(u64, emit.atom_index) << 32 | @intFromEnum(std.elf.R_X86_64.@"64"),
521 .r_addend = code_offset_mapping[entry],
680 .r_addend = emit.code_offset_mapping.items[entry],
522681 }, zo);
523682 table_offset += ptr_size;
524683 }
......@@ -527,6 +686,200 @@ pub fn emitMir(emit: *Emit) Error!void {
527686 }
528687}
529688
689pub fn deinit(emit: *Emit) void {
690 const gpa = emit.bin_file.comp.gpa;
691 emit.code_offset_mapping.deinit(gpa);
692 emit.relocs.deinit(gpa);
693 emit.table_relocs.deinit(gpa);
694 emit.* = undefined;
695}
696
697const RelocInfo = struct {
698 op_index: Lower.InstOpIndex,
699 off: i32 = 0,
700 target: Target,
701
702 const Target = struct {
703 index: u32,
704 is_extern: bool,
705 type: Target.Type,
706 force_pcrel_direct: bool = false,
707
708 const Type = enum { inst, table, symbol, branch, tls, tlv };
709 };
710};
711
712fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocInfo) Error!void {
713 const comp = emit.bin_file.comp;
714 const gpa = comp.gpa;
715 const start_offset: u32 = @intCast(emit.code.items.len);
716 try lowered_inst.encode(emit.code.writer(gpa), .{});
717 const end_offset: u32 = @intCast(emit.code.items.len);
718 for (reloc_info) |reloc| switch (reloc.target.type) {
719 .inst => {
720 const inst_length: u4 = @intCast(end_offset - start_offset);
721 const reloc_offset, const reloc_length = reloc_offset_length: {
722 var reloc_offset = inst_length;
723 var op_index: usize = lowered_inst.ops.len;
724 while (true) {
725 op_index -= 1;
726 const op = lowered_inst.encoding.data.ops[op_index];
727 if (op == .none) continue;
728 const is_mem = op.isMemory();
729 const enc_length: u4 = if (is_mem) switch (lowered_inst.ops[op_index].mem.sib.base) {
730 .rip_inst => 4,
731 else => unreachable,
732 } else @intCast(std.math.divCeil(u7, @intCast(op.immBitSize()), 8) catch unreachable);
733 reloc_offset -= enc_length;
734 if (op_index == reloc.op_index) break :reloc_offset_length .{ reloc_offset, enc_length };
735 assert(!is_mem);
736 }
737 };
738 try emit.relocs.append(emit.lower.allocator, .{
739 .inst_offset = start_offset,
740 .inst_length = inst_length,
741 .source_offset = reloc_offset,
742 .source_length = reloc_length,
743 .target = reloc.target.index,
744 .target_offset = reloc.off,
745 });
746 },
747 .table => try emit.table_relocs.append(emit.lower.allocator, .{
748 .source_offset = end_offset - 4,
749 .target_offset = reloc.off,
750 }),
751 .symbol => if (emit.bin_file.cast(.elf)) |elf_file| {
752 const zo = elf_file.zigObjectPtr().?;
753 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
754 const r_type: std.elf.R_X86_64 = if (!emit.pic)
755 .@"32"
756 else if (reloc.target.is_extern and !reloc.target.force_pcrel_direct)
757 .GOTPCREL
758 else
759 .PC32;
760 try atom.addReloc(gpa, .{
761 .r_offset = end_offset - 4,
762 .r_info = @as(u64, reloc.target.index) << 32 | @intFromEnum(r_type),
763 .r_addend = if (emit.pic) reloc.off - 4 else reloc.off,
764 }, zo);
765 } else if (emit.bin_file.cast(.macho)) |macho_file| {
766 const zo = macho_file.getZigObject().?;
767 const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
768 try atom.addReloc(macho_file, .{
769 .tag = .@"extern",
770 .offset = end_offset - 4,
771 .target = reloc.target.index,
772 .addend = reloc.off,
773 .type = if (reloc.target.is_extern and !reloc.target.force_pcrel_direct) .got_load else .signed,
774 .meta = .{
775 .pcrel = true,
776 .has_subtractor = false,
777 .length = 2,
778 .symbolnum = @intCast(reloc.target.index),
779 },
780 });
781 } else if (emit.bin_file.cast(.coff)) |coff_file| {
782 const atom_index = coff_file.getAtomIndexForSymbol(
783 .{ .sym_index = emit.atom_index, .file = null },
784 ).?;
785 try coff_file.addRelocation(atom_index, .{
786 .type = if (reloc.target.is_extern) .got else .direct,
787 .target = if (reloc.target.is_extern)
788 coff_file.getGlobalByIndex(reloc.target.index)
789 else
790 .{ .sym_index = reloc.target.index, .file = null },
791 .offset = end_offset - 4,
792 .addend = @intCast(reloc.off),
793 .pcrel = true,
794 .length = 2,
795 });
796 } else unreachable,
797 .branch => if (emit.bin_file.cast(.elf)) |elf_file| {
798 const zo = elf_file.zigObjectPtr().?;
799 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
800 const r_type: std.elf.R_X86_64 = .PLT32;
801 try atom.addReloc(gpa, .{
802 .r_offset = end_offset - 4,
803 .r_info = @as(u64, reloc.target.index) << 32 | @intFromEnum(r_type),
804 .r_addend = reloc.off - 4,
805 }, zo);
806 } else if (emit.bin_file.cast(.macho)) |macho_file| {
807 const zo = macho_file.getZigObject().?;
808 const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
809 try atom.addReloc(macho_file, .{
810 .tag = .@"extern",
811 .offset = end_offset - 4,
812 .target = reloc.target.index,
813 .addend = reloc.off,
814 .type = .branch,
815 .meta = .{
816 .pcrel = true,
817 .has_subtractor = false,
818 .length = 2,
819 .symbolnum = @intCast(reloc.target.index),
820 },
821 });
822 } else if (emit.bin_file.cast(.coff)) |coff_file| {
823 const atom_index = coff_file.getAtomIndexForSymbol(
824 .{ .sym_index = emit.atom_index, .file = null },
825 ).?;
826 try coff_file.addRelocation(atom_index, .{
827 .type = if (reloc.target.is_extern) .import else .got,
828 .target = if (reloc.target.is_extern)
829 coff_file.getGlobalByIndex(reloc.target.index)
830 else
831 .{ .sym_index = reloc.target.index, .file = null },
832 .offset = end_offset - 4,
833 .addend = @intCast(reloc.off),
834 .pcrel = true,
835 .length = 2,
836 });
837 } else return emit.fail("TODO implement {s} reloc for {s}", .{
838 @tagName(reloc.target.type), @tagName(emit.bin_file.tag),
839 }),
840 .tls => if (emit.bin_file.cast(.elf)) |elf_file| {
841 const zo = elf_file.zigObjectPtr().?;
842 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
843 const r_type: std.elf.R_X86_64 = if (emit.pic) .TLSLD else unreachable;
844 try atom.addReloc(gpa, .{
845 .r_offset = end_offset - 4,
846 .r_info = @as(u64, reloc.target.index) << 32 | @intFromEnum(r_type),
847 .r_addend = reloc.off - 4,
848 }, zo);
849 } else return emit.fail("TODO implement {s} reloc for {s}", .{
850 @tagName(reloc.target.type), @tagName(emit.bin_file.tag),
851 }),
852 .tlv => if (emit.bin_file.cast(.elf)) |elf_file| {
853 const zo = elf_file.zigObjectPtr().?;
854 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
855 const r_type: std.elf.R_X86_64 = if (emit.pic) .DTPOFF32 else .TPOFF32;
856 try atom.addReloc(gpa, .{
857 .r_offset = end_offset - 4,
858 .r_info = @as(u64, reloc.target.index) << 32 | @intFromEnum(r_type),
859 .r_addend = reloc.off,
860 }, zo);
861 } else if (emit.bin_file.cast(.macho)) |macho_file| {
862 const zo = macho_file.getZigObject().?;
863 const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
864 try atom.addReloc(macho_file, .{
865 .tag = .@"extern",
866 .offset = end_offset - 4,
867 .target = reloc.target.index,
868 .addend = reloc.off,
869 .type = .tlv,
870 .meta = .{
871 .pcrel = true,
872 .has_subtractor = false,
873 .length = 2,
874 .symbolnum = @intCast(reloc.target.index),
875 },
876 });
877 } else return emit.fail("TODO implement {s} reloc for {s}", .{
878 @tagName(reloc.target.type), @tagName(emit.bin_file.tag),
879 }),
880 };
881}
882
530883fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {
531884 return switch (emit.lower.fail(format, args)) {
532885 error.LowerFail => error.EmitFail,
......@@ -610,12 +963,17 @@ fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void {
610963 }
611964}
612965
966const assert = std.debug.assert;
613967const bits = @import("bits.zig");
968const codegen = @import("../../codegen.zig");
969const Emit = @This();
970const encoder = @import("encoder.zig");
971const Instruction = encoder.Instruction;
972const InternPool = @import("../../InternPool.zig");
614973const link = @import("../../link.zig");
615974const log = std.log.scoped(.emit);
616const std = @import("std");
617
618const Air = @import("../../Air.zig");
619const Emit = @This();
620975const Lower = @import("Lower.zig");
621976const Mir = @import("Mir.zig");
977const std = @import("std");
978const Type = @import("../../Type.zig");
979const Zcu = @import("../../Zcu.zig");
src/arch/x86_64/Lower.zig+147-279
......@@ -1,10 +1,6 @@
11//! This file contains the functionality for lowering x86_64 MIR to Instructions
22
3bin_file: *link.File,
43target: *const std.Target,
5output_mode: std.builtin.OutputMode,
6link_mode: std.builtin.LinkMode,
7pic: bool,
84allocator: std.mem.Allocator,
95mir: Mir,
106cc: std.builtin.CallingConvention,
......@@ -17,7 +13,6 @@ result_relocs: [max_result_relocs]Reloc = undefined,
1713
1814const max_result_insts = @max(
1915 1, // non-pseudo instructions
20 3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode
2116 2, // cmovcc: cmovcc \ cmovcc
2217 3, // setcc: setcc \ setcc \ logicop
2318 2, // jcc: jcc \ jcc
......@@ -25,6 +20,7 @@ const max_result_insts = @max(
2520 pseudo_probe_adjust_unrolled_max_insts,
2621 pseudo_probe_adjust_setup_insts,
2722 pseudo_probe_adjust_loop_insts,
23 abi.zigcc.callee_preserved_regs.len * 2, // push_regs/pop_regs
2824 abi.Win64.callee_preserved_regs.len * 2, // push_regs/pop_regs
2925 abi.SysV.callee_preserved_regs.len * 2, // push_regs/pop_regs
3026);
......@@ -33,14 +29,13 @@ const max_result_relocs = @max(
3329 2, // jcc: jcc \ jcc
3430 2, // test \ jcc \ probe \ sub \ jmp
3531 1, // probe \ sub \ jcc
36 3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode
3732);
3833
39const ResultInstIndex = std.math.IntFittingRange(0, max_result_insts - 1);
40const ResultRelocIndex = std.math.IntFittingRange(0, max_result_relocs - 1);
41const InstOpIndex = std.math.IntFittingRange(
34const ResultInstIndex = std.math.IntFittingRange(0, max_result_insts);
35const ResultRelocIndex = std.math.IntFittingRange(0, max_result_relocs);
36pub const InstOpIndex = std.math.IntFittingRange(
4237 0,
43 @typeInfo(@FieldType(Instruction, "ops")).array.len - 1,
38 @typeInfo(@FieldType(Instruction, "ops")).array.len,
4439);
4540
4641pub const pseudo_probe_align_insts = 5; // test \ jcc \ probe \ sub \ jmp
......@@ -54,7 +49,8 @@ pub const Error = error{
5449 LowerFail,
5550 InvalidInstruction,
5651 CannotEncode,
57};
52 CodegenFail,
53} || codegen.GenerateSymbolError;
5854
5955pub const Reloc = struct {
6056 lowered_inst_index: ResultInstIndex,
......@@ -65,14 +61,10 @@ pub const Reloc = struct {
6561 const Target = union(enum) {
6662 inst: Mir.Inst.Index,
6763 table,
68 linker_reloc: u32,
69 linker_pcrel: u32,
70 linker_tlsld: u32,
71 linker_dtpoff: u32,
72 linker_extern_fn: u32,
73 linker_got: u32,
74 linker_direct: u32,
75 linker_import: u32,
64 nav: InternPool.Nav.Index,
65 uav: InternPool.Key.Ptr.BaseAddr.Uav,
66 lazy_sym: link.File.LazySymbol,
67 extern_func: Mir.NullTerminatedString,
7668 };
7769};
7870
......@@ -80,7 +72,7 @@ const Options = struct { allow_frame_locs: bool };
8072
8173/// The returned slice is overwritten by the next call to lowerMir.
8274pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
83 insts: []const Instruction,
75 insts: []Instruction,
8476 relocs: []const Reloc,
8577} {
8678 lower.result_insts = undefined;
......@@ -98,130 +90,130 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
9890 .pseudo => switch (inst.ops) {
9991 .pseudo_cmov_z_and_np_rr => {
10092 assert(inst.data.rr.fixes == ._);
101 try lower.emit(.none, .cmovnz, &.{
93 try lower.encode(.none, .cmovnz, &.{
10294 .{ .reg = inst.data.rr.r2 },
10395 .{ .reg = inst.data.rr.r1 },
10496 });
105 try lower.emit(.none, .cmovnp, &.{
97 try lower.encode(.none, .cmovnp, &.{
10698 .{ .reg = inst.data.rr.r1 },
10799 .{ .reg = inst.data.rr.r2 },
108100 });
109101 },
110102 .pseudo_cmov_nz_or_p_rr => {
111103 assert(inst.data.rr.fixes == ._);
112 try lower.emit(.none, .cmovnz, &.{
104 try lower.encode(.none, .cmovnz, &.{
113105 .{ .reg = inst.data.rr.r1 },
114106 .{ .reg = inst.data.rr.r2 },
115107 });
116 try lower.emit(.none, .cmovp, &.{
108 try lower.encode(.none, .cmovp, &.{
117109 .{ .reg = inst.data.rr.r1 },
118110 .{ .reg = inst.data.rr.r2 },
119111 });
120112 },
121113 .pseudo_cmov_nz_or_p_rm => {
122114 assert(inst.data.rx.fixes == ._);
123 try lower.emit(.none, .cmovnz, &.{
115 try lower.encode(.none, .cmovnz, &.{
124116 .{ .reg = inst.data.rx.r1 },
125117 .{ .mem = lower.mem(1, inst.data.rx.payload) },
126118 });
127 try lower.emit(.none, .cmovp, &.{
119 try lower.encode(.none, .cmovp, &.{
128120 .{ .reg = inst.data.rx.r1 },
129121 .{ .mem = lower.mem(1, inst.data.rx.payload) },
130122 });
131123 },
132124 .pseudo_set_z_and_np_r => {
133125 assert(inst.data.rr.fixes == ._);
134 try lower.emit(.none, .setz, &.{
126 try lower.encode(.none, .setz, &.{
135127 .{ .reg = inst.data.rr.r1 },
136128 });
137 try lower.emit(.none, .setnp, &.{
129 try lower.encode(.none, .setnp, &.{
138130 .{ .reg = inst.data.rr.r2 },
139131 });
140 try lower.emit(.none, .@"and", &.{
132 try lower.encode(.none, .@"and", &.{
141133 .{ .reg = inst.data.rr.r1 },
142134 .{ .reg = inst.data.rr.r2 },
143135 });
144136 },
145137 .pseudo_set_z_and_np_m => {
146138 assert(inst.data.rx.fixes == ._);
147 try lower.emit(.none, .setz, &.{
139 try lower.encode(.none, .setz, &.{
148140 .{ .mem = lower.mem(0, inst.data.rx.payload) },
149141 });
150 try lower.emit(.none, .setnp, &.{
142 try lower.encode(.none, .setnp, &.{
151143 .{ .reg = inst.data.rx.r1 },
152144 });
153 try lower.emit(.none, .@"and", &.{
145 try lower.encode(.none, .@"and", &.{
154146 .{ .mem = lower.mem(0, inst.data.rx.payload) },
155147 .{ .reg = inst.data.rx.r1 },
156148 });
157149 },
158150 .pseudo_set_nz_or_p_r => {
159151 assert(inst.data.rr.fixes == ._);
160 try lower.emit(.none, .setnz, &.{
152 try lower.encode(.none, .setnz, &.{
161153 .{ .reg = inst.data.rr.r1 },
162154 });
163 try lower.emit(.none, .setp, &.{
155 try lower.encode(.none, .setp, &.{
164156 .{ .reg = inst.data.rr.r2 },
165157 });
166 try lower.emit(.none, .@"or", &.{
158 try lower.encode(.none, .@"or", &.{
167159 .{ .reg = inst.data.rr.r1 },
168160 .{ .reg = inst.data.rr.r2 },
169161 });
170162 },
171163 .pseudo_set_nz_or_p_m => {
172164 assert(inst.data.rx.fixes == ._);
173 try lower.emit(.none, .setnz, &.{
165 try lower.encode(.none, .setnz, &.{
174166 .{ .mem = lower.mem(0, inst.data.rx.payload) },
175167 });
176 try lower.emit(.none, .setp, &.{
168 try lower.encode(.none, .setp, &.{
177169 .{ .reg = inst.data.rx.r1 },
178170 });
179 try lower.emit(.none, .@"or", &.{
171 try lower.encode(.none, .@"or", &.{
180172 .{ .mem = lower.mem(0, inst.data.rx.payload) },
181173 .{ .reg = inst.data.rx.r1 },
182174 });
183175 },
184176 .pseudo_j_z_and_np_inst => {
185177 assert(inst.data.inst.fixes == ._);
186 try lower.emit(.none, .jnz, &.{
178 try lower.encode(.none, .jnz, &.{
187179 .{ .imm = lower.reloc(0, .{ .inst = index + 1 }, 0) },
188180 });
189 try lower.emit(.none, .jnp, &.{
181 try lower.encode(.none, .jnp, &.{
190182 .{ .imm = lower.reloc(0, .{ .inst = inst.data.inst.inst }, 0) },
191183 });
192184 },
193185 .pseudo_j_nz_or_p_inst => {
194186 assert(inst.data.inst.fixes == ._);
195 try lower.emit(.none, .jnz, &.{
187 try lower.encode(.none, .jnz, &.{
196188 .{ .imm = lower.reloc(0, .{ .inst = inst.data.inst.inst }, 0) },
197189 });
198 try lower.emit(.none, .jp, &.{
190 try lower.encode(.none, .jp, &.{
199191 .{ .imm = lower.reloc(0, .{ .inst = inst.data.inst.inst }, 0) },
200192 });
201193 },
202194
203195 .pseudo_probe_align_ri_s => {
204 try lower.emit(.none, .@"test", &.{
196 try lower.encode(.none, .@"test", &.{
205197 .{ .reg = inst.data.ri.r1 },
206198 .{ .imm = .s(@bitCast(inst.data.ri.i)) },
207199 });
208 try lower.emit(.none, .jz, &.{
200 try lower.encode(.none, .jz, &.{
209201 .{ .imm = lower.reloc(0, .{ .inst = index + 1 }, 0) },
210202 });
211 try lower.emit(.none, .lea, &.{
203 try lower.encode(.none, .lea, &.{
212204 .{ .reg = inst.data.ri.r1 },
213205 .{ .mem = Memory.initSib(.qword, .{
214206 .base = .{ .reg = inst.data.ri.r1 },
215207 .disp = -page_size,
216208 }) },
217209 });
218 try lower.emit(.none, .@"test", &.{
210 try lower.encode(.none, .@"test", &.{
219211 .{ .mem = Memory.initSib(.dword, .{
220212 .base = .{ .reg = inst.data.ri.r1 },
221213 }) },
222214 .{ .reg = inst.data.ri.r1.to32() },
223215 });
224 try lower.emit(.none, .jmp, &.{
216 try lower.encode(.none, .jmp, &.{
225217 .{ .imm = lower.reloc(0, .{ .inst = index }, 0) },
226218 });
227219 assert(lower.result_insts_len == pseudo_probe_align_insts);
......@@ -229,7 +221,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
229221 .pseudo_probe_adjust_unrolled_ri_s => {
230222 var offset = page_size;
231223 while (offset < @as(i32, @bitCast(inst.data.ri.i))) : (offset += page_size) {
232 try lower.emit(.none, .@"test", &.{
224 try lower.encode(.none, .@"test", &.{
233225 .{ .mem = Memory.initSib(.dword, .{
234226 .base = .{ .reg = inst.data.ri.r1 },
235227 .disp = -offset,
......@@ -237,25 +229,25 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
237229 .{ .reg = inst.data.ri.r1.to32() },
238230 });
239231 }
240 try lower.emit(.none, .sub, &.{
232 try lower.encode(.none, .sub, &.{
241233 .{ .reg = inst.data.ri.r1 },
242234 .{ .imm = .s(@bitCast(inst.data.ri.i)) },
243235 });
244236 assert(lower.result_insts_len <= pseudo_probe_adjust_unrolled_max_insts);
245237 },
246238 .pseudo_probe_adjust_setup_rri_s => {
247 try lower.emit(.none, .mov, &.{
239 try lower.encode(.none, .mov, &.{
248240 .{ .reg = inst.data.rri.r2.to32() },
249241 .{ .imm = .s(@bitCast(inst.data.rri.i)) },
250242 });
251 try lower.emit(.none, .sub, &.{
243 try lower.encode(.none, .sub, &.{
252244 .{ .reg = inst.data.rri.r1 },
253245 .{ .reg = inst.data.rri.r2 },
254246 });
255247 assert(lower.result_insts_len == pseudo_probe_adjust_setup_insts);
256248 },
257249 .pseudo_probe_adjust_loop_rr => {
258 try lower.emit(.none, .@"test", &.{
250 try lower.encode(.none, .@"test", &.{
259251 .{ .mem = Memory.initSib(.dword, .{
260252 .base = .{ .reg = inst.data.rr.r1 },
261253 .scale_index = .{ .scale = 1, .index = inst.data.rr.r2 },
......@@ -263,11 +255,11 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
263255 }) },
264256 .{ .reg = inst.data.rr.r1.to32() },
265257 });
266 try lower.emit(.none, .sub, &.{
258 try lower.encode(.none, .sub, &.{
267259 .{ .reg = inst.data.rr.r2 },
268260 .{ .imm = .s(page_size) },
269261 });
270 try lower.emit(.none, .jae, &.{
262 try lower.encode(.none, .jae, &.{
271263 .{ .imm = lower.reloc(0, .{ .inst = index }, 0) },
272264 });
273265 assert(lower.result_insts_len == pseudo_probe_adjust_loop_insts);
......@@ -275,47 +267,47 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
275267 .pseudo_push_reg_list => try lower.pushPopRegList(.push, inst),
276268 .pseudo_pop_reg_list => try lower.pushPopRegList(.pop, inst),
277269
278 .pseudo_cfi_def_cfa_ri_s => try lower.emit(.directive, .@".cfi_def_cfa", &.{
270 .pseudo_cfi_def_cfa_ri_s => try lower.encode(.directive, .@".cfi_def_cfa", &.{
279271 .{ .reg = inst.data.ri.r1 },
280272 .{ .imm = lower.imm(.ri_s, inst.data.ri.i) },
281273 }),
282 .pseudo_cfi_def_cfa_register_r => try lower.emit(.directive, .@".cfi_def_cfa_register", &.{
274 .pseudo_cfi_def_cfa_register_r => try lower.encode(.directive, .@".cfi_def_cfa_register", &.{
283275 .{ .reg = inst.data.r.r1 },
284276 }),
285 .pseudo_cfi_def_cfa_offset_i_s => try lower.emit(.directive, .@".cfi_def_cfa_offset", &.{
277 .pseudo_cfi_def_cfa_offset_i_s => try lower.encode(.directive, .@".cfi_def_cfa_offset", &.{
286278 .{ .imm = lower.imm(.i_s, inst.data.i.i) },
287279 }),
288 .pseudo_cfi_adjust_cfa_offset_i_s => try lower.emit(.directive, .@".cfi_adjust_cfa_offset", &.{
280 .pseudo_cfi_adjust_cfa_offset_i_s => try lower.encode(.directive, .@".cfi_adjust_cfa_offset", &.{
289281 .{ .imm = lower.imm(.i_s, inst.data.i.i) },
290282 }),
291 .pseudo_cfi_offset_ri_s => try lower.emit(.directive, .@".cfi_offset", &.{
283 .pseudo_cfi_offset_ri_s => try lower.encode(.directive, .@".cfi_offset", &.{
292284 .{ .reg = inst.data.ri.r1 },
293285 .{ .imm = lower.imm(.ri_s, inst.data.ri.i) },
294286 }),
295 .pseudo_cfi_val_offset_ri_s => try lower.emit(.directive, .@".cfi_val_offset", &.{
287 .pseudo_cfi_val_offset_ri_s => try lower.encode(.directive, .@".cfi_val_offset", &.{
296288 .{ .reg = inst.data.ri.r1 },
297289 .{ .imm = lower.imm(.ri_s, inst.data.ri.i) },
298290 }),
299 .pseudo_cfi_rel_offset_ri_s => try lower.emit(.directive, .@".cfi_rel_offset", &.{
291 .pseudo_cfi_rel_offset_ri_s => try lower.encode(.directive, .@".cfi_rel_offset", &.{
300292 .{ .reg = inst.data.ri.r1 },
301293 .{ .imm = lower.imm(.ri_s, inst.data.ri.i) },
302294 }),
303 .pseudo_cfi_register_rr => try lower.emit(.directive, .@".cfi_register", &.{
295 .pseudo_cfi_register_rr => try lower.encode(.directive, .@".cfi_register", &.{
304296 .{ .reg = inst.data.rr.r1 },
305297 .{ .reg = inst.data.rr.r2 },
306298 }),
307 .pseudo_cfi_restore_r => try lower.emit(.directive, .@".cfi_restore", &.{
299 .pseudo_cfi_restore_r => try lower.encode(.directive, .@".cfi_restore", &.{
308300 .{ .reg = inst.data.r.r1 },
309301 }),
310 .pseudo_cfi_undefined_r => try lower.emit(.directive, .@".cfi_undefined", &.{
302 .pseudo_cfi_undefined_r => try lower.encode(.directive, .@".cfi_undefined", &.{
311303 .{ .reg = inst.data.r.r1 },
312304 }),
313 .pseudo_cfi_same_value_r => try lower.emit(.directive, .@".cfi_same_value", &.{
305 .pseudo_cfi_same_value_r => try lower.encode(.directive, .@".cfi_same_value", &.{
314306 .{ .reg = inst.data.r.r1 },
315307 }),
316 .pseudo_cfi_remember_state_none => try lower.emit(.directive, .@".cfi_remember_state", &.{}),
317 .pseudo_cfi_restore_state_none => try lower.emit(.directive, .@".cfi_restore_state", &.{}),
318 .pseudo_cfi_escape_bytes => try lower.emit(.directive, .@".cfi_escape", &.{
308 .pseudo_cfi_remember_state_none => try lower.encode(.directive, .@".cfi_remember_state", &.{}),
309 .pseudo_cfi_restore_state_none => try lower.encode(.directive, .@".cfi_restore_state", &.{}),
310 .pseudo_cfi_escape_bytes => try lower.encode(.directive, .@".cfi_escape", &.{
319311 .{ .bytes = inst.data.bytes.get(lower.mir) },
320312 }),
321313
......@@ -327,16 +319,23 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
327319 .pseudo_dbg_leave_block_none,
328320 .pseudo_dbg_enter_inline_func,
329321 .pseudo_dbg_leave_inline_func,
330 .pseudo_dbg_local_a,
331 .pseudo_dbg_local_ai_s,
332 .pseudo_dbg_local_ai_u,
333 .pseudo_dbg_local_ai_64,
334 .pseudo_dbg_local_as,
335 .pseudo_dbg_local_aso,
336 .pseudo_dbg_local_aro,
337 .pseudo_dbg_local_af,
338 .pseudo_dbg_local_am,
322 .pseudo_dbg_arg_none,
323 .pseudo_dbg_arg_i_s,
324 .pseudo_dbg_arg_i_u,
325 .pseudo_dbg_arg_i_64,
326 .pseudo_dbg_arg_ro,
327 .pseudo_dbg_arg_fa,
328 .pseudo_dbg_arg_m,
329 .pseudo_dbg_arg_val,
339330 .pseudo_dbg_var_args_none,
331 .pseudo_dbg_var_none,
332 .pseudo_dbg_var_i_s,
333 .pseudo_dbg_var_i_u,
334 .pseudo_dbg_var_i_64,
335 .pseudo_dbg_var_ro,
336 .pseudo_dbg_var_fa,
337 .pseudo_dbg_var_m,
338 .pseudo_dbg_var_val,
340339
341340 .pseudo_dead_none,
342341 => {},
......@@ -353,7 +352,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
353352pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error {
354353 @branchHint(.cold);
355354 assert(lower.err_msg == null);
356 lower.err_msg = try Zcu.ErrorMsg.create(lower.allocator, lower.src_loc, format, args);
355 lower.err_msg = try .create(lower.allocator, lower.src_loc, format, args);
357356 return error.LowerFail;
358357}
359358
......@@ -364,7 +363,8 @@ pub fn imm(lower: *const Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
364363 .i_s,
365364 .mi_s,
366365 .rmi_s,
367 .pseudo_dbg_local_ai_s,
366 .pseudo_dbg_arg_i_s,
367 .pseudo_dbg_var_i_s,
368368 => .s(@bitCast(i)),
369369
370370 .ii,
......@@ -379,24 +379,32 @@ pub fn imm(lower: *const Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
379379 .mri,
380380 .rrm,
381381 .rrmi,
382 .pseudo_dbg_local_ai_u,
382 .pseudo_dbg_arg_i_u,
383 .pseudo_dbg_var_i_u,
383384 => .u(i),
384385
385386 .ri_64,
386 .pseudo_dbg_local_ai_64,
387387 => .u(lower.mir.extraData(Mir.Imm64, i).data.decode()),
388388
389 .pseudo_dbg_arg_i_64,
390 .pseudo_dbg_var_i_64,
391 => unreachable,
392
389393 else => unreachable,
390394 };
391395}
392396
393pub fn mem(lower: *Lower, op_index: InstOpIndex, payload: u32) Memory {
394 var m = lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();
397fn mem(lower: *Lower, op_index: InstOpIndex, payload: u32) Memory {
398 var m = lower.mir.resolveMemoryExtra(payload).decode();
395399 switch (m) {
396400 .sib => |*sib| switch (sib.base) {
397 else => {},
401 .none, .reg, .frame => {},
398402 .table => sib.disp = lower.reloc(op_index, .table, sib.disp).signed,
399403 .rip_inst => |inst_index| sib.disp = lower.reloc(op_index, .{ .inst = inst_index }, sib.disp).signed,
404 .nav => |nav| sib.disp = lower.reloc(op_index, .{ .nav = nav }, sib.disp).signed,
405 .uav => |uav| sib.disp = lower.reloc(op_index, .{ .uav = uav }, sib.disp).signed,
406 .lazy_sym => |lazy_sym| sib.disp = lower.reloc(op_index, .{ .lazy_sym = lazy_sym }, sib.disp).signed,
407 .extern_func => |extern_func| sib.disp = lower.reloc(op_index, .{ .extern_func = extern_func }, sib.disp).signed,
400408 },
401409 else => {},
402410 }
......@@ -414,177 +422,40 @@ fn reloc(lower: *Lower, op_index: InstOpIndex, target: Reloc.Target, off: i32) I
414422 return .s(0);
415423}
416424
417fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
418 const emit_prefix = prefix;
419 var emit_mnemonic = mnemonic;
420 var emit_ops_storage: [4]Operand = undefined;
421 const emit_ops = emit_ops_storage[0..ops.len];
422 for (emit_ops, ops, 0..) |*emit_op, op, op_index| {
423 emit_op.* = switch (op) {
424 else => op,
425 .mem => |mem_op| op: switch (mem_op.base()) {
426 else => op,
427 .reloc => |sym_index| {
428 assert(prefix == .none);
429 assert(mem_op.sib.disp == 0);
430 assert(mem_op.sib.scale_index.scale == 0);
431
432 if (lower.bin_file.cast(.elf)) |elf_file| {
433 const zo = elf_file.zigObjectPtr().?;
434 const elf_sym = zo.symbol(sym_index);
435
436 if (elf_sym.flags.is_tls) {
437 // TODO handle extern TLS vars, i.e., emit GD model
438 if (lower.pic) {
439 // Here, we currently assume local dynamic TLS vars, and so
440 // we emit LD model.
441 _ = lower.reloc(1, .{ .linker_tlsld = sym_index }, 0);
442 lower.result_insts[lower.result_insts_len] = try .new(.none, .lea, &.{
443 .{ .reg = .rdi },
444 .{ .mem = Memory.initRip(.none, 0) },
445 }, lower.target);
446 lower.result_insts_len += 1;
447 _ = lower.reloc(0, .{
448 .linker_extern_fn = try elf_file.getGlobalSymbol("__tls_get_addr", null),
449 }, 0);
450 lower.result_insts[lower.result_insts_len] = try .new(.none, .call, &.{
451 .{ .imm = .s(0) },
452 }, lower.target);
453 lower.result_insts_len += 1;
454 _ = lower.reloc(@intCast(op_index), .{ .linker_dtpoff = sym_index }, 0);
455 emit_mnemonic = .lea;
456 break :op .{ .mem = Memory.initSib(.none, .{
457 .base = .{ .reg = .rax },
458 .disp = std.math.minInt(i32),
459 }) };
460 } else {
461 // Since we are linking statically, we emit LE model directly.
462 lower.result_insts[lower.result_insts_len] = try .new(.none, .mov, &.{
463 .{ .reg = .rax },
464 .{ .mem = Memory.initSib(.qword, .{ .base = .{ .reg = .fs } }) },
465 }, lower.target);
466 lower.result_insts_len += 1;
467 _ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
468 emit_mnemonic = .lea;
469 break :op .{ .mem = Memory.initSib(.none, .{
470 .base = .{ .reg = .rax },
471 .disp = std.math.minInt(i32),
472 }) };
473 }
474 }
475
476 if (lower.pic) switch (mnemonic) {
477 .lea => {
478 _ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
479 if (!elf_sym.flags.is_extern_ptr) break :op .{ .mem = Memory.initRip(.none, 0) };
480 emit_mnemonic = .mov;
481 break :op .{ .mem = Memory.initRip(.ptr, 0) };
482 },
483 .mov => {
484 if (elf_sym.flags.is_extern_ptr) {
485 const reg = ops[0].reg;
486 _ = lower.reloc(1, .{ .linker_reloc = sym_index }, 0);
487 lower.result_insts[lower.result_insts_len] = try .new(.none, .mov, &.{
488 .{ .reg = reg.to64() },
489 .{ .mem = Memory.initRip(.qword, 0) },
490 }, lower.target);
491 lower.result_insts_len += 1;
492 break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{ .base = .{
493 .reg = reg.to64(),
494 } }) };
495 }
496 _ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
497 break :op .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) };
498 },
499 else => unreachable,
500 };
501 _ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
502 switch (mnemonic) {
503 .call => break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{
504 .base = .{ .reg = .ds },
505 }) },
506 .lea => {
507 emit_mnemonic = .mov;
508 break :op .{ .imm = .s(0) };
509 },
510 .mov => break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{
511 .base = .{ .reg = .ds },
512 }) },
513 else => unreachable,
514 }
515 } else if (lower.bin_file.cast(.macho)) |macho_file| {
516 const zo = macho_file.getZigObject().?;
517 const macho_sym = zo.symbols.items[sym_index];
518
519 if (macho_sym.flags.tlv) {
520 _ = lower.reloc(1, .{ .linker_reloc = sym_index }, 0);
521 lower.result_insts[lower.result_insts_len] = try .new(.none, .mov, &.{
522 .{ .reg = .rdi },
523 .{ .mem = Memory.initRip(.ptr, 0) },
524 }, lower.target);
525 lower.result_insts_len += 1;
526 lower.result_insts[lower.result_insts_len] = try .new(.none, .call, &.{
527 .{ .mem = Memory.initSib(.qword, .{ .base = .{ .reg = .rdi } }) },
528 }, lower.target);
529 lower.result_insts_len += 1;
530 emit_mnemonic = .mov;
531 break :op .{ .reg = .rax };
532 }
533
534 break :op switch (mnemonic) {
535 .lea => {
536 _ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
537 if (!macho_sym.flags.is_extern_ptr) break :op .{ .mem = Memory.initRip(.none, 0) };
538 emit_mnemonic = .mov;
539 break :op .{ .mem = Memory.initRip(.ptr, 0) };
540 },
541 .mov => {
542 if (macho_sym.flags.is_extern_ptr) {
543 const reg = ops[0].reg;
544 _ = lower.reloc(1, .{ .linker_reloc = sym_index }, 0);
545 lower.result_insts[lower.result_insts_len] = try .new(.none, .mov, &.{
546 .{ .reg = reg.to64() },
547 .{ .mem = Memory.initRip(.qword, 0) },
548 }, lower.target);
549 lower.result_insts_len += 1;
550 break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{ .base = .{
551 .reg = reg.to64(),
552 } }) };
553 }
554 _ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
555 break :op .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) };
556 },
557 else => unreachable,
558 };
559 } else {
560 return lower.fail("TODO: bin format '{s}'", .{@tagName(lower.bin_file.tag)});
561 }
562 },
563 .pcrel => |sym_index| {
564 assert(prefix == .none);
565 assert(mem_op.sib.disp == 0);
566 assert(mem_op.sib.scale_index.scale == 0);
425fn encode(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
426 lower.result_insts[lower.result_insts_len] = try .new(prefix, mnemonic, ops, lower.target);
427 lower.result_insts_len += 1;
428}
567429
568 _ = lower.reloc(@intCast(op_index), .{ .linker_pcrel = sym_index }, 0);
569 break :op switch (lower.bin_file.tag) {
570 .elf => op,
571 .macho => switch (mnemonic) {
572 .lea => .{ .mem = Memory.initRip(.none, 0) },
573 .mov => .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) },
574 else => unreachable,
575 },
576 else => |tag| return lower.fail("TODO: bin format '{s}'", .{@tagName(tag)}),
577 };
578 },
579 },
430const inst_tags_len = @typeInfo(Mir.Inst.Tag).@"enum".fields.len;
431const inst_fixes_len = @typeInfo(Mir.Inst.Fixes).@"enum".fields.len;
432/// Lookup table, indexed by `@intFromEnum(inst.tag) * inst_fixes_len + @intFromEnum(fixes)`.
433/// The value is the resulting `Mnemonic`, or `null` if the combination is not valid.
434const mnemonic_table: [inst_tags_len * inst_fixes_len]?Mnemonic = table: {
435 @setEvalBranchQuota(80_000);
436 var table: [inst_tags_len * inst_fixes_len]?Mnemonic = undefined;
437 for (0..inst_fixes_len) |fixes_i| {
438 const fixes: Mir.Inst.Fixes = @enumFromInt(fixes_i);
439 const prefix, const suffix = affix: {
440 const pattern = if (std.mem.indexOfScalar(u8, @tagName(fixes), ' ')) |i|
441 @tagName(fixes)[i + 1 ..]
442 else
443 @tagName(fixes);
444 const wildcard_idx = std.mem.indexOfScalar(u8, pattern, '_').?;
445 break :affix .{ pattern[0..wildcard_idx], pattern[wildcard_idx + 1 ..] };
580446 };
447 for (0..inst_tags_len) |inst_tag_i| {
448 const inst_tag: Mir.Inst.Tag = @enumFromInt(inst_tag_i);
449 const name = prefix ++ @tagName(inst_tag) ++ suffix;
450 const idx = inst_tag_i * inst_fixes_len + fixes_i;
451 table[idx] = if (@hasField(Mnemonic, name)) @field(Mnemonic, name) else null;
452 }
581453 }
582 lower.result_insts[lower.result_insts_len] = try .new(emit_prefix, emit_mnemonic, emit_ops, lower.target);
583 lower.result_insts_len += 1;
584}
454 break :table table;
455};
585456
586457fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
587 @setEvalBranchQuota(2_800);
458 @setEvalBranchQuota(2_000);
588459 const fixes = switch (inst.ops) {
589460 .none => inst.data.none.fixes,
590461 .inst => inst.data.inst.fixes,
......@@ -604,28 +475,27 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
604475 .rrmi => inst.data.rrix.fixes,
605476 .mi_u, .mi_s => inst.data.x.fixes,
606477 .m => inst.data.x.fixes,
607 .extern_fn_reloc, .got_reloc, .direct_reloc, .import_reloc, .tlv_reloc, .rel => ._,
478 .nav, .uav, .lazy_sym, .extern_func => ._,
608479 else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),
609480 };
610 try lower.emit(switch (fixes) {
481 try lower.encode(switch (fixes) {
611482 inline else => |tag| comptime if (std.mem.indexOfScalar(u8, @tagName(tag), ' ')) |space|
612483 @field(Prefix, @tagName(tag)[0..space])
613484 else
614485 .none,
615486 }, mnemonic: {
616 comptime var max_len = 0;
617 inline for (@typeInfo(Mnemonic).@"enum".fields) |field| max_len = @max(field.name.len, max_len);
618 var buf: [max_len]u8 = undefined;
619
487 if (mnemonic_table[@intFromEnum(inst.tag) * inst_fixes_len + @intFromEnum(fixes)]) |mnemonic| {
488 break :mnemonic mnemonic;
489 }
490 // This combination is invalid; make the theoretical mnemonic name and emit an error with it.
620491 const fixes_name = @tagName(fixes);
621492 const pattern = fixes_name[if (std.mem.indexOfScalar(u8, fixes_name, ' ')) |i| i + " ".len else 0..];
622493 const wildcard_index = std.mem.indexOfScalar(u8, pattern, '_').?;
623 const parts = .{ pattern[0..wildcard_index], @tagName(inst.tag), pattern[wildcard_index + "_".len ..] };
624 const err_msg = "unsupported mnemonic: ";
625 const mnemonic = std.fmt.bufPrint(&buf, "{s}{s}{s}", parts) catch
626 return lower.fail(err_msg ++ "'{s}{s}{s}'", parts);
627 break :mnemonic std.meta.stringToEnum(Mnemonic, mnemonic) orelse
628 return lower.fail(err_msg ++ "'{s}'", .{mnemonic});
494 return lower.fail("unsupported mnemonic: '{s}{s}{s}'", .{
495 pattern[0..wildcard_index],
496 @tagName(inst.tag),
497 pattern[wildcard_index + "_".len ..],
498 });
629499 }, switch (inst.ops) {
630500 .none => &.{},
631501 .inst => &.{
......@@ -738,22 +608,17 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
738608 .{ .mem = lower.mem(2, inst.data.rrix.payload) },
739609 .{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },
740610 },
741 .extern_fn_reloc, .rel => &.{
742 .{ .imm = lower.reloc(0, .{ .linker_extern_fn = inst.data.reloc.sym_index }, inst.data.reloc.off) },
611 .nav => &.{
612 .{ .imm = lower.reloc(0, .{ .nav = inst.data.nav.index }, inst.data.nav.off) },
743613 },
744 .got_reloc, .direct_reloc, .import_reloc => ops: {
745 const reg = inst.data.rx.r1;
746 const extra = lower.mir.extraData(bits.SymbolOffset, inst.data.rx.payload).data;
747 _ = lower.reloc(1, switch (inst.ops) {
748 .got_reloc => .{ .linker_got = extra.sym_index },
749 .direct_reloc => .{ .linker_direct = extra.sym_index },
750 .import_reloc => .{ .linker_import = extra.sym_index },
751 else => unreachable,
752 }, extra.off);
753 break :ops &.{
754 .{ .reg = reg },
755 .{ .mem = Memory.initRip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
756 };
614 .uav => &.{
615 .{ .imm = lower.reloc(0, .{ .uav = inst.data.uav }, 0) },
616 },
617 .lazy_sym => &.{
618 .{ .imm = lower.reloc(0, .{ .lazy_sym = inst.data.lazy_sym }, 0) },
619 },
620 .extern_func => &.{
621 .{ .imm = lower.reloc(0, .{ .extern_func = inst.data.extern_func }, 0) },
757622 },
758623 else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
759624 });
......@@ -773,7 +638,7 @@ fn pushPopRegList(lower: *Lower, comptime mnemonic: Mnemonic, inst: Mir.Inst) Er
773638 else => unreachable,
774639 } });
775640 while (it.next()) |i| {
776 try lower.emit(.none, mnemonic, &.{.{
641 try lower.encode(.none, mnemonic, &.{.{
777642 .reg = callee_preserved_regs[i],
778643 }});
779644 switch (mnemonic) {
......@@ -787,7 +652,7 @@ fn pushPopRegList(lower: *Lower, comptime mnemonic: Mnemonic, inst: Mir.Inst) Er
787652 .push => {
788653 var it = inst.data.reg_list.iterator(.{});
789654 while (it.next()) |i| {
790 try lower.emit(.directive, .@".cfi_rel_offset", &.{
655 try lower.encode(.directive, .@".cfi_rel_offset", &.{
791656 .{ .reg = callee_preserved_regs[i] },
792657 .{ .imm = .s(off) },
793658 });
......@@ -805,12 +670,14 @@ const page_size: i32 = 1 << 12;
805670const abi = @import("abi.zig");
806671const assert = std.debug.assert;
807672const bits = @import("bits.zig");
673const codegen = @import("../../codegen.zig");
808674const encoder = @import("encoder.zig");
809675const link = @import("../../link.zig");
810676const std = @import("std");
811677
812678const Immediate = Instruction.Immediate;
813679const Instruction = encoder.Instruction;
680const InternPool = @import("../../InternPool.zig");
814681const Lower = @This();
815682const Memory = Instruction.Memory;
816683const Mir = @import("Mir.zig");
......@@ -819,3 +686,4 @@ const Zcu = @import("../../Zcu.zig");
819686const Operand = Instruction.Operand;
820687const Prefix = Instruction.Prefix;
821688const Register = bits.Register;
689const Type = @import("../../Type.zig");
src/arch/x86_64/Mir.zig+242-82
......@@ -9,6 +9,8 @@
99instructions: std.MultiArrayList(Inst).Slice,
1010/// The meaning of this data is determined by `Inst.Tag` value.
1111extra: []const u32,
12string_bytes: []const u8,
13locals: []const Local,
1214table: []const Inst.Index,
1315frame_locs: std.MultiArrayList(FrameLoc).Slice,
1416
......@@ -1361,9 +1363,6 @@ pub const Inst = struct {
13611363 /// Immediate (byte), register operands.
13621364 /// Uses `ri` payload.
13631365 ir,
1364 /// Relative displacement operand.
1365 /// Uses `reloc` payload.
1366 rel,
13671366 /// Register, memory operands.
13681367 /// Uses `rx` payload with extra data of type `Memory`.
13691368 rm,
......@@ -1409,21 +1408,18 @@ pub const Inst = struct {
14091408 /// References another Mir instruction directly.
14101409 /// Uses `inst` payload.
14111410 inst,
1412 /// Linker relocation - external function.
1413 /// Uses `reloc` payload.
1414 extern_fn_reloc,
1415 /// Linker relocation - GOT indirection.
1416 /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
1417 got_reloc,
1418 /// Linker relocation - direct reference.
1419 /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
1420 direct_reloc,
1421 /// Linker relocation - imports table indirection (binding).
1422 /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
1423 import_reloc,
1424 /// Linker relocation - threadlocal variable via GOT indirection.
1425 /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
1426 tlv_reloc,
1411 /// References a nav.
1412 /// Uses `nav` payload.
1413 nav,
1414 /// References an uav.
1415 /// Uses `uav` payload.
1416 uav,
1417 /// References a lazy symbol.
1418 /// Uses `lazy_sym` payload.
1419 lazy_sym,
1420 /// References an external symbol.
1421 /// Uses `extern_func` payload.
1422 extern_func,
14271423
14281424 // Pseudo instructions:
14291425
......@@ -1522,6 +1518,7 @@ pub const Inst = struct {
15221518 pseudo_cfi_escape_bytes,
15231519
15241520 /// End of prologue
1521 /// Uses `none` payload.
15251522 pseudo_dbg_prologue_end_none,
15261523 /// Update debug line with is_stmt register set
15271524 /// Uses `line_column` payload.
......@@ -1530,44 +1527,70 @@ pub const Inst = struct {
15301527 /// Uses `line_column` payload.
15311528 pseudo_dbg_line_line_column,
15321529 /// Start of epilogue
1530 /// Uses `none` payload.
15331531 pseudo_dbg_epilogue_begin_none,
15341532 /// Start of lexical block
1533 /// Uses `none` payload.
15351534 pseudo_dbg_enter_block_none,
15361535 /// End of lexical block
1536 /// Uses `none` payload.
15371537 pseudo_dbg_leave_block_none,
15381538 /// Start of inline function
1539 /// Uses `ip_index` payload.
15391540 pseudo_dbg_enter_inline_func,
15401541 /// End of inline function
1542 /// Uses `ip_index` payload.
15411543 pseudo_dbg_leave_inline_func,
1542 /// Local argument or variable.
1543 /// Uses `a` payload.
1544 pseudo_dbg_local_a,
1545 /// Local argument or variable.
1546 /// Uses `ai` payload.
1547 pseudo_dbg_local_ai_s,
1548 /// Local argument or variable.
1549 /// Uses `ai` payload.
1550 pseudo_dbg_local_ai_u,
1551 /// Local argument or variable.
1552 /// Uses `ai` payload with extra data of type `Imm64`.
1553 pseudo_dbg_local_ai_64,
1554 /// Local argument or variable.
1555 /// Uses `as` payload.
1556 pseudo_dbg_local_as,
1557 /// Local argument or variable.
1558 /// Uses `ax` payload with extra data of type `bits.SymbolOffset`.
1559 pseudo_dbg_local_aso,
1560 /// Local argument or variable.
1561 /// Uses `rx` payload with extra data of type `AirOffset`.
1562 pseudo_dbg_local_aro,
1563 /// Local argument or variable.
1564 /// Uses `ax` payload with extra data of type `bits.FrameAddr`.
1565 pseudo_dbg_local_af,
1566 /// Local argument or variable.
1567 /// Uses `ax` payload with extra data of type `Memory`.
1568 pseudo_dbg_local_am,
1544 /// Local argument.
1545 /// Uses `none` payload.
1546 pseudo_dbg_arg_none,
1547 /// Local argument.
1548 /// Uses `i` payload.
1549 pseudo_dbg_arg_i_s,
1550 /// Local argument.
1551 /// Uses `i` payload.
1552 pseudo_dbg_arg_i_u,
1553 /// Local argument.
1554 /// Uses `i64` payload.
1555 pseudo_dbg_arg_i_64,
1556 /// Local argument.
1557 /// Uses `ro` payload.
1558 pseudo_dbg_arg_ro,
1559 /// Local argument.
1560 /// Uses `fa` payload.
1561 pseudo_dbg_arg_fa,
1562 /// Local argument.
1563 /// Uses `x` payload with extra data of type `Memory`.
1564 pseudo_dbg_arg_m,
1565 /// Local argument.
1566 /// Uses `ip_index` payload.
1567 pseudo_dbg_arg_val,
15691568 /// Remaining arguments are varargs.
15701569 pseudo_dbg_var_args_none,
1570 /// Local variable.
1571 /// Uses `none` payload.
1572 pseudo_dbg_var_none,
1573 /// Local variable.
1574 /// Uses `i` payload.
1575 pseudo_dbg_var_i_s,
1576 /// Local variable.
1577 /// Uses `i` payload.
1578 pseudo_dbg_var_i_u,
1579 /// Local variable.
1580 /// Uses `i64` payload.
1581 pseudo_dbg_var_i_64,
1582 /// Local variable.
1583 /// Uses `ro` payload.
1584 pseudo_dbg_var_ro,
1585 /// Local variable.
1586 /// Uses `fa` payload.
1587 pseudo_dbg_var_fa,
1588 /// Local variable.
1589 /// Uses `x` payload with extra data of type `Memory`.
1590 pseudo_dbg_var_m,
1591 /// Local variable.
1592 /// Uses `ip_index` payload.
1593 pseudo_dbg_var_val,
15711594
15721595 /// Tombstone
15731596 /// Emitter should skip this instruction.
......@@ -1584,6 +1607,7 @@ pub const Inst = struct {
15841607 inst: Index,
15851608 },
15861609 /// A 32-bit immediate value.
1610 i64: u64,
15871611 i: struct {
15881612 fixes: Fixes = ._,
15891613 i: u32,
......@@ -1683,31 +1707,18 @@ pub const Inst = struct {
16831707 return std.mem.sliceAsBytes(mir.extra[bytes.payload..])[0..bytes.len];
16841708 }
16851709 },
1686 a: struct {
1687 air_inst: Air.Inst.Index,
1688 },
1689 ai: struct {
1690 air_inst: Air.Inst.Index,
1691 i: u32,
1692 },
1693 as: struct {
1694 air_inst: Air.Inst.Index,
1695 sym_index: u32,
1696 },
1697 ax: struct {
1698 air_inst: Air.Inst.Index,
1699 payload: u32,
1700 },
1701 /// Relocation for the linker where:
1702 /// * `sym_index` is the index of the target
1703 /// * `off` is the offset from the target
1704 reloc: bits.SymbolOffset,
1710 fa: bits.FrameAddr,
1711 ro: bits.RegisterOffset,
1712 nav: bits.NavOffset,
1713 uav: InternPool.Key.Ptr.BaseAddr.Uav,
1714 lazy_sym: link.File.LazySymbol,
1715 extern_func: Mir.NullTerminatedString,
17051716 /// Debug line and column position
17061717 line_column: struct {
17071718 line: u32,
17081719 column: u32,
17091720 },
1710 func: InternPool.Index,
1721 ip_index: InternPool.Index,
17111722 /// Register list
17121723 reg_list: RegisterList,
17131724 };
......@@ -1760,13 +1771,11 @@ pub const Inst = struct {
17601771 }
17611772};
17621773
1763pub const AirOffset = struct { air_inst: Air.Inst.Index, off: i32 };
1764
17651774/// Used in conjunction with payload to transfer a list of used registers in a compact manner.
17661775pub const RegisterList = struct {
17671776 bitset: BitSet,
17681777
1769 const BitSet = IntegerBitSet(32);
1778 const BitSet = std.bit_set.IntegerBitSet(32);
17701779 const Self = @This();
17711780
17721781 pub const empty: RegisterList = .{ .bitset = .initEmpty() };
......@@ -1805,6 +1814,22 @@ pub const RegisterList = struct {
18051814 }
18061815};
18071816
1817pub const NullTerminatedString = enum(u32) {
1818 none = std.math.maxInt(u32),
1819 _,
1820
1821 pub fn toSlice(nts: NullTerminatedString, mir: *const Mir) ?[:0]const u8 {
1822 if (nts == .none) return null;
1823 const string_bytes = mir.string_bytes[@intFromEnum(nts)..];
1824 return string_bytes[0..std.mem.indexOfScalar(u8, string_bytes, 0).? :0];
1825 }
1826};
1827
1828pub const Local = struct {
1829 name: NullTerminatedString,
1830 type: InternPool.Index,
1831};
1832
18081833pub const Imm32 = struct {
18091834 imm: u32,
18101835};
......@@ -1840,11 +1865,10 @@ pub const Memory = struct {
18401865 size: bits.Memory.Size,
18411866 index: Register,
18421867 scale: bits.Memory.Scale,
1843 _: u14 = undefined,
1868 _: u13 = undefined,
18441869 };
18451870
18461871 pub fn encode(mem: bits.Memory) Memory {
1847 assert(mem.base != .reloc or mem.mod != .off);
18481872 return .{
18491873 .info = .{
18501874 .base = mem.base,
......@@ -1866,17 +1890,27 @@ pub const Memory = struct {
18661890 .none, .table => undefined,
18671891 .reg => |reg| @intFromEnum(reg),
18681892 .frame => |frame_index| @intFromEnum(frame_index),
1869 .reloc, .pcrel => |sym_index| sym_index,
18701893 .rip_inst => |inst_index| inst_index,
1894 .nav => |nav| @intFromEnum(nav),
1895 .uav => |uav| @intFromEnum(uav.val),
1896 .lazy_sym => |lazy_sym| @intFromEnum(lazy_sym.ty),
1897 .extern_func => |extern_func| @intFromEnum(extern_func),
18711898 },
18721899 .off = switch (mem.mod) {
18731900 .rm => |rm| @bitCast(rm.disp),
18741901 .off => |off| @truncate(off),
18751902 },
1876 .extra = if (mem.mod == .off)
1877 @intCast(mem.mod.off >> 32)
1878 else
1879 undefined,
1903 .extra = switch (mem.mod) {
1904 .rm => switch (mem.base) {
1905 else => undefined,
1906 .uav => |uav| @intFromEnum(uav.orig_ty),
1907 .lazy_sym => |lazy_sym| @intFromEnum(lazy_sym.kind),
1908 },
1909 .off => switch (mem.base) {
1910 .reg => @intCast(mem.mod.off >> 32),
1911 else => unreachable,
1912 },
1913 },
18801914 };
18811915 }
18821916
......@@ -1894,9 +1928,11 @@ pub const Memory = struct {
18941928 .reg => .{ .reg = @enumFromInt(mem.base) },
18951929 .frame => .{ .frame = @enumFromInt(mem.base) },
18961930 .table => .table,
1897 .reloc => .{ .reloc = mem.base },
1898 .pcrel => .{ .pcrel = mem.base },
18991931 .rip_inst => .{ .rip_inst = mem.base },
1932 .nav => .{ .nav = @enumFromInt(mem.base) },
1933 .uav => .{ .uav = .{ .val = @enumFromInt(mem.base), .orig_ty = @enumFromInt(mem.extra) } },
1934 .lazy_sym => .{ .lazy_sym = .{ .kind = @enumFromInt(mem.extra), .ty = @enumFromInt(mem.base) } },
1935 .extern_func => .{ .extern_func = @enumFromInt(mem.base) },
19001936 },
19011937 .scale_index = switch (mem.info.index) {
19021938 .none => null,
......@@ -1924,11 +1960,132 @@ pub const Memory = struct {
19241960pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
19251961 mir.instructions.deinit(gpa);
19261962 gpa.free(mir.extra);
1963 gpa.free(mir.string_bytes);
1964 gpa.free(mir.locals);
19271965 gpa.free(mir.table);
19281966 mir.frame_locs.deinit(gpa);
19291967 mir.* = undefined;
19301968}
19311969
1970pub fn emit(
1971 mir: Mir,
1972 lf: *link.File,
1973 pt: Zcu.PerThread,
1974 src_loc: Zcu.LazySrcLoc,
1975 func_index: InternPool.Index,
1976 code: *std.ArrayListUnmanaged(u8),
1977 debug_output: link.File.DebugInfoOutput,
1978) codegen.CodeGenError!void {
1979 const zcu = pt.zcu;
1980 const comp = zcu.comp;
1981 const gpa = comp.gpa;
1982 const func = zcu.funcInfo(func_index);
1983 const fn_info = zcu.typeToFunc(.fromInterned(func.ty)).?;
1984 const nav = func.owner_nav;
1985 const mod = zcu.navFileScope(nav).mod.?;
1986 var e: Emit = .{
1987 .lower = .{
1988 .target = &mod.resolved_target.result,
1989 .allocator = gpa,
1990 .mir = mir,
1991 .cc = fn_info.cc,
1992 .src_loc = src_loc,
1993 },
1994 .bin_file = lf,
1995 .pt = pt,
1996 .pic = mod.pic,
1997 .atom_index = sym: {
1998 if (lf.cast(.elf)) |ef| break :sym try ef.zigObjectPtr().?.getOrCreateMetadataForNav(zcu, nav);
1999 if (lf.cast(.macho)) |mf| break :sym try mf.getZigObject().?.getOrCreateMetadataForNav(mf, nav);
2000 if (lf.cast(.coff)) |cf| {
2001 const atom = try cf.getOrCreateAtomForNav(nav);
2002 break :sym cf.getAtom(atom).getSymbolIndex().?;
2003 }
2004 if (lf.cast(.plan9)) |p9f| break :sym try p9f.seeNav(pt, nav);
2005 unreachable;
2006 },
2007 .debug_output = debug_output,
2008 .code = code,
2009
2010 .prev_di_loc = .{
2011 .line = func.lbrace_line,
2012 .column = func.lbrace_column,
2013 .is_stmt = switch (debug_output) {
2014 .dwarf => |dwarf| dwarf.dwarf.debug_line.header.default_is_stmt,
2015 .plan9 => undefined,
2016 .none => undefined,
2017 },
2018 },
2019 .prev_di_pc = 0,
2020
2021 .code_offset_mapping = .empty,
2022 .relocs = .empty,
2023 .table_relocs = .empty,
2024 };
2025 defer e.deinit();
2026 e.emitMir() catch |err| switch (err) {
2027 error.LowerFail, error.EmitFail => return zcu.codegenFailMsg(nav, e.lower.err_msg.?),
2028 error.InvalidInstruction, error.CannotEncode => return zcu.codegenFail(nav, "emit MIR failed: {s} (Zig compiler bug)", .{@errorName(err)}),
2029 else => return zcu.codegenFail(nav, "emit MIR failed: {s}", .{@errorName(err)}),
2030 };
2031}
2032
2033pub fn emitLazy(
2034 mir: Mir,
2035 lf: *link.File,
2036 pt: Zcu.PerThread,
2037 src_loc: Zcu.LazySrcLoc,
2038 lazy_sym: link.File.LazySymbol,
2039 code: *std.ArrayListUnmanaged(u8),
2040 debug_output: link.File.DebugInfoOutput,
2041) codegen.CodeGenError!void {
2042 const zcu = pt.zcu;
2043 const comp = zcu.comp;
2044 const gpa = comp.gpa;
2045 const mod = comp.root_mod;
2046 var e: Emit = .{
2047 .lower = .{
2048 .target = &mod.resolved_target.result,
2049 .allocator = gpa,
2050 .mir = mir,
2051 .cc = .auto,
2052 .src_loc = src_loc,
2053 },
2054 .bin_file = lf,
2055 .pt = pt,
2056 .pic = mod.pic,
2057 .atom_index = sym: {
2058 if (lf.cast(.elf)) |ef| break :sym ef.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(ef, pt, lazy_sym) catch |err|
2059 return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)});
2060 if (lf.cast(.macho)) |mf| break :sym mf.getZigObject().?.getOrCreateMetadataForLazySymbol(mf, pt, lazy_sym) catch |err|
2061 return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)});
2062 if (lf.cast(.coff)) |cf| {
2063 const atom = cf.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
2064 return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)});
2065 break :sym cf.getAtom(atom).getSymbolIndex().?;
2066 }
2067 if (lf.cast(.plan9)) |p9f| break :sym p9f.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
2068 return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)});
2069 unreachable;
2070 },
2071 .debug_output = debug_output,
2072 .code = code,
2073
2074 .prev_di_loc = undefined,
2075 .prev_di_pc = undefined,
2076
2077 .code_offset_mapping = .empty,
2078 .relocs = .empty,
2079 .table_relocs = .empty,
2080 };
2081 defer e.deinit();
2082 e.emitMir() catch |err| switch (err) {
2083 error.LowerFail, error.EmitFail => return zcu.codegenFailTypeMsg(lazy_sym.ty, e.lower.err_msg.?),
2084 error.InvalidInstruction, error.CannotEncode => return zcu.codegenFailType(lazy_sym.ty, "emit MIR failed: {s} (Zig compiler bug)", .{@errorName(err)}),
2085 else => return zcu.codegenFailType(lazy_sym.ty, "emit MIR failed: {s}", .{@errorName(err)}),
2086 };
2087}
2088
19322089pub fn extraData(mir: Mir, comptime T: type, index: u32) struct { data: T, end: u32 } {
19332090 const fields = std.meta.fields(T);
19342091 var i: u32 = index;
......@@ -1937,7 +2094,7 @@ pub fn extraData(mir: Mir, comptime T: type, index: u32) struct { data: T, end:
19372094 @field(result, field.name) = switch (field.type) {
19382095 u32 => mir.extra[i],
19392096 i32, Memory.Info => @bitCast(mir.extra[i]),
1940 bits.FrameIndex, Air.Inst.Index => @enumFromInt(mir.extra[i]),
2097 bits.FrameIndex => @enumFromInt(mir.extra[i]),
19412098 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
19422099 };
19432100 i += 1;
......@@ -1958,9 +2115,10 @@ pub fn resolveFrameAddr(mir: Mir, frame_addr: bits.FrameAddr) bits.RegisterOffse
19582115 return .{ .reg = frame_loc.base, .off = frame_loc.disp + frame_addr.off };
19592116}
19602117
1961pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {
2118pub fn resolveMemoryExtra(mir: Mir, payload: u32) Memory {
2119 const mem = mir.extraData(Mir.Memory, payload).data;
19622120 return switch (mem.info.base) {
1963 .none, .reg, .table, .reloc, .pcrel, .rip_inst => mem,
2121 .none, .reg, .table, .rip_inst, .nav, .uav, .lazy_sym, .extern_func => mem,
19642122 .frame => if (mir.frame_locs.len > 0) .{
19652123 .info = .{
19662124 .base = .reg,
......@@ -1982,8 +2140,10 @@ const builtin = @import("builtin");
19822140const encoder = @import("encoder.zig");
19832141const std = @import("std");
19842142
1985const Air = @import("../../Air.zig");
1986const IntegerBitSet = std.bit_set.IntegerBitSet;
19872143const InternPool = @import("../../InternPool.zig");
19882144const Mir = @This();
19892145const Register = bits.Register;
2146const Emit = @import("Emit.zig");
2147const codegen = @import("../../codegen.zig");
2148const link = @import("../../link.zig");
2149const Zcu = @import("../../Zcu.zig");
src/arch/x86_64/bits.zig+16-12
......@@ -4,6 +4,8 @@ const expect = std.testing.expect;
44
55const Allocator = std.mem.Allocator;
66const ArrayList = std.ArrayList;
7const InternPool = @import("../../InternPool.zig");
8const link = @import("../../link.zig");
79const Mir = @import("Mir.zig");
810
911/// EFLAGS condition codes
......@@ -684,8 +686,6 @@ test "Register id - different classes" {
684686 try expect(Register.xmm0.id() == Register.ymm0.id());
685687 try expect(Register.xmm0.id() != Register.mm0.id());
686688 try expect(Register.mm0.id() != Register.st0.id());
687
688 try expect(Register.es.id() == 0b110000);
689689}
690690
691691test "Register enc - different classes" {
......@@ -750,20 +750,22 @@ pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
750750
751751pub const RegisterOffset = struct { reg: Register, off: i32 = 0 };
752752
753pub const SymbolOffset = struct { sym_index: u32, off: i32 = 0 };
753pub const NavOffset = struct { index: InternPool.Nav.Index, off: i32 = 0 };
754754
755755pub const Memory = struct {
756756 base: Base = .none,
757757 mod: Mod = .{ .rm = .{} },
758758
759 pub const Base = union(enum(u3)) {
759 pub const Base = union(enum(u4)) {
760760 none,
761761 reg: Register,
762762 frame: FrameIndex,
763763 table,
764 reloc: u32,
765 pcrel: u32,
766764 rip_inst: Mir.Inst.Index,
765 nav: InternPool.Nav.Index,
766 uav: InternPool.Key.Ptr.BaseAddr.Uav,
767 lazy_sym: link.File.LazySymbol,
768 extern_func: Mir.NullTerminatedString,
767769
768770 pub const Tag = @typeInfo(Base).@"union".tag_type.?;
769771 };
......@@ -899,7 +901,10 @@ pub const Memory = struct {
899901pub const Immediate = union(enum) {
900902 signed: i32,
901903 unsigned: u64,
902 reloc: SymbolOffset,
904 nav: NavOffset,
905 uav: InternPool.Key.Ptr.BaseAddr.Uav,
906 lazy_sym: link.File.LazySymbol,
907 extern_func: Mir.NullTerminatedString,
903908
904909 pub fn u(x: u64) Immediate {
905910 return .{ .unsigned = x };
......@@ -909,10 +914,6 @@ pub const Immediate = union(enum) {
909914 return .{ .signed = x };
910915 }
911916
912 pub fn rel(sym_off: SymbolOffset) Immediate {
913 return .{ .reloc = sym_off };
914 }
915
916917 pub fn format(
917918 imm: Immediate,
918919 comptime _: []const u8,
......@@ -921,7 +922,10 @@ pub const Immediate = union(enum) {
921922 ) @TypeOf(writer).Error!void {
922923 switch (imm) {
923924 inline else => |int| try writer.print("{d}", .{int}),
924 .reloc => |sym_off| try writer.print("Symbol({[sym_index]d}) + {[off]d}", sym_off),
925 .nav => |nav_off| try writer.print("Nav({d}) + {d}", .{ @intFromEnum(nav_off.nav), nav_off.off }),
926 .uav => |uav| try writer.print("Uav({d})", .{@intFromEnum(uav.val)}),
927 .lazy_sym => |lazy_sym| try writer.print("LazySym({s}, {d})", .{ @tagName(lazy_sym.kind), @intFromEnum(lazy_sym.ty) }),
928 .extern_func => |extern_func| try writer.print("ExternFunc({d})", .{@intFromEnum(extern_func)}),
925929 }
926930 }
927931};
src/arch/x86_64/encoder.zig+11-6
......@@ -138,7 +138,7 @@ pub const Instruction = struct {
138138 .moffs => true,
139139 .rip => false,
140140 .sib => |s| switch (s.base) {
141 .none, .frame, .table, .reloc, .pcrel, .rip_inst => false,
141 .none, .frame, .table, .rip_inst, .nav, .uav, .lazy_sym, .extern_func => false,
142142 .reg => |reg| reg.isClass(.segment),
143143 },
144144 };
......@@ -211,7 +211,7 @@ pub const Instruction = struct {
211211 .none, .imm => 0b00,
212212 .reg => |reg| @truncate(reg.enc() >> 3),
213213 .mem => |mem| switch (mem.base()) {
214 .none, .frame, .table, .reloc, .pcrel, .rip_inst => 0b00, // rsp, rbp, and rip are not extended
214 .none, .frame, .table, .rip_inst, .nav, .uav, .lazy_sym, .extern_func => 0b00, // rsp, rbp, and rip are not extended
215215 .reg => |reg| @truncate(reg.enc() >> 3),
216216 },
217217 .bytes => unreachable,
......@@ -281,9 +281,14 @@ pub const Instruction = struct {
281281 .reg => |reg| try writer.print("{s}", .{@tagName(reg)}),
282282 .frame => |frame_index| try writer.print("{}", .{frame_index}),
283283 .table => try writer.print("Table", .{}),
284 .reloc => |sym_index| try writer.print("Symbol({d})", .{sym_index}),
285 .pcrel => |sym_index| try writer.print("PcRelSymbol({d})", .{sym_index}),
286284 .rip_inst => |inst_index| try writer.print("RipInst({d})", .{inst_index}),
285 .nav => |nav| try writer.print("Nav({d})", .{@intFromEnum(nav)}),
286 .uav => |uav| try writer.print("Uav({d})", .{@intFromEnum(uav.val)}),
287 .lazy_sym => |lazy_sym| try writer.print("LazySym({s}, {d})", .{
288 @tagName(lazy_sym.kind),
289 @intFromEnum(lazy_sym.ty),
290 }),
291 .extern_func => |extern_func| try writer.print("ExternFunc({d})", .{@intFromEnum(extern_func)}),
287292 }
288293 if (mem.scaleIndex()) |si| {
289294 if (any) try writer.writeAll(" + ");
......@@ -718,11 +723,11 @@ pub const Instruction = struct {
718723 try encoder.modRm_indirectDisp32(operand_enc, 0);
719724 try encoder.disp32(undefined);
720725 } else return error.CannotEncode,
721 .reloc => if (@TypeOf(encoder).options.allow_symbols) {
726 .nav, .uav, .lazy_sym, .extern_func => if (@TypeOf(encoder).options.allow_symbols) {
722727 try encoder.modRm_indirectDisp32(operand_enc, 0);
723728 try encoder.disp32(undefined);
724729 } else return error.CannotEncode,
725 .pcrel, .rip_inst => {
730 .rip_inst => {
726731 try encoder.modRm_RIPDisp32(operand_enc);
727732 try encoder.disp32(sib.disp);
728733 },
src/codegen.zig+194-112
......@@ -85,13 +85,99 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) ?*co
8585 }
8686}
8787
88/// Every code generation backend has a different MIR representation. However, we want to pass
89/// MIR from codegen to the linker *regardless* of which backend is in use. So, we use this: a
90/// union of all MIR types. The active tag is known from the backend in use; see `AnyMir.tag`.
91pub const AnyMir = union {
92 aarch64: @import("arch/aarch64/Mir.zig"),
93 arm: @import("arch/arm/Mir.zig"),
94 powerpc: noreturn, //@import("arch/powerpc/Mir.zig"),
95 riscv64: @import("arch/riscv64/Mir.zig"),
96 sparc64: @import("arch/sparc64/Mir.zig"),
97 x86_64: @import("arch/x86_64/Mir.zig"),
98 wasm: @import("arch/wasm/Mir.zig"),
99 c: @import("codegen/c.zig").Mir,
100
101 pub inline fn tag(comptime backend: std.builtin.CompilerBackend) []const u8 {
102 return switch (backend) {
103 .stage2_aarch64 => "aarch64",
104 .stage2_arm => "arm",
105 .stage2_powerpc => "powerpc",
106 .stage2_riscv64 => "riscv64",
107 .stage2_sparc64 => "sparc64",
108 .stage2_x86_64 => "x86_64",
109 .stage2_wasm => "wasm",
110 .stage2_c => "c",
111 else => unreachable,
112 };
113 }
114
115 pub fn deinit(mir: *AnyMir, zcu: *const Zcu) void {
116 const gpa = zcu.gpa;
117 const backend = target_util.zigBackend(zcu.root_mod.resolved_target.result, zcu.comp.config.use_llvm);
118 switch (backend) {
119 else => unreachable,
120 inline .stage2_aarch64,
121 .stage2_arm,
122 .stage2_powerpc,
123 .stage2_riscv64,
124 .stage2_sparc64,
125 .stage2_x86_64,
126 .stage2_wasm,
127 .stage2_c,
128 => |backend_ct| @field(mir, tag(backend_ct)).deinit(gpa),
129 }
130 }
131};
132
133/// Runs code generation for a function. This process converts the `Air` emitted by `Sema`,
134/// alongside annotated `Liveness` data, to machine code in the form of MIR (see `AnyMir`).
135///
136/// This is supposed to be a "pure" process, but some backends are currently buggy; see
137/// `Zcu.Feature.separate_thread` for details.
88138pub fn generateFunction(
89139 lf: *link.File,
90140 pt: Zcu.PerThread,
91141 src_loc: Zcu.LazySrcLoc,
92142 func_index: InternPool.Index,
93 air: Air,
94 liveness: Air.Liveness,
143 air: *const Air,
144 liveness: *const Air.Liveness,
145) CodeGenError!AnyMir {
146 const zcu = pt.zcu;
147 const func = zcu.funcInfo(func_index);
148 const target = zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;
149 switch (target_util.zigBackend(target, false)) {
150 else => unreachable,
151 inline .stage2_aarch64,
152 .stage2_arm,
153 .stage2_powerpc,
154 .stage2_riscv64,
155 .stage2_sparc64,
156 .stage2_x86_64,
157 .stage2_wasm,
158 .stage2_c,
159 => |backend| {
160 dev.check(devFeatureForBackend(backend));
161 const CodeGen = importBackend(backend);
162 const mir = try CodeGen.generate(lf, pt, src_loc, func_index, air, liveness);
163 return @unionInit(AnyMir, AnyMir.tag(backend), mir);
164 },
165 }
166}
167
168/// Converts the MIR returned by `generateFunction` to finalized machine code to be placed in
169/// the output binary. This is called from linker implementations, and may query linker state.
170///
171/// This function is not called for the C backend, as `link.C` directly understands its MIR.
172///
173/// The `air` parameter is not supposed to exist, but some backends are currently buggy; see
174/// `Zcu.Feature.separate_thread` for details.
175pub fn emitFunction(
176 lf: *link.File,
177 pt: Zcu.PerThread,
178 src_loc: Zcu.LazySrcLoc,
179 func_index: InternPool.Index,
180 any_mir: *const AnyMir,
95181 code: *std.ArrayListUnmanaged(u8),
96182 debug_output: link.File.DebugInfoOutput,
97183) CodeGenError!void {
......@@ -108,7 +194,8 @@ pub fn generateFunction(
108194 .stage2_x86_64,
109195 => |backend| {
110196 dev.check(devFeatureForBackend(backend));
111 return importBackend(backend).generate(lf, pt, src_loc, func_index, air, liveness, code, debug_output);
197 const mir = &@field(any_mir, AnyMir.tag(backend));
198 return mir.emit(lf, pt, src_loc, func_index, code, debug_output);
112199 },
113200 }
114201}
......@@ -695,7 +782,6 @@ fn lowerUavRef(
695782 const comp = lf.comp;
696783 const target = &comp.root_mod.resolved_target.result;
697784 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
698 const is_obj = comp.config.output_mode == .Obj;
699785 const uav_val = uav.val;
700786 const uav_ty = Type.fromInterned(ip.typeOf(uav_val));
701787 const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn";
......@@ -715,21 +801,7 @@ fn lowerUavRef(
715801 dev.check(link.File.Tag.wasm.devFeature());
716802 const wasm = lf.cast(.wasm).?;
717803 assert(reloc_parent == .none);
718 if (is_obj) {
719 try wasm.out_relocs.append(gpa, .{
720 .offset = @intCast(code.items.len),
721 .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav.val) },
722 .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64,
723 .addend = @intCast(offset),
724 });
725 } else {
726 try wasm.uav_fixups.ensureUnusedCapacity(gpa, 1);
727 wasm.uav_fixups.appendAssumeCapacity(.{
728 .uavs_exe_index = try wasm.refUavExe(uav.val, uav.orig_ty),
729 .offset = @intCast(code.items.len),
730 .addend = @intCast(offset),
731 });
732 }
804 try wasm.addUavReloc(code.items.len, uav.val, uav.orig_ty, @intCast(offset));
733805 code.appendNTimesAssumeCapacity(0, ptr_width_bytes);
734806 return;
735807 },
......@@ -879,73 +951,39 @@ pub const GenResult = union(enum) {
879951 };
880952};
881953
882fn genNavRef(
954pub fn genNavRef(
883955 lf: *link.File,
884956 pt: Zcu.PerThread,
885957 src_loc: Zcu.LazySrcLoc,
886 val: Value,
887958 nav_index: InternPool.Nav.Index,
888959 target: std.Target,
889960) CodeGenError!GenResult {
890961 const zcu = pt.zcu;
891962 const ip = &zcu.intern_pool;
892 const ty = val.typeOf(zcu);
893 log.debug("genNavRef: val = {}", .{val.fmtValue(pt)});
894
895 if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) {
896 const imm: u64 = switch (@divExact(target.ptrBitWidth(), 8)) {
897 1 => 0xaa,
898 2 => 0xaaaa,
899 4 => 0xaaaaaaaa,
900 8 => 0xaaaaaaaaaaaaaaaa,
901 else => unreachable,
902 };
903 return .{ .mcv = .{ .immediate = imm } };
904 }
905
906 const comp = lf.comp;
907 const gpa = comp.gpa;
908
909 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
910 if (ty.castPtrToFn(zcu)) |fn_ty| {
911 if (zcu.typeToFunc(fn_ty).?.is_generic) {
912 return .{ .mcv = .{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? } };
913 }
914 } else if (ty.zigTypeTag(zcu) == .pointer) {
915 const elem_ty = ty.elemType2(zcu);
916 if (!elem_ty.hasRuntimeBits(zcu)) {
917 return .{ .mcv = .{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? } };
918 }
919 }
920
921963 const nav = ip.getNav(nav_index);
922 assert(!nav.isThreadlocal(ip));
964 log.debug("genNavRef({})", .{nav.fqn.fmt(ip)});
923965
924 const lib_name, const linkage, const visibility = if (nav.getExtern(ip)) |e|
925 .{ e.lib_name, e.linkage, e.visibility }
966 const lib_name, const linkage, const is_threadlocal = if (nav.getExtern(ip)) |e|
967 .{ e.lib_name, e.linkage, e.is_threadlocal and zcu.comp.config.any_non_single_threaded }
926968 else
927 .{ .none, .internal, .default };
928
929 const name = nav.name;
969 .{ .none, .internal, false };
930970 if (lf.cast(.elf)) |elf_file| {
931971 const zo = elf_file.zigObjectPtr().?;
932972 switch (linkage) {
933973 .internal => {
934974 const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index);
975 if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;
935976 return .{ .mcv = .{ .lea_symbol = sym_index } };
936977 },
937978 .strong, .weak => {
938 const sym_index = try elf_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
979 const sym_index = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
939980 switch (linkage) {
940981 .internal => unreachable,
941982 .strong => {},
942983 .weak => zo.symbol(sym_index).flags.weak = true,
943984 .link_once => unreachable,
944985 }
945 switch (visibility) {
946 .default => zo.symbol(sym_index).flags.is_extern_ptr = true,
947 .hidden, .protected => {},
948 }
986 if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;
949987 return .{ .mcv = .{ .lea_symbol = sym_index } };
950988 },
951989 .link_once => unreachable,
......@@ -955,21 +993,18 @@ fn genNavRef(
955993 switch (linkage) {
956994 .internal => {
957995 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index);
958 const sym = zo.symbols.items[sym_index];
959 return .{ .mcv = .{ .lea_symbol = sym.nlist_idx } };
996 if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;
997 return .{ .mcv = .{ .lea_symbol = sym_index } };
960998 },
961999 .strong, .weak => {
962 const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
1000 const sym_index = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
9631001 switch (linkage) {
9641002 .internal => unreachable,
9651003 .strong => {},
9661004 .weak => zo.symbols.items[sym_index].flags.weak = true,
9671005 .link_once => unreachable,
9681006 }
969 switch (visibility) {
970 .default => zo.symbols.items[sym_index].flags.is_extern_ptr = true,
971 .hidden, .protected => {},
972 }
1007 if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;
9731008 return .{ .mcv = .{ .lea_symbol = sym_index } };
9741009 },
9751010 .link_once => unreachable,
......@@ -980,12 +1015,12 @@ fn genNavRef(
9801015 .internal => {
9811016 const atom_index = try coff_file.getOrCreateAtomForNav(nav_index);
9821017 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
983 return .{ .mcv = .{ .load_got = sym_index } };
1018 return .{ .mcv = .{ .lea_symbol = sym_index } };
9841019 },
9851020 .strong, .weak => {
986 const global_index = try coff_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
987 try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT
988 return .{ .mcv = .{ .load_got = link.File.Coff.global_symbol_bit | global_index } };
1021 const global_index = try coff_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
1022 try coff_file.need_got_table.put(zcu.gpa, global_index, {}); // needs GOT
1023 return .{ .mcv = .{ .lea_symbol = global_index } };
9891024 },
9901025 .link_once => unreachable,
9911026 }
......@@ -994,11 +1029,12 @@ fn genNavRef(
9941029 const atom = p9.getAtom(atom_index);
9951030 return .{ .mcv = .{ .memory = atom.getOffsetTableAddress(p9) } };
9961031 } else {
997 const msg = try ErrorMsg.create(gpa, src_loc, "TODO genNavRef for target {}", .{target});
1032 const msg = try ErrorMsg.create(zcu.gpa, src_loc, "TODO genNavRef for target {}", .{target});
9981033 return .{ .fail = msg };
9991034 }
10001035}
10011036
1037/// deprecated legacy code path
10021038pub fn genTypedValue(
10031039 lf: *link.File,
10041040 pt: Zcu.PerThread,
......@@ -1006,45 +1042,96 @@ pub fn genTypedValue(
10061042 val: Value,
10071043 target: std.Target,
10081044) CodeGenError!GenResult {
1045 return switch (try lowerValue(pt, val, &target)) {
1046 .none => .{ .mcv = .none },
1047 .undef => .{ .mcv = .undef },
1048 .immediate => |imm| .{ .mcv = .{ .immediate = imm } },
1049 .lea_nav => |nav| genNavRef(lf, pt, src_loc, nav, target),
1050 .lea_uav => |uav| switch (try lf.lowerUav(
1051 pt,
1052 uav.val,
1053 Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),
1054 src_loc,
1055 )) {
1056 .mcv => |mcv| .{ .mcv = switch (mcv) {
1057 else => unreachable,
1058 .load_direct => |sym_index| .{ .lea_direct = sym_index },
1059 .load_symbol => |sym_index| .{ .lea_symbol = sym_index },
1060 } },
1061 .fail => |em| .{ .fail = em },
1062 },
1063 .load_uav => |uav| lf.lowerUav(
1064 pt,
1065 uav.val,
1066 Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),
1067 src_loc,
1068 ),
1069 };
1070}
1071
1072const LowerResult = union(enum) {
1073 none,
1074 undef,
1075 /// The bit-width of the immediate may be smaller than `u64`. For example, on 32-bit targets
1076 /// such as ARM, the immediate will never exceed 32-bits.
1077 immediate: u64,
1078 lea_nav: InternPool.Nav.Index,
1079 lea_uav: InternPool.Key.Ptr.BaseAddr.Uav,
1080 load_uav: InternPool.Key.Ptr.BaseAddr.Uav,
1081};
1082
1083pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allocator.Error!LowerResult {
10091084 const zcu = pt.zcu;
10101085 const ip = &zcu.intern_pool;
10111086 const ty = val.typeOf(zcu);
10121087
1013 log.debug("genTypedValue: val = {}", .{val.fmtValue(pt)});
1088 log.debug("lowerValue(@as({}, {}))", .{ ty.fmt(pt), val.fmtValue(pt) });
10141089
1015 if (val.isUndef(zcu)) return .{ .mcv = .undef };
1090 if (val.isUndef(zcu)) return .undef;
10161091
10171092 switch (ty.zigTypeTag(zcu)) {
1018 .void => return .{ .mcv = .none },
1093 .void => return .none,
10191094 .pointer => switch (ty.ptrSize(zcu)) {
10201095 .slice => {},
10211096 else => switch (val.toIntern()) {
10221097 .null_value => {
1023 return .{ .mcv = .{ .immediate = 0 } };
1098 return .{ .immediate = 0 };
10241099 },
10251100 else => switch (ip.indexToKey(val.toIntern())) {
10261101 .int => {
1027 return .{ .mcv = .{ .immediate = val.toUnsignedInt(zcu) } };
1102 return .{ .immediate = val.toUnsignedInt(zcu) };
10281103 },
10291104 .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {
1030 .nav => |nav| return genNavRef(lf, pt, src_loc, val, nav, target),
1031 .uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).hasRuntimeBits(zcu))
1032 return switch (try lf.lowerUav(
1033 pt,
1034 uav.val,
1035 Type.fromInterned(uav.orig_ty).ptrAlignment(zcu),
1036 src_loc,
1037 )) {
1038 .mcv => |mcv| return .{ .mcv = switch (mcv) {
1039 .load_direct => |sym_index| .{ .lea_direct = sym_index },
1040 .load_symbol => |sym_index| .{ .lea_symbol = sym_index },
1105 .nav => |nav| {
1106 if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) {
1107 const imm: u64 = switch (@divExact(target.ptrBitWidth(), 8)) {
1108 1 => 0xaa,
1109 2 => 0xaaaa,
1110 4 => 0xaaaaaaaa,
1111 8 => 0xaaaaaaaaaaaaaaaa,
10411112 else => unreachable,
1042 } },
1043 .fail => |em| return .{ .fail = em },
1113 };
1114 return .{ .immediate = imm };
10441115 }
1116
1117 if (ty.castPtrToFn(zcu)) |fn_ty| {
1118 if (zcu.typeToFunc(fn_ty).?.is_generic) {
1119 return .{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? };
1120 }
1121 } else if (ty.zigTypeTag(zcu) == .pointer) {
1122 const elem_ty = ty.elemType2(zcu);
1123 if (!elem_ty.hasRuntimeBits(zcu)) {
1124 return .{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? };
1125 }
1126 }
1127
1128 return .{ .lea_nav = nav };
1129 },
1130 .uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).hasRuntimeBits(zcu))
1131 return .{ .lea_uav = uav }
10451132 else
1046 return .{ .mcv = .{ .immediate = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu)
1047 .forward(@intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() | 1)) / 3)) } },
1133 return .{ .immediate = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu)
1134 .forward(@intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() | 1)) / 3)) },
10481135 else => {},
10491136 },
10501137 else => {},
......@@ -1058,39 +1145,35 @@ pub fn genTypedValue(
10581145 .signed => @bitCast(val.toSignedInt(zcu)),
10591146 .unsigned => val.toUnsignedInt(zcu),
10601147 };
1061 return .{ .mcv = .{ .immediate = unsigned } };
1148 return .{ .immediate = unsigned };
10621149 }
10631150 },
10641151 .bool => {
1065 return .{ .mcv = .{ .immediate = @intFromBool(val.toBool()) } };
1152 return .{ .immediate = @intFromBool(val.toBool()) };
10661153 },
10671154 .optional => {
10681155 if (ty.isPtrLikeOptional(zcu)) {
1069 return genTypedValue(
1070 lf,
1156 return lowerValue(
10711157 pt,
1072 src_loc,
1073 val.optionalValue(zcu) orelse return .{ .mcv = .{ .immediate = 0 } },
1158 val.optionalValue(zcu) orelse return .{ .immediate = 0 },
10741159 target,
10751160 );
10761161 } else if (ty.abiSize(zcu) == 1) {
1077 return .{ .mcv = .{ .immediate = @intFromBool(!val.isNull(zcu)) } };
1162 return .{ .immediate = @intFromBool(!val.isNull(zcu)) };
10781163 }
10791164 },
10801165 .@"enum" => {
10811166 const enum_tag = ip.indexToKey(val.toIntern()).enum_tag;
1082 return genTypedValue(
1083 lf,
1167 return lowerValue(
10841168 pt,
1085 src_loc,
10861169 Value.fromInterned(enum_tag.int),
10871170 target,
10881171 );
10891172 },
10901173 .error_set => {
10911174 const err_name = ip.indexToKey(val.toIntern()).err.name;
1092 const error_index = try pt.getErrorValue(err_name);
1093 return .{ .mcv = .{ .immediate = error_index } };
1175 const error_index = ip.getErrorValueIfExists(err_name).?;
1176 return .{ .immediate = error_index };
10941177 },
10951178 .error_union => {
10961179 const err_type = ty.errorUnionSet(zcu);
......@@ -1099,20 +1182,16 @@ pub fn genTypedValue(
10991182 // We use the error type directly as the type.
11001183 const err_int_ty = try pt.errorIntType();
11011184 switch (ip.indexToKey(val.toIntern()).error_union.val) {
1102 .err_name => |err_name| return genTypedValue(
1103 lf,
1185 .err_name => |err_name| return lowerValue(
11041186 pt,
1105 src_loc,
11061187 Value.fromInterned(try pt.intern(.{ .err = .{
11071188 .ty = err_type.toIntern(),
11081189 .name = err_name,
11091190 } })),
11101191 target,
11111192 ),
1112 .payload => return genTypedValue(
1113 lf,
1193 .payload => return lowerValue(
11141194 pt,
1115 src_loc,
11161195 try pt.intValue(err_int_ty, 0),
11171196 target,
11181197 ),
......@@ -1132,7 +1211,10 @@ pub fn genTypedValue(
11321211 else => {},
11331212 }
11341213
1135 return lf.lowerUav(pt, val.toIntern(), .none, src_loc);
1214 return .{ .load_uav = .{
1215 .val = val.toIntern(),
1216 .orig_ty = (try pt.singleConstPtrType(ty)).toIntern(),
1217 } };
11361218}
11371219
11381220pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 {
src/codegen/c.zig+123-23
......@@ -3,6 +3,7 @@ const builtin = @import("builtin");
33const assert = std.debug.assert;
44const mem = std.mem;
55const log = std.log.scoped(.c);
6const Allocator = mem.Allocator;
67
78const dev = @import("../dev.zig");
89const link = @import("../link.zig");
......@@ -30,6 +31,35 @@ pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features {
3031 }) else null; // we don't currently ask zig1 to use safe optimization modes
3132}
3233
34/// For most backends, MIR is basically a sequence of machine code instructions, perhaps with some
35/// "pseudo instructions" thrown in. For the C backend, it is instead the generated C code for a
36/// single function. We also need to track some information to get merged into the global `link.C`
37/// state, including:
38/// * The UAVs used, so declarations can be emitted in `flush`
39/// * The types used, so declarations can be emitted in `flush`
40/// * The lazy functions used, so definitions can be emitted in `flush`
41pub const Mir = struct {
42 /// This map contains all the UAVs we saw generating this function.
43 /// `link.C` will merge them into its `uavs`/`aligned_uavs` fields.
44 /// Key is the value of the UAV; value is the UAV's alignment, or
45 /// `.none` for natural alignment. The specified alignment is never
46 /// less than the natural alignment.
47 uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
48 // These remaining fields are essentially just an owned version of `link.C.AvBlock`.
49 code: []u8,
50 fwd_decl: []u8,
51 ctype_pool: CType.Pool,
52 lazy_fns: LazyFnMap,
53
54 pub fn deinit(mir: *Mir, gpa: Allocator) void {
55 mir.uavs.deinit(gpa);
56 gpa.free(mir.code);
57 gpa.free(mir.fwd_decl);
58 mir.ctype_pool.deinit(gpa);
59 mir.lazy_fns.deinit(gpa);
60 }
61};
62
3363pub const CType = @import("c/Type.zig");
3464
3565pub const CValue = union(enum) {
......@@ -671,7 +701,7 @@ pub const Object = struct {
671701
672702/// This data is available both when outputting .c code and when outputting an .h file.
673703pub const DeclGen = struct {
674 gpa: mem.Allocator,
704 gpa: Allocator,
675705 pt: Zcu.PerThread,
676706 mod: *Module,
677707 pass: Pass,
......@@ -682,10 +712,12 @@ pub const DeclGen = struct {
682712 error_msg: ?*Zcu.ErrorMsg,
683713 ctype_pool: CType.Pool,
684714 scratch: std.ArrayListUnmanaged(u32),
685 /// Keeps track of anonymous decls that need to be rendered before this
686 /// (named) Decl in the output C code.
687 uav_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.AvBlock),
688 aligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
715 /// This map contains all the UAVs we saw generating this function.
716 /// `link.C` will merge them into its `uavs`/`aligned_uavs` fields.
717 /// Key is the value of the UAV; value is the UAV's alignment, or
718 /// `.none` for natural alignment. The specified alignment is never
719 /// less than the natural alignment.
720 uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
689721
690722 pub const Pass = union(enum) {
691723 nav: InternPool.Nav.Index,
......@@ -753,21 +785,17 @@ pub const DeclGen = struct {
753785 // Indicate that the anon decl should be rendered to the output so that
754786 // our reference above is not undefined.
755787 const ptr_type = ip.indexToKey(uav.orig_ty).ptr_type;
756 const gop = try dg.uav_deps.getOrPut(dg.gpa, uav.val);
757 if (!gop.found_existing) gop.value_ptr.* = .{};
758
759 // Only insert an alignment entry if the alignment is greater than ABI
760 // alignment. If there is already an entry, keep the greater alignment.
761 const explicit_alignment = ptr_type.flags.alignment;
762 if (explicit_alignment != .none) {
763 const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(zcu);
764 if (explicit_alignment.order(abi_alignment).compare(.gt)) {
765 const aligned_gop = try dg.aligned_uavs.getOrPut(dg.gpa, uav.val);
766 aligned_gop.value_ptr.* = if (aligned_gop.found_existing)
767 aligned_gop.value_ptr.maxStrict(explicit_alignment)
768 else
769 explicit_alignment;
770 }
788 const gop = try dg.uavs.getOrPut(dg.gpa, uav.val);
789 if (!gop.found_existing) gop.value_ptr.* = .none;
790 // If there is an explicit alignment, greater than the current one, use it.
791 // Note that we intentionally start at `.none`, so `gop.value_ptr.*` is never
792 // underaligned, so we don't need to worry about the `.none` case here.
793 if (ptr_type.flags.alignment != .none) {
794 // Resolve the current alignment so we can choose the bigger one.
795 const cur_alignment: Alignment = if (gop.value_ptr.* == .none) abi: {
796 break :abi Type.fromInterned(ptr_type.child).abiAlignment(zcu);
797 } else gop.value_ptr.*;
798 gop.value_ptr.* = cur_alignment.maxStrict(ptr_type.flags.alignment);
771799 }
772800 }
773801
......@@ -2895,7 +2923,79 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
28952923 }
28962924}
28972925
2898pub fn genFunc(f: *Function) !void {
2926pub fn generate(
2927 lf: *link.File,
2928 pt: Zcu.PerThread,
2929 src_loc: Zcu.LazySrcLoc,
2930 func_index: InternPool.Index,
2931 air: *const Air,
2932 liveness: *const Air.Liveness,
2933) @import("../codegen.zig").CodeGenError!Mir {
2934 const zcu = pt.zcu;
2935 const gpa = zcu.gpa;
2936
2937 _ = src_loc;
2938 assert(lf.tag == .c);
2939
2940 const func = zcu.funcInfo(func_index);
2941
2942 var function: Function = .{
2943 .value_map = .init(gpa),
2944 .air = air.*,
2945 .liveness = liveness.*,
2946 .func_index = func_index,
2947 .object = .{
2948 .dg = .{
2949 .gpa = gpa,
2950 .pt = pt,
2951 .mod = zcu.navFileScope(func.owner_nav).mod.?,
2952 .error_msg = null,
2953 .pass = .{ .nav = func.owner_nav },
2954 .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,
2955 .expected_block = null,
2956 .fwd_decl = .init(gpa),
2957 .ctype_pool = .empty,
2958 .scratch = .empty,
2959 .uavs = .empty,
2960 },
2961 .code = .init(gpa),
2962 .indent_writer = undefined, // set later so we can get a pointer to object.code
2963 },
2964 .lazy_fns = .empty,
2965 };
2966 defer {
2967 function.object.code.deinit();
2968 function.object.dg.fwd_decl.deinit();
2969 function.object.dg.ctype_pool.deinit(gpa);
2970 function.object.dg.scratch.deinit(gpa);
2971 function.object.dg.uavs.deinit(gpa);
2972 function.deinit();
2973 }
2974 try function.object.dg.ctype_pool.init(gpa);
2975 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
2976
2977 genFunc(&function) catch |err| switch (err) {
2978 error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.object.dg.error_msg.?),
2979 error.OutOfMemory => |e| return e,
2980 };
2981
2982 var mir: Mir = .{
2983 .uavs = .empty,
2984 .code = &.{},
2985 .fwd_decl = &.{},
2986 .ctype_pool = .empty,
2987 .lazy_fns = .empty,
2988 };
2989 errdefer mir.deinit(gpa);
2990 mir.uavs = function.object.dg.uavs.move();
2991 mir.code = try function.object.code.toOwnedSlice();
2992 mir.fwd_decl = try function.object.dg.fwd_decl.toOwnedSlice();
2993 mir.ctype_pool = function.object.dg.ctype_pool.move();
2994 mir.lazy_fns = function.lazy_fns.move();
2995 return mir;
2996}
2997
2998fn genFunc(f: *Function) !void {
28992999 const tracy = trace(@src());
29003000 defer tracy.end();
29013001
......@@ -8482,7 +8582,7 @@ fn iterateBigTomb(f: *Function, inst: Air.Inst.Index) BigTomb {
84828582
84838583/// A naive clone of this map would create copies of the ArrayList which is
84848584/// stored in the values. This function additionally clones the values.
8485fn cloneFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) !LocalsMap {
8585fn cloneFreeLocalsMap(gpa: Allocator, map: *LocalsMap) !LocalsMap {
84868586 var cloned = try map.clone(gpa);
84878587 const values = cloned.values();
84888588 var i: usize = 0;
......@@ -8499,7 +8599,7 @@ fn cloneFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) !LocalsMap {
84998599 return cloned;
85008600}
85018601
8502fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void {
8602fn deinitFreeLocalsMap(gpa: Allocator, map: *LocalsMap) void {
85038603 for (map.values()) |*value| {
85048604 value.deinit(gpa);
85058605 }
src/codegen/llvm.zig+41-17
......@@ -1121,8 +1121,8 @@ pub const Object = struct {
11211121 o: *Object,
11221122 pt: Zcu.PerThread,
11231123 func_index: InternPool.Index,
1124 air: Air,
1125 liveness: Air.Liveness,
1124 air: *const Air,
1125 liveness: *const Air.Liveness,
11261126 ) !void {
11271127 assert(std.meta.eql(pt, o.pt));
11281128 const zcu = pt.zcu;
......@@ -1479,8 +1479,8 @@ pub const Object = struct {
14791479
14801480 var fg: FuncGen = .{
14811481 .gpa = gpa,
1482 .air = air,
1483 .liveness = liveness,
1482 .air = air.*,
1483 .liveness = liveness.*,
14841484 .ng = &ng,
14851485 .wip = wip,
14861486 .is_naked = fn_info.cc == .naked,
......@@ -1506,10 +1506,9 @@ pub const Object = struct {
15061506 deinit_wip = false;
15071507
15081508 fg.genBody(air.getMainBody(), .poi) catch |err| switch (err) {
1509 error.CodegenFail => {
1510 try zcu.failed_codegen.put(gpa, func.owner_nav, ng.err_msg.?);
1511 ng.err_msg = null;
1512 return;
1509 error.CodegenFail => switch (zcu.codegenFailMsg(func.owner_nav, ng.err_msg.?)) {
1510 error.CodegenFail => return,
1511 error.OutOfMemory => |e| return e,
15131512 },
15141513 else => |e| return e,
15151514 };
......@@ -1561,10 +1560,9 @@ pub const Object = struct {
15611560 .err_msg = null,
15621561 };
15631562 ng.genDecl() catch |err| switch (err) {
1564 error.CodegenFail => {
1565 try pt.zcu.failed_codegen.put(pt.zcu.gpa, nav_index, ng.err_msg.?);
1566 ng.err_msg = null;
1567 return;
1563 error.CodegenFail => switch (pt.zcu.codegenFailMsg(nav_index, ng.err_msg.?)) {
1564 error.CodegenFail => return,
1565 error.OutOfMemory => |e| return e,
15681566 },
15691567 else => |e| return e,
15701568 };
......@@ -1586,6 +1584,27 @@ pub const Object = struct {
15861584 const global_index = self.nav_map.get(nav_index).?;
15871585 const comp = zcu.comp;
15881586
1587 // If we're on COFF and linking with LLD, the linker cares about our exports to determine the subsystem in use.
1588 coff_export_flags: {
1589 const lf = comp.bin_file orelse break :coff_export_flags;
1590 const lld = lf.cast(.lld) orelse break :coff_export_flags;
1591 const coff = switch (lld.ofmt) {
1592 .elf, .wasm => break :coff_export_flags,
1593 .coff => |*coff| coff,
1594 };
1595 if (!ip.isFunctionType(ip.getNav(nav_index).typeOf(ip))) break :coff_export_flags;
1596 const flags = &coff.lld_export_flags;
1597 for (export_indices) |export_index| {
1598 const name = export_index.ptr(zcu).opts.name;
1599 if (name.eqlSlice("main", ip)) flags.c_main = true;
1600 if (name.eqlSlice("WinMain", ip)) flags.winmain = true;
1601 if (name.eqlSlice("wWinMain", ip)) flags.wwinmain = true;
1602 if (name.eqlSlice("WinMainCRTStartup", ip)) flags.winmain_crt_startup = true;
1603 if (name.eqlSlice("wWinMainCRTStartup", ip)) flags.wwinmain_crt_startup = true;
1604 if (name.eqlSlice("DllMainCRTStartup", ip)) flags.dllmain_crt_startup = true;
1605 }
1606 }
1607
15891608 if (export_indices.len != 0) {
15901609 return updateExportedGlobal(self, zcu, global_index, export_indices);
15911610 } else {
......@@ -9490,15 +9509,21 @@ pub const FuncGen = struct {
94909509
94919510 const inst_ty = self.typeOfIndex(inst);
94929511
9493 const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
9494 if (name == .none) return arg_val;
9495
94969512 const func = zcu.funcInfo(zcu.navValue(self.ng.nav_index).toIntern());
9513 const func_zir = func.zir_body_inst.resolveFull(&zcu.intern_pool).?;
9514 const file = zcu.fileByIndex(func_zir.file);
9515
9516 const mod = file.mod.?;
9517 if (mod.strip) return arg_val;
9518 const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
9519 const zir = &file.zir.?;
9520 const name = zir.nullTerminatedString(zir.getParamName(zir.getParamBody(func_zir.inst)[arg.zir_param_index]).?);
9521
94979522 const lbrace_line = zcu.navSrcLine(func.owner_nav) + func.lbrace_line + 1;
94989523 const lbrace_col = func.lbrace_column + 1;
94999524
95009525 const debug_parameter = try o.builder.debugParameter(
9501 try o.builder.metadataString(name.toSlice(self.air)),
9526 try o.builder.metadataString(name),
95029527 self.file,
95039528 self.scope,
95049529 lbrace_line,
......@@ -9516,7 +9541,6 @@ pub const FuncGen = struct {
95169541 },
95179542 };
95189543
9519 const mod = self.ng.ownerModule();
95209544 if (isByRef(inst_ty, zcu)) {
95219545 _ = try self.wip.callIntrinsic(
95229546 .normal,
src/codegen/spirv.zig+6-5
......@@ -230,8 +230,9 @@ pub const Object = struct {
230230 defer nav_gen.deinit();
231231
232232 nav_gen.genNav(do_codegen) catch |err| switch (err) {
233 error.CodegenFail => {
234 try zcu.failed_codegen.put(gpa, nav_index, nav_gen.error_msg.?);
233 error.CodegenFail => switch (zcu.codegenFailMsg(nav_index, nav_gen.error_msg.?)) {
234 error.CodegenFail => {},
235 error.OutOfMemory => |e| return e,
235236 },
236237 else => |other| {
237238 // There might be an error that happened *after* self.error_msg
......@@ -249,12 +250,12 @@ pub const Object = struct {
249250 self: *Object,
250251 pt: Zcu.PerThread,
251252 func_index: InternPool.Index,
252 air: Air,
253 liveness: Air.Liveness,
253 air: *const Air,
254 liveness: *const Air.Liveness,
254255 ) !void {
255256 const nav = pt.zcu.funcInfo(func_index).owner_nav;
256257 // TODO: Separate types for generating decls and functions?
257 try self.genNav(pt, nav, air, liveness, true);
258 try self.genNav(pt, nav, air.*, liveness.*, true);
258259 }
259260
260261 pub fn updateNav(
src/codegen/spirv/Section.zig-2
......@@ -386,8 +386,6 @@ test "SPIR-V Section emit() - string" {
386386}
387387
388388test "SPIR-V Section emit() - extended mask" {
389 if (@import("builtin").zig_backend == .stage1) return error.SkipZigTest;
390
391389 var section = Section{};
392390 defer section.deinit(std.testing.allocator);
393391
src/dev.zig+9
......@@ -25,6 +25,9 @@ pub const Env = enum {
2525 /// - `zig build-* -fno-emit-bin`
2626 sema,
2727
28 /// - `zig build-* -ofmt=c`
29 cbe,
30
2831 /// - sema
2932 /// - `zig build-* -fincremental -fno-llvm -fno-lld -target x86_64-linux --listen=-`
3033 @"x86_64-linux",
......@@ -144,6 +147,12 @@ pub const Env = enum {
144147 => true,
145148 else => Env.ast_gen.supports(feature),
146149 },
150 .cbe => switch (feature) {
151 .c_backend,
152 .c_linker,
153 => true,
154 else => Env.sema.supports(feature),
155 },
147156 .@"x86_64-linux" => switch (feature) {
148157 .build_command,
149158 .stdio_listen,
src/libs/freebsd.zig+6-9
......@@ -985,7 +985,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
985985 assert(comp.freebsd_so_files == null);
986986 comp.freebsd_so_files = so_files;
987987
988 var task_buffer: [libs.len]link.Task = undefined;
988 var task_buffer: [libs.len]link.PrelinkTask = undefined;
989989 var task_buffer_i: usize = 0;
990990
991991 {
......@@ -1004,7 +1004,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
10041004 }
10051005 }
10061006
1007 comp.queueLinkTasks(task_buffer[0..task_buffer_i]);
1007 comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]);
10081008}
10091009
10101010fn buildSharedLib(
......@@ -1019,10 +1019,6 @@ fn buildSharedLib(
10191019 defer tracy.end();
10201020
10211021 const basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover });
1022 const emit_bin = Compilation.EmitLoc{
1023 .directory = bin_directory,
1024 .basename = basename,
1025 };
10261022 const version: Version = .{ .major = lib.sover, .minor = 0, .patch = 0 };
10271023 const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?);
10281024 const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename;
......@@ -1077,13 +1073,14 @@ fn buildSharedLib(
10771073 .dirs = comp.dirs.withoutLocalCache(),
10781074 .thread_pool = comp.thread_pool,
10791075 .self_exe_path = comp.self_exe_path,
1080 .cache_mode = .incremental,
1076 // Because we manually cache the whole set of objects, we don't cache the individual objects
1077 // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path.
1078 .cache_mode = .none,
10811079 .config = config,
10821080 .root_mod = root_mod,
10831081 .root_name = lib.name,
10841082 .libc_installation = comp.libc_installation,
1085 .emit_bin = emit_bin,
1086 .emit_h = null,
1083 .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) },
10871084 .verbose_cc = comp.verbose_cc,
10881085 .verbose_link = comp.verbose_link,
10891086 .verbose_air = comp.verbose_air,
src/libs/glibc.zig+6-9
......@@ -1148,7 +1148,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
11481148 assert(comp.glibc_so_files == null);
11491149 comp.glibc_so_files = so_files;
11501150
1151 var task_buffer: [libs.len]link.Task = undefined;
1151 var task_buffer: [libs.len]link.PrelinkTask = undefined;
11521152 var task_buffer_i: usize = 0;
11531153
11541154 {
......@@ -1170,7 +1170,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
11701170 }
11711171 }
11721172
1173 comp.queueLinkTasks(task_buffer[0..task_buffer_i]);
1173 comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]);
11741174}
11751175
11761176fn buildSharedLib(
......@@ -1185,10 +1185,6 @@ fn buildSharedLib(
11851185 defer tracy.end();
11861186
11871187 const basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover });
1188 const emit_bin = Compilation.EmitLoc{
1189 .directory = bin_directory,
1190 .basename = basename,
1191 };
11921188 const version: Version = .{ .major = lib.sover, .minor = 0, .patch = 0 };
11931189 const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?);
11941190 const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename;
......@@ -1243,13 +1239,14 @@ fn buildSharedLib(
12431239 .dirs = comp.dirs.withoutLocalCache(),
12441240 .thread_pool = comp.thread_pool,
12451241 .self_exe_path = comp.self_exe_path,
1246 .cache_mode = .incremental,
1242 // Because we manually cache the whole set of objects, we don't cache the individual objects
1243 // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path.
1244 .cache_mode = .none,
12471245 .config = config,
12481246 .root_mod = root_mod,
12491247 .root_name = lib.name,
12501248 .libc_installation = comp.libc_installation,
1251 .emit_bin = emit_bin,
1252 .emit_h = null,
1249 .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) },
12531250 .verbose_cc = comp.verbose_cc,
12541251 .verbose_link = comp.verbose_link,
12551252 .verbose_air = comp.verbose_air,
src/libs/libcxx.zig+4-28
......@@ -122,17 +122,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
122122 const output_mode = .Lib;
123123 const link_mode = .static;
124124 const target = comp.root_mod.resolved_target.result;
125 const basename = try std.zig.binNameAlloc(arena, .{
126 .root_name = root_name,
127 .target = target,
128 .output_mode = output_mode,
129 .link_mode = link_mode,
130 });
131
132 const emit_bin = Compilation.EmitLoc{
133 .directory = null, // Put it in the cache directory.
134 .basename = basename,
135 };
136125
137126 const cxxabi_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxxabi", "include" });
138127 const cxx_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxx", "include" });
......@@ -271,8 +260,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
271260 .root_name = root_name,
272261 .thread_pool = comp.thread_pool,
273262 .libc_installation = comp.libc_installation,
274 .emit_bin = emit_bin,
275 .emit_h = null,
263 .emit_bin = .yes_cache,
276264 .c_source_files = c_source_files.items,
277265 .verbose_cc = comp.verbose_cc,
278266 .verbose_link = comp.verbose_link,
......@@ -308,7 +296,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
308296 assert(comp.libcxx_static_lib == null);
309297 const crt_file = try sub_compilation.toCrtFile();
310298 comp.libcxx_static_lib = crt_file;
311 comp.queueLinkTaskMode(crt_file.full_object_path, &config);
299 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
312300}
313301
314302pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void {
......@@ -327,17 +315,6 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
327315 const output_mode = .Lib;
328316 const link_mode = .static;
329317 const target = comp.root_mod.resolved_target.result;
330 const basename = try std.zig.binNameAlloc(arena, .{
331 .root_name = root_name,
332 .target = target,
333 .output_mode = output_mode,
334 .link_mode = link_mode,
335 });
336
337 const emit_bin = Compilation.EmitLoc{
338 .directory = null, // Put it in the cache directory.
339 .basename = basename,
340 };
341318
342319 const cxxabi_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxxabi", "include" });
343320 const cxx_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxx", "include" });
......@@ -467,8 +444,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
467444 .root_name = root_name,
468445 .thread_pool = comp.thread_pool,
469446 .libc_installation = comp.libc_installation,
470 .emit_bin = emit_bin,
471 .emit_h = null,
447 .emit_bin = .yes_cache,
472448 .c_source_files = c_source_files.items,
473449 .verbose_cc = comp.verbose_cc,
474450 .verbose_link = comp.verbose_link,
......@@ -504,7 +480,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
504480 assert(comp.libcxxabi_static_lib == null);
505481 const crt_file = try sub_compilation.toCrtFile();
506482 comp.libcxxabi_static_lib = crt_file;
507 comp.queueLinkTaskMode(crt_file.full_object_path, &config);
483 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
508484}
509485
510486pub fn addCxxArgs(
src/libs/libtsan.zig+2-8
......@@ -45,11 +45,6 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
4545 .link_mode = link_mode,
4646 });
4747
48 const emit_bin = Compilation.EmitLoc{
49 .directory = null, // Put it in the cache directory.
50 .basename = basename,
51 };
52
5348 const optimize_mode = comp.compilerRtOptMode();
5449 const strip = comp.compilerRtStrip();
5550 const unwind_tables: std.builtin.UnwindTables =
......@@ -287,8 +282,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
287282 .root_mod = root_mod,
288283 .root_name = root_name,
289284 .libc_installation = comp.libc_installation,
290 .emit_bin = emit_bin,
291 .emit_h = null,
285 .emit_bin = .yes_cache,
292286 .c_source_files = c_source_files.items,
293287 .verbose_cc = comp.verbose_cc,
294288 .verbose_link = comp.verbose_link,
......@@ -325,7 +319,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
325319 };
326320
327321 const crt_file = try sub_compilation.toCrtFile();
328 comp.queueLinkTaskMode(crt_file.full_object_path, &config);
322 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
329323 assert(comp.tsan_lib == null);
330324 comp.tsan_lib = crt_file;
331325}
src/libs/libunwind.zig+3-14
......@@ -31,7 +31,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
3131 const unwind_tables: std.builtin.UnwindTables =
3232 if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .@"async";
3333 const config = Compilation.Config.resolve(.{
34 .output_mode = .Lib,
34 .output_mode = output_mode,
3535 .resolved_target = comp.root_mod.resolved_target,
3636 .is_test = false,
3737 .have_zcu = false,
......@@ -85,17 +85,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
8585 };
8686
8787 const root_name = "unwind";
88 const link_mode = .static;
89 const basename = try std.zig.binNameAlloc(arena, .{
90 .root_name = root_name,
91 .target = target,
92 .output_mode = output_mode,
93 .link_mode = link_mode,
94 });
95 const emit_bin = Compilation.EmitLoc{
96 .directory = null, // Put it in the cache directory.
97 .basename = basename,
98 };
9988 var c_source_files: [unwind_src_list.len]Compilation.CSourceFile = undefined;
10089 for (unwind_src_list, 0..) |unwind_src, i| {
10190 var cflags = std.ArrayList([]const u8).init(arena);
......@@ -160,7 +149,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
160149 .main_mod = null,
161150 .thread_pool = comp.thread_pool,
162151 .libc_installation = comp.libc_installation,
163 .emit_bin = emit_bin,
152 .emit_bin = .yes_cache,
164153 .function_sections = comp.function_sections,
165154 .c_source_files = &c_source_files,
166155 .verbose_cc = comp.verbose_cc,
......@@ -195,7 +184,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
195184 };
196185
197186 const crt_file = try sub_compilation.toCrtFile();
198 comp.queueLinkTaskMode(crt_file.full_object_path, &config);
187 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
199188 assert(comp.libunwind_static_lib == null);
200189 comp.libunwind_static_lib = crt_file;
201190}
src/libs/musl.zig+2-3
......@@ -252,8 +252,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
252252 .thread_pool = comp.thread_pool,
253253 .root_name = "c",
254254 .libc_installation = comp.libc_installation,
255 .emit_bin = .{ .directory = null, .basename = "libc.so" },
256 .emit_h = null,
255 .emit_bin = .yes_cache,
257256 .verbose_cc = comp.verbose_cc,
258257 .verbose_link = comp.verbose_link,
259258 .verbose_air = comp.verbose_air,
......@@ -278,7 +277,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
278277 errdefer comp.gpa.free(basename);
279278
280279 const crt_file = try sub_compilation.toCrtFile();
281 comp.queueLinkTaskMode(crt_file.full_object_path, &config);
280 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
282281 {
283282 comp.mutex.lock();
284283 defer comp.mutex.unlock();
src/libs/netbsd.zig+6-9
......@@ -650,7 +650,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
650650 assert(comp.netbsd_so_files == null);
651651 comp.netbsd_so_files = so_files;
652652
653 var task_buffer: [libs.len]link.Task = undefined;
653 var task_buffer: [libs.len]link.PrelinkTask = undefined;
654654 var task_buffer_i: usize = 0;
655655
656656 {
......@@ -669,7 +669,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
669669 }
670670 }
671671
672 comp.queueLinkTasks(task_buffer[0..task_buffer_i]);
672 comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]);
673673}
674674
675675fn buildSharedLib(
......@@ -684,10 +684,6 @@ fn buildSharedLib(
684684 defer tracy.end();
685685
686686 const basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover });
687 const emit_bin = Compilation.EmitLoc{
688 .directory = bin_directory,
689 .basename = basename,
690 };
691687 const version: Version = .{ .major = lib.sover, .minor = 0, .patch = 0 };
692688 const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?);
693689 const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename;
......@@ -741,13 +737,14 @@ fn buildSharedLib(
741737 .dirs = comp.dirs.withoutLocalCache(),
742738 .thread_pool = comp.thread_pool,
743739 .self_exe_path = comp.self_exe_path,
744 .cache_mode = .incremental,
740 // Because we manually cache the whole set of objects, we don't cache the individual objects
741 // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path.
742 .cache_mode = .none,
745743 .config = config,
746744 .root_mod = root_mod,
747745 .root_name = lib.name,
748746 .libc_installation = comp.libc_installation,
749 .emit_bin = emit_bin,
750 .emit_h = null,
747 .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) },
751748 .verbose_cc = comp.verbose_cc,
752749 .verbose_link = comp.verbose_link,
753750 .verbose_air = comp.verbose_air,
src/link.zig+233-447
......@@ -8,7 +8,6 @@ const log = std.log.scoped(.link);
88const trace = @import("tracy.zig").trace;
99const wasi_libc = @import("libs/wasi_libc.zig");
1010
11const Air = @import("Air.zig");
1211const Allocator = std.mem.Allocator;
1312const Cache = std.Build.Cache;
1413const Path = std.Build.Cache.Path;
......@@ -19,15 +18,13 @@ const Zcu = @import("Zcu.zig");
1918const InternPool = @import("InternPool.zig");
2019const Type = @import("Type.zig");
2120const Value = @import("Value.zig");
22const LlvmObject = @import("codegen/llvm.zig").Object;
23const lldMain = @import("main.zig").lldMain;
2421const Package = @import("Package.zig");
2522const dev = @import("dev.zig");
26const ThreadSafeQueue = @import("ThreadSafeQueue.zig").ThreadSafeQueue;
2723const target_util = @import("target.zig");
2824const codegen = @import("codegen.zig");
2925
3026pub const LdScript = @import("link/LdScript.zig");
27pub const Queue = @import("link/Queue.zig");
3128
3229pub const Diags = struct {
3330 /// Stored here so that function definitions can distinguish between
......@@ -386,10 +383,11 @@ pub const File = struct {
386383 emit: Path,
387384
388385 file: ?fs.File,
389 /// When linking with LLD, this linker code will output an object file only at
390 /// this location, and then this path can be placed on the LLD linker line.
391 zcu_object_sub_path: ?[]const u8 = null,
392 disable_lld_caching: bool,
386 /// When using the LLVM backend, the emitted object is written to a file with this name. This
387 /// object file then becomes a normal link input to LLD or a self-hosted linker.
388 ///
389 /// To convert this to an actual path, see `Compilation.resolveEmitPath` (with `kind == .temp`).
390 zcu_object_basename: ?[]const u8 = null,
393391 gc_sections: bool,
394392 print_gc_sections: bool,
395393 build_id: std.zig.BuildId,
......@@ -425,7 +423,7 @@ pub const File = struct {
425423 tsaware: bool,
426424 nxcompat: bool,
427425 dynamicbase: bool,
428 compress_debug_sections: Elf.CompressDebugSections,
426 compress_debug_sections: Lld.Elf.CompressDebugSections,
429427 bind_global_refs_locally: bool,
430428 import_symbols: bool,
431429 import_table: bool,
......@@ -436,9 +434,8 @@ pub const File = struct {
436434 export_symbol_names: []const []const u8,
437435 global_base: ?u64,
438436 build_id: std.zig.BuildId,
439 disable_lld_caching: bool,
440 hash_style: Elf.HashStyle,
441 sort_section: ?Elf.SortSection,
437 hash_style: Lld.Elf.HashStyle,
438 sort_section: ?Lld.Elf.SortSection,
442439 major_subsystem_version: ?u16,
443440 minor_subsystem_version: ?u16,
444441 gc_sections: ?bool,
......@@ -522,12 +519,20 @@ pub const File = struct {
522519 emit: Path,
523520 options: OpenOptions,
524521 ) !*File {
522 if (comp.config.use_lld) {
523 dev.check(.lld_linker);
524 assert(comp.zcu == null or comp.config.use_llvm);
525 // LLD does not support incremental linking.
526 const lld: *Lld = try .createEmpty(arena, comp, emit, options);
527 return &lld.base;
528 }
525529 switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
526530 inline else => |tag| {
527531 dev.check(tag.devFeature());
528532 const ptr = try tag.Type().open(arena, comp, emit, options);
529533 return &ptr.base;
530534 },
535 .lld => unreachable, // not known from ofmt
531536 }
532537 }
533538
......@@ -537,12 +542,19 @@ pub const File = struct {
537542 emit: Path,
538543 options: OpenOptions,
539544 ) !*File {
545 if (comp.config.use_lld) {
546 dev.check(.lld_linker);
547 assert(comp.zcu == null or comp.config.use_llvm);
548 const lld: *Lld = try .createEmpty(arena, comp, emit, options);
549 return &lld.base;
550 }
540551 switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
541552 inline else => |tag| {
542553 dev.check(tag.devFeature());
543554 const ptr = try tag.Type().createEmpty(arena, comp, emit, options);
544555 return &ptr.base;
545556 },
557 .lld => unreachable, // not known from ofmt
546558 }
547559 }
548560
......@@ -555,6 +567,7 @@ pub const File = struct {
555567 const comp = base.comp;
556568 const gpa = comp.gpa;
557569 switch (base.tag) {
570 .lld => assert(base.file == null),
558571 .coff, .elf, .macho, .plan9, .wasm, .goff, .xcoff => {
559572 if (base.file != null) return;
560573 dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
......@@ -587,13 +600,12 @@ pub const File = struct {
587600 }
588601 }
589602 }
590 const use_lld = build_options.have_llvm and comp.config.use_lld;
591603 const output_mode = comp.config.output_mode;
592604 const link_mode = comp.config.link_mode;
593605 base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
594606 .truncate = false,
595607 .read = true,
596 .mode = determineMode(use_lld, output_mode, link_mode),
608 .mode = determineMode(output_mode, link_mode),
597609 });
598610 },
599611 .c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }),
......@@ -619,7 +631,6 @@ pub const File = struct {
619631 const comp = base.comp;
620632 const output_mode = comp.config.output_mode;
621633 const link_mode = comp.config.link_mode;
622 const use_lld = build_options.have_llvm and comp.config.use_lld;
623634
624635 switch (output_mode) {
625636 .Obj => return,
......@@ -630,13 +641,9 @@ pub const File = struct {
630641 .Exe => {},
631642 }
632643 switch (base.tag) {
644 .lld => assert(base.file == null),
633645 .elf => if (base.file) |f| {
634646 dev.check(.elf_linker);
635 if (base.zcu_object_sub_path != null and use_lld) {
636 // The file we have open is not the final file that we want to
637 // make executable, so we don't have to close it.
638 return;
639 }
640647 f.close();
641648 base.file = null;
642649
......@@ -651,11 +658,6 @@ pub const File = struct {
651658 },
652659 .coff, .macho, .plan9, .wasm, .goff, .xcoff => if (base.file) |f| {
653660 dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
654 if (base.zcu_object_sub_path != null) {
655 // The file we have open is not the final file that we want to
656 // make executable, so we don't have to close it.
657 return;
658 }
659661 f.close();
660662 base.file = null;
661663
......@@ -693,6 +695,7 @@ pub const File = struct {
693695 pub fn getGlobalSymbol(base: *File, name: []const u8, lib_name: ?[]const u8) UpdateNavError!u32 {
694696 log.debug("getGlobalSymbol '{s}' (expected in '{?s}')", .{ name, lib_name });
695697 switch (base.tag) {
698 .lld => unreachable,
696699 .plan9 => unreachable,
697700 .spirv => unreachable,
698701 .c => unreachable,
......@@ -704,10 +707,13 @@ pub const File = struct {
704707 }
705708
706709 /// May be called before or after updateExports for any given Nav.
707 pub fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {
710 /// Asserts that the ZCU is not using the LLVM backend.
711 fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {
712 assert(base.comp.zcu.?.llvm_object == null);
708713 const nav = pt.zcu.intern_pool.getNav(nav_index);
709714 assert(nav.status == .fully_resolved);
710715 switch (base.tag) {
716 .lld => unreachable,
711717 inline else => |tag| {
712718 dev.check(tag.devFeature());
713719 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateNav(pt, nav_index);
......@@ -721,8 +727,11 @@ pub const File = struct {
721727 TypeFailureReported,
722728 };
723729
724 pub fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {
730 /// Never called when LLVM is codegenning the ZCU.
731 fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {
732 assert(base.comp.zcu.?.llvm_object == null);
725733 switch (base.tag) {
734 .lld => unreachable,
726735 else => {},
727736 inline .elf => |tag| {
728737 dev.check(tag.devFeature());
......@@ -732,17 +741,24 @@ pub const File = struct {
732741 }
733742
734743 /// May be called before or after updateExports for any given Decl.
735 pub fn updateFunc(
744 /// The active tag of `mir` is determined by the backend used for the module this function is in.
745 /// Never called when LLVM is codegenning the ZCU.
746 fn updateFunc(
736747 base: *File,
737748 pt: Zcu.PerThread,
738749 func_index: InternPool.Index,
739 air: Air,
740 liveness: Air.Liveness,
750 /// This is owned by the caller, but the callee is permitted to mutate it provided
751 /// that `mir.deinit` remains legal for the caller. For instance, the callee can
752 /// take ownership of an embedded slice and replace it with `&.{}` in `mir`.
753 mir: *codegen.AnyMir,
741754 ) UpdateNavError!void {
755 assert(base.comp.zcu.?.llvm_object == null);
742756 switch (base.tag) {
757 .lld => unreachable,
758 .spirv => unreachable, // see corresponding special case in `Zcu.PerThread.runCodegenInner`
743759 inline else => |tag| {
744760 dev.check(tag.devFeature());
745 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(pt, func_index, air, liveness);
761 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(pt, func_index, mir);
746762 },
747763 }
748764 }
......@@ -755,7 +771,9 @@ pub const File = struct {
755771
756772 /// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because
757773 /// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`.
758 pub fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateLineNumberError!void {
774 /// Never called when LLVM is codegenning the ZCU.
775 fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateLineNumberError!void {
776 assert(base.comp.zcu.?.llvm_object == null);
759777 {
760778 const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?;
761779 const file = pt.zcu.fileByIndex(ti.file);
......@@ -764,6 +782,7 @@ pub const File = struct {
764782 }
765783
766784 switch (base.tag) {
785 .lld => unreachable,
767786 .spirv => {},
768787 .goff, .xcoff => {},
769788 inline else => |tag| {
......@@ -803,8 +822,7 @@ pub const File = struct {
803822 OutOfMemory,
804823 };
805824
806 /// Commit pending changes and write headers. Takes into account final output mode
807 /// and `use_lld`, not only `effectiveOutputMode`.
825 /// Commit pending changes and write headers. Takes into account final output mode.
808826 /// `arena` has the lifetime of the call to `Compilation.update`.
809827 pub fn flush(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
810828 const comp = base.comp;
......@@ -826,15 +844,7 @@ pub const File = struct {
826844 };
827845 return;
828846 }
829
830847 assert(base.post_prelink);
831
832 const use_lld = build_options.have_llvm and comp.config.use_lld;
833 const output_mode = comp.config.output_mode;
834 const link_mode = comp.config.link_mode;
835 if (use_lld and output_mode == .Lib and link_mode == .static) {
836 return base.linkAsArchive(arena, tid, prog_node);
837 }
838848 switch (base.tag) {
839849 inline else => |tag| {
840850 dev.check(tag.devFeature());
......@@ -843,17 +853,6 @@ pub const File = struct {
843853 }
844854 }
845855
846 /// Commit pending changes and write headers. Works based on `effectiveOutputMode`
847 /// rather than final output mode.
848 pub fn flushModule(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
849 switch (base.tag) {
850 inline else => |tag| {
851 dev.check(tag.devFeature());
852 return @as(*tag.Type(), @fieldParentPtr("base", base)).flushModule(arena, tid, prog_node);
853 },
854 }
855 }
856
857856 pub const UpdateExportsError = error{
858857 OutOfMemory,
859858 AnalysisFail,
......@@ -863,13 +862,16 @@ pub const File = struct {
863862 /// a list of size 1, meaning that `exported` is exported once. However, it is possible
864863 /// to export the same thing with multiple different symbol names (aliases).
865864 /// May be called before or after updateDecl for any given Decl.
865 /// Never called when LLVM is codegenning the ZCU.
866866 pub fn updateExports(
867867 base: *File,
868868 pt: Zcu.PerThread,
869869 exported: Zcu.Exported,
870870 export_indices: []const Zcu.Export.Index,
871871 ) UpdateExportsError!void {
872 assert(base.comp.zcu.?.llvm_object == null);
872873 switch (base.tag) {
874 .lld => unreachable,
873875 inline else => |tag| {
874876 dev.check(tag.devFeature());
875877 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateExports(pt, exported, export_indices);
......@@ -895,8 +897,11 @@ pub const File = struct {
895897 /// `Nav`'s address was not yet resolved, or the containing atom gets moved in virtual memory.
896898 /// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate
897899 /// the block/atom.
900 /// Never called when LLVM is codegenning the ZCU.
898901 pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) !u64 {
902 assert(base.comp.zcu.?.llvm_object == null);
899903 switch (base.tag) {
904 .lld => unreachable,
900905 .c => unreachable,
901906 .spirv => unreachable,
902907 .wasm => unreachable,
......@@ -908,6 +913,7 @@ pub const File = struct {
908913 }
909914 }
910915
916 /// Never called when LLVM is codegenning the ZCU.
911917 pub fn lowerUav(
912918 base: *File,
913919 pt: Zcu.PerThread,
......@@ -915,7 +921,9 @@ pub const File = struct {
915921 decl_align: InternPool.Alignment,
916922 src_loc: Zcu.LazySrcLoc,
917923 ) !codegen.GenResult {
924 assert(base.comp.zcu.?.llvm_object == null);
918925 switch (base.tag) {
926 .lld => unreachable,
919927 .c => unreachable,
920928 .spirv => unreachable,
921929 .wasm => unreachable,
......@@ -927,8 +935,11 @@ pub const File = struct {
927935 }
928936 }
929937
938 /// Never called when LLVM is codegenning the ZCU.
930939 pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 {
940 assert(base.comp.zcu.?.llvm_object == null);
931941 switch (base.tag) {
942 .lld => unreachable,
932943 .c => unreachable,
933944 .spirv => unreachable,
934945 .wasm => unreachable,
......@@ -940,12 +951,16 @@ pub const File = struct {
940951 }
941952 }
942953
954 /// Never called when LLVM is codegenning the ZCU.
943955 pub fn deleteExport(
944956 base: *File,
945957 exported: Zcu.Exported,
946958 name: InternPool.NullTerminatedString,
947959 ) void {
960 assert(base.comp.zcu.?.llvm_object == null);
948961 switch (base.tag) {
962 .lld => unreachable,
963
949964 .plan9,
950965 .spirv,
951966 .goff,
......@@ -961,6 +976,7 @@ pub const File = struct {
961976
962977 /// Opens a path as an object file and parses it into the linker.
963978 fn openLoadObject(base: *File, path: Path) anyerror!void {
979 if (base.tag == .lld) return;
964980 const diags = &base.comp.link_diags;
965981 const input = try openObjectInput(diags, path);
966982 errdefer input.object.file.close();
......@@ -970,6 +986,7 @@ pub const File = struct {
970986 /// Opens a path as a static library and parses it into the linker.
971987 /// If `query` is non-null, allows GNU ld scripts.
972988 fn openLoadArchive(base: *File, path: Path, opt_query: ?UnresolvedInput.Query) anyerror!void {
989 if (base.tag == .lld) return;
973990 if (opt_query) |query| {
974991 const archive = try openObject(path, query.must_link, query.hidden);
975992 errdefer archive.file.close();
......@@ -992,6 +1009,7 @@ pub const File = struct {
9921009 /// Opens a path as a shared library and parses it into the linker.
9931010 /// Handles GNU ld scripts.
9941011 fn openLoadDso(base: *File, path: Path, query: UnresolvedInput.Query) anyerror!void {
1012 if (base.tag == .lld) return;
9951013 const dso = try openDso(path, query.needed, query.weak, query.reexport);
9961014 errdefer dso.file.close();
9971015 loadInput(base, .{ .dso = dso }) catch |err| switch (err) {
......@@ -1044,8 +1062,7 @@ pub const File = struct {
10441062 }
10451063
10461064 pub fn loadInput(base: *File, input: Input) anyerror!void {
1047 const use_lld = build_options.have_llvm and base.comp.config.use_lld;
1048 if (use_lld) return;
1065 if (base.tag == .lld) return;
10491066 switch (base.tag) {
10501067 inline .elf, .wasm => |tag| {
10511068 dev.check(tag.devFeature());
......@@ -1057,186 +1074,23 @@ pub const File = struct {
10571074
10581075 /// Called when all linker inputs have been sent via `loadInput`. After
10591076 /// this, `loadInput` will not be called anymore.
1060 pub fn prelink(base: *File, prog_node: std.Progress.Node) FlushError!void {
1077 pub fn prelink(base: *File) FlushError!void {
10611078 assert(!base.post_prelink);
1062 const use_lld = build_options.have_llvm and base.comp.config.use_lld;
1063 if (use_lld) return;
10641079
10651080 // In this case, an object file is created by the LLVM backend, so
10661081 // there is no prelink phase. The Zig code is linked as a standard
10671082 // object along with the others.
1068 if (base.zcu_object_sub_path != null) return;
1083 if (base.zcu_object_basename != null) return;
10691084
10701085 switch (base.tag) {
10711086 inline .wasm => |tag| {
10721087 dev.check(tag.devFeature());
1073 return @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(prog_node);
1088 return @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node);
10741089 },
10751090 else => {},
10761091 }
10771092 }
10781093
1079 pub fn linkAsArchive(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
1080 dev.check(.lld_linker);
1081
1082 const tracy = trace(@src());
1083 defer tracy.end();
1084
1085 const comp = base.comp;
1086 const diags = &comp.link_diags;
1087
1088 return linkAsArchiveInner(base, arena, tid, prog_node) catch |err| switch (err) {
1089 error.OutOfMemory => return error.OutOfMemory,
1090 error.LinkFailure => return error.LinkFailure,
1091 else => |e| return diags.fail("failed to link as archive: {s}", .{@errorName(e)}),
1092 };
1093 }
1094
1095 fn linkAsArchiveInner(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
1096 const comp = base.comp;
1097
1098 const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
1099 const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
1100 const full_out_path_z = try arena.dupeZ(u8, full_out_path);
1101 const opt_zcu = comp.zcu;
1102
1103 // If there is no Zig code to compile, then we should skip flushing the output file
1104 // because it will not be part of the linker line anyway.
1105 const zcu_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {
1106 try base.flushModule(arena, tid, prog_node);
1107
1108 const dirname = fs.path.dirname(full_out_path_z) orelse ".";
1109 break :blk try fs.path.join(arena, &.{ dirname, base.zcu_object_sub_path.? });
1110 } else null;
1111
1112 log.debug("zcu_obj_path={s}", .{if (zcu_obj_path) |s| s else "(null)"});
1113
1114 const compiler_rt_path: ?Path = if (comp.compiler_rt_strat == .obj)
1115 comp.compiler_rt_obj.?.full_object_path
1116 else
1117 null;
1118
1119 const ubsan_rt_path: ?Path = if (comp.ubsan_rt_strat == .obj)
1120 comp.ubsan_rt_obj.?.full_object_path
1121 else
1122 null;
1123
1124 // This function follows the same pattern as link.Elf.linkWithLLD so if you want some
1125 // insight as to what's going on here you can read that function body which is more
1126 // well-commented.
1127
1128 const id_symlink_basename = "llvm-ar.id";
1129
1130 var man: Cache.Manifest = undefined;
1131 defer if (!base.disable_lld_caching) man.deinit();
1132
1133 const link_inputs = comp.link_inputs;
1134
1135 var digest: [Cache.hex_digest_len]u8 = undefined;
1136
1137 if (!base.disable_lld_caching) {
1138 man = comp.cache_parent.obtain();
1139
1140 // We are about to obtain this lock, so here we give other processes a chance first.
1141 base.releaseLock();
1142
1143 try hashInputs(&man, link_inputs);
1144
1145 for (comp.c_object_table.keys()) |key| {
1146 _ = try man.addFilePath(key.status.success.object_path, null);
1147 }
1148 for (comp.win32_resource_table.keys()) |key| {
1149 _ = try man.addFile(key.status.success.res_path, null);
1150 }
1151 try man.addOptionalFile(zcu_obj_path);
1152 try man.addOptionalFilePath(compiler_rt_path);
1153 try man.addOptionalFilePath(ubsan_rt_path);
1154
1155 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
1156 _ = try man.hit();
1157 digest = man.final();
1158
1159 var prev_digest_buf: [digest.len]u8 = undefined;
1160 const prev_digest: []u8 = Cache.readSmallFile(
1161 directory.handle,
1162 id_symlink_basename,
1163 &prev_digest_buf,
1164 ) catch |err| b: {
1165 log.debug("archive new_digest={s} readFile error: {s}", .{ std.fmt.fmtSliceHexLower(&digest), @errorName(err) });
1166 break :b prev_digest_buf[0..0];
1167 };
1168 if (mem.eql(u8, prev_digest, &digest)) {
1169 log.debug("archive digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});
1170 base.lock = man.toOwnedLock();
1171 return;
1172 }
1173
1174 // We are about to change the output file to be different, so we invalidate the build hash now.
1175 directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
1176 error.FileNotFound => {},
1177 else => |e| return e,
1178 };
1179 }
1180
1181 var object_files: std.ArrayListUnmanaged([*:0]const u8) = .empty;
1182
1183 try object_files.ensureUnusedCapacity(arena, link_inputs.len);
1184 for (link_inputs) |input| {
1185 object_files.appendAssumeCapacity(try input.path().?.toStringZ(arena));
1186 }
1187
1188 try object_files.ensureUnusedCapacity(arena, comp.c_object_table.count() +
1189 comp.win32_resource_table.count() + 2);
1190
1191 for (comp.c_object_table.keys()) |key| {
1192 object_files.appendAssumeCapacity(try key.status.success.object_path.toStringZ(arena));
1193 }
1194 for (comp.win32_resource_table.keys()) |key| {
1195 object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path));
1196 }
1197 if (zcu_obj_path) |p| object_files.appendAssumeCapacity(try arena.dupeZ(u8, p));
1198 if (compiler_rt_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
1199 if (ubsan_rt_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
1200
1201 if (comp.verbose_link) {
1202 std.debug.print("ar rcs {s}", .{full_out_path_z});
1203 for (object_files.items) |arg| {
1204 std.debug.print(" {s}", .{arg});
1205 }
1206 std.debug.print("\n", .{});
1207 }
1208
1209 const llvm_bindings = @import("codegen/llvm/bindings.zig");
1210 const llvm = @import("codegen/llvm.zig");
1211 const target = comp.root_mod.resolved_target.result;
1212 llvm.initializeLLVMTarget(target.cpu.arch);
1213 const bad = llvm_bindings.WriteArchive(
1214 full_out_path_z,
1215 object_files.items.ptr,
1216 object_files.items.len,
1217 switch (target.os.tag) {
1218 .aix => .AIXBIG,
1219 .windows => .COFF,
1220 else => if (target.os.tag.isDarwin()) .DARWIN else .GNU,
1221 },
1222 );
1223 if (bad) return error.UnableToWriteArchive;
1224
1225 if (!base.disable_lld_caching) {
1226 Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
1227 log.warn("failed to save archive hash digest file: {s}", .{@errorName(err)});
1228 };
1229
1230 if (man.have_exclusive_lock) {
1231 man.writeManifest() catch |err| {
1232 log.warn("failed to write cache manifest when archiving: {s}", .{@errorName(err)});
1233 };
1234 }
1235
1236 base.lock = man.toOwnedLock();
1237 }
1238 }
1239
12401094 pub const Tag = enum {
12411095 coff,
12421096 elf,
......@@ -1247,6 +1101,7 @@ pub const File = struct {
12471101 plan9,
12481102 goff,
12491103 xcoff,
1104 lld,
12501105
12511106 pub fn Type(comptime tag: Tag) type {
12521107 return switch (tag) {
......@@ -1259,10 +1114,11 @@ pub const File = struct {
12591114 .plan9 => Plan9,
12601115 .goff => Goff,
12611116 .xcoff => Xcoff,
1117 .lld => Lld,
12621118 };
12631119 }
12641120
1265 pub fn fromObjectFormat(ofmt: std.Target.ObjectFormat) Tag {
1121 fn fromObjectFormat(ofmt: std.Target.ObjectFormat) Tag {
12661122 return switch (ofmt) {
12671123 .coff => .coff,
12681124 .elf => .elf,
......@@ -1290,15 +1146,7 @@ pub const File = struct {
12901146 ty: InternPool.Index,
12911147 };
12921148
1293 pub fn effectiveOutputMode(
1294 use_lld: bool,
1295 output_mode: std.builtin.OutputMode,
1296 ) std.builtin.OutputMode {
1297 return if (use_lld) .Obj else output_mode;
1298 }
1299
13001149 pub fn determineMode(
1301 use_lld: bool,
13021150 output_mode: std.builtin.OutputMode,
13031151 link_mode: std.builtin.LinkMode,
13041152 ) fs.File.Mode {
......@@ -1307,7 +1155,7 @@ pub const File = struct {
13071155 // more leniently. As another data point, C's fopen seems to open files with the
13081156 // 666 mode.
13091157 const executable_mode = if (builtin.target.os.tag == .windows) 0 else 0o777;
1310 switch (effectiveOutputMode(use_lld, output_mode)) {
1158 switch (output_mode) {
13111159 .Lib => return switch (link_mode) {
13121160 .dynamic => executable_mode,
13131161 .static => fs.File.default_mode,
......@@ -1345,21 +1193,6 @@ pub const File = struct {
13451193 return output_mode == .Lib and !self.isStatic();
13461194 }
13471195
1348 pub fn emitLlvmObject(
1349 base: File,
1350 arena: Allocator,
1351 llvm_object: LlvmObject.Ptr,
1352 prog_node: std.Progress.Node,
1353 ) !void {
1354 return base.comp.emitLlvmObject(arena, .{
1355 .root_dir = base.emit.root_dir,
1356 .sub_path = std.fs.path.dirname(base.emit.sub_path) orelse "",
1357 }, .{
1358 .directory = null,
1359 .basename = base.zcu_object_sub_path.?,
1360 }, llvm_object, prog_node);
1361 }
1362
13631196 pub fn cgFail(
13641197 base: *File,
13651198 nav_index: InternPool.Nav.Index,
......@@ -1370,6 +1203,7 @@ pub const File = struct {
13701203 return base.comp.zcu.?.codegenFail(nav_index, format, args);
13711204 }
13721205
1206 pub const Lld = @import("link/Lld.zig");
13731207 pub const C = @import("link/C.zig");
13741208 pub const Coff = @import("link/Coff.zig");
13751209 pub const Plan9 = @import("link/Plan9.zig");
......@@ -1382,40 +1216,7 @@ pub const File = struct {
13821216 pub const Dwarf = @import("link/Dwarf.zig");
13831217};
13841218
1385/// Does all the tasks in the queue. Runs in exactly one separate thread
1386/// from the rest of compilation. All tasks performed here are
1387/// single-threaded with respect to one another.
1388pub fn flushTaskQueue(tid: usize, comp: *Compilation) void {
1389 const diags = &comp.link_diags;
1390 // As soon as check() is called, another `flushTaskQueue` call could occur,
1391 // so the safety lock must go after the check.
1392 while (comp.link_task_queue.check()) |tasks| {
1393 comp.link_task_queue_safety.lock();
1394 defer comp.link_task_queue_safety.unlock();
1395
1396 if (comp.remaining_prelink_tasks > 0) {
1397 comp.link_task_queue_postponed.ensureUnusedCapacity(comp.gpa, tasks.len) catch |err| switch (err) {
1398 error.OutOfMemory => return diags.setAllocFailure(),
1399 };
1400 }
1401
1402 for (tasks) |task| doTask(comp, tid, task);
1403
1404 if (comp.remaining_prelink_tasks == 0) {
1405 if (comp.bin_file) |base| if (!base.post_prelink) {
1406 base.prelink(comp.work_queue_progress_node) catch |err| switch (err) {
1407 error.OutOfMemory => diags.setAllocFailure(),
1408 error.LinkFailure => continue,
1409 };
1410 base.post_prelink = true;
1411 for (comp.link_task_queue_postponed.items) |task| doTask(comp, tid, task);
1412 comp.link_task_queue_postponed.clearRetainingCapacity();
1413 };
1414 }
1415 }
1416}
1417
1418pub const Task = union(enum) {
1219pub const PrelinkTask = union(enum) {
14191220 /// Loads the objects, shared objects, and archives that are already
14201221 /// known from the command line.
14211222 load_explicitly_provided,
......@@ -1433,32 +1234,74 @@ pub const Task = union(enum) {
14331234 /// Tells the linker to load an input which could be an object file,
14341235 /// archive, or shared library.
14351236 load_input: Input,
1436
1237};
1238pub const ZcuTask = union(enum) {
14371239 /// Write the constant value for a Decl to the output file.
1438 codegen_nav: InternPool.Nav.Index,
1240 link_nav: InternPool.Nav.Index,
14391241 /// Write the machine code for a function to the output file.
1440 codegen_func: CodegenFunc,
1441 codegen_type: InternPool.Index,
1442
1242 link_func: LinkFunc,
1243 link_type: InternPool.Index,
14431244 update_line_number: InternPool.TrackedInst.Index,
1444
1445 pub const CodegenFunc = struct {
1245 pub fn deinit(task: ZcuTask, zcu: *const Zcu) void {
1246 switch (task) {
1247 .link_nav,
1248 .link_type,
1249 .update_line_number,
1250 => {},
1251 .link_func => |link_func| {
1252 switch (link_func.mir.status.load(.monotonic)) {
1253 .pending => unreachable, // cannot deinit until MIR done
1254 .failed => {}, // MIR not populated so doesn't need freeing
1255 .ready => link_func.mir.value.deinit(zcu),
1256 }
1257 zcu.gpa.destroy(link_func.mir);
1258 },
1259 }
1260 }
1261 pub const LinkFunc = struct {
14461262 /// This will either be a non-generic `func_decl` or a `func_instance`.
14471263 func: InternPool.Index,
1448 /// This `Air` is owned by the `Job` and allocated with `gpa`.
1449 /// It must be deinited when the job is processed.
1450 air: Air,
1264 /// This pointer is allocated into `gpa` and must be freed when the `ZcuTask` is processed.
1265 /// The pointer is shared with the codegen worker, which will populate the MIR inside once
1266 /// it has been generated. It's important that the `link_func` is queued at the same time as
1267 /// the codegen job to ensure that the linker receives functions in a deterministic order,
1268 /// allowing reproducible builds.
1269 mir: *SharedMir,
1270 /// This is not actually used by `doZcuTask`. Instead, `Queue` uses this value as a heuristic
1271 /// to avoid queueing too much AIR/MIR for codegen/link at a time. Essentially, we cap the
1272 /// total number of AIR bytes which are being processed at once, preventing unbounded memory
1273 /// usage when AIR is produced faster than it is processed.
1274 air_bytes: u32,
1275
1276 pub const SharedMir = struct {
1277 /// This is initially `.pending`. When `value` is populated, the codegen thread will set
1278 /// this to `.ready`, and alert the queue if needed. It could also end up `.failed`.
1279 /// The action of storing a value (other than `.pending`) to this atomic transfers
1280 /// ownership of memory assoicated with `value` to this `ZcuTask`.
1281 status: std.atomic.Value(enum(u8) {
1282 /// We are waiting on codegen to generate MIR (or die trying).
1283 pending,
1284 /// `value` is not populated and will not be populated. Just drop the task from the queue and move on.
1285 failed,
1286 /// `value` is populated with the MIR from the backend in use, which is not LLVM.
1287 ready,
1288 }),
1289 /// This is `undefined` until `ready` is set to `true`. Once populated, this MIR belongs
1290 /// to the `ZcuTask`, and must be `deinit`ed when it is processed. Allocated into `gpa`.
1291 value: codegen.AnyMir,
1292 };
14511293 };
14521294};
14531295
1454pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
1296pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
14551297 const diags = &comp.link_diags;
1298 const base = comp.bin_file orelse {
1299 comp.link_prog_node.completeOne();
1300 return;
1301 };
14561302 switch (task) {
14571303 .load_explicitly_provided => {
1458 comp.remaining_prelink_tasks -= 1;
1459 const base = comp.bin_file orelse return;
1460
1461 const prog_node = comp.work_queue_progress_node.start("Parse Linker Inputs", comp.link_inputs.len);
1304 const prog_node = comp.link_prog_node.start("Parse Inputs", comp.link_inputs.len);
14621305 defer prog_node.end();
14631306 for (comp.link_inputs) |input| {
14641307 base.loadInput(input) catch |err| switch (err) {
......@@ -1475,10 +1318,7 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
14751318 }
14761319 },
14771320 .load_host_libc => {
1478 comp.remaining_prelink_tasks -= 1;
1479 const base = comp.bin_file orelse return;
1480
1481 const prog_node = comp.work_queue_progress_node.start("Linker Parse Host libc", 0);
1321 const prog_node = comp.link_prog_node.start("Parse Host libc", 0);
14821322 defer prog_node.end();
14831323
14841324 const target = comp.root_mod.resolved_target.result;
......@@ -1537,9 +1377,7 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
15371377 }
15381378 },
15391379 .load_object => |path| {
1540 comp.remaining_prelink_tasks -= 1;
1541 const base = comp.bin_file orelse return;
1542 const prog_node = comp.work_queue_progress_node.start("Linker Parse Object", 0);
1380 const prog_node = comp.link_prog_node.start("Parse Object", 0);
15431381 defer prog_node.end();
15441382 base.openLoadObject(path) catch |err| switch (err) {
15451383 error.LinkFailure => return, // error reported via diags
......@@ -1547,9 +1385,7 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
15471385 };
15481386 },
15491387 .load_archive => |path| {
1550 comp.remaining_prelink_tasks -= 1;
1551 const base = comp.bin_file orelse return;
1552 const prog_node = comp.work_queue_progress_node.start("Linker Parse Archive", 0);
1388 const prog_node = comp.link_prog_node.start("Parse Archive", 0);
15531389 defer prog_node.end();
15541390 base.openLoadArchive(path, null) catch |err| switch (err) {
15551391 error.LinkFailure => return, // error reported via link_diags
......@@ -1557,9 +1393,7 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
15571393 };
15581394 },
15591395 .load_dso => |path| {
1560 comp.remaining_prelink_tasks -= 1;
1561 const base = comp.bin_file orelse return;
1562 const prog_node = comp.work_queue_progress_node.start("Linker Parse Shared Library", 0);
1396 const prog_node = comp.link_prog_node.start("Parse Shared Library", 0);
15631397 defer prog_node.end();
15641398 base.openLoadDso(path, .{
15651399 .preferred_mode = .dynamic,
......@@ -1570,9 +1404,7 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
15701404 };
15711405 },
15721406 .load_input => |input| {
1573 comp.remaining_prelink_tasks -= 1;
1574 const base = comp.bin_file orelse return;
1575 const prog_node = comp.work_queue_progress_node.start("Linker Parse Input", 0);
1407 const prog_node = comp.link_prog_node.start("Parse Input", 0);
15761408 defer prog_node.end();
15771409 base.loadInput(input) catch |err| switch (err) {
15781410 error.LinkFailure => return, // error reported via link_diags
......@@ -1585,159 +1417,113 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
15851417 },
15861418 };
15871419 },
1588 .codegen_nav => |nav_index| {
1589 if (comp.remaining_prelink_tasks == 0) {
1590 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
1591 defer pt.deactivate();
1592 pt.linkerUpdateNav(nav_index) catch |err| switch (err) {
1420 }
1421}
1422pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {
1423 const diags = &comp.link_diags;
1424 const zcu = comp.zcu.?;
1425 const ip = &zcu.intern_pool;
1426 const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid));
1427 defer pt.deactivate();
1428 switch (task) {
1429 .link_nav => |nav_index| {
1430 const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);
1431 const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0);
1432 defer nav_prog_node.end();
1433 if (zcu.llvm_object) |llvm_object| {
1434 llvm_object.updateNav(pt, nav_index) catch |err| switch (err) {
15931435 error.OutOfMemory => diags.setAllocFailure(),
15941436 };
1595 } else {
1596 comp.link_task_queue_postponed.appendAssumeCapacity(task);
1597 }
1598 },
1599 .codegen_func => |func| {
1600 if (comp.remaining_prelink_tasks == 0) {
1601 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
1602 defer pt.deactivate();
1603 var air = func.air;
1604 defer air.deinit(comp.gpa);
1605 pt.linkerUpdateFunc(func.func, &air) catch |err| switch (err) {
1437 } else if (comp.bin_file) |lf| {
1438 lf.updateNav(pt, nav_index) catch |err| switch (err) {
16061439 error.OutOfMemory => diags.setAllocFailure(),
1440 error.CodegenFail => zcu.assertCodegenFailed(nav_index),
1441 error.Overflow, error.RelocationNotByteAligned => {
1442 switch (zcu.codegenFail(nav_index, "unable to codegen: {s}", .{@errorName(err)})) {
1443 error.CodegenFail => return,
1444 error.OutOfMemory => return diags.setAllocFailure(),
1445 }
1446 // Not a retryable failure.
1447 },
16071448 };
1608 } else {
1609 comp.link_task_queue_postponed.appendAssumeCapacity(task);
16101449 }
16111450 },
1612 .codegen_type => |ty| {
1613 if (comp.remaining_prelink_tasks == 0) {
1614 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
1615 defer pt.deactivate();
1616 pt.linkerUpdateContainerType(ty) catch |err| switch (err) {
1617 error.OutOfMemory => diags.setAllocFailure(),
1451 .link_func => |func| {
1452 const nav = zcu.funcInfo(func.func).owner_nav;
1453 const fqn_slice = ip.getNav(nav).fqn.toSlice(ip);
1454 const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0);
1455 defer nav_prog_node.end();
1456 switch (func.mir.status.load(.monotonic)) {
1457 .pending => unreachable,
1458 .ready => {},
1459 .failed => return,
1460 }
1461 assert(zcu.llvm_object == null); // LLVM codegen doesn't produce MIR
1462 const mir = &func.mir.value;
1463 if (comp.bin_file) |lf| {
1464 lf.updateFunc(pt, func.func, mir) catch |err| switch (err) {
1465 error.OutOfMemory => return diags.setAllocFailure(),
1466 error.CodegenFail => return zcu.assertCodegenFailed(nav),
1467 error.Overflow, error.RelocationNotByteAligned => {
1468 switch (zcu.codegenFail(nav, "unable to codegen: {s}", .{@errorName(err)})) {
1469 error.OutOfMemory => return diags.setAllocFailure(),
1470 error.CodegenFail => return,
1471 }
1472 },
16181473 };
1619 } else {
1620 comp.link_task_queue_postponed.appendAssumeCapacity(task);
1474 }
1475 },
1476 .link_type => |ty| {
1477 const name = Type.fromInterned(ty).containerTypeName(ip).toSlice(ip);
1478 const nav_prog_node = comp.link_prog_node.start(name, 0);
1479 defer nav_prog_node.end();
1480 if (zcu.llvm_object == null) {
1481 if (comp.bin_file) |lf| {
1482 lf.updateContainerType(pt, ty) catch |err| switch (err) {
1483 error.OutOfMemory => diags.setAllocFailure(),
1484 error.TypeFailureReported => assert(zcu.failed_types.contains(ty)),
1485 };
1486 }
16211487 }
16221488 },
16231489 .update_line_number => |ti| {
1624 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
1625 defer pt.deactivate();
1626 pt.linkerUpdateLineNumber(ti) catch |err| switch (err) {
1627 error.OutOfMemory => diags.setAllocFailure(),
1628 };
1490 const nav_prog_node = comp.link_prog_node.start("Update line number", 0);
1491 defer nav_prog_node.end();
1492 if (pt.zcu.llvm_object == null) {
1493 if (comp.bin_file) |lf| {
1494 lf.updateLineNumber(pt, ti) catch |err| switch (err) {
1495 error.OutOfMemory => diags.setAllocFailure(),
1496 else => |e| log.err("update line number failed: {s}", .{@errorName(e)}),
1497 };
1498 }
1499 }
16291500 },
16301501 }
16311502}
1632
1633pub fn spawnLld(
1634 comp: *Compilation,
1635 arena: Allocator,
1636 argv: []const []const u8,
1637) !void {
1638 if (comp.verbose_link) {
1639 // Skip over our own name so that the LLD linker name is the first argv item.
1640 Compilation.dump_argv(argv[1..]);
1641 }
1642
1643 // If possible, we run LLD as a child process because it does not always
1644 // behave properly as a library, unfortunately.
1645 // https://github.com/ziglang/zig/issues/3825
1646 if (!std.process.can_spawn) {
1647 const exit_code = try lldMain(arena, argv, false);
1648 if (exit_code == 0) return;
1649 if (comp.clang_passthrough_mode) std.process.exit(exit_code);
1650 return error.LinkFailure;
1651 }
1652
1653 var stderr: []u8 = &.{};
1654 defer comp.gpa.free(stderr);
1655
1656 var child = std.process.Child.init(argv, arena);
1657 const term = (if (comp.clang_passthrough_mode) term: {
1658 child.stdin_behavior = .Inherit;
1659 child.stdout_behavior = .Inherit;
1660 child.stderr_behavior = .Inherit;
1661
1662 break :term child.spawnAndWait();
1663 } else term: {
1664 child.stdin_behavior = .Ignore;
1665 child.stdout_behavior = .Ignore;
1666 child.stderr_behavior = .Pipe;
1667
1668 child.spawn() catch |err| break :term err;
1669 stderr = try child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize));
1670 break :term child.wait();
1671 }) catch |first_err| term: {
1672 const err = switch (first_err) {
1673 error.NameTooLong => err: {
1674 const s = fs.path.sep_str;
1675 const rand_int = std.crypto.random.int(u64);
1676 const rsp_path = "tmp" ++ s ++ std.fmt.hex(rand_int) ++ ".rsp";
1677
1678 const rsp_file = try comp.dirs.local_cache.handle.createFileZ(rsp_path, .{});
1679 defer comp.dirs.local_cache.handle.deleteFileZ(rsp_path) catch |err|
1680 log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) });
1681 {
1682 defer rsp_file.close();
1683 var rsp_buf = std.io.bufferedWriter(rsp_file.writer());
1684 const rsp_writer = rsp_buf.writer();
1685 for (argv[2..]) |arg| {
1686 try rsp_writer.writeByte('"');
1687 for (arg) |c| {
1688 switch (c) {
1689 '\"', '\\' => try rsp_writer.writeByte('\\'),
1690 else => {},
1691 }
1692 try rsp_writer.writeByte(c);
1693 }
1694 try rsp_writer.writeByte('"');
1695 try rsp_writer.writeByte('\n');
1696 }
1697 try rsp_buf.flush();
1698 }
1699
1700 var rsp_child = std.process.Child.init(&.{ argv[0], argv[1], try std.fmt.allocPrint(
1701 arena,
1702 "@{s}",
1703 .{try comp.dirs.local_cache.join(arena, &.{rsp_path})},
1704 ) }, arena);
1705 if (comp.clang_passthrough_mode) {
1706 rsp_child.stdin_behavior = .Inherit;
1707 rsp_child.stdout_behavior = .Inherit;
1708 rsp_child.stderr_behavior = .Inherit;
1709
1710 break :term rsp_child.spawnAndWait() catch |err| break :err err;
1711 } else {
1712 rsp_child.stdin_behavior = .Ignore;
1713 rsp_child.stdout_behavior = .Ignore;
1714 rsp_child.stderr_behavior = .Pipe;
1715
1716 rsp_child.spawn() catch |err| break :err err;
1717 stderr = try rsp_child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize));
1718 break :term rsp_child.wait() catch |err| break :err err;
1503/// After the main pipeline is done, but before flush, the compilation may need to link one final
1504/// `Nav` into the binary: the `builtin.test_functions` value. Since the link thread isn't running
1505/// by then, we expose this function which can be called directly.
1506pub fn linkTestFunctionsNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) void {
1507 const zcu = pt.zcu;
1508 const comp = zcu.comp;
1509 const diags = &comp.link_diags;
1510 if (zcu.llvm_object) |llvm_object| {
1511 llvm_object.updateNav(pt, nav_index) catch |err| switch (err) {
1512 error.OutOfMemory => diags.setAllocFailure(),
1513 };
1514 } else if (comp.bin_file) |lf| {
1515 lf.updateNav(pt, nav_index) catch |err| switch (err) {
1516 error.OutOfMemory => diags.setAllocFailure(),
1517 error.CodegenFail => zcu.assertCodegenFailed(nav_index),
1518 error.Overflow, error.RelocationNotByteAligned => {
1519 switch (zcu.codegenFail(nav_index, "unable to codegen: {s}", .{@errorName(err)})) {
1520 error.CodegenFail => return,
1521 error.OutOfMemory => return diags.setAllocFailure(),
17191522 }
1523 // Not a retryable failure.
17201524 },
1721 else => first_err,
17221525 };
1723 log.err("unable to spawn LLD {s}: {s}", .{ argv[0], @errorName(err) });
1724 return error.UnableToSpawnSelf;
1725 };
1726
1727 const diags = &comp.link_diags;
1728 switch (term) {
1729 .Exited => |code| if (code != 0) {
1730 if (comp.clang_passthrough_mode) std.process.exit(code);
1731 diags.lockAndParseLldStderr(argv[1], stderr);
1732 return error.LinkFailure;
1733 },
1734 else => {
1735 if (comp.clang_passthrough_mode) std.process.abort();
1736 return diags.fail("{s} terminated with stderr:\n{s}", .{ argv[0], stderr });
1737 },
17381526 }
1739
1740 if (stderr.len > 0) log.warn("unexpected LLD stderr:\n{s}", .{stderr});
17411527}
17421528
17431529/// Provided by the CLI, processed into `LinkInput` instances at the start of
src/link/C.zig+53-93
......@@ -17,7 +17,7 @@ const link = @import("../link.zig");
1717const trace = @import("../tracy.zig").trace;
1818const Type = @import("../Type.zig");
1919const Value = @import("../Value.zig");
20const Air = @import("../Air.zig");
20const AnyMir = @import("../codegen.zig").AnyMir;
2121
2222pub const zig_h = "#include \"zig.h\"\n";
2323
......@@ -145,7 +145,6 @@ pub fn createEmpty(
145145 .stack_size = options.stack_size orelse 16777216,
146146 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
147147 .file = file,
148 .disable_lld_caching = options.disable_lld_caching,
149148 .build_id = options.build_id,
150149 },
151150 };
......@@ -167,6 +166,9 @@ pub fn deinit(self: *C) void {
167166 self.uavs.deinit(gpa);
168167 self.aligned_uavs.deinit(gpa);
169168
169 self.exported_navs.deinit(gpa);
170 self.exported_uavs.deinit(gpa);
171
170172 self.string_bytes.deinit(gpa);
171173 self.fwd_decl_buf.deinit(gpa);
172174 self.code_buf.deinit(gpa);
......@@ -178,73 +180,23 @@ pub fn updateFunc(
178180 self: *C,
179181 pt: Zcu.PerThread,
180182 func_index: InternPool.Index,
181 air: Air,
182 liveness: Air.Liveness,
183 mir: *AnyMir,
183184) link.File.UpdateNavError!void {
184185 const zcu = pt.zcu;
185186 const gpa = zcu.gpa;
186187 const func = zcu.funcInfo(func_index);
187 const gop = try self.navs.getOrPut(gpa, func.owner_nav);
188 if (!gop.found_existing) gop.value_ptr.* = .{};
189 const ctype_pool = &gop.value_ptr.ctype_pool;
190 const lazy_fns = &gop.value_ptr.lazy_fns;
191 const fwd_decl = &self.fwd_decl_buf;
192 const code = &self.code_buf;
193 try ctype_pool.init(gpa);
194 ctype_pool.clearRetainingCapacity();
195 lazy_fns.clearRetainingCapacity();
196 fwd_decl.clearRetainingCapacity();
197 code.clearRetainingCapacity();
198
199 var function: codegen.Function = .{
200 .value_map = codegen.CValueMap.init(gpa),
201 .air = air,
202 .liveness = liveness,
203 .func_index = func_index,
204 .object = .{
205 .dg = .{
206 .gpa = gpa,
207 .pt = pt,
208 .mod = zcu.navFileScope(func.owner_nav).mod.?,
209 .error_msg = null,
210 .pass = .{ .nav = func.owner_nav },
211 .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,
212 .expected_block = null,
213 .fwd_decl = fwd_decl.toManaged(gpa),
214 .ctype_pool = ctype_pool.*,
215 .scratch = .{},
216 .uav_deps = self.uavs,
217 .aligned_uavs = self.aligned_uavs,
218 },
219 .code = code.toManaged(gpa),
220 .indent_writer = undefined, // set later so we can get a pointer to object.code
221 },
222 .lazy_fns = lazy_fns.*,
223 };
224 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
225 defer {
226 self.uavs = function.object.dg.uav_deps;
227 self.aligned_uavs = function.object.dg.aligned_uavs;
228 fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged();
229 ctype_pool.* = function.object.dg.ctype_pool.move();
230 ctype_pool.freeUnusedCapacity(gpa);
231 function.object.dg.scratch.deinit(gpa);
232 lazy_fns.* = function.lazy_fns.move();
233 lazy_fns.shrinkAndFree(gpa, lazy_fns.count());
234 code.* = function.object.code.moveToUnmanaged();
235 function.deinit();
236 }
237188
238 try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1);
239 codegen.genFunc(&function) catch |err| switch (err) {
240 error.AnalysisFail => {
241 zcu.failed_codegen.putAssumeCapacityNoClobber(func.owner_nav, function.object.dg.error_msg.?);
242 return;
243 },
244 else => |e| return e,
189 const gop = try self.navs.getOrPut(gpa, func.owner_nav);
190 if (gop.found_existing) gop.value_ptr.deinit(gpa);
191 gop.value_ptr.* = .{
192 .code = .empty,
193 .fwd_decl = .empty,
194 .ctype_pool = mir.c.ctype_pool.move(),
195 .lazy_fns = mir.c.lazy_fns.move(),
245196 };
246 gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items);
247 gop.value_ptr.code = try self.addString(function.object.code.items);
197 gop.value_ptr.code = try self.addString(mir.c.code);
198 gop.value_ptr.fwd_decl = try self.addString(mir.c.fwd_decl);
199 try self.addUavsFromCodegen(&mir.c.uavs);
248200}
249201
250202fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
......@@ -268,16 +220,14 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
268220 .fwd_decl = fwd_decl.toManaged(gpa),
269221 .ctype_pool = codegen.CType.Pool.empty,
270222 .scratch = .{},
271 .uav_deps = self.uavs,
272 .aligned_uavs = self.aligned_uavs,
223 .uavs = .empty,
273224 },
274225 .code = code.toManaged(gpa),
275226 .indent_writer = undefined, // set later so we can get a pointer to object.code
276227 };
277228 object.indent_writer = .{ .underlying_writer = object.code.writer() };
278229 defer {
279 self.uavs = object.dg.uav_deps;
280 self.aligned_uavs = object.dg.aligned_uavs;
230 object.dg.uavs.deinit(gpa);
281231 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
282232 object.dg.ctype_pool.deinit(object.dg.gpa);
283233 object.dg.scratch.deinit(gpa);
......@@ -296,8 +246,10 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
296246 else => |e| return e,
297247 };
298248
249 try self.addUavsFromCodegen(&object.dg.uavs);
250
299251 object.dg.ctype_pool.freeUnusedCapacity(gpa);
300 object.dg.uav_deps.values()[i] = .{
252 self.uavs.values()[i] = .{
301253 .code = try self.addString(object.code.items),
302254 .fwd_decl = try self.addString(object.dg.fwd_decl.items),
303255 .ctype_pool = object.dg.ctype_pool.move(),
......@@ -344,16 +296,14 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
344296 .fwd_decl = fwd_decl.toManaged(gpa),
345297 .ctype_pool = ctype_pool.*,
346298 .scratch = .{},
347 .uav_deps = self.uavs,
348 .aligned_uavs = self.aligned_uavs,
299 .uavs = .empty,
349300 },
350301 .code = code.toManaged(gpa),
351302 .indent_writer = undefined, // set later so we can get a pointer to object.code
352303 };
353304 object.indent_writer = .{ .underlying_writer = object.code.writer() };
354305 defer {
355 self.uavs = object.dg.uav_deps;
356 self.aligned_uavs = object.dg.aligned_uavs;
306 object.dg.uavs.deinit(gpa);
357307 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
358308 ctype_pool.* = object.dg.ctype_pool.move();
359309 ctype_pool.freeUnusedCapacity(gpa);
......@@ -361,16 +311,16 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
361311 code.* = object.code.moveToUnmanaged();
362312 }
363313
364 try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1);
365314 codegen.genDecl(&object) catch |err| switch (err) {
366 error.AnalysisFail => {
367 zcu.failed_codegen.putAssumeCapacityNoClobber(nav_index, object.dg.error_msg.?);
368 return;
315 error.AnalysisFail => switch (zcu.codegenFailMsg(nav_index, object.dg.error_msg.?)) {
316 error.CodegenFail => return,
317 error.OutOfMemory => |e| return e,
369318 },
370319 else => |e| return e,
371320 };
372321 gop.value_ptr.code = try self.addString(object.code.items);
373322 gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items);
323 try self.addUavsFromCodegen(&object.dg.uavs);
374324}
375325
376326pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
......@@ -381,10 +331,6 @@ pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedIn
381331 _ = ti_id;
382332}
383333
384pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
385 return self.flushModule(arena, tid, prog_node);
386}
387
388334fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
389335 const gpa = self.base.comp.gpa;
390336 var defines = std.ArrayList(u8).init(gpa);
......@@ -400,7 +346,7 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
400346 return defines;
401347}
402348
403pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
349pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
404350 _ = arena; // Has the same lifetime as the call to Compilation.update.
405351
406352 const tracy = trace(@src());
......@@ -676,16 +622,14 @@ fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) F
676622 .fwd_decl = fwd_decl.toManaged(gpa),
677623 .ctype_pool = ctype_pool.*,
678624 .scratch = .{},
679 .uav_deps = self.uavs,
680 .aligned_uavs = self.aligned_uavs,
625 .uavs = .empty,
681626 },
682627 .code = code.toManaged(gpa),
683628 .indent_writer = undefined, // set later so we can get a pointer to object.code
684629 };
685630 object.indent_writer = .{ .underlying_writer = object.code.writer() };
686631 defer {
687 self.uavs = object.dg.uav_deps;
688 self.aligned_uavs = object.dg.aligned_uavs;
632 object.dg.uavs.deinit(gpa);
689633 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
690634 ctype_pool.* = object.dg.ctype_pool.move();
691635 ctype_pool.freeUnusedCapacity(gpa);
......@@ -697,6 +641,8 @@ fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) F
697641 error.AnalysisFail => unreachable,
698642 else => |e| return e,
699643 };
644
645 try self.addUavsFromCodegen(&object.dg.uavs);
700646}
701647
702648fn flushLazyFn(
......@@ -724,8 +670,7 @@ fn flushLazyFn(
724670 .fwd_decl = fwd_decl.toManaged(gpa),
725671 .ctype_pool = ctype_pool.*,
726672 .scratch = .{},
727 .uav_deps = .{},
728 .aligned_uavs = .{},
673 .uavs = .empty,
729674 },
730675 .code = code.toManaged(gpa),
731676 .indent_writer = undefined, // set later so we can get a pointer to object.code
......@@ -734,8 +679,7 @@ fn flushLazyFn(
734679 defer {
735680 // If this assert trips just handle the anon_decl_deps the same as
736681 // `updateFunc()` does.
737 assert(object.dg.uav_deps.count() == 0);
738 assert(object.dg.aligned_uavs.count() == 0);
682 assert(object.dg.uavs.count() == 0);
739683 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
740684 ctype_pool.* = object.dg.ctype_pool.move();
741685 ctype_pool.freeUnusedCapacity(gpa);
......@@ -871,12 +815,10 @@ pub fn updateExports(
871815 .fwd_decl = fwd_decl.toManaged(gpa),
872816 .ctype_pool = decl_block.ctype_pool,
873817 .scratch = .{},
874 .uav_deps = .{},
875 .aligned_uavs = .{},
818 .uavs = .empty,
876819 };
877820 defer {
878 assert(dg.uav_deps.count() == 0);
879 assert(dg.aligned_uavs.count() == 0);
821 assert(dg.uavs.count() == 0);
880822 fwd_decl.* = dg.fwd_decl.moveToUnmanaged();
881823 ctype_pool.* = dg.ctype_pool.move();
882824 ctype_pool.freeUnusedCapacity(gpa);
......@@ -896,3 +838,21 @@ pub fn deleteExport(
896838 .uav => |uav| _ = self.exported_uavs.swapRemove(uav),
897839 }
898840}
841
842fn addUavsFromCodegen(c: *C, uavs: *const std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment)) Allocator.Error!void {
843 const gpa = c.base.comp.gpa;
844 try c.uavs.ensureUnusedCapacity(gpa, uavs.count());
845 try c.aligned_uavs.ensureUnusedCapacity(gpa, uavs.count());
846 for (uavs.keys(), uavs.values()) |uav_val, uav_align| {
847 {
848 const gop = c.uavs.getOrPutAssumeCapacity(uav_val);
849 if (!gop.found_existing) gop.value_ptr.* = .{};
850 }
851 if (uav_align != .none) {
852 const gop = c.aligned_uavs.getOrPutAssumeCapacity(uav_val);
853 gop.value_ptr.* = if (gop.found_existing) max: {
854 break :max gop.value_ptr.*.maxStrict(uav_align);
855 } else uav_align;
856 }
857 }
858}
src/link/Coff.zig+21-700
......@@ -1,26 +1,14 @@
1//! The main driver of the COFF linker.
2//! Currently uses our own implementation for the incremental linker, and falls back to
3//! LLD for traditional linking (linking relocatable object files).
4//! LLD is also the default linker for LLVM.
5
6/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
7llvm_object: ?LlvmObject.Ptr = null,
1//! The main driver of the self-hosted COFF linker.
82
93base: link.File,
104image_base: u64,
11subsystem: ?std.Target.SubSystem,
12tsaware: bool,
13nxcompat: bool,
14dynamicbase: bool,
155/// TODO this and minor_subsystem_version should be combined into one property and left as
166/// default or populated together. They should not be separate fields.
177major_subsystem_version: u16,
188minor_subsystem_version: u16,
19lib_directories: []const Directory,
209entry: link.File.OpenOptions.Entry,
2110entry_addr: ?u32,
2211module_definition_file: ?[]const u8,
23pdb_out_path: ?[]const u8,
2412repro: bool,
2513
2614ptr_width: PtrWidth,
......@@ -226,7 +214,6 @@ pub fn createEmpty(
226214 const output_mode = comp.config.output_mode;
227215 const link_mode = comp.config.link_mode;
228216 const use_llvm = comp.config.use_llvm;
229 const use_lld = build_options.have_llvm and comp.config.use_lld;
230217
231218 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {
232219 0...32 => .p32,
......@@ -237,29 +224,21 @@ pub fn createEmpty(
237224 else => 0x1000,
238225 };
239226
240 // If using LLD to link, this code should produce an object file so that it
241 // can be passed to LLD.
242 // If using LLVM to generate the object file for the zig compilation unit,
243 // we need a place to put the object file so that it can be subsequently
244 // handled.
245 const zcu_object_sub_path = if (!use_lld and !use_llvm)
246 null
247 else
248 try allocPrint(arena, "{s}.obj", .{emit.sub_path});
249
250227 const coff = try arena.create(Coff);
251228 coff.* = .{
252229 .base = .{
253230 .tag = .coff,
254231 .comp = comp,
255232 .emit = emit,
256 .zcu_object_sub_path = zcu_object_sub_path,
233 .zcu_object_basename = if (use_llvm)
234 try std.fmt.allocPrint(arena, "{s}_zcu.obj", .{fs.path.stem(emit.sub_path)})
235 else
236 null,
257237 .stack_size = options.stack_size orelse 16777216,
258238 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
259239 .print_gc_sections = options.print_gc_sections,
260240 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
261241 .file = null,
262 .disable_lld_caching = options.disable_lld_caching,
263242 .build_id = options.build_id,
264243 },
265244 .ptr_width = ptr_width,
......@@ -284,45 +263,23 @@ pub fn createEmpty(
284263 .Obj => 0,
285264 },
286265
287 // Subsystem depends on the set of public symbol names from linked objects.
288 // See LinkerDriver::inferSubsystem from the LLD project for the flow chart.
289 .subsystem = options.subsystem,
290
291266 .entry = options.entry,
292267
293 .tsaware = options.tsaware,
294 .nxcompat = options.nxcompat,
295 .dynamicbase = options.dynamicbase,
296268 .major_subsystem_version = options.major_subsystem_version orelse 6,
297269 .minor_subsystem_version = options.minor_subsystem_version orelse 0,
298 .lib_directories = options.lib_directories,
299270 .entry_addr = math.cast(u32, options.entry_addr orelse 0) orelse
300271 return error.EntryAddressTooBig,
301272 .module_definition_file = options.module_definition_file,
302 .pdb_out_path = options.pdb_out_path,
303273 .repro = options.repro,
304274 };
305 if (use_llvm and comp.config.have_zcu) {
306 coff.llvm_object = try LlvmObject.create(arena, comp);
307 }
308275 errdefer coff.base.destroy();
309276
310 if (use_lld and (use_llvm or !comp.config.have_zcu)) {
311 // LLVM emits the object file (if any); LLD links it into the final product.
312 return coff;
313 }
314
315 // What path should this COFF linker code output to?
316 // If using LLD to link, this code should produce an object file so that it
317 // can be passed to LLD.
318 const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path;
319 coff.base.file = try emit.root_dir.handle.createFile(sub_path, .{
277 coff.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
320278 .truncate = true,
321279 .read = true,
322 .mode = link.File.determineMode(use_lld, output_mode, link_mode),
280 .mode = link.File.determineMode(output_mode, link_mode),
323281 });
324282
325 assert(coff.llvm_object == null);
326283 const gpa = comp.gpa;
327284
328285 try coff.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32));
......@@ -428,8 +385,6 @@ pub fn open(
428385pub fn deinit(coff: *Coff) void {
429386 const gpa = coff.base.comp.gpa;
430387
431 if (coff.llvm_object) |llvm_object| llvm_object.deinit();
432
433388 for (coff.sections.items(.free_list)) |*free_list| {
434389 free_list.deinit(gpa);
435390 }
......@@ -1097,15 +1052,11 @@ pub fn updateFunc(
10971052 coff: *Coff,
10981053 pt: Zcu.PerThread,
10991054 func_index: InternPool.Index,
1100 air: Air,
1101 liveness: Air.Liveness,
1055 mir: *const codegen.AnyMir,
11021056) link.File.UpdateNavError!void {
11031057 if (build_options.skip_non_native and builtin.object_format != .coff) {
11041058 @panic("Attempted to compile for object format that was disabled by build configuration");
11051059 }
1106 if (coff.llvm_object) |llvm_object| {
1107 return llvm_object.updateFunc(pt, func_index, air, liveness);
1108 }
11091060 const tracy = trace(@src());
11101061 defer tracy.end();
11111062
......@@ -1122,29 +1073,15 @@ pub fn updateFunc(
11221073 var code_buffer: std.ArrayListUnmanaged(u8) = .empty;
11231074 defer code_buffer.deinit(gpa);
11241075
1125 codegen.generateFunction(
1076 try codegen.emitFunction(
11261077 &coff.base,
11271078 pt,
11281079 zcu.navSrcLoc(nav_index),
11291080 func_index,
1130 air,
1131 liveness,
1081 mir,
11321082 &code_buffer,
11331083 .none,
1134 ) catch |err| switch (err) {
1135 error.CodegenFail => return error.CodegenFail,
1136 error.OutOfMemory => return error.OutOfMemory,
1137 error.Overflow, error.RelocationNotByteAligned => |e| {
1138 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
1139 gpa,
1140 zcu.navSrcLoc(nav_index),
1141 "unable to codegen: {s}",
1142 .{@errorName(e)},
1143 ));
1144 try zcu.retryable_failures.append(zcu.gpa, AnalUnit.wrap(.{ .func = func_index }));
1145 return error.CodegenFail;
1146 },
1147 };
1084 );
11481085
11491086 try coff.updateNavCode(pt, nav_index, code_buffer.items, .FUNCTION);
11501087
......@@ -1205,7 +1142,6 @@ pub fn updateNav(
12051142 if (build_options.skip_non_native and builtin.object_format != .coff) {
12061143 @panic("Attempted to compile for object format that was disabled by build configuration");
12071144 }
1208 if (coff.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav_index);
12091145 const tracy = trace(@src());
12101146 defer tracy.end();
12111147
......@@ -1330,7 +1266,7 @@ pub fn getOrCreateAtomForLazySymbol(
13301266 }
13311267 state_ptr.* = .pending_flush;
13321268 const atom = atom_ptr.*;
1333 // anyerror needs to be deferred until flushModule
1269 // anyerror needs to be deferred until flush
13341270 if (lazy_sym.ty != .anyerror_type) try coff.updateLazySymbolAtom(pt, lazy_sym, atom, switch (lazy_sym.kind) {
13351271 .code => coff.text_section_index.?,
13361272 .const_data => coff.rdata_section_index.?,
......@@ -1463,8 +1399,6 @@ fn updateNavCode(
14631399}
14641400
14651401pub fn freeNav(coff: *Coff, nav_index: InternPool.NavIndex) void {
1466 if (coff.llvm_object) |llvm_object| return llvm_object.freeNav(nav_index);
1467
14681402 const gpa = coff.base.comp.gpa;
14691403
14701404 if (coff.decls.fetchOrderedRemove(nav_index)) |const_kv| {
......@@ -1485,50 +1419,7 @@ pub fn updateExports(
14851419 }
14861420
14871421 const zcu = pt.zcu;
1488 const ip = &zcu.intern_pool;
1489 const comp = coff.base.comp;
1490 const target = comp.root_mod.resolved_target.result;
1491
1492 if (comp.config.use_llvm) {
1493 // Even in the case of LLVM, we need to notice certain exported symbols in order to
1494 // detect the default subsystem.
1495 for (export_indices) |export_idx| {
1496 const exp = export_idx.ptr(zcu);
1497 const exported_nav_index = switch (exp.exported) {
1498 .nav => |nav| nav,
1499 .uav => continue,
1500 };
1501 const exported_nav = ip.getNav(exported_nav_index);
1502 const exported_ty = exported_nav.typeOf(ip);
1503 if (!ip.isFunctionType(exported_ty)) continue;
1504 const c_cc = target.cCallingConvention().?;
1505 const winapi_cc: std.builtin.CallingConvention = switch (target.cpu.arch) {
1506 .x86 => .{ .x86_stdcall = .{} },
1507 else => c_cc,
1508 };
1509 const exported_cc = Type.fromInterned(exported_ty).fnCallingConvention(zcu);
1510 const CcTag = std.builtin.CallingConvention.Tag;
1511 if (@as(CcTag, exported_cc) == @as(CcTag, c_cc) and exp.opts.name.eqlSlice("main", ip) and comp.config.link_libc) {
1512 zcu.stage1_flags.have_c_main = true;
1513 } else if (@as(CcTag, exported_cc) == @as(CcTag, winapi_cc) and target.os.tag == .windows) {
1514 if (exp.opts.name.eqlSlice("WinMain", ip)) {
1515 zcu.stage1_flags.have_winmain = true;
1516 } else if (exp.opts.name.eqlSlice("wWinMain", ip)) {
1517 zcu.stage1_flags.have_wwinmain = true;
1518 } else if (exp.opts.name.eqlSlice("WinMainCRTStartup", ip)) {
1519 zcu.stage1_flags.have_winmain_crt_startup = true;
1520 } else if (exp.opts.name.eqlSlice("wWinMainCRTStartup", ip)) {
1521 zcu.stage1_flags.have_wwinmain_crt_startup = true;
1522 } else if (exp.opts.name.eqlSlice("DllMainCRTStartup", ip)) {
1523 zcu.stage1_flags.have_dllmain_crt_startup = true;
1524 }
1525 }
1526 }
1527 }
1528
1529 if (coff.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
1530
1531 const gpa = comp.gpa;
1422 const gpa = zcu.gpa;
15321423
15331424 const metadata = switch (exported) {
15341425 .nav => |nav| blk: {
......@@ -1621,7 +1512,6 @@ pub fn deleteExport(
16211512 exported: Zcu.Exported,
16221513 name: InternPool.NullTerminatedString,
16231514) void {
1624 if (coff.llvm_object) |_| return;
16251515 const metadata = switch (exported) {
16261516 .nav => |nav| coff.navs.getPtr(nav),
16271517 .uav => |uav| coff.uavs.getPtr(uav),
......@@ -1680,571 +1570,7 @@ fn resolveGlobalSymbol(coff: *Coff, current: SymbolWithLoc) !void {
16801570 gop.value_ptr.* = current;
16811571}
16821572
1683pub fn flush(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
1684 const comp = coff.base.comp;
1685 const use_lld = build_options.have_llvm and comp.config.use_lld;
1686 const diags = &comp.link_diags;
1687 if (use_lld) {
1688 return coff.linkWithLLD(arena, tid, prog_node) catch |err| switch (err) {
1689 error.OutOfMemory => return error.OutOfMemory,
1690 error.LinkFailure => return error.LinkFailure,
1691 else => |e| return diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),
1692 };
1693 }
1694 switch (comp.config.output_mode) {
1695 .Exe, .Obj => return coff.flushModule(arena, tid, prog_node),
1696 .Lib => return diags.fail("writing lib files not yet implemented for COFF", .{}),
1697 }
1698}
1699
1700fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
1701 dev.check(.lld_linker);
1702
1703 const tracy = trace(@src());
1704 defer tracy.end();
1705
1706 const comp = coff.base.comp;
1707 const gpa = comp.gpa;
1708
1709 const directory = coff.base.emit.root_dir; // Just an alias to make it shorter to type.
1710 const full_out_path = try directory.join(arena, &[_][]const u8{coff.base.emit.sub_path});
1711
1712 // If there is no Zig code to compile, then we should skip flushing the output file because it
1713 // will not be part of the linker line anyway.
1714 const module_obj_path: ?[]const u8 = if (comp.zcu != null) blk: {
1715 try coff.flushModule(arena, tid, prog_node);
1716
1717 if (fs.path.dirname(full_out_path)) |dirname| {
1718 break :blk try fs.path.join(arena, &.{ dirname, coff.base.zcu_object_sub_path.? });
1719 } else {
1720 break :blk coff.base.zcu_object_sub_path.?;
1721 }
1722 } else null;
1723
1724 const sub_prog_node = prog_node.start("LLD Link", 0);
1725 defer sub_prog_node.end();
1726
1727 const is_lib = comp.config.output_mode == .Lib;
1728 const is_dyn_lib = comp.config.link_mode == .dynamic and is_lib;
1729 const is_exe_or_dyn_lib = is_dyn_lib or comp.config.output_mode == .Exe;
1730 const link_in_crt = comp.config.link_libc and is_exe_or_dyn_lib;
1731 const target = comp.root_mod.resolved_target.result;
1732 const optimize_mode = comp.root_mod.optimize_mode;
1733 const entry_name: ?[]const u8 = switch (coff.entry) {
1734 // This logic isn't quite right for disabled or enabled. No point in fixing it
1735 // when the goal is to eliminate dependency on LLD anyway.
1736 // https://github.com/ziglang/zig/issues/17751
1737 .disabled, .default, .enabled => null,
1738 .named => |name| name,
1739 };
1740
1741 // See link/Elf.zig for comments on how this mechanism works.
1742 const id_symlink_basename = "lld.id";
1743
1744 var man: Cache.Manifest = undefined;
1745 defer if (!coff.base.disable_lld_caching) man.deinit();
1746
1747 var digest: [Cache.hex_digest_len]u8 = undefined;
1748
1749 if (!coff.base.disable_lld_caching) {
1750 man = comp.cache_parent.obtain();
1751 coff.base.releaseLock();
1752
1753 comptime assert(Compilation.link_hash_implementation_version == 14);
1754
1755 try link.hashInputs(&man, comp.link_inputs);
1756 for (comp.c_object_table.keys()) |key| {
1757 _ = try man.addFilePath(key.status.success.object_path, null);
1758 }
1759 for (comp.win32_resource_table.keys()) |key| {
1760 _ = try man.addFile(key.status.success.res_path, null);
1761 }
1762 try man.addOptionalFile(module_obj_path);
1763 man.hash.addOptionalBytes(entry_name);
1764 man.hash.add(coff.base.stack_size);
1765 man.hash.add(coff.image_base);
1766 man.hash.add(coff.base.build_id);
1767 {
1768 // TODO remove this, libraries must instead be resolved by the frontend.
1769 for (coff.lib_directories) |lib_directory| man.hash.addOptionalBytes(lib_directory.path);
1770 }
1771 man.hash.add(comp.skip_linker_dependencies);
1772 if (comp.config.link_libc) {
1773 man.hash.add(comp.libc_installation != null);
1774 if (comp.libc_installation) |libc_installation| {
1775 man.hash.addBytes(libc_installation.crt_dir.?);
1776 if (target.abi == .msvc or target.abi == .itanium) {
1777 man.hash.addBytes(libc_installation.msvc_lib_dir.?);
1778 man.hash.addBytes(libc_installation.kernel32_lib_dir.?);
1779 }
1780 }
1781 }
1782 man.hash.addListOfBytes(comp.windows_libs.keys());
1783 man.hash.addListOfBytes(comp.force_undefined_symbols.keys());
1784 man.hash.addOptional(coff.subsystem);
1785 man.hash.add(comp.config.is_test);
1786 man.hash.add(coff.tsaware);
1787 man.hash.add(coff.nxcompat);
1788 man.hash.add(coff.dynamicbase);
1789 man.hash.add(coff.base.allow_shlib_undefined);
1790 // strip does not need to go into the linker hash because it is part of the hash namespace
1791 man.hash.add(coff.major_subsystem_version);
1792 man.hash.add(coff.minor_subsystem_version);
1793 man.hash.add(coff.repro);
1794 man.hash.addOptional(comp.version);
1795 try man.addOptionalFile(coff.module_definition_file);
1796
1797 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
1798 _ = try man.hit();
1799 digest = man.final();
1800 var prev_digest_buf: [digest.len]u8 = undefined;
1801 const prev_digest: []u8 = Cache.readSmallFile(
1802 directory.handle,
1803 id_symlink_basename,
1804 &prev_digest_buf,
1805 ) catch |err| blk: {
1806 log.debug("COFF LLD new_digest={s} error: {s}", .{ std.fmt.fmtSliceHexLower(&digest), @errorName(err) });
1807 // Handle this as a cache miss.
1808 break :blk prev_digest_buf[0..0];
1809 };
1810 if (mem.eql(u8, prev_digest, &digest)) {
1811 log.debug("COFF LLD digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});
1812 // Hot diggity dog! The output binary is already there.
1813 coff.base.lock = man.toOwnedLock();
1814 return;
1815 }
1816 log.debug("COFF LLD prev_digest={s} new_digest={s}", .{ std.fmt.fmtSliceHexLower(prev_digest), std.fmt.fmtSliceHexLower(&digest) });
1817
1818 // We are about to change the output file to be different, so we invalidate the build hash now.
1819 directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
1820 error.FileNotFound => {},
1821 else => |e| return e,
1822 };
1823 }
1824
1825 if (comp.config.output_mode == .Obj) {
1826 // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy
1827 // here. TODO: think carefully about how we can avoid this redundant operation when doing
1828 // build-obj. See also the corresponding TODO in linkAsArchive.
1829 const the_object_path = blk: {
1830 if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
1831
1832 if (comp.c_object_table.count() != 0)
1833 break :blk comp.c_object_table.keys()[0].status.success.object_path;
1834
1835 if (module_obj_path) |p|
1836 break :blk Path.initCwd(p);
1837
1838 // TODO I think this is unreachable. Audit this situation when solving the above TODO
1839 // regarding eliding redundant object -> object transformations.
1840 return error.NoObjectsToLink;
1841 };
1842 try std.fs.Dir.copyFile(
1843 the_object_path.root_dir.handle,
1844 the_object_path.sub_path,
1845 directory.handle,
1846 coff.base.emit.sub_path,
1847 .{},
1848 );
1849 } else {
1850 // Create an LLD command line and invoke it.
1851 var argv = std.ArrayList([]const u8).init(gpa);
1852 defer argv.deinit();
1853 // We will invoke ourselves as a child process to gain access to LLD.
1854 // This is necessary because LLD does not behave properly as a library -
1855 // it calls exit() and does not reset all global data between invocations.
1856 const linker_command = "lld-link";
1857 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
1858
1859 if (target.isMinGW()) {
1860 try argv.append("-lldmingw");
1861 }
1862
1863 try argv.append("-ERRORLIMIT:0");
1864 try argv.append("-NOLOGO");
1865 if (comp.config.debug_format != .strip) {
1866 try argv.append("-DEBUG");
1867
1868 const out_ext = std.fs.path.extension(full_out_path);
1869 const out_pdb = coff.pdb_out_path orelse try allocPrint(arena, "{s}.pdb", .{
1870 full_out_path[0 .. full_out_path.len - out_ext.len],
1871 });
1872 const out_pdb_basename = std.fs.path.basename(out_pdb);
1873
1874 try argv.append(try allocPrint(arena, "-PDB:{s}", .{out_pdb}));
1875 try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb_basename}));
1876 }
1877 if (comp.version) |version| {
1878 try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));
1879 }
1880
1881 if (target_util.llvmMachineAbi(target)) |mabi| {
1882 try argv.append(try allocPrint(arena, "-MLLVM:-target-abi={s}", .{mabi}));
1883 }
1884
1885 try argv.append(try allocPrint(arena, "-MLLVM:-float-abi={s}", .{if (target.abi.float() == .hard) "hard" else "soft"}));
1886
1887 if (comp.config.lto != .none) {
1888 switch (optimize_mode) {
1889 .Debug => {},
1890 .ReleaseSmall => try argv.append("-OPT:lldlto=2"),
1891 .ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"),
1892 }
1893 }
1894 if (comp.config.output_mode == .Exe) {
1895 try argv.append(try allocPrint(arena, "-STACK:{d}", .{coff.base.stack_size}));
1896 }
1897 try argv.append(try allocPrint(arena, "-BASE:{d}", .{coff.image_base}));
1898
1899 switch (coff.base.build_id) {
1900 .none => try argv.append("-BUILD-ID:NO"),
1901 .fast => try argv.append("-BUILD-ID"),
1902 .uuid, .sha1, .md5, .hexstring => {},
1903 }
1904
1905 if (target.cpu.arch == .x86) {
1906 try argv.append("-MACHINE:X86");
1907 } else if (target.cpu.arch == .x86_64) {
1908 try argv.append("-MACHINE:X64");
1909 } else if (target.cpu.arch == .thumb) {
1910 try argv.append("-MACHINE:ARM");
1911 } else if (target.cpu.arch == .aarch64) {
1912 try argv.append("-MACHINE:ARM64");
1913 }
1914
1915 for (comp.force_undefined_symbols.keys()) |symbol| {
1916 try argv.append(try allocPrint(arena, "-INCLUDE:{s}", .{symbol}));
1917 }
1918
1919 if (is_dyn_lib) {
1920 try argv.append("-DLL");
1921 }
1922
1923 if (entry_name) |name| {
1924 try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{name}));
1925 }
1926
1927 if (coff.repro) {
1928 try argv.append("-BREPRO");
1929 }
1930
1931 if (coff.tsaware) {
1932 try argv.append("-tsaware");
1933 }
1934 if (coff.nxcompat) {
1935 try argv.append("-nxcompat");
1936 }
1937 if (!coff.dynamicbase) {
1938 try argv.append("-dynamicbase:NO");
1939 }
1940 if (coff.base.allow_shlib_undefined) {
1941 try argv.append("-FORCE:UNRESOLVED");
1942 }
1943
1944 try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
1945
1946 if (comp.implib_emit) |emit| {
1947 const implib_out_path = try emit.root_dir.join(arena, &[_][]const u8{emit.sub_path});
1948 try argv.append(try allocPrint(arena, "-IMPLIB:{s}", .{implib_out_path}));
1949 }
1950
1951 if (comp.config.link_libc) {
1952 if (comp.libc_installation) |libc_installation| {
1953 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));
1954
1955 if (target.abi == .msvc or target.abi == .itanium) {
1956 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.msvc_lib_dir.?}));
1957 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.kernel32_lib_dir.?}));
1958 }
1959 }
1960 }
1961
1962 for (coff.lib_directories) |lib_directory| {
1963 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_directory.path orelse "."}));
1964 }
1965
1966 try argv.ensureUnusedCapacity(comp.link_inputs.len);
1967 for (comp.link_inputs) |link_input| switch (link_input) {
1968 .dso_exact => unreachable, // not applicable to PE/COFF
1969 inline .dso, .res => |x| {
1970 argv.appendAssumeCapacity(try x.path.toString(arena));
1971 },
1972 .object, .archive => |obj| {
1973 if (obj.must_link) {
1974 argv.appendAssumeCapacity(try allocPrint(arena, "-WHOLEARCHIVE:{}", .{@as(Path, obj.path)}));
1975 } else {
1976 argv.appendAssumeCapacity(try obj.path.toString(arena));
1977 }
1978 },
1979 };
1980
1981 for (comp.c_object_table.keys()) |key| {
1982 try argv.append(try key.status.success.object_path.toString(arena));
1983 }
1984
1985 for (comp.win32_resource_table.keys()) |key| {
1986 try argv.append(key.status.success.res_path);
1987 }
1988
1989 if (module_obj_path) |p| {
1990 try argv.append(p);
1991 }
1992
1993 if (coff.module_definition_file) |def| {
1994 try argv.append(try allocPrint(arena, "-DEF:{s}", .{def}));
1995 }
1996
1997 const resolved_subsystem: ?std.Target.SubSystem = blk: {
1998 if (coff.subsystem) |explicit| break :blk explicit;
1999 switch (target.os.tag) {
2000 .windows => {
2001 if (comp.zcu) |module| {
2002 if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib)
2003 break :blk null;
2004 if (module.stage1_flags.have_c_main or comp.config.is_test or
2005 module.stage1_flags.have_winmain_crt_startup or
2006 module.stage1_flags.have_wwinmain_crt_startup)
2007 {
2008 break :blk .Console;
2009 }
2010 if (module.stage1_flags.have_winmain or module.stage1_flags.have_wwinmain)
2011 break :blk .Windows;
2012 }
2013 },
2014 .uefi => break :blk .EfiApplication,
2015 else => {},
2016 }
2017 break :blk null;
2018 };
2019
2020 const Mode = enum { uefi, win32 };
2021 const mode: Mode = mode: {
2022 if (resolved_subsystem) |subsystem| {
2023 const subsystem_suffix = try allocPrint(arena, ",{d}.{d}", .{
2024 coff.major_subsystem_version, coff.minor_subsystem_version,
2025 });
2026
2027 switch (subsystem) {
2028 .Console => {
2029 try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{
2030 subsystem_suffix,
2031 }));
2032 break :mode .win32;
2033 },
2034 .EfiApplication => {
2035 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{
2036 subsystem_suffix,
2037 }));
2038 break :mode .uefi;
2039 },
2040 .EfiBootServiceDriver => {
2041 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{
2042 subsystem_suffix,
2043 }));
2044 break :mode .uefi;
2045 },
2046 .EfiRom => {
2047 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{
2048 subsystem_suffix,
2049 }));
2050 break :mode .uefi;
2051 },
2052 .EfiRuntimeDriver => {
2053 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{
2054 subsystem_suffix,
2055 }));
2056 break :mode .uefi;
2057 },
2058 .Native => {
2059 try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{
2060 subsystem_suffix,
2061 }));
2062 break :mode .win32;
2063 },
2064 .Posix => {
2065 try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{
2066 subsystem_suffix,
2067 }));
2068 break :mode .win32;
2069 },
2070 .Windows => {
2071 try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{
2072 subsystem_suffix,
2073 }));
2074 break :mode .win32;
2075 },
2076 }
2077 } else if (target.os.tag == .uefi) {
2078 break :mode .uefi;
2079 } else {
2080 break :mode .win32;
2081 }
2082 };
2083
2084 switch (mode) {
2085 .uefi => try argv.appendSlice(&[_][]const u8{
2086 "-BASE:0",
2087 "-ENTRY:EfiMain",
2088 "-OPT:REF",
2089 "-SAFESEH:NO",
2090 "-MERGE:.rdata=.data",
2091 "-NODEFAULTLIB",
2092 "-SECTION:.xdata,D",
2093 }),
2094 .win32 => {
2095 if (link_in_crt) {
2096 if (target.abi.isGnu()) {
2097 if (target.cpu.arch == .x86) {
2098 try argv.append("-ALTERNATENAME:__image_base__=___ImageBase");
2099 } else {
2100 try argv.append("-ALTERNATENAME:__image_base__=__ImageBase");
2101 }
2102
2103 if (is_dyn_lib) {
2104 try argv.append(try comp.crtFileAsString(arena, "dllcrt2.obj"));
2105 if (target.cpu.arch == .x86) {
2106 try argv.append("-ALTERNATENAME:__DllMainCRTStartup@12=_DllMainCRTStartup@12");
2107 } else {
2108 try argv.append("-ALTERNATENAME:_DllMainCRTStartup=DllMainCRTStartup");
2109 }
2110 } else {
2111 try argv.append(try comp.crtFileAsString(arena, "crt2.obj"));
2112 }
2113
2114 try argv.append(try comp.crtFileAsString(arena, "libmingw32.lib"));
2115 } else {
2116 try argv.append(switch (comp.config.link_mode) {
2117 .static => "libcmt.lib",
2118 .dynamic => "msvcrt.lib",
2119 });
2120
2121 const lib_str = switch (comp.config.link_mode) {
2122 .static => "lib",
2123 .dynamic => "",
2124 };
2125 try argv.append(try allocPrint(arena, "{s}vcruntime.lib", .{lib_str}));
2126 try argv.append(try allocPrint(arena, "{s}ucrt.lib", .{lib_str}));
2127
2128 //Visual C++ 2015 Conformance Changes
2129 //https://msdn.microsoft.com/en-us/library/bb531344.aspx
2130 try argv.append("legacy_stdio_definitions.lib");
2131
2132 // msvcrt depends on kernel32 and ntdll
2133 try argv.append("kernel32.lib");
2134 try argv.append("ntdll.lib");
2135 }
2136 } else {
2137 try argv.append("-NODEFAULTLIB");
2138 if (!is_lib and entry_name == null) {
2139 if (comp.zcu) |module| {
2140 if (module.stage1_flags.have_winmain_crt_startup) {
2141 try argv.append("-ENTRY:WinMainCRTStartup");
2142 } else {
2143 try argv.append("-ENTRY:wWinMainCRTStartup");
2144 }
2145 } else {
2146 try argv.append("-ENTRY:wWinMainCRTStartup");
2147 }
2148 }
2149 }
2150 },
2151 }
2152
2153 if (comp.config.link_libc and link_in_crt) {
2154 if (comp.zigc_static_lib) |zigc| {
2155 try argv.append(try zigc.full_object_path.toString(arena));
2156 }
2157 }
2158
2159 // libc++ dep
2160 if (comp.config.link_libcpp) {
2161 try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena));
2162 try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena));
2163 }
2164
2165 // libunwind dep
2166 if (comp.config.link_libunwind) {
2167 try argv.append(try comp.libunwind_static_lib.?.full_object_path.toString(arena));
2168 }
2169
2170 if (comp.config.any_fuzz) {
2171 try argv.append(try comp.fuzzer_lib.?.full_object_path.toString(arena));
2172 }
2173
2174 const ubsan_rt_path: ?Path = blk: {
2175 if (comp.ubsan_rt_lib) |x| break :blk x.full_object_path;
2176 if (comp.ubsan_rt_obj) |x| break :blk x.full_object_path;
2177 break :blk null;
2178 };
2179 if (ubsan_rt_path) |path| {
2180 try argv.append(try path.toString(arena));
2181 }
2182
2183 if (is_exe_or_dyn_lib and !comp.skip_linker_dependencies) {
2184 // MSVC compiler_rt is missing some stuff, so we build it unconditionally but
2185 // and rely on weak linkage to allow MSVC compiler_rt functions to override ours.
2186 if (comp.compiler_rt_obj) |obj| try argv.append(try obj.full_object_path.toString(arena));
2187 if (comp.compiler_rt_lib) |lib| try argv.append(try lib.full_object_path.toString(arena));
2188 }
2189
2190 try argv.ensureUnusedCapacity(comp.windows_libs.count());
2191 for (comp.windows_libs.keys()) |key| {
2192 const lib_basename = try allocPrint(arena, "{s}.lib", .{key});
2193 if (comp.crt_files.get(lib_basename)) |crt_file| {
2194 argv.appendAssumeCapacity(try crt_file.full_object_path.toString(arena));
2195 continue;
2196 }
2197 if (try findLib(arena, lib_basename, coff.lib_directories)) |full_path| {
2198 argv.appendAssumeCapacity(full_path);
2199 continue;
2200 }
2201 if (target.abi.isGnu()) {
2202 const fallback_name = try allocPrint(arena, "lib{s}.dll.a", .{key});
2203 if (try findLib(arena, fallback_name, coff.lib_directories)) |full_path| {
2204 argv.appendAssumeCapacity(full_path);
2205 continue;
2206 }
2207 }
2208 if (target.abi == .msvc or target.abi == .itanium) {
2209 argv.appendAssumeCapacity(lib_basename);
2210 continue;
2211 }
2212
2213 log.err("DLL import library for -l{s} not found", .{key});
2214 return error.DllImportLibraryNotFound;
2215 }
2216
2217 try link.spawnLld(comp, arena, argv.items);
2218 }
2219
2220 if (!coff.base.disable_lld_caching) {
2221 // Update the file with the digest. If it fails we can continue; it only
2222 // means that the next invocation will have an unnecessary cache miss.
2223 Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
2224 log.warn("failed to save linking hash digest file: {s}", .{@errorName(err)});
2225 };
2226 // Again failure here only means an unnecessary cache miss.
2227 man.writeManifest() catch |err| {
2228 log.warn("failed to write cache manifest when linking: {s}", .{@errorName(err)});
2229 };
2230 // We hang on to this lock so that the output file path can be used without
2231 // other processes clobbering it.
2232 coff.base.lock = man.toOwnedLock();
2233 }
2234}
2235
2236fn findLib(arena: Allocator, name: []const u8, lib_directories: []const Directory) !?[]const u8 {
2237 for (lib_directories) |lib_directory| {
2238 lib_directory.handle.access(name, .{}) catch |err| switch (err) {
2239 error.FileNotFound => continue,
2240 else => |e| return e,
2241 };
2242 return try lib_directory.join(arena, &.{name});
2243 }
2244 return null;
2245}
2246
2247pub fn flushModule(
1573pub fn flush(
22481574 coff: *Coff,
22491575 arena: Allocator,
22501576 tid: Zcu.PerThread.Id,
......@@ -2256,22 +1582,22 @@ pub fn flushModule(
22561582 const comp = coff.base.comp;
22571583 const diags = &comp.link_diags;
22581584
2259 if (coff.llvm_object) |llvm_object| {
2260 try coff.base.emitLlvmObject(arena, llvm_object, prog_node);
2261 return;
1585 switch (coff.base.comp.config.output_mode) {
1586 .Exe, .Obj => {},
1587 .Lib => return diags.fail("writing lib files not yet implemented for COFF", .{}),
22621588 }
22631589
22641590 const sub_prog_node = prog_node.start("COFF Flush", 0);
22651591 defer sub_prog_node.end();
22661592
2267 return flushModuleInner(coff, arena, tid) catch |err| switch (err) {
1593 return flushInner(coff, arena, tid) catch |err| switch (err) {
22681594 error.OutOfMemory => return error.OutOfMemory,
22691595 error.LinkFailure => return error.LinkFailure,
22701596 else => |e| return diags.fail("COFF flush failed: {s}", .{@errorName(e)}),
22711597 };
22721598}
22731599
2274fn flushModuleInner(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id) !void {
1600fn flushInner(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id) !void {
22751601 _ = arena;
22761602
22771603 const comp = coff.base.comp;
......@@ -2397,7 +1723,6 @@ pub fn getNavVAddr(
23971723 nav_index: InternPool.Nav.Index,
23981724 reloc_info: link.File.RelocInfo,
23991725) !u64 {
2400 assert(coff.llvm_object == null);
24011726 const zcu = pt.zcu;
24021727 const ip = &zcu.intern_pool;
24031728 const nav = ip.getNav(nav_index);
......@@ -2442,7 +1767,7 @@ pub fn lowerUav(
24421767 const atom = coff.getAtom(metadata.atom);
24431768 const existing_addr = atom.getSymbol(coff).value;
24441769 if (uav_alignment.check(existing_addr))
2445 return .{ .mcv = .{ .load_direct = atom.getSymbolIndex().? } };
1770 return .{ .mcv = .{ .load_symbol = atom.getSymbolIndex().? } };
24461771 }
24471772
24481773 var name_buf: [32]u8 = undefined;
......@@ -2474,7 +1799,7 @@ pub fn lowerUav(
24741799 .section = coff.rdata_section_index.?,
24751800 });
24761801 return .{ .mcv = .{
2477 .load_direct = coff.getAtom(atom_index).getSymbolIndex().?,
1802 .load_symbol = coff.getAtom(atom_index).getSymbolIndex().?,
24781803 } };
24791804}
24801805
......@@ -2483,8 +1808,6 @@ pub fn getUavVAddr(
24831808 uav: InternPool.Index,
24841809 reloc_info: link.File.RelocInfo,
24851810) !u64 {
2486 assert(coff.llvm_object == null);
2487
24881811 const this_atom_index = coff.uavs.get(uav).?.atom;
24891812 const sym_index = coff.getAtom(this_atom_index).getSymbolIndex().?;
24901813 const atom_index = coff.getAtomIndexForSymbol(.{
......@@ -3796,9 +3119,7 @@ const link = @import("../link.zig");
37963119const target_util = @import("../target.zig");
37973120const trace = @import("../tracy.zig").trace;
37983121
3799const Air = @import("../Air.zig");
38003122const Compilation = @import("../Compilation.zig");
3801const LlvmObject = @import("../codegen/llvm.zig").Object;
38023123const Zcu = @import("../Zcu.zig");
38033124const InternPool = @import("../InternPool.zig");
38043125const TableSection = @import("table_section.zig").TableSection;
src/link/Dwarf.zig+204-23
......@@ -1474,24 +1474,59 @@ pub const WipNav = struct {
14741474 try cfa.write(wip_nav);
14751475 }
14761476
1477 pub const LocalTag = enum { local_arg, local_var };
1478 pub fn genLocalDebugInfo(
1477 pub const LocalVarTag = enum { arg, local_var };
1478 pub fn genLocalVarDebugInfo(
14791479 wip_nav: *WipNav,
1480 tag: LocalTag,
1481 name: []const u8,
1480 tag: LocalVarTag,
1481 opt_name: ?[]const u8,
14821482 ty: Type,
14831483 loc: Loc,
14841484 ) UpdateError!void {
14851485 assert(wip_nav.func != .none);
14861486 try wip_nav.abbrevCode(switch (tag) {
1487 inline else => |ct_tag| @field(AbbrevCode, @tagName(ct_tag)),
1487 .arg => if (opt_name) |_| .arg else .unnamed_arg,
1488 .local_var => if (opt_name) |_| .local_var else unreachable,
14881489 });
1489 try wip_nav.strp(name);
1490 if (opt_name) |name| try wip_nav.strp(name);
14901491 try wip_nav.refType(ty);
14911492 try wip_nav.infoExprLoc(loc);
14921493 wip_nav.any_children = true;
14931494 }
14941495
1496 pub const LocalConstTag = enum { comptime_arg, local_const };
1497 pub fn genLocalConstDebugInfo(
1498 wip_nav: *WipNav,
1499 src_loc: Zcu.LazySrcLoc,
1500 tag: LocalConstTag,
1501 opt_name: ?[]const u8,
1502 val: Value,
1503 ) UpdateError!void {
1504 assert(wip_nav.func != .none);
1505 const pt = wip_nav.pt;
1506 const zcu = pt.zcu;
1507 const ty = val.typeOf(zcu);
1508 const has_runtime_bits = ty.hasRuntimeBits(zcu);
1509 const has_comptime_state = ty.comptimeOnly(zcu) and try ty.onePossibleValue(pt) == null;
1510 try wip_nav.abbrevCode(if (has_runtime_bits and has_comptime_state) switch (tag) {
1511 .comptime_arg => if (opt_name) |_| .comptime_arg_runtime_bits_comptime_state else .unnamed_comptime_arg_runtime_bits_comptime_state,
1512 .local_const => if (opt_name) |_| .local_const_runtime_bits_comptime_state else unreachable,
1513 } else if (has_comptime_state) switch (tag) {
1514 .comptime_arg => if (opt_name) |_| .comptime_arg_comptime_state else .unnamed_comptime_arg_comptime_state,
1515 .local_const => if (opt_name) |_| .local_const_comptime_state else unreachable,
1516 } else if (has_runtime_bits) switch (tag) {
1517 .comptime_arg => if (opt_name) |_| .comptime_arg_runtime_bits else .unnamed_comptime_arg_runtime_bits,
1518 .local_const => if (opt_name) |_| .local_const_runtime_bits else unreachable,
1519 } else switch (tag) {
1520 .comptime_arg => if (opt_name) |_| .comptime_arg else .unnamed_comptime_arg,
1521 .local_const => if (opt_name) |_| .local_const else unreachable,
1522 });
1523 if (opt_name) |name| try wip_nav.strp(name);
1524 try wip_nav.refType(ty);
1525 if (has_runtime_bits) try wip_nav.blockValue(src_loc, val);
1526 if (has_comptime_state) try wip_nav.refValue(val);
1527 wip_nav.any_children = true;
1528 }
1529
14951530 pub fn genVarArgsDebugInfo(wip_nav: *WipNav) UpdateError!void {
14961531 assert(wip_nav.func != .none);
14971532 try wip_nav.abbrevCode(.is_var_args);
......@@ -1825,7 +1860,8 @@ pub const WipNav = struct {
18251860 fn getNavEntry(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!struct { Unit.Index, Entry.Index } {
18261861 const zcu = wip_nav.pt.zcu;
18271862 const ip = &zcu.intern_pool;
1828 const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav_index).srcInst(ip).resolveFile(ip)).mod.?);
1863 const nav = ip.getNav(nav_index);
1864 const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?);
18291865 const gop = try wip_nav.dwarf.navs.getOrPut(wip_nav.dwarf.gpa, nav_index);
18301866 if (gop.found_existing) return .{ unit, gop.value_ptr.* };
18311867 const entry = try wip_nav.dwarf.addCommonEntry(unit);
......@@ -1842,10 +1878,16 @@ pub const WipNav = struct {
18421878 const zcu = wip_nav.pt.zcu;
18431879 const ip = &zcu.intern_pool;
18441880 const maybe_inst_index = ty.typeDeclInst(zcu);
1845 const unit = if (maybe_inst_index) |inst_index|
1846 try wip_nav.dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?)
1847 else
1848 .main;
1881 const unit = if (maybe_inst_index) |inst_index| switch (switch (ip.indexToKey(ty.toIntern())) {
1882 else => unreachable,
1883 .struct_type => ip.loadStructType(ty.toIntern()).name_nav,
1884 .union_type => ip.loadUnionType(ty.toIntern()).name_nav,
1885 .enum_type => ip.loadEnumType(ty.toIntern()).name_nav,
1886 .opaque_type => ip.loadOpaqueType(ty.toIntern()).name_nav,
1887 }) {
1888 .none => try wip_nav.dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?),
1889 else => |name_nav| return wip_nav.getNavEntry(name_nav.unwrap().?),
1890 } else .main;
18491891 const gop = try wip_nav.dwarf.types.getOrPut(wip_nav.dwarf.gpa, ty.toIntern());
18501892 if (gop.found_existing) return .{ unit, gop.value_ptr.* };
18511893 const entry = try wip_nav.dwarf.addCommonEntry(unit);
......@@ -1864,10 +1906,8 @@ pub const WipNav = struct {
18641906 const ip = &zcu.intern_pool;
18651907 const ty = value.typeOf(zcu);
18661908 if (std.debug.runtime_safety) assert(ty.comptimeOnly(zcu) and try ty.onePossibleValue(wip_nav.pt) == null);
1867 if (!value.isUndef(zcu)) {
1868 if (ty.toIntern() == .type_type) return wip_nav.getTypeEntry(value.toType());
1869 if (ip.isFunctionType(ty.toIntern())) return wip_nav.getNavEntry(zcu.funcInfo(value.toIntern()).owner_nav);
1870 }
1909 if (ty.toIntern() == .type_type) return wip_nav.getTypeEntry(value.toType());
1910 if (ip.isFunctionType(ty.toIntern()) and !value.isUndef(zcu)) return wip_nav.getNavEntry(zcu.funcInfo(value.toIntern()).owner_nav);
18711911 const gop = try wip_nav.dwarf.values.getOrPut(wip_nav.dwarf.gpa, value.toIntern());
18721912 const unit: Unit.Index = .main;
18731913 if (gop.found_existing) return .{ unit, gop.value_ptr.* };
......@@ -1916,7 +1956,10 @@ pub const WipNav = struct {
19161956 &wip_nav.debug_info,
19171957 .{ .debug_output = .{ .dwarf = wip_nav } },
19181958 );
1919 assert(old_len + bytes == wip_nav.debug_info.items.len);
1959 if (old_len + bytes != wip_nav.debug_info.items.len) {
1960 std.debug.print("{} [{}]: {} != {}\n", .{ ty.fmt(wip_nav.pt), ty.toIntern(), bytes, wip_nav.debug_info.items.len - old_len });
1961 unreachable;
1962 }
19201963 }
19211964
19221965 const AbbrevCodeForForm = struct {
......@@ -2788,6 +2831,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
27882831 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
27892832 if (type_gop.found_existing) {
27902833 if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;
2834 assert(!nav_gop.found_existing);
27912835 nav_gop.value_ptr.* = type_gop.value_ptr.*;
27922836 } else {
27932837 if (nav_gop.found_existing)
......@@ -2890,6 +2934,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
28902934 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
28912935 if (type_gop.found_existing) {
28922936 if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;
2937 assert(!nav_gop.found_existing);
28932938 nav_gop.value_ptr.* = type_gop.value_ptr.*;
28942939 } else {
28952940 if (nav_gop.found_existing)
......@@ -2928,6 +2973,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
29282973 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
29292974 if (type_gop.found_existing) {
29302975 if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;
2976 assert(!nav_gop.found_existing);
29312977 nav_gop.value_ptr.* = type_gop.value_ptr.*;
29322978 } else {
29332979 if (nav_gop.found_existing)
......@@ -2998,6 +3044,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
29983044 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
29993045 if (type_gop.found_existing) {
30003046 if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;
3047 assert(!nav_gop.found_existing);
30013048 nav_gop.value_ptr.* = type_gop.value_ptr.*;
30023049 } else {
30033050 if (nav_gop.found_existing)
......@@ -3164,6 +3211,7 @@ fn updateLazyType(
31643211) UpdateError!void {
31653212 const zcu = pt.zcu;
31663213 const ip = &zcu.intern_pool;
3214 assert(ip.typeOf(type_index) == .type_type);
31673215 const ty: Type = .fromInterned(type_index);
31683216 switch (type_index) {
31693217 .generic_poison_type => log.debug("updateLazyType({s})", .{"anytype"}),
......@@ -3200,6 +3248,10 @@ fn updateLazyType(
32003248 defer dwarf.gpa.free(name);
32013249
32023250 switch (ip.indexToKey(type_index)) {
3251 .undef => {
3252 try wip_nav.abbrevCode(.undefined_comptime_value);
3253 try wip_nav.refType(.type);
3254 },
32033255 .int_type => |int_type| {
32043256 try wip_nav.abbrevCode(.numeric_type);
32053257 try wip_nav.strp(name);
......@@ -3633,7 +3685,6 @@ fn updateLazyType(
36333685 },
36343686
36353687 // values, not types
3636 .undef,
36373688 .simple_value,
36383689 .variable,
36393690 .@"extern",
......@@ -3666,7 +3717,11 @@ fn updateLazyValue(
36663717) UpdateError!void {
36673718 const zcu = pt.zcu;
36683719 const ip = &zcu.intern_pool;
3669 log.debug("updateLazyValue({})", .{Value.fromInterned(value_index).fmtValue(pt)});
3720 assert(ip.typeOf(value_index) != .type_type);
3721 log.debug("updateLazyValue(@as({}, {}))", .{
3722 Value.fromInterned(value_index).typeOf(zcu).fmt(pt),
3723 Value.fromInterned(value_index).fmtValue(pt),
3724 });
36703725 var wip_nav: WipNav = .{
36713726 .dwarf = dwarf,
36723727 .pt = pt,
......@@ -3710,9 +3765,8 @@ fn updateLazyValue(
37103765 .inferred_error_set_type,
37113766 => unreachable, // already handled
37123767 .undef => |ty| {
3713 try wip_nav.abbrevCode(.aggregate_comptime_value);
3768 try wip_nav.abbrevCode(.undefined_comptime_value);
37143769 try wip_nav.refType(.fromInterned(ty));
3715 try uleb128(diw, @intFromEnum(AbbrevCode.null));
37163770 },
37173771 .simple_value => unreachable, // opv state
37183772 .variable, .@"extern" => unreachable, // not a value
......@@ -4391,7 +4445,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A
43914445 return @intFromEnum(abbrev_code);
43924446}
43934447
4394pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4448pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
43954449 const zcu = pt.zcu;
43964450 const ip = &zcu.intern_pool;
43974451
......@@ -4890,8 +4944,22 @@ const AbbrevCode = enum {
48904944 block,
48914945 empty_inlined_func,
48924946 inlined_func,
4893 local_arg,
4947 arg,
4948 unnamed_arg,
4949 comptime_arg,
4950 unnamed_comptime_arg,
4951 comptime_arg_runtime_bits,
4952 unnamed_comptime_arg_runtime_bits,
4953 comptime_arg_comptime_state,
4954 unnamed_comptime_arg_comptime_state,
4955 comptime_arg_runtime_bits_comptime_state,
4956 unnamed_comptime_arg_runtime_bits_comptime_state,
48944957 local_var,
4958 local_const,
4959 local_const_runtime_bits,
4960 local_const_comptime_state,
4961 local_const_runtime_bits_comptime_state,
4962 undefined_comptime_value,
48954963 data2_comptime_value,
48964964 data4_comptime_value,
48974965 data8_comptime_value,
......@@ -5663,7 +5731,7 @@ const AbbrevCode = enum {
56635731 .{ .high_pc, .data4 },
56645732 },
56655733 },
5666 .local_arg = .{
5734 .arg = .{
56675735 .tag = .formal_parameter,
56685736 .attrs = &.{
56695737 .{ .name, .strp },
......@@ -5671,6 +5739,81 @@ const AbbrevCode = enum {
56715739 .{ .location, .exprloc },
56725740 },
56735741 },
5742 .unnamed_arg = .{
5743 .tag = .formal_parameter,
5744 .attrs = &.{
5745 .{ .type, .ref_addr },
5746 .{ .location, .exprloc },
5747 },
5748 },
5749 .comptime_arg = .{
5750 .tag = .formal_parameter,
5751 .attrs = &.{
5752 .{ .const_expr, .flag_present },
5753 .{ .name, .strp },
5754 .{ .type, .ref_addr },
5755 },
5756 },
5757 .unnamed_comptime_arg = .{
5758 .tag = .formal_parameter,
5759 .attrs = &.{
5760 .{ .const_expr, .flag_present },
5761 .{ .type, .ref_addr },
5762 },
5763 },
5764 .comptime_arg_runtime_bits = .{
5765 .tag = .formal_parameter,
5766 .attrs = &.{
5767 .{ .const_expr, .flag_present },
5768 .{ .name, .strp },
5769 .{ .type, .ref_addr },
5770 .{ .const_value, .block },
5771 },
5772 },
5773 .unnamed_comptime_arg_runtime_bits = .{
5774 .tag = .formal_parameter,
5775 .attrs = &.{
5776 .{ .const_expr, .flag_present },
5777 .{ .type, .ref_addr },
5778 .{ .const_value, .block },
5779 },
5780 },
5781 .comptime_arg_comptime_state = .{
5782 .tag = .formal_parameter,
5783 .attrs = &.{
5784 .{ .const_expr, .flag_present },
5785 .{ .name, .strp },
5786 .{ .type, .ref_addr },
5787 .{ .ZIG_comptime_value, .ref_addr },
5788 },
5789 },
5790 .unnamed_comptime_arg_comptime_state = .{
5791 .tag = .formal_parameter,
5792 .attrs = &.{
5793 .{ .const_expr, .flag_present },
5794 .{ .type, .ref_addr },
5795 .{ .ZIG_comptime_value, .ref_addr },
5796 },
5797 },
5798 .comptime_arg_runtime_bits_comptime_state = .{
5799 .tag = .formal_parameter,
5800 .attrs = &.{
5801 .{ .const_expr, .flag_present },
5802 .{ .name, .strp },
5803 .{ .type, .ref_addr },
5804 .{ .const_value, .block },
5805 .{ .ZIG_comptime_value, .ref_addr },
5806 },
5807 },
5808 .unnamed_comptime_arg_runtime_bits_comptime_state = .{
5809 .tag = .formal_parameter,
5810 .attrs = &.{
5811 .{ .const_expr, .flag_present },
5812 .{ .type, .ref_addr },
5813 .{ .const_value, .block },
5814 .{ .ZIG_comptime_value, .ref_addr },
5815 },
5816 },
56745817 .local_var = .{
56755818 .tag = .variable,
56765819 .attrs = &.{
......@@ -5679,6 +5822,44 @@ const AbbrevCode = enum {
56795822 .{ .location, .exprloc },
56805823 },
56815824 },
5825 .local_const = .{
5826 .tag = .constant,
5827 .attrs = &.{
5828 .{ .name, .strp },
5829 .{ .type, .ref_addr },
5830 },
5831 },
5832 .local_const_runtime_bits = .{
5833 .tag = .constant,
5834 .attrs = &.{
5835 .{ .name, .strp },
5836 .{ .type, .ref_addr },
5837 .{ .const_value, .block },
5838 },
5839 },
5840 .local_const_comptime_state = .{
5841 .tag = .constant,
5842 .attrs = &.{
5843 .{ .name, .strp },
5844 .{ .type, .ref_addr },
5845 .{ .ZIG_comptime_value, .ref_addr },
5846 },
5847 },
5848 .local_const_runtime_bits_comptime_state = .{
5849 .tag = .constant,
5850 .attrs = &.{
5851 .{ .name, .strp },
5852 .{ .type, .ref_addr },
5853 .{ .const_value, .block },
5854 .{ .ZIG_comptime_value, .ref_addr },
5855 },
5856 },
5857 .undefined_comptime_value = .{
5858 .tag = .ZIG_comptime_value,
5859 .attrs = &.{
5860 .{ .type, .ref_addr },
5861 },
5862 },
56825863 .data2_comptime_value = .{
56835864 .tag = .ZIG_comptime_value,
56845865 .attrs = &.{
src/link/Elf.zig+13-815
......@@ -4,7 +4,6 @@ base: link.File,
44zig_object: ?*ZigObject,
55rpath_table: std.StringArrayHashMapUnmanaged(void),
66image_base: u64,
7emit_relocs: bool,
87z_nodelete: bool,
98z_notext: bool,
109z_defs: bool,
......@@ -16,25 +15,11 @@ z_relro: bool,
1615z_common_page_size: ?u64,
1716/// TODO make this non optional and resolve the default in open()
1817z_max_page_size: ?u64,
19hash_style: HashStyle,
20compress_debug_sections: CompressDebugSections,
21symbol_wrap_set: std.StringArrayHashMapUnmanaged(void),
22sort_section: ?SortSection,
2318soname: ?[]const u8,
24bind_global_refs_locally: bool,
25linker_script: ?[]const u8,
26version_script: ?[]const u8,
27allow_undefined_version: bool,
28enable_new_dtags: ?bool,
29print_icf_sections: bool,
30print_map: bool,
3119entry_name: ?[]const u8,
3220
3321ptr_width: PtrWidth,
3422
35/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
36llvm_object: ?LlvmObject.Ptr = null,
37
3823/// A list of all input files.
3924/// First index is a special "null file". Order is otherwise not observed.
4025files: std.MultiArrayList(File.Entry) = .{},
......@@ -204,9 +189,6 @@ const minimum_atom_size = 64;
204189pub const min_text_capacity = padToIdeal(minimum_atom_size);
205190
206191pub const PtrWidth = enum { p32, p64 };
207pub const HashStyle = enum { sysv, gnu, both };
208pub const CompressDebugSections = enum { none, zlib, zstd };
209pub const SortSection = enum { name, alignment };
210192
211193pub fn createEmpty(
212194 arena: Allocator,
......@@ -217,7 +199,6 @@ pub fn createEmpty(
217199 const target = comp.root_mod.resolved_target.result;
218200 assert(target.ofmt == .elf);
219201
220 const use_lld = build_options.have_llvm and comp.config.use_lld;
221202 const use_llvm = comp.config.use_llvm;
222203 const opt_zcu = comp.zcu;
223204 const output_mode = comp.config.output_mode;
......@@ -268,16 +249,6 @@ pub fn createEmpty(
268249 const is_dyn_lib = output_mode == .Lib and link_mode == .dynamic;
269250 const default_sym_version: elf.Versym = if (is_dyn_lib or comp.config.rdynamic) .GLOBAL else .LOCAL;
270251
271 // If using LLD to link, this code should produce an object file so that it
272 // can be passed to LLD.
273 // If using LLVM to generate the object file for the zig compilation unit,
274 // we need a place to put the object file so that it can be subsequently
275 // handled.
276 const zcu_object_sub_path = if (!use_lld and !use_llvm)
277 null
278 else
279 try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path});
280
281252 var rpath_table: std.StringArrayHashMapUnmanaged(void) = .empty;
282253 try rpath_table.entries.resize(arena, options.rpath_list.len);
283254 @memcpy(rpath_table.entries.items(.key), options.rpath_list);
......@@ -289,13 +260,15 @@ pub fn createEmpty(
289260 .tag = .elf,
290261 .comp = comp,
291262 .emit = emit,
292 .zcu_object_sub_path = zcu_object_sub_path,
263 .zcu_object_basename = if (use_llvm)
264 try std.fmt.allocPrint(arena, "{s}_zcu.o", .{fs.path.stem(emit.sub_path)})
265 else
266 null,
293267 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
294268 .print_gc_sections = options.print_gc_sections,
295269 .stack_size = options.stack_size orelse 16777216,
296270 .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os,
297271 .file = null,
298 .disable_lld_caching = options.disable_lld_caching,
299272 .build_id = options.build_id,
300273 },
301274 .zig_object = null,
......@@ -320,7 +293,6 @@ pub fn createEmpty(
320293 };
321294 },
322295
323 .emit_relocs = options.emit_relocs,
324296 .z_nodelete = options.z_nodelete,
325297 .z_notext = options.z_notext,
326298 .z_defs = options.z_defs,
......@@ -330,30 +302,11 @@ pub fn createEmpty(
330302 .z_relro = options.z_relro,
331303 .z_common_page_size = options.z_common_page_size,
332304 .z_max_page_size = options.z_max_page_size,
333 .hash_style = options.hash_style,
334 .compress_debug_sections = options.compress_debug_sections,
335 .symbol_wrap_set = options.symbol_wrap_set,
336 .sort_section = options.sort_section,
337305 .soname = options.soname,
338 .bind_global_refs_locally = options.bind_global_refs_locally,
339 .linker_script = options.linker_script,
340 .version_script = options.version_script,
341 .allow_undefined_version = options.allow_undefined_version,
342 .enable_new_dtags = options.enable_new_dtags,
343 .print_icf_sections = options.print_icf_sections,
344 .print_map = options.print_map,
345306 .dump_argv_list = .empty,
346307 };
347 if (use_llvm and comp.config.have_zcu) {
348 self.llvm_object = try LlvmObject.create(arena, comp);
349 }
350308 errdefer self.base.destroy();
351309
352 if (use_lld and (use_llvm or !comp.config.have_zcu)) {
353 // LLVM emits the object file (if any); LLD links it into the final product.
354 return self;
355 }
356
357310 // --verbose-link
358311 if (comp.verbose_link) try dumpArgvInit(self, arena);
359312
......@@ -361,13 +314,11 @@ pub fn createEmpty(
361314 const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .static);
362315
363316 // What path should this ELF linker code output to?
364 // If using LLD to link, this code should produce an object file so that it
365 // can be passed to LLD.
366 const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path;
317 const sub_path = emit.sub_path;
367318 self.base.file = try emit.root_dir.handle.createFile(sub_path, .{
368319 .truncate = true,
369320 .read = true,
370 .mode = link.File.determineMode(use_lld, output_mode, link_mode),
321 .mode = link.File.determineMode(output_mode, link_mode),
371322 });
372323
373324 const gpa = comp.gpa;
......@@ -457,8 +408,6 @@ pub fn open(
457408pub fn deinit(self: *Elf) void {
458409 const gpa = self.base.comp.gpa;
459410
460 if (self.llvm_object) |llvm_object| llvm_object.deinit();
461
462411 for (self.file_handles.items) |fh| {
463412 fh.close();
464413 }
......@@ -515,7 +464,6 @@ pub fn deinit(self: *Elf) void {
515464}
516465
517466pub fn getNavVAddr(self: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
518 assert(self.llvm_object == null);
519467 return self.zigObjectPtr().?.getNavVAddr(self, pt, nav_index, reloc_info);
520468}
521469
......@@ -530,7 +478,6 @@ pub fn lowerUav(
530478}
531479
532480pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
533 assert(self.llvm_object == null);
534481 return self.zigObjectPtr().?.getUavVAddr(self, uav, reloc_info);
535482}
536483
......@@ -795,60 +742,36 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
795742}
796743
797744pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
798 const comp = self.base.comp;
799 const use_lld = build_options.have_llvm and comp.config.use_lld;
800 const diags = &comp.link_diags;
801 if (use_lld) {
802 return self.linkWithLLD(arena, tid, prog_node) catch |err| switch (err) {
803 error.OutOfMemory => return error.OutOfMemory,
804 error.LinkFailure => return error.LinkFailure,
805 else => |e| return diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),
806 };
807 }
808 try self.flushModule(arena, tid, prog_node);
809}
810
811pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
812745 const tracy = trace(@src());
813746 defer tracy.end();
814747
815748 const comp = self.base.comp;
816749 const diags = &comp.link_diags;
817750
818 if (self.llvm_object) |llvm_object| {
819 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
820 const use_lld = build_options.have_llvm and comp.config.use_lld;
821 if (use_lld) return;
822 }
823
824751 if (comp.verbose_link) Compilation.dump_argv(self.dump_argv_list.items);
825752
826753 const sub_prog_node = prog_node.start("ELF Flush", 0);
827754 defer sub_prog_node.end();
828755
829 return flushModuleInner(self, arena, tid) catch |err| switch (err) {
756 return flushInner(self, arena, tid) catch |err| switch (err) {
830757 error.OutOfMemory => return error.OutOfMemory,
831758 error.LinkFailure => return error.LinkFailure,
832759 else => |e| return diags.fail("ELF flush failed: {s}", .{@errorName(e)}),
833760 };
834761}
835762
836fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
763fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
837764 const comp = self.base.comp;
838765 const gpa = comp.gpa;
839766 const diags = &comp.link_diags;
840767
841 const module_obj_path: ?Path = if (self.base.zcu_object_sub_path) |path| .{
842 .root_dir = self.base.emit.root_dir,
843 .sub_path = if (fs.path.dirname(self.base.emit.sub_path)) |dirname|
844 try fs.path.join(arena, &.{ dirname, path })
845 else
846 path,
768 const zcu_obj_path: ?Path = if (self.base.zcu_object_basename) |raw| p: {
769 break :p try comp.resolveEmitPathFlush(arena, .temp, raw);
847770 } else null;
848771
849772 if (self.zigObjectPtr()) |zig_object| try zig_object.flush(self, tid);
850773
851 if (module_obj_path) |path| openParseObjectReportingFailure(self, path);
774 if (zcu_obj_path) |path| openParseObjectReportingFailure(self, path);
852775
853776 switch (comp.config.output_mode) {
854777 .Obj => return relocatable.flushObject(self, comp),
......@@ -1508,639 +1431,6 @@ pub fn initOutputSection(self: *Elf, args: struct {
15081431 return out_shndx;
15091432}
15101433
1511fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
1512 dev.check(.lld_linker);
1513
1514 const tracy = trace(@src());
1515 defer tracy.end();
1516
1517 const comp = self.base.comp;
1518 const gpa = comp.gpa;
1519 const diags = &comp.link_diags;
1520
1521 const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type.
1522 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
1523
1524 // If there is no Zig code to compile, then we should skip flushing the output file because it
1525 // will not be part of the linker line anyway.
1526 const module_obj_path: ?[]const u8 = if (comp.zcu != null) blk: {
1527 try self.flushModule(arena, tid, prog_node);
1528
1529 if (fs.path.dirname(full_out_path)) |dirname| {
1530 break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? });
1531 } else {
1532 break :blk self.base.zcu_object_sub_path.?;
1533 }
1534 } else null;
1535
1536 const sub_prog_node = prog_node.start("LLD Link", 0);
1537 defer sub_prog_node.end();
1538
1539 const output_mode = comp.config.output_mode;
1540 const is_obj = output_mode == .Obj;
1541 const is_lib = output_mode == .Lib;
1542 const link_mode = comp.config.link_mode;
1543 const is_dyn_lib = link_mode == .dynamic and is_lib;
1544 const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe;
1545 const have_dynamic_linker = link_mode == .dynamic and is_exe_or_dyn_lib;
1546 const target = self.getTarget();
1547 const compiler_rt_path: ?Path = blk: {
1548 if (comp.compiler_rt_lib) |x| break :blk x.full_object_path;
1549 if (comp.compiler_rt_obj) |x| break :blk x.full_object_path;
1550 break :blk null;
1551 };
1552 const ubsan_rt_path: ?Path = blk: {
1553 if (comp.ubsan_rt_lib) |x| break :blk x.full_object_path;
1554 if (comp.ubsan_rt_obj) |x| break :blk x.full_object_path;
1555 break :blk null;
1556 };
1557
1558 // Here we want to determine whether we can save time by not invoking LLD when the
1559 // output is unchanged. None of the linker options or the object files that are being
1560 // linked are in the hash that namespaces the directory we are outputting to. Therefore,
1561 // we must hash those now, and the resulting digest will form the "id" of the linking
1562 // job we are about to perform.
1563 // After a successful link, we store the id in the metadata of a symlink named "lld.id" in
1564 // the artifact directory. So, now, we check if this symlink exists, and if it matches
1565 // our digest. If so, we can skip linking. Otherwise, we proceed with invoking LLD.
1566 const id_symlink_basename = "lld.id";
1567
1568 var man: std.Build.Cache.Manifest = undefined;
1569 defer if (!self.base.disable_lld_caching) man.deinit();
1570
1571 var digest: [std.Build.Cache.hex_digest_len]u8 = undefined;
1572
1573 if (!self.base.disable_lld_caching) {
1574 man = comp.cache_parent.obtain();
1575
1576 // We are about to obtain this lock, so here we give other processes a chance first.
1577 self.base.releaseLock();
1578
1579 comptime assert(Compilation.link_hash_implementation_version == 14);
1580
1581 try man.addOptionalFile(self.linker_script);
1582 try man.addOptionalFile(self.version_script);
1583 man.hash.add(self.allow_undefined_version);
1584 man.hash.addOptional(self.enable_new_dtags);
1585 try link.hashInputs(&man, comp.link_inputs);
1586 for (comp.c_object_table.keys()) |key| {
1587 _ = try man.addFilePath(key.status.success.object_path, null);
1588 }
1589 try man.addOptionalFile(module_obj_path);
1590 try man.addOptionalFilePath(compiler_rt_path);
1591 try man.addOptionalFilePath(ubsan_rt_path);
1592 try man.addOptionalFilePath(if (comp.tsan_lib) |l| l.full_object_path else null);
1593 try man.addOptionalFilePath(if (comp.fuzzer_lib) |l| l.full_object_path else null);
1594
1595 // We can skip hashing libc and libc++ components that we are in charge of building from Zig
1596 // installation sources because they are always a product of the compiler version + target information.
1597 man.hash.addOptionalBytes(self.entry_name);
1598 man.hash.add(self.image_base);
1599 man.hash.add(self.base.gc_sections);
1600 man.hash.addOptional(self.sort_section);
1601 man.hash.add(comp.link_eh_frame_hdr);
1602 man.hash.add(self.emit_relocs);
1603 man.hash.add(comp.config.rdynamic);
1604 man.hash.addListOfBytes(self.rpath_table.keys());
1605 if (output_mode == .Exe) {
1606 man.hash.add(self.base.stack_size);
1607 }
1608 man.hash.add(self.base.build_id);
1609 man.hash.addListOfBytes(self.symbol_wrap_set.keys());
1610 man.hash.add(comp.skip_linker_dependencies);
1611 man.hash.add(self.z_nodelete);
1612 man.hash.add(self.z_notext);
1613 man.hash.add(self.z_defs);
1614 man.hash.add(self.z_origin);
1615 man.hash.add(self.z_nocopyreloc);
1616 man.hash.add(self.z_now);
1617 man.hash.add(self.z_relro);
1618 man.hash.add(self.z_common_page_size orelse 0);
1619 man.hash.add(self.z_max_page_size orelse 0);
1620 man.hash.add(self.hash_style);
1621 // strip does not need to go into the linker hash because it is part of the hash namespace
1622 if (comp.config.link_libc) {
1623 man.hash.add(comp.libc_installation != null);
1624 if (comp.libc_installation) |libc_installation| {
1625 man.hash.addBytes(libc_installation.crt_dir.?);
1626 }
1627 }
1628 if (have_dynamic_linker) {
1629 man.hash.addOptionalBytes(target.dynamic_linker.get());
1630 }
1631 man.hash.addOptionalBytes(self.soname);
1632 man.hash.addOptional(comp.version);
1633 man.hash.addListOfBytes(comp.force_undefined_symbols.keys());
1634 man.hash.add(self.base.allow_shlib_undefined);
1635 man.hash.add(self.bind_global_refs_locally);
1636 man.hash.add(self.compress_debug_sections);
1637 man.hash.add(comp.config.any_sanitize_thread);
1638 man.hash.add(comp.config.any_fuzz);
1639 man.hash.addOptionalBytes(comp.sysroot);
1640
1641 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
1642 _ = try man.hit();
1643 digest = man.final();
1644
1645 var prev_digest_buf: [digest.len]u8 = undefined;
1646 const prev_digest: []u8 = std.Build.Cache.readSmallFile(
1647 directory.handle,
1648 id_symlink_basename,
1649 &prev_digest_buf,
1650 ) catch |err| blk: {
1651 log.debug("ELF LLD new_digest={s} error: {s}", .{ std.fmt.fmtSliceHexLower(&digest), @errorName(err) });
1652 // Handle this as a cache miss.
1653 break :blk prev_digest_buf[0..0];
1654 };
1655 if (mem.eql(u8, prev_digest, &digest)) {
1656 log.debug("ELF LLD digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});
1657 // Hot diggity dog! The output binary is already there.
1658 self.base.lock = man.toOwnedLock();
1659 return;
1660 }
1661 log.debug("ELF LLD prev_digest={s} new_digest={s}", .{ std.fmt.fmtSliceHexLower(prev_digest), std.fmt.fmtSliceHexLower(&digest) });
1662
1663 // We are about to change the output file to be different, so we invalidate the build hash now.
1664 directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
1665 error.FileNotFound => {},
1666 else => |e| return e,
1667 };
1668 }
1669
1670 // Due to a deficiency in LLD, we need to special-case BPF to a simple file
1671 // copy when generating relocatables. Normally, we would expect `lld -r` to work.
1672 // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails
1673 // before even generating the relocatable.
1674 //
1675 // For m68k, we go through this path because LLD doesn't support it yet, but LLVM can
1676 // produce usable object files.
1677 if (output_mode == .Obj and
1678 (comp.config.lto != .none or
1679 target.cpu.arch.isBpf() or
1680 target.cpu.arch == .lanai or
1681 target.cpu.arch == .m68k or
1682 target.cpu.arch.isSPARC() or
1683 target.cpu.arch == .ve or
1684 target.cpu.arch == .xcore))
1685 {
1686 // In this case we must do a simple file copy
1687 // here. TODO: think carefully about how we can avoid this redundant operation when doing
1688 // build-obj. See also the corresponding TODO in linkAsArchive.
1689 const the_object_path = blk: {
1690 if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
1691
1692 if (comp.c_object_table.count() != 0)
1693 break :blk comp.c_object_table.keys()[0].status.success.object_path;
1694
1695 if (module_obj_path) |p|
1696 break :blk Path.initCwd(p);
1697
1698 // TODO I think this is unreachable. Audit this situation when solving the above TODO
1699 // regarding eliding redundant object -> object transformations.
1700 return error.NoObjectsToLink;
1701 };
1702 try std.fs.Dir.copyFile(
1703 the_object_path.root_dir.handle,
1704 the_object_path.sub_path,
1705 directory.handle,
1706 self.base.emit.sub_path,
1707 .{},
1708 );
1709 } else {
1710 // Create an LLD command line and invoke it.
1711 var argv = std.ArrayList([]const u8).init(gpa);
1712 defer argv.deinit();
1713 // We will invoke ourselves as a child process to gain access to LLD.
1714 // This is necessary because LLD does not behave properly as a library -
1715 // it calls exit() and does not reset all global data between invocations.
1716 const linker_command = "ld.lld";
1717 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
1718 if (is_obj) {
1719 try argv.append("-r");
1720 }
1721
1722 try argv.append("--error-limit=0");
1723
1724 if (comp.sysroot) |sysroot| {
1725 try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot}));
1726 }
1727
1728 if (target_util.llvmMachineAbi(target)) |mabi| {
1729 try argv.appendSlice(&.{
1730 "-mllvm",
1731 try std.fmt.allocPrint(arena, "-target-abi={s}", .{mabi}),
1732 });
1733 }
1734
1735 try argv.appendSlice(&.{
1736 "-mllvm",
1737 try std.fmt.allocPrint(arena, "-float-abi={s}", .{if (target.abi.float() == .hard) "hard" else "soft"}),
1738 });
1739
1740 if (comp.config.lto != .none) {
1741 switch (comp.root_mod.optimize_mode) {
1742 .Debug => {},
1743 .ReleaseSmall => try argv.append("--lto-O2"),
1744 .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"),
1745 }
1746 }
1747 switch (comp.root_mod.optimize_mode) {
1748 .Debug => {},
1749 .ReleaseSmall => try argv.append("-O2"),
1750 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
1751 }
1752
1753 if (self.entry_name) |name| {
1754 try argv.appendSlice(&.{ "--entry", name });
1755 }
1756
1757 for (comp.force_undefined_symbols.keys()) |sym| {
1758 try argv.append("-u");
1759 try argv.append(sym);
1760 }
1761
1762 switch (self.hash_style) {
1763 .gnu => try argv.append("--hash-style=gnu"),
1764 .sysv => try argv.append("--hash-style=sysv"),
1765 .both => {}, // this is the default
1766 }
1767
1768 if (output_mode == .Exe) {
1769 try argv.appendSlice(&.{
1770 "-z",
1771 try std.fmt.allocPrint(arena, "stack-size={d}", .{self.base.stack_size}),
1772 });
1773 }
1774
1775 switch (self.base.build_id) {
1776 .none => try argv.append("--build-id=none"),
1777 .fast, .uuid, .sha1, .md5 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
1778 @tagName(self.base.build_id),
1779 })),
1780 .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{
1781 std.fmt.fmtSliceHexLower(hs.toSlice()),
1782 })),
1783 }
1784
1785 try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base}));
1786
1787 if (self.linker_script) |linker_script| {
1788 try argv.append("-T");
1789 try argv.append(linker_script);
1790 }
1791
1792 if (self.sort_section) |how| {
1793 const arg = try std.fmt.allocPrint(arena, "--sort-section={s}", .{@tagName(how)});
1794 try argv.append(arg);
1795 }
1796
1797 if (self.base.gc_sections) {
1798 try argv.append("--gc-sections");
1799 }
1800
1801 if (self.base.print_gc_sections) {
1802 try argv.append("--print-gc-sections");
1803 }
1804
1805 if (self.print_icf_sections) {
1806 try argv.append("--print-icf-sections");
1807 }
1808
1809 if (self.print_map) {
1810 try argv.append("--print-map");
1811 }
1812
1813 if (comp.link_eh_frame_hdr) {
1814 try argv.append("--eh-frame-hdr");
1815 }
1816
1817 if (self.emit_relocs) {
1818 try argv.append("--emit-relocs");
1819 }
1820
1821 if (comp.config.rdynamic) {
1822 try argv.append("--export-dynamic");
1823 }
1824
1825 if (comp.config.debug_format == .strip) {
1826 try argv.append("-s");
1827 }
1828
1829 if (self.z_nodelete) {
1830 try argv.append("-z");
1831 try argv.append("nodelete");
1832 }
1833 if (self.z_notext) {
1834 try argv.append("-z");
1835 try argv.append("notext");
1836 }
1837 if (self.z_defs) {
1838 try argv.append("-z");
1839 try argv.append("defs");
1840 }
1841 if (self.z_origin) {
1842 try argv.append("-z");
1843 try argv.append("origin");
1844 }
1845 if (self.z_nocopyreloc) {
1846 try argv.append("-z");
1847 try argv.append("nocopyreloc");
1848 }
1849 if (self.z_now) {
1850 // LLD defaults to -zlazy
1851 try argv.append("-znow");
1852 }
1853 if (!self.z_relro) {
1854 // LLD defaults to -zrelro
1855 try argv.append("-znorelro");
1856 }
1857 if (self.z_common_page_size) |size| {
1858 try argv.append("-z");
1859 try argv.append(try std.fmt.allocPrint(arena, "common-page-size={d}", .{size}));
1860 }
1861 if (self.z_max_page_size) |size| {
1862 try argv.append("-z");
1863 try argv.append(try std.fmt.allocPrint(arena, "max-page-size={d}", .{size}));
1864 }
1865
1866 if (getLDMOption(target)) |ldm| {
1867 try argv.append("-m");
1868 try argv.append(ldm);
1869 }
1870
1871 if (link_mode == .static) {
1872 if (target.cpu.arch.isArm()) {
1873 try argv.append("-Bstatic");
1874 } else {
1875 try argv.append("-static");
1876 }
1877 } else if (switch (target.os.tag) {
1878 else => is_dyn_lib,
1879 .haiku => is_exe_or_dyn_lib,
1880 }) {
1881 try argv.append("-shared");
1882 }
1883
1884 if (comp.config.pie and output_mode == .Exe) {
1885 try argv.append("-pie");
1886 }
1887
1888 if (is_exe_or_dyn_lib and target.os.tag == .netbsd) {
1889 // Add options to produce shared objects with only 2 PT_LOAD segments.
1890 // NetBSD expects 2 PT_LOAD segments in a shared object, otherwise
1891 // ld.elf_so fails loading dynamic libraries with "not found" error.
1892 // See https://github.com/ziglang/zig/issues/9109 .
1893 try argv.append("--no-rosegment");
1894 try argv.append("-znorelro");
1895 }
1896
1897 try argv.append("-o");
1898 try argv.append(full_out_path);
1899
1900 // csu prelude
1901 const csu = try comp.getCrtPaths(arena);
1902 if (csu.crt0) |p| try argv.append(try p.toString(arena));
1903 if (csu.crti) |p| try argv.append(try p.toString(arena));
1904 if (csu.crtbegin) |p| try argv.append(try p.toString(arena));
1905
1906 for (self.rpath_table.keys()) |rpath| {
1907 try argv.appendSlice(&.{ "-rpath", rpath });
1908 }
1909
1910 for (self.symbol_wrap_set.keys()) |symbol_name| {
1911 try argv.appendSlice(&.{ "-wrap", symbol_name });
1912 }
1913
1914 if (comp.config.link_libc) {
1915 if (comp.libc_installation) |libc_installation| {
1916 try argv.append("-L");
1917 try argv.append(libc_installation.crt_dir.?);
1918 }
1919 }
1920
1921 if (have_dynamic_linker and
1922 (comp.config.link_libc or comp.root_mod.resolved_target.is_explicit_dynamic_linker))
1923 {
1924 if (target.dynamic_linker.get()) |dynamic_linker| {
1925 try argv.append("-dynamic-linker");
1926 try argv.append(dynamic_linker);
1927 }
1928 }
1929
1930 if (is_dyn_lib) {
1931 if (self.soname) |soname| {
1932 try argv.append("-soname");
1933 try argv.append(soname);
1934 }
1935 if (self.version_script) |version_script| {
1936 try argv.append("-version-script");
1937 try argv.append(version_script);
1938 }
1939 if (self.allow_undefined_version) {
1940 try argv.append("--undefined-version");
1941 } else {
1942 try argv.append("--no-undefined-version");
1943 }
1944 if (self.enable_new_dtags) |enable_new_dtags| {
1945 if (enable_new_dtags) {
1946 try argv.append("--enable-new-dtags");
1947 } else {
1948 try argv.append("--disable-new-dtags");
1949 }
1950 }
1951 }
1952
1953 // Positional arguments to the linker such as object files.
1954 var whole_archive = false;
1955
1956 for (self.base.comp.link_inputs) |link_input| switch (link_input) {
1957 .res => unreachable, // Windows-only
1958 .dso => continue,
1959 .object, .archive => |obj| {
1960 if (obj.must_link and !whole_archive) {
1961 try argv.append("-whole-archive");
1962 whole_archive = true;
1963 } else if (!obj.must_link and whole_archive) {
1964 try argv.append("-no-whole-archive");
1965 whole_archive = false;
1966 }
1967 try argv.append(try obj.path.toString(arena));
1968 },
1969 .dso_exact => |dso_exact| {
1970 assert(dso_exact.name[0] == ':');
1971 try argv.appendSlice(&.{ "-l", dso_exact.name });
1972 },
1973 };
1974
1975 if (whole_archive) {
1976 try argv.append("-no-whole-archive");
1977 whole_archive = false;
1978 }
1979
1980 for (comp.c_object_table.keys()) |key| {
1981 try argv.append(try key.status.success.object_path.toString(arena));
1982 }
1983
1984 if (module_obj_path) |p| {
1985 try argv.append(p);
1986 }
1987
1988 if (comp.tsan_lib) |lib| {
1989 assert(comp.config.any_sanitize_thread);
1990 try argv.append(try lib.full_object_path.toString(arena));
1991 }
1992
1993 if (comp.fuzzer_lib) |lib| {
1994 assert(comp.config.any_fuzz);
1995 try argv.append(try lib.full_object_path.toString(arena));
1996 }
1997
1998 if (ubsan_rt_path) |p| {
1999 try argv.append(try p.toString(arena));
2000 }
2001
2002 // Shared libraries.
2003 if (is_exe_or_dyn_lib) {
2004 // Worst-case, we need an --as-needed argument for every lib, as well
2005 // as one before and one after.
2006 try argv.ensureUnusedCapacity(2 * self.base.comp.link_inputs.len + 2);
2007 argv.appendAssumeCapacity("--as-needed");
2008 var as_needed = true;
2009
2010 for (self.base.comp.link_inputs) |link_input| switch (link_input) {
2011 .res => unreachable, // Windows-only
2012 .object, .archive, .dso_exact => continue,
2013 .dso => |dso| {
2014 const lib_as_needed = !dso.needed;
2015 switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) {
2016 0b00, 0b11 => {},
2017 0b01 => {
2018 argv.appendAssumeCapacity("--no-as-needed");
2019 as_needed = false;
2020 },
2021 0b10 => {
2022 argv.appendAssumeCapacity("--as-needed");
2023 as_needed = true;
2024 },
2025 }
2026
2027 // By this time, we depend on these libs being dynamically linked
2028 // libraries and not static libraries (the check for that needs to be earlier),
2029 // but they could be full paths to .so files, in which case we
2030 // want to avoid prepending "-l".
2031 argv.appendAssumeCapacity(try dso.path.toString(arena));
2032 },
2033 };
2034
2035 if (!as_needed) {
2036 argv.appendAssumeCapacity("--as-needed");
2037 as_needed = true;
2038 }
2039
2040 // libc++ dep
2041 if (comp.config.link_libcpp) {
2042 try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena));
2043 try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena));
2044 }
2045
2046 // libunwind dep
2047 if (comp.config.link_libunwind) {
2048 try argv.append(try comp.libunwind_static_lib.?.full_object_path.toString(arena));
2049 }
2050
2051 // libc dep
2052 diags.flags.missing_libc = false;
2053 if (comp.config.link_libc) {
2054 if (comp.libc_installation != null) {
2055 const needs_grouping = link_mode == .static;
2056 if (needs_grouping) try argv.append("--start-group");
2057 try argv.appendSlice(target_util.libcFullLinkFlags(target));
2058 if (needs_grouping) try argv.append("--end-group");
2059 } else if (target.isGnuLibC()) {
2060 for (glibc.libs) |lib| {
2061 if (lib.removed_in) |rem_in| {
2062 if (target.os.versionRange().gnuLibCVersion().?.order(rem_in) != .lt) continue;
2063 }
2064
2065 const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
2066 comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
2067 });
2068 try argv.append(lib_path);
2069 }
2070 try argv.append(try comp.crtFileAsString(arena, "libc_nonshared.a"));
2071 } else if (target.isMuslLibC()) {
2072 try argv.append(try comp.crtFileAsString(arena, switch (link_mode) {
2073 .static => "libc.a",
2074 .dynamic => "libc.so",
2075 }));
2076 } else if (target.isFreeBSDLibC()) {
2077 for (freebsd.libs) |lib| {
2078 const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
2079 comp.freebsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
2080 });
2081 try argv.append(lib_path);
2082 }
2083 } else if (target.isNetBSDLibC()) {
2084 for (netbsd.libs) |lib| {
2085 const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
2086 comp.netbsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
2087 });
2088 try argv.append(lib_path);
2089 }
2090 } else {
2091 diags.flags.missing_libc = true;
2092 }
2093
2094 if (comp.zigc_static_lib) |zigc| {
2095 try argv.append(try zigc.full_object_path.toString(arena));
2096 }
2097 }
2098 }
2099
2100 // compiler-rt. Since compiler_rt exports symbols like `memset`, it needs
2101 // to be after the shared libraries, so they are picked up from the shared
2102 // libraries, not libcompiler_rt.
2103 if (compiler_rt_path) |p| {
2104 try argv.append(try p.toString(arena));
2105 }
2106
2107 // crt postlude
2108 if (csu.crtend) |p| try argv.append(try p.toString(arena));
2109 if (csu.crtn) |p| try argv.append(try p.toString(arena));
2110
2111 if (self.base.allow_shlib_undefined) {
2112 try argv.append("--allow-shlib-undefined");
2113 }
2114
2115 switch (self.compress_debug_sections) {
2116 .none => {},
2117 .zlib => try argv.append("--compress-debug-sections=zlib"),
2118 .zstd => try argv.append("--compress-debug-sections=zstd"),
2119 }
2120
2121 if (self.bind_global_refs_locally) {
2122 try argv.append("-Bsymbolic");
2123 }
2124
2125 try link.spawnLld(comp, arena, argv.items);
2126 }
2127
2128 if (!self.base.disable_lld_caching) {
2129 // Update the file with the digest. If it fails we can continue; it only
2130 // means that the next invocation will have an unnecessary cache miss.
2131 std.Build.Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
2132 log.warn("failed to save linking hash digest file: {s}", .{@errorName(err)});
2133 };
2134 // Again failure here only means an unnecessary cache miss.
2135 man.writeManifest() catch |err| {
2136 log.warn("failed to write cache manifest when linking: {s}", .{@errorName(err)});
2137 };
2138 // We hang on to this lock so that the output file path can be used without
2139 // other processes clobbering it.
2140 self.base.lock = man.toOwnedLock();
2141 }
2142}
2143
21441434pub fn writeShdrTable(self: *Elf) !void {
21451435 const gpa = self.base.comp.gpa;
21461436 const target_endian = self.getTarget().cpu.arch.endian();
......@@ -2385,7 +1675,6 @@ pub fn writeElfHeader(self: *Elf) !void {
23851675}
23861676
23871677pub fn freeNav(self: *Elf, nav: InternPool.Nav.Index) void {
2388 if (self.llvm_object) |llvm_object| return llvm_object.freeNav(nav);
23891678 return self.zigObjectPtr().?.freeNav(self, nav);
23901679}
23911680
......@@ -2393,14 +1682,12 @@ pub fn updateFunc(
23931682 self: *Elf,
23941683 pt: Zcu.PerThread,
23951684 func_index: InternPool.Index,
2396 air: Air,
2397 liveness: Air.Liveness,
1685 mir: *const codegen.AnyMir,
23981686) link.File.UpdateNavError!void {
23991687 if (build_options.skip_non_native and builtin.object_format != .elf) {
24001688 @panic("Attempted to compile for object format that was disabled by build configuration");
24011689 }
2402 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
2403 return self.zigObjectPtr().?.updateFunc(self, pt, func_index, air, liveness);
1690 return self.zigObjectPtr().?.updateFunc(self, pt, func_index, mir);
24041691}
24051692
24061693pub fn updateNav(
......@@ -2411,7 +1698,6 @@ pub fn updateNav(
24111698 if (build_options.skip_non_native and builtin.object_format != .elf) {
24121699 @panic("Attempted to compile for object format that was disabled by build configuration");
24131700 }
2414 if (self.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav);
24151701 return self.zigObjectPtr().?.updateNav(self, pt, nav);
24161702}
24171703
......@@ -2423,7 +1709,6 @@ pub fn updateContainerType(
24231709 if (build_options.skip_non_native and builtin.object_format != .elf) {
24241710 @panic("Attempted to compile for object format that was disabled by build configuration");
24251711 }
2426 if (self.llvm_object) |_| return;
24271712 const zcu = pt.zcu;
24281713 const gpa = zcu.gpa;
24291714 return self.zigObjectPtr().?.updateContainerType(pt, ty) catch |err| switch (err) {
......@@ -2449,12 +1734,10 @@ pub fn updateExports(
24491734 if (build_options.skip_non_native and builtin.object_format != .elf) {
24501735 @panic("Attempted to compile for object format that was disabled by build configuration");
24511736 }
2452 if (self.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
24531737 return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices);
24541738}
24551739
24561740pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
2457 if (self.llvm_object) |_| return;
24581741 return self.zigObjectPtr().?.updateLineNumber(pt, ti_id);
24591742}
24601743
......@@ -2463,7 +1746,6 @@ pub fn deleteExport(
24631746 exported: Zcu.Exported,
24641747 name: InternPool.NullTerminatedString,
24651748) void {
2466 if (self.llvm_object) |_| return;
24671749 return self.zigObjectPtr().?.deleteExport(self, exported, name);
24681750}
24691751
......@@ -4140,85 +3422,6 @@ fn shdrTo32(shdr: elf.Elf64_Shdr) elf.Elf32_Shdr {
41403422 };
41413423}
41423424
4143fn getLDMOption(target: std.Target) ?[]const u8 {
4144 // This should only return emulations understood by LLD's parseEmulation().
4145 return switch (target.cpu.arch) {
4146 .aarch64 => switch (target.os.tag) {
4147 .linux => "aarch64linux",
4148 else => "aarch64elf",
4149 },
4150 .aarch64_be => switch (target.os.tag) {
4151 .linux => "aarch64linuxb",
4152 else => "aarch64elfb",
4153 },
4154 .amdgcn => "elf64_amdgpu",
4155 .arm, .thumb => switch (target.os.tag) {
4156 .linux => "armelf_linux_eabi",
4157 else => "armelf",
4158 },
4159 .armeb, .thumbeb => switch (target.os.tag) {
4160 .linux => "armelfb_linux_eabi",
4161 else => "armelfb",
4162 },
4163 .hexagon => "hexagonelf",
4164 .loongarch32 => "elf32loongarch",
4165 .loongarch64 => "elf64loongarch",
4166 .mips => switch (target.os.tag) {
4167 .freebsd => "elf32btsmip_fbsd",
4168 else => "elf32btsmip",
4169 },
4170 .mipsel => switch (target.os.tag) {
4171 .freebsd => "elf32ltsmip_fbsd",
4172 else => "elf32ltsmip",
4173 },
4174 .mips64 => switch (target.os.tag) {
4175 .freebsd => switch (target.abi) {
4176 .gnuabin32, .muslabin32 => "elf32btsmipn32_fbsd",
4177 else => "elf64btsmip_fbsd",
4178 },
4179 else => switch (target.abi) {
4180 .gnuabin32, .muslabin32 => "elf32btsmipn32",
4181 else => "elf64btsmip",
4182 },
4183 },
4184 .mips64el => switch (target.os.tag) {
4185 .freebsd => switch (target.abi) {
4186 .gnuabin32, .muslabin32 => "elf32ltsmipn32_fbsd",
4187 else => "elf64ltsmip_fbsd",
4188 },
4189 else => switch (target.abi) {
4190 .gnuabin32, .muslabin32 => "elf32ltsmipn32",
4191 else => "elf64ltsmip",
4192 },
4193 },
4194 .msp430 => "msp430elf",
4195 .powerpc => switch (target.os.tag) {
4196 .freebsd => "elf32ppc_fbsd",
4197 .linux => "elf32ppclinux",
4198 else => "elf32ppc",
4199 },
4200 .powerpcle => switch (target.os.tag) {
4201 .linux => "elf32lppclinux",
4202 else => "elf32lppc",
4203 },
4204 .powerpc64 => "elf64ppc",
4205 .powerpc64le => "elf64lppc",
4206 .riscv32 => "elf32lriscv",
4207 .riscv64 => "elf64lriscv",
4208 .s390x => "elf64_s390",
4209 .sparc64 => "elf64_sparc",
4210 .x86 => switch (target.os.tag) {
4211 .freebsd => "elf_i386_fbsd",
4212 else => "elf_i386",
4213 },
4214 .x86_64 => switch (target.abi) {
4215 .gnux32, .muslx32 => "elf32_x86_64",
4216 else => "elf_x86_64",
4217 },
4218 else => null,
4219 };
4220}
4221
42223425pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
42233426 return actual_size +| (actual_size / ideal_factor);
42243427}
......@@ -5303,10 +4506,7 @@ const codegen = @import("../codegen.zig");
53034506const dev = @import("../dev.zig");
53044507const eh_frame = @import("Elf/eh_frame.zig");
53054508const gc = @import("Elf/gc.zig");
5306const glibc = @import("../libs/glibc.zig");
53074509const musl = @import("../libs/musl.zig");
5308const freebsd = @import("../libs/freebsd.zig");
5309const netbsd = @import("../libs/netbsd.zig");
53104510const link = @import("../link.zig");
53114511const relocatable = @import("Elf/relocatable.zig");
53124512const relocation = @import("Elf/relocation.zig");
......@@ -5315,7 +4515,6 @@ const trace = @import("../tracy.zig").trace;
53154515const synthetic_sections = @import("Elf/synthetic_sections.zig");
53164516
53174517const Merge = @import("Elf/Merge.zig");
5318const Air = @import("../Air.zig");
53194518const Archive = @import("Elf/Archive.zig");
53204519const AtomList = @import("Elf/AtomList.zig");
53214520const Compilation = @import("../Compilation.zig");
......@@ -5332,7 +4531,6 @@ const GotSection = synthetic_sections.GotSection;
53324531const GotPltSection = synthetic_sections.GotPltSection;
53334532const HashSection = synthetic_sections.HashSection;
53344533const LinkerDefined = @import("Elf/LinkerDefined.zig");
5335const LlvmObject = @import("../codegen/llvm.zig").Object;
53364534const Zcu = @import("../Zcu.zig");
53374535const Object = @import("Elf/Object.zig");
53384536const InternPool = @import("../InternPool.zig");
src/link/Elf/Symbol.zig-3
......@@ -462,9 +462,6 @@ pub const Flags = packed struct {
462462
463463 /// Whether the symbol is a TLS variable.
464464 is_tls: bool = false,
465
466 /// Whether the symbol is an extern pointer (as opposed to function).
467 is_extern_ptr: bool = false,
468465};
469466
470467pub const Extra = struct {
src/link/Elf/ZigObject.zig+9-17
......@@ -310,7 +310,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
310310 if (self.dwarf) |*dwarf| {
311311 const pt: Zcu.PerThread = .activate(elf_file.base.comp.zcu.?, tid);
312312 defer pt.deactivate();
313 try dwarf.flushModule(pt);
313 try dwarf.flush(pt);
314314
315315 const gpa = elf_file.base.comp.gpa;
316316 const cpu_arch = elf_file.getTarget().cpu.arch;
......@@ -481,7 +481,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
481481 self.debug_str_section_dirty = false;
482482 }
483483
484 // The point of flushModule() is to commit changes, so in theory, nothing should
484 // The point of flush() is to commit changes, so in theory, nothing should
485485 // be dirty after this. However, it is possible for some things to remain
486486 // dirty because they fail to be written in the event of compile errors,
487487 // such as debug_line_header_dirty and debug_info_header_dirty.
......@@ -661,7 +661,7 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {
661661 if (shdr.sh_type == elf.SHT_NOBITS) continue;
662662 if (atom_ptr.scanRelocsRequiresCode(elf_file)) {
663663 // TODO ideally we don't have to fetch the code here.
664 // Perhaps it would make sense to save the code until flushModule where we
664 // Perhaps it would make sense to save the code until flush where we
665665 // would free all of generated code?
666666 const code = try self.codeAlloc(elf_file, atom_index);
667667 defer gpa.free(code);
......@@ -1075,7 +1075,7 @@ pub fn getOrCreateMetadataForLazySymbol(
10751075 }
10761076 state_ptr.* = .pending_flush;
10771077 const symbol_index = symbol_index_ptr.*;
1078 // anyerror needs to be deferred until flushModule
1078 // anyerror needs to be deferred until flush
10791079 if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(elf_file, pt, lazy_sym, symbol_index);
10801080 return symbol_index;
10811081}
......@@ -1142,7 +1142,6 @@ fn getNavShdrIndex(
11421142 const gpa = elf_file.base.comp.gpa;
11431143 const ptr_size = elf_file.ptrWidthBytes();
11441144 const ip = &zcu.intern_pool;
1145 const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
11461145 const nav_val = zcu.navValue(nav_index);
11471146 if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) {
11481147 if (self.text_index) |symbol_index|
......@@ -1162,7 +1161,7 @@ fn getNavShdrIndex(
11621161 else => .{ true, false, nav_val.toIntern() },
11631162 };
11641163 const has_relocs = self.symbol(sym_index).atom(elf_file).?.relocs(elf_file).len > 0;
1165 if (any_non_single_threaded and is_threadlocal) {
1164 if (is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) {
11661165 const is_bss = !has_relocs and for (code) |byte| {
11671166 if (byte != 0) break false;
11681167 } else true;
......@@ -1416,8 +1415,7 @@ pub fn updateFunc(
14161415 elf_file: *Elf,
14171416 pt: Zcu.PerThread,
14181417 func_index: InternPool.Index,
1419 air: Air,
1420 liveness: Air.Liveness,
1418 mir: *const codegen.AnyMir,
14211419) link.File.UpdateNavError!void {
14221420 const tracy = trace(@src());
14231421 defer tracy.end();
......@@ -1438,13 +1436,12 @@ pub fn updateFunc(
14381436 var debug_wip_nav = if (self.dwarf) |*dwarf| try dwarf.initWipNav(pt, func.owner_nav, sym_index) else null;
14391437 defer if (debug_wip_nav) |*wip_nav| wip_nav.deinit();
14401438
1441 try codegen.generateFunction(
1439 try codegen.emitFunction(
14421440 &elf_file.base,
14431441 pt,
14441442 zcu.navSrcLoc(func.owner_nav),
14451443 func_index,
1446 air,
1447 liveness,
1444 mir,
14481445 &code_buffer,
14491446 if (debug_wip_nav) |*dn| .{ .dwarf = dn } else .none,
14501447 );
......@@ -1544,11 +1541,7 @@ pub fn updateNav(
15441541 nav.name.toSlice(ip),
15451542 @"extern".lib_name.toSlice(ip),
15461543 );
1547 if (!ip.isFunctionType(@"extern".ty)) {
1548 const sym = self.symbol(sym_index);
1549 sym.flags.is_extern_ptr = true;
1550 if (@"extern".is_threadlocal) sym.flags.is_tls = true;
1551 }
1544 if (@"extern".is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) self.symbol(sym_index).flags.is_tls = true;
15521545 if (self.dwarf) |*dwarf| dwarf: {
15531546 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf;
15541547 defer debug_wip_nav.deinit();
......@@ -2361,7 +2354,6 @@ const trace = @import("../../tracy.zig").trace;
23612354const std = @import("std");
23622355const Allocator = std.mem.Allocator;
23632356
2364const Air = @import("../../Air.zig");
23652357const Archive = @import("Archive.zig");
23662358const Atom = @import("Atom.zig");
23672359const Dwarf = @import("../Dwarf.zig");
src/link/Goff.zig+21-28
......@@ -13,14 +13,12 @@ const Path = std.Build.Cache.Path;
1313const Zcu = @import("../Zcu.zig");
1414const InternPool = @import("../InternPool.zig");
1515const Compilation = @import("../Compilation.zig");
16const codegen = @import("../codegen.zig");
1617const link = @import("../link.zig");
1718const trace = @import("../tracy.zig").trace;
1819const build_options = @import("build_options");
19const Air = @import("../Air.zig");
20const LlvmObject = @import("../codegen/llvm.zig").Object;
2120
2221base: link.File,
23llvm_object: LlvmObject.Ptr,
2422
2523pub fn createEmpty(
2624 arena: Allocator,
......@@ -36,23 +34,20 @@ pub fn createEmpty(
3634 assert(!use_lld); // Caught by Compilation.Config.resolve.
3735 assert(target.os.tag == .zos); // Caught by Compilation.Config.resolve.
3836
39 const llvm_object = try LlvmObject.create(arena, comp);
4037 const goff = try arena.create(Goff);
4138 goff.* = .{
4239 .base = .{
4340 .tag = .goff,
4441 .comp = comp,
4542 .emit = emit,
46 .zcu_object_sub_path = emit.sub_path,
43 .zcu_object_basename = emit.sub_path,
4744 .gc_sections = options.gc_sections orelse false,
4845 .print_gc_sections = options.print_gc_sections,
4946 .stack_size = options.stack_size orelse 0,
5047 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
5148 .file = null,
52 .disable_lld_caching = options.disable_lld_caching,
5349 .build_id = options.build_id,
5450 },
55 .llvm_object = llvm_object,
5651 };
5752
5853 return goff;
......@@ -70,27 +65,27 @@ pub fn open(
7065}
7166
7267pub fn deinit(self: *Goff) void {
73 self.llvm_object.deinit();
68 _ = self;
7469}
7570
7671pub fn updateFunc(
7772 self: *Goff,
7873 pt: Zcu.PerThread,
7974 func_index: InternPool.Index,
80 air: Air,
81 liveness: Air.Liveness,
75 mir: *const codegen.AnyMir,
8276) link.File.UpdateNavError!void {
83 if (build_options.skip_non_native and builtin.object_format != .goff)
84 @panic("Attempted to compile for object format that was disabled by build configuration");
85
86 try self.llvm_object.updateFunc(pt, func_index, air, liveness);
77 _ = self;
78 _ = pt;
79 _ = func_index;
80 _ = mir;
81 unreachable; // we always use llvm
8782}
8883
8984pub fn updateNav(self: *Goff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
90 if (build_options.skip_non_native and builtin.object_format != .goff)
91 @panic("Attempted to compile for object format that was disabled by build configuration");
92
93 return self.llvm_object.updateNav(pt, nav);
85 _ = self;
86 _ = pt;
87 _ = nav;
88 unreachable; // we always use llvm
9489}
9590
9691pub fn updateExports(
......@@ -99,21 +94,19 @@ pub fn updateExports(
9994 exported: Zcu.Exported,
10095 export_indices: []const Zcu.Export.Index,
10196) !void {
102 if (build_options.skip_non_native and builtin.object_format != .goff)
103 @panic("Attempted to compile for object format that was disabled by build configuration");
104
105 return self.llvm_object.updateExports(pt, exported, export_indices);
97 _ = self;
98 _ = pt;
99 _ = exported;
100 _ = export_indices;
101 unreachable; // we always use llvm
106102}
107103
108104pub fn flush(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
109 return self.flushModule(arena, tid, prog_node);
110}
111
112pub fn flushModule(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
113105 if (build_options.skip_non_native and builtin.object_format != .goff)
114106 @panic("Attempted to compile for object format that was disabled by build configuration");
115107
108 _ = self;
109 _ = arena;
116110 _ = tid;
117
118 try self.base.emitLlvmObject(arena, self.llvm_object, prog_node);
111 _ = prog_node;
119112}
src/link/Lld.zig created+1757
......@@ -0,0 +1,1757 @@
1base: link.File,
2ofmt: union(enum) {
3 elf: Elf,
4 coff: Coff,
5 wasm: Wasm,
6},
7
8const Coff = struct {
9 image_base: u64,
10 entry: link.File.OpenOptions.Entry,
11 pdb_out_path: ?[]const u8,
12 repro: bool,
13 tsaware: bool,
14 nxcompat: bool,
15 dynamicbase: bool,
16 /// TODO this and minor_subsystem_version should be combined into one property and left as
17 /// default or populated together. They should not be separate fields.
18 major_subsystem_version: u16,
19 minor_subsystem_version: u16,
20 lib_directories: []const Cache.Directory,
21 module_definition_file: ?[]const u8,
22 subsystem: ?std.Target.SubSystem,
23 /// These flags are populated by `codegen.llvm.updateExports` to allow us to guess the subsystem.
24 lld_export_flags: struct {
25 c_main: bool,
26 winmain: bool,
27 wwinmain: bool,
28 winmain_crt_startup: bool,
29 wwinmain_crt_startup: bool,
30 dllmain_crt_startup: bool,
31 },
32 fn init(comp: *Compilation, options: link.File.OpenOptions) !Coff {
33 const target = comp.root_mod.resolved_target.result;
34 const output_mode = comp.config.output_mode;
35 return .{
36 .image_base = options.image_base orelse switch (output_mode) {
37 .Exe => switch (target.cpu.arch) {
38 .aarch64, .x86_64 => 0x140000000,
39 .thumb, .x86 => 0x400000,
40 else => unreachable,
41 },
42 .Lib => switch (target.cpu.arch) {
43 .aarch64, .x86_64 => 0x180000000,
44 .thumb, .x86 => 0x10000000,
45 else => unreachable,
46 },
47 .Obj => 0,
48 },
49 .entry = options.entry,
50 .pdb_out_path = options.pdb_out_path,
51 .repro = options.repro,
52 .tsaware = options.tsaware,
53 .nxcompat = options.nxcompat,
54 .dynamicbase = options.dynamicbase,
55 .major_subsystem_version = options.major_subsystem_version orelse 6,
56 .minor_subsystem_version = options.minor_subsystem_version orelse 0,
57 .lib_directories = options.lib_directories,
58 .module_definition_file = options.module_definition_file,
59 // Subsystem depends on the set of public symbol names from linked objects.
60 // See LinkerDriver::inferSubsystem from the LLD project for the flow chart.
61 .subsystem = options.subsystem,
62 // These flags are initially all `false`; the LLVM backend populates them when it learns about exports.
63 .lld_export_flags = .{
64 .c_main = false,
65 .winmain = false,
66 .wwinmain = false,
67 .winmain_crt_startup = false,
68 .wwinmain_crt_startup = false,
69 .dllmain_crt_startup = false,
70 },
71 };
72 }
73};
74pub const Elf = struct {
75 entry_name: ?[]const u8,
76 hash_style: HashStyle,
77 image_base: u64,
78 linker_script: ?[]const u8,
79 version_script: ?[]const u8,
80 sort_section: ?SortSection,
81 print_icf_sections: bool,
82 print_map: bool,
83 emit_relocs: bool,
84 z_nodelete: bool,
85 z_notext: bool,
86 z_defs: bool,
87 z_origin: bool,
88 z_nocopyreloc: bool,
89 z_now: bool,
90 z_relro: bool,
91 z_common_page_size: ?u64,
92 z_max_page_size: ?u64,
93 rpath_list: []const []const u8,
94 symbol_wrap_set: []const []const u8,
95 soname: ?[]const u8,
96 allow_undefined_version: bool,
97 enable_new_dtags: ?bool,
98 compress_debug_sections: CompressDebugSections,
99 bind_global_refs_locally: bool,
100 pub const HashStyle = enum { sysv, gnu, both };
101 pub const SortSection = enum { name, alignment };
102 pub const CompressDebugSections = enum { none, zlib, zstd };
103
104 fn init(comp: *Compilation, options: link.File.OpenOptions) !Elf {
105 const PtrWidth = enum { p32, p64 };
106 const target = comp.root_mod.resolved_target.result;
107 const output_mode = comp.config.output_mode;
108 const is_dyn_lib = output_mode == .Lib and comp.config.link_mode == .dynamic;
109 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {
110 0...32 => .p32,
111 33...64 => .p64,
112 else => return error.UnsupportedElfArchitecture,
113 };
114 const default_entry_name: []const u8 = switch (target.cpu.arch) {
115 .mips, .mipsel, .mips64, .mips64el => "__start",
116 else => "_start",
117 };
118 return .{
119 .entry_name = switch (options.entry) {
120 .disabled => null,
121 .default => if (output_mode != .Exe) null else default_entry_name,
122 .enabled => default_entry_name,
123 .named => |name| name,
124 },
125 .hash_style = options.hash_style,
126 .image_base = b: {
127 if (is_dyn_lib) break :b 0;
128 if (output_mode == .Exe and comp.config.pie) break :b 0;
129 break :b options.image_base orelse switch (ptr_width) {
130 .p32 => 0x10000,
131 .p64 => 0x1000000,
132 };
133 },
134 .linker_script = options.linker_script,
135 .version_script = options.version_script,
136 .sort_section = options.sort_section,
137 .print_icf_sections = options.print_icf_sections,
138 .print_map = options.print_map,
139 .emit_relocs = options.emit_relocs,
140 .z_nodelete = options.z_nodelete,
141 .z_notext = options.z_notext,
142 .z_defs = options.z_defs,
143 .z_origin = options.z_origin,
144 .z_nocopyreloc = options.z_nocopyreloc,
145 .z_now = options.z_now,
146 .z_relro = options.z_relro,
147 .z_common_page_size = options.z_common_page_size,
148 .z_max_page_size = options.z_max_page_size,
149 .rpath_list = options.rpath_list,
150 .symbol_wrap_set = options.symbol_wrap_set.keys(),
151 .soname = options.soname,
152 .allow_undefined_version = options.allow_undefined_version,
153 .enable_new_dtags = options.enable_new_dtags,
154 .compress_debug_sections = options.compress_debug_sections,
155 .bind_global_refs_locally = options.bind_global_refs_locally,
156 };
157 }
158};
159const Wasm = struct {
160 /// Symbol name of the entry function to export
161 entry_name: ?[]const u8,
162 /// When true, will import the function table from the host environment.
163 import_table: bool,
164 /// When true, will export the function table to the host environment.
165 export_table: bool,
166 /// When defined, sets the initial memory size of the memory.
167 initial_memory: ?u64,
168 /// When defined, sets the maximum memory size of the memory.
169 max_memory: ?u64,
170 /// When defined, sets the start of the data section.
171 global_base: ?u64,
172 /// Set of *global* symbol names to export to the host environment.
173 export_symbol_names: []const []const u8,
174 /// When true, will allow undefined symbols
175 import_symbols: bool,
176 fn init(comp: *Compilation, options: link.File.OpenOptions) !Wasm {
177 const default_entry_name: []const u8 = switch (comp.config.wasi_exec_model) {
178 .reactor => "_initialize",
179 .command => "_start",
180 };
181 return .{
182 .entry_name = switch (options.entry) {
183 .disabled => null,
184 .default => if (comp.config.output_mode != .Exe) null else default_entry_name,
185 .enabled => default_entry_name,
186 .named => |name| name,
187 },
188 .import_table = options.import_table,
189 .export_table = options.export_table,
190 .initial_memory = options.initial_memory,
191 .max_memory = options.max_memory,
192 .global_base = options.global_base,
193 .export_symbol_names = options.export_symbol_names,
194 .import_symbols = options.import_symbols,
195 };
196 }
197};
198
199pub fn createEmpty(
200 arena: Allocator,
201 comp: *Compilation,
202 emit: Cache.Path,
203 options: link.File.OpenOptions,
204) !*Lld {
205 const target = comp.root_mod.resolved_target.result;
206 const output_mode = comp.config.output_mode;
207 const optimize_mode = comp.root_mod.optimize_mode;
208 const is_native_os = comp.root_mod.resolved_target.is_native_os;
209
210 const obj_file_ext: []const u8 = switch (target.ofmt) {
211 .coff => "obj",
212 .elf, .wasm => "o",
213 else => unreachable,
214 };
215 const gc_sections: bool = options.gc_sections orelse switch (target.ofmt) {
216 .coff => optimize_mode != .Debug,
217 .elf => optimize_mode != .Debug and output_mode != .Obj,
218 .wasm => output_mode != .Obj,
219 else => unreachable,
220 };
221 const stack_size: u64 = options.stack_size orelse default: {
222 if (target.ofmt == .wasm and target.os.tag == .freestanding)
223 break :default 1 * 1024 * 1024; // 1 MiB
224 break :default 16 * 1024 * 1024; // 16 MiB
225 };
226
227 const lld = try arena.create(Lld);
228 lld.* = .{
229 .base = .{
230 .tag = .lld,
231 .comp = comp,
232 .emit = emit,
233 .zcu_object_basename = try allocPrint(arena, "{s}_zcu.{s}", .{ fs.path.stem(emit.sub_path), obj_file_ext }),
234 .gc_sections = gc_sections,
235 .print_gc_sections = options.print_gc_sections,
236 .stack_size = stack_size,
237 .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os,
238 .file = null,
239 .build_id = options.build_id,
240 },
241 .ofmt = switch (target.ofmt) {
242 .coff => .{ .coff = try .init(comp, options) },
243 .elf => .{ .elf = try .init(comp, options) },
244 .wasm => .{ .wasm = try .init(comp, options) },
245 else => unreachable,
246 },
247 };
248 return lld;
249}
250pub fn deinit(lld: *Lld) void {
251 _ = lld;
252}
253pub fn flush(
254 lld: *Lld,
255 arena: Allocator,
256 tid: Zcu.PerThread.Id,
257 prog_node: std.Progress.Node,
258) link.File.FlushError!void {
259 dev.check(.lld_linker);
260 _ = tid;
261
262 const tracy = trace(@src());
263 defer tracy.end();
264
265 const sub_prog_node = prog_node.start("LLD Link", 0);
266 defer sub_prog_node.end();
267
268 const comp = lld.base.comp;
269 const result = if (comp.config.output_mode == .Lib and comp.config.link_mode == .static) r: {
270 if (!@import("build_options").have_llvm or !comp.config.use_lib_llvm) {
271 return lld.base.comp.link_diags.fail("using lld without libllvm not implemented", .{});
272 }
273 break :r linkAsArchive(lld, arena);
274 } else switch (lld.ofmt) {
275 .coff => coffLink(lld, arena),
276 .elf => elfLink(lld, arena),
277 .wasm => wasmLink(lld, arena),
278 };
279 result catch |err| switch (err) {
280 error.OutOfMemory, error.LinkFailure => |e| return e,
281 else => |e| return lld.base.comp.link_diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),
282 };
283}
284
285fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
286 const base = &lld.base;
287 const comp = base.comp;
288 const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
289 const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
290 const full_out_path_z = try arena.dupeZ(u8, full_out_path);
291 const opt_zcu = comp.zcu;
292
293 const zcu_obj_path: ?Cache.Path = if (opt_zcu != null) p: {
294 break :p try comp.resolveEmitPathFlush(arena, .temp, base.zcu_object_basename.?);
295 } else null;
296
297 log.debug("zcu_obj_path={?}", .{zcu_obj_path});
298
299 const compiler_rt_path: ?Cache.Path = if (comp.compiler_rt_strat == .obj)
300 comp.compiler_rt_obj.?.full_object_path
301 else
302 null;
303
304 const ubsan_rt_path: ?Cache.Path = if (comp.ubsan_rt_strat == .obj)
305 comp.ubsan_rt_obj.?.full_object_path
306 else
307 null;
308
309 // This function follows the same pattern as link.Elf.linkWithLLD so if you want some
310 // insight as to what's going on here you can read that function body which is more
311 // well-commented.
312
313 const link_inputs = comp.link_inputs;
314
315 var object_files: std.ArrayListUnmanaged([*:0]const u8) = .empty;
316
317 try object_files.ensureUnusedCapacity(arena, link_inputs.len);
318 for (link_inputs) |input| {
319 object_files.appendAssumeCapacity(try input.path().?.toStringZ(arena));
320 }
321
322 try object_files.ensureUnusedCapacity(arena, comp.c_object_table.count() +
323 comp.win32_resource_table.count() + 2);
324
325 for (comp.c_object_table.keys()) |key| {
326 object_files.appendAssumeCapacity(try key.status.success.object_path.toStringZ(arena));
327 }
328 for (comp.win32_resource_table.keys()) |key| {
329 object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path));
330 }
331 if (zcu_obj_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
332 if (compiler_rt_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
333 if (ubsan_rt_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
334
335 if (comp.verbose_link) {
336 std.debug.print("ar rcs {s}", .{full_out_path_z});
337 for (object_files.items) |arg| {
338 std.debug.print(" {s}", .{arg});
339 }
340 std.debug.print("\n", .{});
341 }
342
343 const llvm_bindings = @import("../codegen/llvm/bindings.zig");
344 const llvm = @import("../codegen/llvm.zig");
345 const target = comp.root_mod.resolved_target.result;
346 llvm.initializeLLVMTarget(target.cpu.arch);
347 const bad = llvm_bindings.WriteArchive(
348 full_out_path_z,
349 object_files.items.ptr,
350 object_files.items.len,
351 switch (target.os.tag) {
352 .aix => .AIXBIG,
353 .windows => .COFF,
354 else => if (target.os.tag.isDarwin()) .DARWIN else .GNU,
355 },
356 );
357 if (bad) return error.UnableToWriteArchive;
358}
359
360fn coffLink(lld: *Lld, arena: Allocator) !void {
361 const comp = lld.base.comp;
362 const gpa = comp.gpa;
363 const base = &lld.base;
364 const coff = &lld.ofmt.coff;
365
366 const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
367 const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
368
369 const zcu_obj_path: ?Cache.Path = if (comp.zcu != null) p: {
370 break :p try comp.resolveEmitPathFlush(arena, .temp, base.zcu_object_basename.?);
371 } else null;
372
373 const is_lib = comp.config.output_mode == .Lib;
374 const is_dyn_lib = comp.config.link_mode == .dynamic and is_lib;
375 const is_exe_or_dyn_lib = is_dyn_lib or comp.config.output_mode == .Exe;
376 const link_in_crt = comp.config.link_libc and is_exe_or_dyn_lib;
377 const target = comp.root_mod.resolved_target.result;
378 const optimize_mode = comp.root_mod.optimize_mode;
379 const entry_name: ?[]const u8 = switch (coff.entry) {
380 // This logic isn't quite right for disabled or enabled. No point in fixing it
381 // when the goal is to eliminate dependency on LLD anyway.
382 // https://github.com/ziglang/zig/issues/17751
383 .disabled, .default, .enabled => null,
384 .named => |name| name,
385 };
386
387 if (comp.config.output_mode == .Obj) {
388 // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy
389 // here. TODO: think carefully about how we can avoid this redundant operation when doing
390 // build-obj. See also the corresponding TODO in linkAsArchive.
391 const the_object_path = blk: {
392 if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
393
394 if (comp.c_object_table.count() != 0)
395 break :blk comp.c_object_table.keys()[0].status.success.object_path;
396
397 if (zcu_obj_path) |p|
398 break :blk p;
399
400 // TODO I think this is unreachable. Audit this situation when solving the above TODO
401 // regarding eliding redundant object -> object transformations.
402 return error.NoObjectsToLink;
403 };
404 try std.fs.Dir.copyFile(
405 the_object_path.root_dir.handle,
406 the_object_path.sub_path,
407 directory.handle,
408 base.emit.sub_path,
409 .{},
410 );
411 } else {
412 // Create an LLD command line and invoke it.
413 var argv = std.ArrayList([]const u8).init(gpa);
414 defer argv.deinit();
415 // We will invoke ourselves as a child process to gain access to LLD.
416 // This is necessary because LLD does not behave properly as a library -
417 // it calls exit() and does not reset all global data between invocations.
418 const linker_command = "lld-link";
419 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
420
421 if (target.isMinGW()) {
422 try argv.append("-lldmingw");
423 }
424
425 try argv.append("-ERRORLIMIT:0");
426 try argv.append("-NOLOGO");
427 if (comp.config.debug_format != .strip) {
428 try argv.append("-DEBUG");
429
430 const out_ext = std.fs.path.extension(full_out_path);
431 const out_pdb = coff.pdb_out_path orelse try allocPrint(arena, "{s}.pdb", .{
432 full_out_path[0 .. full_out_path.len - out_ext.len],
433 });
434 const out_pdb_basename = std.fs.path.basename(out_pdb);
435
436 try argv.append(try allocPrint(arena, "-PDB:{s}", .{out_pdb}));
437 try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb_basename}));
438 }
439 if (comp.version) |version| {
440 try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));
441 }
442
443 if (target_util.llvmMachineAbi(target)) |mabi| {
444 try argv.append(try allocPrint(arena, "-MLLVM:-target-abi={s}", .{mabi}));
445 }
446
447 try argv.append(try allocPrint(arena, "-MLLVM:-float-abi={s}", .{if (target.abi.float() == .hard) "hard" else "soft"}));
448
449 if (comp.config.lto != .none) {
450 switch (optimize_mode) {
451 .Debug => {},
452 .ReleaseSmall => try argv.append("-OPT:lldlto=2"),
453 .ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"),
454 }
455 }
456 if (comp.config.output_mode == .Exe) {
457 try argv.append(try allocPrint(arena, "-STACK:{d}", .{base.stack_size}));
458 }
459 try argv.append(try allocPrint(arena, "-BASE:{d}", .{coff.image_base}));
460
461 switch (base.build_id) {
462 .none => try argv.append("-BUILD-ID:NO"),
463 .fast => try argv.append("-BUILD-ID"),
464 .uuid, .sha1, .md5, .hexstring => {},
465 }
466
467 if (target.cpu.arch == .x86) {
468 try argv.append("-MACHINE:X86");
469 } else if (target.cpu.arch == .x86_64) {
470 try argv.append("-MACHINE:X64");
471 } else if (target.cpu.arch == .thumb) {
472 try argv.append("-MACHINE:ARM");
473 } else if (target.cpu.arch == .aarch64) {
474 try argv.append("-MACHINE:ARM64");
475 }
476
477 for (comp.force_undefined_symbols.keys()) |symbol| {
478 try argv.append(try allocPrint(arena, "-INCLUDE:{s}", .{symbol}));
479 }
480
481 if (is_dyn_lib) {
482 try argv.append("-DLL");
483 }
484
485 if (entry_name) |name| {
486 try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{name}));
487 }
488
489 if (coff.repro) {
490 try argv.append("-BREPRO");
491 }
492
493 if (coff.tsaware) {
494 try argv.append("-tsaware");
495 }
496 if (coff.nxcompat) {
497 try argv.append("-nxcompat");
498 }
499 if (!coff.dynamicbase) {
500 try argv.append("-dynamicbase:NO");
501 }
502 if (base.allow_shlib_undefined) {
503 try argv.append("-FORCE:UNRESOLVED");
504 }
505
506 try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
507
508 if (comp.emit_implib) |raw_emit_path| {
509 const path = try comp.resolveEmitPathFlush(arena, .temp, raw_emit_path);
510 try argv.append(try allocPrint(arena, "-IMPLIB:{}", .{path}));
511 }
512
513 if (comp.config.link_libc) {
514 if (comp.libc_installation) |libc_installation| {
515 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));
516
517 if (target.abi == .msvc or target.abi == .itanium) {
518 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.msvc_lib_dir.?}));
519 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.kernel32_lib_dir.?}));
520 }
521 }
522 }
523
524 for (coff.lib_directories) |lib_directory| {
525 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_directory.path orelse "."}));
526 }
527
528 try argv.ensureUnusedCapacity(comp.link_inputs.len);
529 for (comp.link_inputs) |link_input| switch (link_input) {
530 .dso_exact => unreachable, // not applicable to PE/COFF
531 inline .dso, .res => |x| {
532 argv.appendAssumeCapacity(try x.path.toString(arena));
533 },
534 .object, .archive => |obj| {
535 if (obj.must_link) {
536 argv.appendAssumeCapacity(try allocPrint(arena, "-WHOLEARCHIVE:{}", .{@as(Cache.Path, obj.path)}));
537 } else {
538 argv.appendAssumeCapacity(try obj.path.toString(arena));
539 }
540 },
541 };
542
543 for (comp.c_object_table.keys()) |key| {
544 try argv.append(try key.status.success.object_path.toString(arena));
545 }
546
547 for (comp.win32_resource_table.keys()) |key| {
548 try argv.append(key.status.success.res_path);
549 }
550
551 if (zcu_obj_path) |p| {
552 try argv.append(try p.toString(arena));
553 }
554
555 if (coff.module_definition_file) |def| {
556 try argv.append(try allocPrint(arena, "-DEF:{s}", .{def}));
557 }
558
559 const resolved_subsystem: ?std.Target.SubSystem = blk: {
560 if (coff.subsystem) |explicit| break :blk explicit;
561 switch (target.os.tag) {
562 .windows => {
563 if (comp.zcu != null) {
564 if (coff.lld_export_flags.dllmain_crt_startup or is_dyn_lib)
565 break :blk null;
566 if (coff.lld_export_flags.c_main or comp.config.is_test or
567 coff.lld_export_flags.winmain_crt_startup or
568 coff.lld_export_flags.wwinmain_crt_startup)
569 {
570 break :blk .Console;
571 }
572 if (coff.lld_export_flags.winmain or coff.lld_export_flags.wwinmain)
573 break :blk .Windows;
574 }
575 },
576 .uefi => break :blk .EfiApplication,
577 else => {},
578 }
579 break :blk null;
580 };
581
582 const Mode = enum { uefi, win32 };
583 const mode: Mode = mode: {
584 if (resolved_subsystem) |subsystem| {
585 const subsystem_suffix = try allocPrint(arena, ",{d}.{d}", .{
586 coff.major_subsystem_version, coff.minor_subsystem_version,
587 });
588
589 switch (subsystem) {
590 .Console => {
591 try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{
592 subsystem_suffix,
593 }));
594 break :mode .win32;
595 },
596 .EfiApplication => {
597 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{
598 subsystem_suffix,
599 }));
600 break :mode .uefi;
601 },
602 .EfiBootServiceDriver => {
603 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{
604 subsystem_suffix,
605 }));
606 break :mode .uefi;
607 },
608 .EfiRom => {
609 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{
610 subsystem_suffix,
611 }));
612 break :mode .uefi;
613 },
614 .EfiRuntimeDriver => {
615 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{
616 subsystem_suffix,
617 }));
618 break :mode .uefi;
619 },
620 .Native => {
621 try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{
622 subsystem_suffix,
623 }));
624 break :mode .win32;
625 },
626 .Posix => {
627 try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{
628 subsystem_suffix,
629 }));
630 break :mode .win32;
631 },
632 .Windows => {
633 try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{
634 subsystem_suffix,
635 }));
636 break :mode .win32;
637 },
638 }
639 } else if (target.os.tag == .uefi) {
640 break :mode .uefi;
641 } else {
642 break :mode .win32;
643 }
644 };
645
646 switch (mode) {
647 .uefi => try argv.appendSlice(&[_][]const u8{
648 "-BASE:0",
649 "-ENTRY:EfiMain",
650 "-OPT:REF",
651 "-SAFESEH:NO",
652 "-MERGE:.rdata=.data",
653 "-NODEFAULTLIB",
654 "-SECTION:.xdata,D",
655 }),
656 .win32 => {
657 if (link_in_crt) {
658 if (target.abi.isGnu()) {
659 if (target.cpu.arch == .x86) {
660 try argv.append("-ALTERNATENAME:__image_base__=___ImageBase");
661 } else {
662 try argv.append("-ALTERNATENAME:__image_base__=__ImageBase");
663 }
664
665 if (is_dyn_lib) {
666 try argv.append(try comp.crtFileAsString(arena, "dllcrt2.obj"));
667 if (target.cpu.arch == .x86) {
668 try argv.append("-ALTERNATENAME:__DllMainCRTStartup@12=_DllMainCRTStartup@12");
669 } else {
670 try argv.append("-ALTERNATENAME:_DllMainCRTStartup=DllMainCRTStartup");
671 }
672 } else {
673 try argv.append(try comp.crtFileAsString(arena, "crt2.obj"));
674 }
675
676 try argv.append(try comp.crtFileAsString(arena, "libmingw32.lib"));
677 } else {
678 try argv.append(switch (comp.config.link_mode) {
679 .static => "libcmt.lib",
680 .dynamic => "msvcrt.lib",
681 });
682
683 const lib_str = switch (comp.config.link_mode) {
684 .static => "lib",
685 .dynamic => "",
686 };
687 try argv.append(try allocPrint(arena, "{s}vcruntime.lib", .{lib_str}));
688 try argv.append(try allocPrint(arena, "{s}ucrt.lib", .{lib_str}));
689
690 //Visual C++ 2015 Conformance Changes
691 //https://msdn.microsoft.com/en-us/library/bb531344.aspx
692 try argv.append("legacy_stdio_definitions.lib");
693
694 // msvcrt depends on kernel32 and ntdll
695 try argv.append("kernel32.lib");
696 try argv.append("ntdll.lib");
697 }
698 } else {
699 try argv.append("-NODEFAULTLIB");
700 if (!is_lib and entry_name == null) {
701 if (comp.zcu != null) {
702 if (coff.lld_export_flags.winmain_crt_startup) {
703 try argv.append("-ENTRY:WinMainCRTStartup");
704 } else {
705 try argv.append("-ENTRY:wWinMainCRTStartup");
706 }
707 } else {
708 try argv.append("-ENTRY:wWinMainCRTStartup");
709 }
710 }
711 }
712 },
713 }
714
715 if (comp.config.link_libc and link_in_crt) {
716 if (comp.zigc_static_lib) |zigc| {
717 try argv.append(try zigc.full_object_path.toString(arena));
718 }
719 }
720
721 // libc++ dep
722 if (comp.config.link_libcpp) {
723 try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena));
724 try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena));
725 }
726
727 // libunwind dep
728 if (comp.config.link_libunwind) {
729 try argv.append(try comp.libunwind_static_lib.?.full_object_path.toString(arena));
730 }
731
732 if (comp.config.any_fuzz) {
733 try argv.append(try comp.fuzzer_lib.?.full_object_path.toString(arena));
734 }
735
736 const ubsan_rt_path: ?Cache.Path = blk: {
737 if (comp.ubsan_rt_lib) |x| break :blk x.full_object_path;
738 if (comp.ubsan_rt_obj) |x| break :blk x.full_object_path;
739 break :blk null;
740 };
741 if (ubsan_rt_path) |path| {
742 try argv.append(try path.toString(arena));
743 }
744
745 if (is_exe_or_dyn_lib and !comp.skip_linker_dependencies) {
746 // MSVC compiler_rt is missing some stuff, so we build it unconditionally but
747 // and rely on weak linkage to allow MSVC compiler_rt functions to override ours.
748 if (comp.compiler_rt_obj) |obj| try argv.append(try obj.full_object_path.toString(arena));
749 if (comp.compiler_rt_lib) |lib| try argv.append(try lib.full_object_path.toString(arena));
750 }
751
752 try argv.ensureUnusedCapacity(comp.windows_libs.count());
753 for (comp.windows_libs.keys()) |key| {
754 const lib_basename = try allocPrint(arena, "{s}.lib", .{key});
755 if (comp.crt_files.get(lib_basename)) |crt_file| {
756 argv.appendAssumeCapacity(try crt_file.full_object_path.toString(arena));
757 continue;
758 }
759 if (try findLib(arena, lib_basename, coff.lib_directories)) |full_path| {
760 argv.appendAssumeCapacity(full_path);
761 continue;
762 }
763 if (target.abi.isGnu()) {
764 const fallback_name = try allocPrint(arena, "lib{s}.dll.a", .{key});
765 if (try findLib(arena, fallback_name, coff.lib_directories)) |full_path| {
766 argv.appendAssumeCapacity(full_path);
767 continue;
768 }
769 }
770 if (target.abi == .msvc or target.abi == .itanium) {
771 argv.appendAssumeCapacity(lib_basename);
772 continue;
773 }
774
775 log.err("DLL import library for -l{s} not found", .{key});
776 return error.DllImportLibraryNotFound;
777 }
778
779 try spawnLld(comp, arena, argv.items);
780 }
781}
782fn findLib(arena: Allocator, name: []const u8, lib_directories: []const Cache.Directory) !?[]const u8 {
783 for (lib_directories) |lib_directory| {
784 lib_directory.handle.access(name, .{}) catch |err| switch (err) {
785 error.FileNotFound => continue,
786 else => |e| return e,
787 };
788 return try lib_directory.join(arena, &.{name});
789 }
790 return null;
791}
792
793fn elfLink(lld: *Lld, arena: Allocator) !void {
794 const comp = lld.base.comp;
795 const gpa = comp.gpa;
796 const diags = &comp.link_diags;
797 const base = &lld.base;
798 const elf = &lld.ofmt.elf;
799
800 const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
801 const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
802
803 const zcu_obj_path: ?Cache.Path = if (comp.zcu != null) p: {
804 break :p try comp.resolveEmitPathFlush(arena, .temp, base.zcu_object_basename.?);
805 } else null;
806
807 const output_mode = comp.config.output_mode;
808 const is_obj = output_mode == .Obj;
809 const is_lib = output_mode == .Lib;
810 const link_mode = comp.config.link_mode;
811 const is_dyn_lib = link_mode == .dynamic and is_lib;
812 const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe;
813 const have_dynamic_linker = link_mode == .dynamic and is_exe_or_dyn_lib;
814 const target = comp.root_mod.resolved_target.result;
815 const compiler_rt_path: ?Cache.Path = blk: {
816 if (comp.compiler_rt_lib) |x| break :blk x.full_object_path;
817 if (comp.compiler_rt_obj) |x| break :blk x.full_object_path;
818 break :blk null;
819 };
820 const ubsan_rt_path: ?Cache.Path = blk: {
821 if (comp.ubsan_rt_lib) |x| break :blk x.full_object_path;
822 if (comp.ubsan_rt_obj) |x| break :blk x.full_object_path;
823 break :blk null;
824 };
825
826 // Due to a deficiency in LLD, we need to special-case BPF to a simple file
827 // copy when generating relocatables. Normally, we would expect `lld -r` to work.
828 // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails
829 // before even generating the relocatable.
830 //
831 // For m68k, we go through this path because LLD doesn't support it yet, but LLVM can
832 // produce usable object files.
833 if (output_mode == .Obj and
834 (comp.config.lto != .none or
835 target.cpu.arch.isBpf() or
836 target.cpu.arch == .lanai or
837 target.cpu.arch == .m68k or
838 target.cpu.arch.isSPARC() or
839 target.cpu.arch == .ve or
840 target.cpu.arch == .xcore))
841 {
842 // In this case we must do a simple file copy
843 // here. TODO: think carefully about how we can avoid this redundant operation when doing
844 // build-obj. See also the corresponding TODO in linkAsArchive.
845 const the_object_path = blk: {
846 if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
847
848 if (comp.c_object_table.count() != 0)
849 break :blk comp.c_object_table.keys()[0].status.success.object_path;
850
851 if (zcu_obj_path) |p|
852 break :blk p;
853
854 // TODO I think this is unreachable. Audit this situation when solving the above TODO
855 // regarding eliding redundant object -> object transformations.
856 return error.NoObjectsToLink;
857 };
858 try std.fs.Dir.copyFile(
859 the_object_path.root_dir.handle,
860 the_object_path.sub_path,
861 directory.handle,
862 base.emit.sub_path,
863 .{},
864 );
865 } else {
866 // Create an LLD command line and invoke it.
867 var argv = std.ArrayList([]const u8).init(gpa);
868 defer argv.deinit();
869 // We will invoke ourselves as a child process to gain access to LLD.
870 // This is necessary because LLD does not behave properly as a library -
871 // it calls exit() and does not reset all global data between invocations.
872 const linker_command = "ld.lld";
873 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
874 if (is_obj) {
875 try argv.append("-r");
876 }
877
878 try argv.append("--error-limit=0");
879
880 if (comp.sysroot) |sysroot| {
881 try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot}));
882 }
883
884 if (target_util.llvmMachineAbi(target)) |mabi| {
885 try argv.appendSlice(&.{
886 "-mllvm",
887 try std.fmt.allocPrint(arena, "-target-abi={s}", .{mabi}),
888 });
889 }
890
891 try argv.appendSlice(&.{
892 "-mllvm",
893 try std.fmt.allocPrint(arena, "-float-abi={s}", .{if (target.abi.float() == .hard) "hard" else "soft"}),
894 });
895
896 if (comp.config.lto != .none) {
897 switch (comp.root_mod.optimize_mode) {
898 .Debug => {},
899 .ReleaseSmall => try argv.append("--lto-O2"),
900 .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"),
901 }
902 }
903 switch (comp.root_mod.optimize_mode) {
904 .Debug => {},
905 .ReleaseSmall => try argv.append("-O2"),
906 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
907 }
908
909 if (elf.entry_name) |name| {
910 try argv.appendSlice(&.{ "--entry", name });
911 }
912
913 for (comp.force_undefined_symbols.keys()) |sym| {
914 try argv.append("-u");
915 try argv.append(sym);
916 }
917
918 switch (elf.hash_style) {
919 .gnu => try argv.append("--hash-style=gnu"),
920 .sysv => try argv.append("--hash-style=sysv"),
921 .both => {}, // this is the default
922 }
923
924 if (output_mode == .Exe) {
925 try argv.appendSlice(&.{
926 "-z",
927 try std.fmt.allocPrint(arena, "stack-size={d}", .{base.stack_size}),
928 });
929 }
930
931 switch (base.build_id) {
932 .none => try argv.append("--build-id=none"),
933 .fast, .uuid, .sha1, .md5 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
934 @tagName(base.build_id),
935 })),
936 .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{
937 std.fmt.fmtSliceHexLower(hs.toSlice()),
938 })),
939 }
940
941 try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{elf.image_base}));
942
943 if (elf.linker_script) |linker_script| {
944 try argv.append("-T");
945 try argv.append(linker_script);
946 }
947
948 if (elf.sort_section) |how| {
949 const arg = try std.fmt.allocPrint(arena, "--sort-section={s}", .{@tagName(how)});
950 try argv.append(arg);
951 }
952
953 if (base.gc_sections) {
954 try argv.append("--gc-sections");
955 }
956
957 if (base.print_gc_sections) {
958 try argv.append("--print-gc-sections");
959 }
960
961 if (elf.print_icf_sections) {
962 try argv.append("--print-icf-sections");
963 }
964
965 if (elf.print_map) {
966 try argv.append("--print-map");
967 }
968
969 if (comp.link_eh_frame_hdr) {
970 try argv.append("--eh-frame-hdr");
971 }
972
973 if (elf.emit_relocs) {
974 try argv.append("--emit-relocs");
975 }
976
977 if (comp.config.rdynamic) {
978 try argv.append("--export-dynamic");
979 }
980
981 if (comp.config.debug_format == .strip) {
982 try argv.append("-s");
983 }
984
985 if (elf.z_nodelete) {
986 try argv.append("-z");
987 try argv.append("nodelete");
988 }
989 if (elf.z_notext) {
990 try argv.append("-z");
991 try argv.append("notext");
992 }
993 if (elf.z_defs) {
994 try argv.append("-z");
995 try argv.append("defs");
996 }
997 if (elf.z_origin) {
998 try argv.append("-z");
999 try argv.append("origin");
1000 }
1001 if (elf.z_nocopyreloc) {
1002 try argv.append("-z");
1003 try argv.append("nocopyreloc");
1004 }
1005 if (elf.z_now) {
1006 // LLD defaults to -zlazy
1007 try argv.append("-znow");
1008 }
1009 if (!elf.z_relro) {
1010 // LLD defaults to -zrelro
1011 try argv.append("-znorelro");
1012 }
1013 if (elf.z_common_page_size) |size| {
1014 try argv.append("-z");
1015 try argv.append(try std.fmt.allocPrint(arena, "common-page-size={d}", .{size}));
1016 }
1017 if (elf.z_max_page_size) |size| {
1018 try argv.append("-z");
1019 try argv.append(try std.fmt.allocPrint(arena, "max-page-size={d}", .{size}));
1020 }
1021
1022 if (getLDMOption(target)) |ldm| {
1023 try argv.append("-m");
1024 try argv.append(ldm);
1025 }
1026
1027 if (link_mode == .static) {
1028 if (target.cpu.arch.isArm()) {
1029 try argv.append("-Bstatic");
1030 } else {
1031 try argv.append("-static");
1032 }
1033 } else if (switch (target.os.tag) {
1034 else => is_dyn_lib,
1035 .haiku => is_exe_or_dyn_lib,
1036 }) {
1037 try argv.append("-shared");
1038 }
1039
1040 if (comp.config.pie and output_mode == .Exe) {
1041 try argv.append("-pie");
1042 }
1043
1044 if (is_exe_or_dyn_lib and target.os.tag == .netbsd) {
1045 // Add options to produce shared objects with only 2 PT_LOAD segments.
1046 // NetBSD expects 2 PT_LOAD segments in a shared object, otherwise
1047 // ld.elf_so fails loading dynamic libraries with "not found" error.
1048 // See https://github.com/ziglang/zig/issues/9109 .
1049 try argv.append("--no-rosegment");
1050 try argv.append("-znorelro");
1051 }
1052
1053 try argv.append("-o");
1054 try argv.append(full_out_path);
1055
1056 // csu prelude
1057 const csu = try comp.getCrtPaths(arena);
1058 if (csu.crt0) |p| try argv.append(try p.toString(arena));
1059 if (csu.crti) |p| try argv.append(try p.toString(arena));
1060 if (csu.crtbegin) |p| try argv.append(try p.toString(arena));
1061
1062 for (elf.rpath_list) |rpath| {
1063 try argv.appendSlice(&.{ "-rpath", rpath });
1064 }
1065
1066 for (elf.symbol_wrap_set) |symbol_name| {
1067 try argv.appendSlice(&.{ "-wrap", symbol_name });
1068 }
1069
1070 if (comp.config.link_libc) {
1071 if (comp.libc_installation) |libc_installation| {
1072 try argv.append("-L");
1073 try argv.append(libc_installation.crt_dir.?);
1074 }
1075 }
1076
1077 if (have_dynamic_linker and
1078 (comp.config.link_libc or comp.root_mod.resolved_target.is_explicit_dynamic_linker))
1079 {
1080 if (target.dynamic_linker.get()) |dynamic_linker| {
1081 try argv.append("-dynamic-linker");
1082 try argv.append(dynamic_linker);
1083 }
1084 }
1085
1086 if (is_dyn_lib) {
1087 if (elf.soname) |soname| {
1088 try argv.append("-soname");
1089 try argv.append(soname);
1090 }
1091 if (elf.version_script) |version_script| {
1092 try argv.append("-version-script");
1093 try argv.append(version_script);
1094 }
1095 if (elf.allow_undefined_version) {
1096 try argv.append("--undefined-version");
1097 } else {
1098 try argv.append("--no-undefined-version");
1099 }
1100 if (elf.enable_new_dtags) |enable_new_dtags| {
1101 if (enable_new_dtags) {
1102 try argv.append("--enable-new-dtags");
1103 } else {
1104 try argv.append("--disable-new-dtags");
1105 }
1106 }
1107 }
1108
1109 // Positional arguments to the linker such as object files.
1110 var whole_archive = false;
1111
1112 for (base.comp.link_inputs) |link_input| switch (link_input) {
1113 .res => unreachable, // Windows-only
1114 .dso => continue,
1115 .object, .archive => |obj| {
1116 if (obj.must_link and !whole_archive) {
1117 try argv.append("-whole-archive");
1118 whole_archive = true;
1119 } else if (!obj.must_link and whole_archive) {
1120 try argv.append("-no-whole-archive");
1121 whole_archive = false;
1122 }
1123 try argv.append(try obj.path.toString(arena));
1124 },
1125 .dso_exact => |dso_exact| {
1126 assert(dso_exact.name[0] == ':');
1127 try argv.appendSlice(&.{ "-l", dso_exact.name });
1128 },
1129 };
1130
1131 if (whole_archive) {
1132 try argv.append("-no-whole-archive");
1133 whole_archive = false;
1134 }
1135
1136 for (comp.c_object_table.keys()) |key| {
1137 try argv.append(try key.status.success.object_path.toString(arena));
1138 }
1139
1140 if (zcu_obj_path) |p| {
1141 try argv.append(try p.toString(arena));
1142 }
1143
1144 if (comp.tsan_lib) |lib| {
1145 assert(comp.config.any_sanitize_thread);
1146 try argv.append(try lib.full_object_path.toString(arena));
1147 }
1148
1149 if (comp.fuzzer_lib) |lib| {
1150 assert(comp.config.any_fuzz);
1151 try argv.append(try lib.full_object_path.toString(arena));
1152 }
1153
1154 if (ubsan_rt_path) |p| {
1155 try argv.append(try p.toString(arena));
1156 }
1157
1158 // Shared libraries.
1159 if (is_exe_or_dyn_lib) {
1160 // Worst-case, we need an --as-needed argument for every lib, as well
1161 // as one before and one after.
1162 try argv.ensureUnusedCapacity(2 * base.comp.link_inputs.len + 2);
1163 argv.appendAssumeCapacity("--as-needed");
1164 var as_needed = true;
1165
1166 for (base.comp.link_inputs) |link_input| switch (link_input) {
1167 .res => unreachable, // Windows-only
1168 .object, .archive, .dso_exact => continue,
1169 .dso => |dso| {
1170 const lib_as_needed = !dso.needed;
1171 switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) {
1172 0b00, 0b11 => {},
1173 0b01 => {
1174 argv.appendAssumeCapacity("--no-as-needed");
1175 as_needed = false;
1176 },
1177 0b10 => {
1178 argv.appendAssumeCapacity("--as-needed");
1179 as_needed = true;
1180 },
1181 }
1182
1183 // By this time, we depend on these libs being dynamically linked
1184 // libraries and not static libraries (the check for that needs to be earlier),
1185 // but they could be full paths to .so files, in which case we
1186 // want to avoid prepending "-l".
1187 argv.appendAssumeCapacity(try dso.path.toString(arena));
1188 },
1189 };
1190
1191 if (!as_needed) {
1192 argv.appendAssumeCapacity("--as-needed");
1193 as_needed = true;
1194 }
1195
1196 // libc++ dep
1197 if (comp.config.link_libcpp) {
1198 try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena));
1199 try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena));
1200 }
1201
1202 // libunwind dep
1203 if (comp.config.link_libunwind) {
1204 try argv.append(try comp.libunwind_static_lib.?.full_object_path.toString(arena));
1205 }
1206
1207 // libc dep
1208 diags.flags.missing_libc = false;
1209 if (comp.config.link_libc) {
1210 if (comp.libc_installation != null) {
1211 const needs_grouping = link_mode == .static;
1212 if (needs_grouping) try argv.append("--start-group");
1213 try argv.appendSlice(target_util.libcFullLinkFlags(target));
1214 if (needs_grouping) try argv.append("--end-group");
1215 } else if (target.isGnuLibC()) {
1216 for (glibc.libs) |lib| {
1217 if (lib.removed_in) |rem_in| {
1218 if (target.os.versionRange().gnuLibCVersion().?.order(rem_in) != .lt) continue;
1219 }
1220
1221 const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
1222 comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
1223 });
1224 try argv.append(lib_path);
1225 }
1226 try argv.append(try comp.crtFileAsString(arena, "libc_nonshared.a"));
1227 } else if (target.isMuslLibC()) {
1228 try argv.append(try comp.crtFileAsString(arena, switch (link_mode) {
1229 .static => "libc.a",
1230 .dynamic => "libc.so",
1231 }));
1232 } else if (target.isFreeBSDLibC()) {
1233 for (freebsd.libs) |lib| {
1234 const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
1235 comp.freebsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
1236 });
1237 try argv.append(lib_path);
1238 }
1239 } else if (target.isNetBSDLibC()) {
1240 for (netbsd.libs) |lib| {
1241 const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
1242 comp.netbsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
1243 });
1244 try argv.append(lib_path);
1245 }
1246 } else {
1247 diags.flags.missing_libc = true;
1248 }
1249
1250 if (comp.zigc_static_lib) |zigc| {
1251 try argv.append(try zigc.full_object_path.toString(arena));
1252 }
1253 }
1254 }
1255
1256 // compiler-rt. Since compiler_rt exports symbols like `memset`, it needs
1257 // to be after the shared libraries, so they are picked up from the shared
1258 // libraries, not libcompiler_rt.
1259 if (compiler_rt_path) |p| {
1260 try argv.append(try p.toString(arena));
1261 }
1262
1263 // crt postlude
1264 if (csu.crtend) |p| try argv.append(try p.toString(arena));
1265 if (csu.crtn) |p| try argv.append(try p.toString(arena));
1266
1267 if (base.allow_shlib_undefined) {
1268 try argv.append("--allow-shlib-undefined");
1269 }
1270
1271 switch (elf.compress_debug_sections) {
1272 .none => {},
1273 .zlib => try argv.append("--compress-debug-sections=zlib"),
1274 .zstd => try argv.append("--compress-debug-sections=zstd"),
1275 }
1276
1277 if (elf.bind_global_refs_locally) {
1278 try argv.append("-Bsymbolic");
1279 }
1280
1281 try spawnLld(comp, arena, argv.items);
1282 }
1283}
1284fn getLDMOption(target: std.Target) ?[]const u8 {
1285 // This should only return emulations understood by LLD's parseEmulation().
1286 return switch (target.cpu.arch) {
1287 .aarch64 => switch (target.os.tag) {
1288 .linux => "aarch64linux",
1289 else => "aarch64elf",
1290 },
1291 .aarch64_be => switch (target.os.tag) {
1292 .linux => "aarch64linuxb",
1293 else => "aarch64elfb",
1294 },
1295 .amdgcn => "elf64_amdgpu",
1296 .arm, .thumb => switch (target.os.tag) {
1297 .linux => "armelf_linux_eabi",
1298 else => "armelf",
1299 },
1300 .armeb, .thumbeb => switch (target.os.tag) {
1301 .linux => "armelfb_linux_eabi",
1302 else => "armelfb",
1303 },
1304 .hexagon => "hexagonelf",
1305 .loongarch32 => "elf32loongarch",
1306 .loongarch64 => "elf64loongarch",
1307 .mips => switch (target.os.tag) {
1308 .freebsd => "elf32btsmip_fbsd",
1309 else => "elf32btsmip",
1310 },
1311 .mipsel => switch (target.os.tag) {
1312 .freebsd => "elf32ltsmip_fbsd",
1313 else => "elf32ltsmip",
1314 },
1315 .mips64 => switch (target.os.tag) {
1316 .freebsd => switch (target.abi) {
1317 .gnuabin32, .muslabin32 => "elf32btsmipn32_fbsd",
1318 else => "elf64btsmip_fbsd",
1319 },
1320 else => switch (target.abi) {
1321 .gnuabin32, .muslabin32 => "elf32btsmipn32",
1322 else => "elf64btsmip",
1323 },
1324 },
1325 .mips64el => switch (target.os.tag) {
1326 .freebsd => switch (target.abi) {
1327 .gnuabin32, .muslabin32 => "elf32ltsmipn32_fbsd",
1328 else => "elf64ltsmip_fbsd",
1329 },
1330 else => switch (target.abi) {
1331 .gnuabin32, .muslabin32 => "elf32ltsmipn32",
1332 else => "elf64ltsmip",
1333 },
1334 },
1335 .msp430 => "msp430elf",
1336 .powerpc => switch (target.os.tag) {
1337 .freebsd => "elf32ppc_fbsd",
1338 .linux => "elf32ppclinux",
1339 else => "elf32ppc",
1340 },
1341 .powerpcle => switch (target.os.tag) {
1342 .linux => "elf32lppclinux",
1343 else => "elf32lppc",
1344 },
1345 .powerpc64 => "elf64ppc",
1346 .powerpc64le => "elf64lppc",
1347 .riscv32 => "elf32lriscv",
1348 .riscv64 => "elf64lriscv",
1349 .s390x => "elf64_s390",
1350 .sparc64 => "elf64_sparc",
1351 .x86 => switch (target.os.tag) {
1352 .freebsd => "elf_i386_fbsd",
1353 else => "elf_i386",
1354 },
1355 .x86_64 => switch (target.abi) {
1356 .gnux32, .muslx32 => "elf32_x86_64",
1357 else => "elf_x86_64",
1358 },
1359 else => null,
1360 };
1361}
1362fn wasmLink(lld: *Lld, arena: Allocator) !void {
1363 const comp = lld.base.comp;
1364 const shared_memory = comp.config.shared_memory;
1365 const export_memory = comp.config.export_memory;
1366 const import_memory = comp.config.import_memory;
1367 const target = comp.root_mod.resolved_target.result;
1368 const base = &lld.base;
1369 const wasm = &lld.ofmt.wasm;
1370
1371 const gpa = comp.gpa;
1372
1373 const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
1374 const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
1375
1376 const zcu_obj_path: ?Cache.Path = if (comp.zcu != null) p: {
1377 break :p try comp.resolveEmitPathFlush(arena, .temp, base.zcu_object_basename.?);
1378 } else null;
1379
1380 const is_obj = comp.config.output_mode == .Obj;
1381 const compiler_rt_path: ?Cache.Path = blk: {
1382 if (comp.compiler_rt_lib) |lib| break :blk lib.full_object_path;
1383 if (comp.compiler_rt_obj) |obj| break :blk obj.full_object_path;
1384 break :blk null;
1385 };
1386 const ubsan_rt_path: ?Cache.Path = blk: {
1387 if (comp.ubsan_rt_lib) |lib| break :blk lib.full_object_path;
1388 if (comp.ubsan_rt_obj) |obj| break :blk obj.full_object_path;
1389 break :blk null;
1390 };
1391
1392 if (is_obj) {
1393 // LLD's WASM driver does not support the equivalent of `-r` so we do a simple file copy
1394 // here. TODO: think carefully about how we can avoid this redundant operation when doing
1395 // build-obj. See also the corresponding TODO in linkAsArchive.
1396 const the_object_path = blk: {
1397 if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
1398
1399 if (comp.c_object_table.count() != 0)
1400 break :blk comp.c_object_table.keys()[0].status.success.object_path;
1401
1402 if (zcu_obj_path) |p|
1403 break :blk p;
1404
1405 // TODO I think this is unreachable. Audit this situation when solving the above TODO
1406 // regarding eliding redundant object -> object transformations.
1407 return error.NoObjectsToLink;
1408 };
1409 try fs.Dir.copyFile(
1410 the_object_path.root_dir.handle,
1411 the_object_path.sub_path,
1412 directory.handle,
1413 base.emit.sub_path,
1414 .{},
1415 );
1416 } else {
1417 // Create an LLD command line and invoke it.
1418 var argv = std.ArrayList([]const u8).init(gpa);
1419 defer argv.deinit();
1420 // We will invoke ourselves as a child process to gain access to LLD.
1421 // This is necessary because LLD does not behave properly as a library -
1422 // it calls exit() and does not reset all global data between invocations.
1423 const linker_command = "wasm-ld";
1424 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
1425 try argv.append("--error-limit=0");
1426
1427 if (comp.config.lto != .none) {
1428 switch (comp.root_mod.optimize_mode) {
1429 .Debug => {},
1430 .ReleaseSmall => try argv.append("-O2"),
1431 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
1432 }
1433 }
1434
1435 if (import_memory) {
1436 try argv.append("--import-memory");
1437 }
1438
1439 if (export_memory) {
1440 try argv.append("--export-memory");
1441 }
1442
1443 if (wasm.import_table) {
1444 assert(!wasm.export_table);
1445 try argv.append("--import-table");
1446 }
1447
1448 if (wasm.export_table) {
1449 assert(!wasm.import_table);
1450 try argv.append("--export-table");
1451 }
1452
1453 // For wasm-ld we only need to specify '--no-gc-sections' when the user explicitly
1454 // specified it as garbage collection is enabled by default.
1455 if (!base.gc_sections) {
1456 try argv.append("--no-gc-sections");
1457 }
1458
1459 if (comp.config.debug_format == .strip) {
1460 try argv.append("-s");
1461 }
1462
1463 if (wasm.initial_memory) |initial_memory| {
1464 const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory});
1465 try argv.append(arg);
1466 }
1467
1468 if (wasm.max_memory) |max_memory| {
1469 const arg = try std.fmt.allocPrint(arena, "--max-memory={d}", .{max_memory});
1470 try argv.append(arg);
1471 }
1472
1473 if (shared_memory) {
1474 try argv.append("--shared-memory");
1475 }
1476
1477 if (wasm.global_base) |global_base| {
1478 const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base});
1479 try argv.append(arg);
1480 } else {
1481 // We prepend it by default, so when a stack overflow happens the runtime will trap correctly,
1482 // rather than silently overwrite all global declarations. See https://github.com/ziglang/zig/issues/4496
1483 //
1484 // The user can overwrite this behavior by setting the global-base
1485 try argv.append("--stack-first");
1486 }
1487
1488 // Users are allowed to specify which symbols they want to export to the wasm host.
1489 for (wasm.export_symbol_names) |symbol_name| {
1490 const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name});
1491 try argv.append(arg);
1492 }
1493
1494 if (comp.config.rdynamic) {
1495 try argv.append("--export-dynamic");
1496 }
1497
1498 if (wasm.entry_name) |entry_name| {
1499 try argv.appendSlice(&.{ "--entry", entry_name });
1500 } else {
1501 try argv.append("--no-entry");
1502 }
1503
1504 try argv.appendSlice(&.{
1505 "-z",
1506 try std.fmt.allocPrint(arena, "stack-size={d}", .{base.stack_size}),
1507 });
1508
1509 switch (base.build_id) {
1510 .none => try argv.append("--build-id=none"),
1511 .fast, .uuid, .sha1 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
1512 @tagName(base.build_id),
1513 })),
1514 .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{
1515 std.fmt.fmtSliceHexLower(hs.toSlice()),
1516 })),
1517 .md5 => {},
1518 }
1519
1520 if (wasm.import_symbols) {
1521 try argv.append("--allow-undefined");
1522 }
1523
1524 if (comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic) {
1525 try argv.append("--shared");
1526 }
1527 if (comp.config.pie) {
1528 try argv.append("--pie");
1529 }
1530
1531 try argv.appendSlice(&.{ "-o", full_out_path });
1532
1533 if (target.cpu.arch == .wasm64) {
1534 try argv.append("-mwasm64");
1535 }
1536
1537 const is_exe_or_dyn_lib = comp.config.output_mode == .Exe or
1538 (comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic);
1539
1540 if (comp.config.link_libc and is_exe_or_dyn_lib) {
1541 if (target.os.tag == .wasi) {
1542 for (comp.wasi_emulated_libs) |crt_file| {
1543 try argv.append(try comp.crtFileAsString(
1544 arena,
1545 wasi_libc.emulatedLibCRFileLibName(crt_file),
1546 ));
1547 }
1548
1549 try argv.append(try comp.crtFileAsString(
1550 arena,
1551 wasi_libc.execModelCrtFileFullName(comp.config.wasi_exec_model),
1552 ));
1553 try argv.append(try comp.crtFileAsString(arena, "libc.a"));
1554 }
1555
1556 if (comp.zigc_static_lib) |zigc| {
1557 try argv.append(try zigc.full_object_path.toString(arena));
1558 }
1559
1560 if (comp.config.link_libcpp) {
1561 try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena));
1562 try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena));
1563 }
1564 }
1565
1566 // Positional arguments to the linker such as object files.
1567 var whole_archive = false;
1568 for (comp.link_inputs) |link_input| switch (link_input) {
1569 .object, .archive => |obj| {
1570 if (obj.must_link and !whole_archive) {
1571 try argv.append("-whole-archive");
1572 whole_archive = true;
1573 } else if (!obj.must_link and whole_archive) {
1574 try argv.append("-no-whole-archive");
1575 whole_archive = false;
1576 }
1577 try argv.append(try obj.path.toString(arena));
1578 },
1579 .dso => |dso| {
1580 try argv.append(try dso.path.toString(arena));
1581 },
1582 .dso_exact => unreachable,
1583 .res => unreachable,
1584 };
1585 if (whole_archive) {
1586 try argv.append("-no-whole-archive");
1587 whole_archive = false;
1588 }
1589
1590 for (comp.c_object_table.keys()) |key| {
1591 try argv.append(try key.status.success.object_path.toString(arena));
1592 }
1593 if (zcu_obj_path) |p| {
1594 try argv.append(try p.toString(arena));
1595 }
1596
1597 if (compiler_rt_path) |p| {
1598 try argv.append(try p.toString(arena));
1599 }
1600
1601 if (ubsan_rt_path) |p| {
1602 try argv.append(try p.toStringZ(arena));
1603 }
1604
1605 try spawnLld(comp, arena, argv.items);
1606
1607 // Give +x to the .wasm file if it is an executable and the OS is WASI.
1608 // Some systems may be configured to execute such binaries directly. Even if that
1609 // is not the case, it means we will get "exec format error" when trying to run
1610 // it, and then can react to that in the same way as trying to run an ELF file
1611 // from a foreign CPU architecture.
1612 if (fs.has_executable_bit and target.os.tag == .wasi and
1613 comp.config.output_mode == .Exe)
1614 {
1615 // TODO: what's our strategy for reporting linker errors from this function?
1616 // report a nice error here with the file path if it fails instead of
1617 // just returning the error code.
1618 // chmod does not interact with umask, so we use a conservative -rwxr--r-- here.
1619 std.posix.fchmodat(fs.cwd().fd, full_out_path, 0o744, 0) catch |err| switch (err) {
1620 error.OperationNotSupported => unreachable, // Not a symlink.
1621 else => |e| return e,
1622 };
1623 }
1624 }
1625}
1626
1627fn spawnLld(
1628 comp: *Compilation,
1629 arena: Allocator,
1630 argv: []const []const u8,
1631) !void {
1632 if (comp.verbose_link) {
1633 // Skip over our own name so that the LLD linker name is the first argv item.
1634 Compilation.dump_argv(argv[1..]);
1635 }
1636
1637 // If possible, we run LLD as a child process because it does not always
1638 // behave properly as a library, unfortunately.
1639 // https://github.com/ziglang/zig/issues/3825
1640 if (!std.process.can_spawn) {
1641 const exit_code = try lldMain(arena, argv, false);
1642 if (exit_code == 0) return;
1643 if (comp.clang_passthrough_mode) std.process.exit(exit_code);
1644 return error.LinkFailure;
1645 }
1646
1647 var stderr: []u8 = &.{};
1648 defer comp.gpa.free(stderr);
1649
1650 var child = std.process.Child.init(argv, arena);
1651 const term = (if (comp.clang_passthrough_mode) term: {
1652 child.stdin_behavior = .Inherit;
1653 child.stdout_behavior = .Inherit;
1654 child.stderr_behavior = .Inherit;
1655
1656 break :term child.spawnAndWait();
1657 } else term: {
1658 child.stdin_behavior = .Ignore;
1659 child.stdout_behavior = .Ignore;
1660 child.stderr_behavior = .Pipe;
1661
1662 child.spawn() catch |err| break :term err;
1663 stderr = try child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize));
1664 break :term child.wait();
1665 }) catch |first_err| term: {
1666 const err = switch (first_err) {
1667 error.NameTooLong => err: {
1668 const s = fs.path.sep_str;
1669 const rand_int = std.crypto.random.int(u64);
1670 const rsp_path = "tmp" ++ s ++ std.fmt.hex(rand_int) ++ ".rsp";
1671
1672 const rsp_file = try comp.dirs.local_cache.handle.createFileZ(rsp_path, .{});
1673 defer comp.dirs.local_cache.handle.deleteFileZ(rsp_path) catch |err|
1674 log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) });
1675 {
1676 defer rsp_file.close();
1677 var rsp_buf = std.io.bufferedWriter(rsp_file.writer());
1678 const rsp_writer = rsp_buf.writer();
1679 for (argv[2..]) |arg| {
1680 try rsp_writer.writeByte('"');
1681 for (arg) |c| {
1682 switch (c) {
1683 '\"', '\\' => try rsp_writer.writeByte('\\'),
1684 else => {},
1685 }
1686 try rsp_writer.writeByte(c);
1687 }
1688 try rsp_writer.writeByte('"');
1689 try rsp_writer.writeByte('\n');
1690 }
1691 try rsp_buf.flush();
1692 }
1693
1694 var rsp_child = std.process.Child.init(&.{ argv[0], argv[1], try std.fmt.allocPrint(
1695 arena,
1696 "@{s}",
1697 .{try comp.dirs.local_cache.join(arena, &.{rsp_path})},
1698 ) }, arena);
1699 if (comp.clang_passthrough_mode) {
1700 rsp_child.stdin_behavior = .Inherit;
1701 rsp_child.stdout_behavior = .Inherit;
1702 rsp_child.stderr_behavior = .Inherit;
1703
1704 break :term rsp_child.spawnAndWait() catch |err| break :err err;
1705 } else {
1706 rsp_child.stdin_behavior = .Ignore;
1707 rsp_child.stdout_behavior = .Ignore;
1708 rsp_child.stderr_behavior = .Pipe;
1709
1710 rsp_child.spawn() catch |err| break :err err;
1711 stderr = try rsp_child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize));
1712 break :term rsp_child.wait() catch |err| break :err err;
1713 }
1714 },
1715 else => first_err,
1716 };
1717 log.err("unable to spawn LLD {s}: {s}", .{ argv[0], @errorName(err) });
1718 return error.UnableToSpawnSelf;
1719 };
1720
1721 const diags = &comp.link_diags;
1722 switch (term) {
1723 .Exited => |code| if (code != 0) {
1724 if (comp.clang_passthrough_mode) std.process.exit(code);
1725 diags.lockAndParseLldStderr(argv[1], stderr);
1726 return error.LinkFailure;
1727 },
1728 else => {
1729 if (comp.clang_passthrough_mode) std.process.abort();
1730 return diags.fail("{s} terminated with stderr:\n{s}", .{ argv[0], stderr });
1731 },
1732 }
1733
1734 if (stderr.len > 0) log.warn("unexpected LLD stderr:\n{s}", .{stderr});
1735}
1736
1737const std = @import("std");
1738const Allocator = std.mem.Allocator;
1739const Cache = std.Build.Cache;
1740const allocPrint = std.fmt.allocPrint;
1741const assert = std.debug.assert;
1742const fs = std.fs;
1743const log = std.log.scoped(.link);
1744const mem = std.mem;
1745
1746const Compilation = @import("../Compilation.zig");
1747const Zcu = @import("../Zcu.zig");
1748const dev = @import("../dev.zig");
1749const freebsd = @import("../libs/freebsd.zig");
1750const glibc = @import("../libs/glibc.zig");
1751const netbsd = @import("../libs/netbsd.zig");
1752const wasi_libc = @import("../libs/wasi_libc.zig");
1753const link = @import("../link.zig");
1754const lldMain = @import("../main.zig").lldMain;
1755const target_util = @import("../target.zig");
1756const trace = @import("../tracy.zig").trace;
1757const Lld = @This();
src/link/MachO.zig+19-64
......@@ -6,9 +6,6 @@ base: link.File,
66
77rpath_list: []const []const u8,
88
9/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
10llvm_object: ?LlvmObject.Ptr = null,
11
129/// Debug symbols bundle (or dSym).
1310d_sym: ?DebugSymbols = null,
1411
......@@ -176,13 +173,6 @@ pub fn createEmpty(
176173 const output_mode = comp.config.output_mode;
177174 const link_mode = comp.config.link_mode;
178175
179 // If using LLVM to generate the object file for the zig compilation unit,
180 // we need a place to put the object file so that it can be subsequently
181 // handled.
182 const zcu_object_sub_path = if (!use_llvm)
183 null
184 else
185 try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path});
186176 const allow_shlib_undefined = options.allow_shlib_undefined orelse false;
187177
188178 const self = try arena.create(MachO);
......@@ -191,13 +181,15 @@ pub fn createEmpty(
191181 .tag = .macho,
192182 .comp = comp,
193183 .emit = emit,
194 .zcu_object_sub_path = zcu_object_sub_path,
184 .zcu_object_basename = if (use_llvm)
185 try std.fmt.allocPrint(arena, "{s}_zcu.o", .{fs.path.stem(emit.sub_path)})
186 else
187 null,
195188 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
196189 .print_gc_sections = options.print_gc_sections,
197190 .stack_size = options.stack_size orelse 16777216,
198191 .allow_shlib_undefined = allow_shlib_undefined,
199192 .file = null,
200 .disable_lld_caching = options.disable_lld_caching,
201193 .build_id = options.build_id,
202194 },
203195 .rpath_list = options.rpath_list,
......@@ -225,15 +217,12 @@ pub fn createEmpty(
225217 .force_load_objc = options.force_load_objc,
226218 .discard_local_symbols = options.discard_local_symbols,
227219 };
228 if (use_llvm and comp.config.have_zcu) {
229 self.llvm_object = try LlvmObject.create(arena, comp);
230 }
231220 errdefer self.base.destroy();
232221
233222 self.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
234223 .truncate = true,
235224 .read = true,
236 .mode = link.File.determineMode(false, output_mode, link_mode),
225 .mode = link.File.determineMode(output_mode, link_mode),
237226 });
238227
239228 // Append null file
......@@ -280,8 +269,6 @@ pub fn open(
280269pub fn deinit(self: *MachO) void {
281270 const gpa = self.base.comp.gpa;
282271
283 if (self.llvm_object) |llvm_object| llvm_object.deinit();
284
285272 if (self.d_sym) |*d_sym| {
286273 d_sym.deinit();
287274 }
......@@ -349,15 +336,6 @@ pub fn flush(
349336 arena: Allocator,
350337 tid: Zcu.PerThread.Id,
351338 prog_node: std.Progress.Node,
352) link.File.FlushError!void {
353 try self.flushModule(arena, tid, prog_node);
354}
355
356pub fn flushModule(
357 self: *MachO,
358 arena: Allocator,
359 tid: Zcu.PerThread.Id,
360 prog_node: std.Progress.Node,
361339) link.File.FlushError!void {
362340 const tracy = trace(@src());
363341 defer tracy.end();
......@@ -366,28 +344,19 @@ pub fn flushModule(
366344 const gpa = comp.gpa;
367345 const diags = &self.base.comp.link_diags;
368346
369 if (self.llvm_object) |llvm_object| {
370 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
371 }
372
373347 const sub_prog_node = prog_node.start("MachO Flush", 0);
374348 defer sub_prog_node.end();
375349
376 const directory = self.base.emit.root_dir;
377 const module_obj_path: ?Path = if (self.base.zcu_object_sub_path) |path| .{
378 .root_dir = directory,
379 .sub_path = if (fs.path.dirname(self.base.emit.sub_path)) |dirname|
380 try fs.path.join(arena, &.{ dirname, path })
381 else
382 path,
350 const zcu_obj_path: ?Path = if (self.base.zcu_object_basename) |raw| p: {
351 break :p try comp.resolveEmitPathFlush(arena, .temp, raw);
383352 } else null;
384353
385354 // --verbose-link
386355 if (comp.verbose_link) try self.dumpArgv(comp);
387356
388 if (self.getZigObject()) |zo| try zo.flushModule(self, tid);
389 if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path);
390 if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path);
357 if (self.getZigObject()) |zo| try zo.flush(self, tid);
358 if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, zcu_obj_path);
359 if (self.base.isObject()) return relocatable.flushObject(self, comp, zcu_obj_path);
391360
392361 var positionals = std.ArrayList(link.Input).init(gpa);
393362 defer positionals.deinit();
......@@ -409,7 +378,7 @@ pub fn flushModule(
409378 positionals.appendAssumeCapacity(try link.openObjectInput(diags, key.status.success.object_path));
410379 }
411380
412 if (module_obj_path) |path| try positionals.append(try link.openObjectInput(diags, path));
381 if (zcu_obj_path) |path| try positionals.append(try link.openObjectInput(diags, path));
413382
414383 if (comp.config.any_sanitize_thread) {
415384 try positionals.append(try link.openObjectInput(diags, comp.tsan_lib.?.full_object_path));
......@@ -629,7 +598,7 @@ pub fn flushModule(
629598 error.LinkFailure => return error.LinkFailure,
630599 else => |e| return diags.fail("failed to calculate and write uuid: {s}", .{@errorName(e)}),
631600 };
632 if (self.getDebugSymbols()) |dsym| dsym.flushModule(self) catch |err| switch (err) {
601 if (self.getDebugSymbols()) |dsym| dsym.flush(self) catch |err| switch (err) {
633602 error.OutOfMemory => return error.OutOfMemory,
634603 else => |e| return diags.fail("failed to get debug symbols: {s}", .{@errorName(e)}),
635604 };
......@@ -658,12 +627,9 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
658627
659628 const directory = self.base.emit.root_dir;
660629 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
661 const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: {
662 if (fs.path.dirname(full_out_path)) |dirname| {
663 break :blk try fs.path.join(arena, &.{ dirname, path });
664 } else {
665 break :blk path;
666 }
630 const zcu_obj_path: ?[]const u8 = if (self.base.zcu_object_basename) |raw| p: {
631 const p = try comp.resolveEmitPathFlush(arena, .temp, raw);
632 break :p try p.toString(arena);
667633 } else null;
668634
669635 var argv = std.ArrayList([]const u8).init(arena);
......@@ -692,7 +658,7 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
692658 try argv.append(try key.status.success.object_path.toString(arena));
693659 }
694660
695 if (module_obj_path) |p| {
661 if (zcu_obj_path) |p| {
696662 try argv.append(p);
697663 }
698664 } else {
......@@ -784,7 +750,7 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
784750 try argv.append(try key.status.success.object_path.toString(arena));
785751 }
786752
787 if (module_obj_path) |p| {
753 if (zcu_obj_path) |p| {
788754 try argv.append(p);
789755 }
790756
......@@ -3073,26 +3039,22 @@ pub fn updateFunc(
30733039 self: *MachO,
30743040 pt: Zcu.PerThread,
30753041 func_index: InternPool.Index,
3076 air: Air,
3077 liveness: Air.Liveness,
3042 mir: *const codegen.AnyMir,
30783043) link.File.UpdateNavError!void {
30793044 if (build_options.skip_non_native and builtin.object_format != .macho) {
30803045 @panic("Attempted to compile for object format that was disabled by build configuration");
30813046 }
3082 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
3083 return self.getZigObject().?.updateFunc(self, pt, func_index, air, liveness);
3047 return self.getZigObject().?.updateFunc(self, pt, func_index, mir);
30843048}
30853049
30863050pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
30873051 if (build_options.skip_non_native and builtin.object_format != .macho) {
30883052 @panic("Attempted to compile for object format that was disabled by build configuration");
30893053 }
3090 if (self.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav);
30913054 return self.getZigObject().?.updateNav(self, pt, nav);
30923055}
30933056
30943057pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
3095 if (self.llvm_object) |_| return;
30963058 return self.getZigObject().?.updateLineNumber(pt, ti_id);
30973059}
30983060
......@@ -3105,7 +3067,6 @@ pub fn updateExports(
31053067 if (build_options.skip_non_native and builtin.object_format != .macho) {
31063068 @panic("Attempted to compile for object format that was disabled by build configuration");
31073069 }
3108 if (self.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
31093070 return self.getZigObject().?.updateExports(self, pt, exported, export_indices);
31103071}
31113072
......@@ -3114,17 +3075,14 @@ pub fn deleteExport(
31143075 exported: Zcu.Exported,
31153076 name: InternPool.NullTerminatedString,
31163077) void {
3117 if (self.llvm_object) |_| return;
31183078 return self.getZigObject().?.deleteExport(self, exported, name);
31193079}
31203080
31213081pub fn freeNav(self: *MachO, nav: InternPool.Nav.Index) void {
3122 if (self.llvm_object) |llvm_object| return llvm_object.freeNav(nav);
31233082 return self.getZigObject().?.freeNav(nav);
31243083}
31253084
31263085pub fn getNavVAddr(self: *MachO, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
3127 assert(self.llvm_object == null);
31283086 return self.getZigObject().?.getNavVAddr(self, pt, nav_index, reloc_info);
31293087}
31303088
......@@ -3139,7 +3097,6 @@ pub fn lowerUav(
31393097}
31403098
31413099pub fn getUavVAddr(self: *MachO, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
3142 assert(self.llvm_object == null);
31433100 return self.getZigObject().?.getUavVAddr(self, uav, reloc_info);
31443101}
31453102
......@@ -5473,7 +5430,6 @@ const target_util = @import("../target.zig");
54735430const trace = @import("../tracy.zig").trace;
54745431const synthetic = @import("MachO/synthetic.zig");
54755432
5476const Air = @import("../Air.zig");
54775433const Alignment = Atom.Alignment;
54785434const Allocator = mem.Allocator;
54795435const Archive = @import("MachO/Archive.zig");
......@@ -5496,7 +5452,6 @@ const ObjcStubsSection = synthetic.ObjcStubsSection;
54965452const Object = @import("MachO/Object.zig");
54975453const LazyBind = bind.LazyBind;
54985454const LaSymbolPtrSection = synthetic.LaSymbolPtrSection;
5499const LlvmObject = @import("../codegen/llvm.zig").Object;
55005455const Md5 = std.crypto.hash.Md5;
55015456const Zcu = @import("../Zcu.zig");
55025457const InternPool = @import("../InternPool.zig");
src/link/MachO/DebugSymbols.zig+1-1
......@@ -178,7 +178,7 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) !u64
178178 return offset;
179179}
180180
181pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
181pub fn flush(self: *DebugSymbols, macho_file: *MachO) !void {
182182 const zo = macho_file.getZigObject().?;
183183 for (self.relocs.items) |*reloc| {
184184 const sym = zo.symbols.items[reloc.target];
src/link/MachO/Symbol.zig-3
......@@ -389,9 +389,6 @@ pub const Flags = packed struct {
389389 /// ZigObject specific flags
390390 /// Whether the symbol has a trampoline
391391 trampoline: bool = false,
392
393 /// Whether the symbol is an extern pointer (as opposed to function).
394 is_extern_ptr: bool = false,
395392};
396393
397394pub const SectionFlags = packed struct(u8) {
src/link/MachO/ZigObject.zig+9-17
......@@ -550,7 +550,7 @@ pub fn getInputSection(self: ZigObject, atom: Atom, macho_file: *MachO) macho.se
550550 return sect;
551551}
552552
553pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.File.FlushError!void {
553pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.File.FlushError!void {
554554 const diags = &macho_file.base.comp.link_diags;
555555
556556 // Handle any lazy symbols that were emitted by incremental compilation.
......@@ -589,7 +589,7 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id)
589589 if (self.dwarf) |*dwarf| {
590590 const pt: Zcu.PerThread = .activate(macho_file.base.comp.zcu.?, tid);
591591 defer pt.deactivate();
592 dwarf.flushModule(pt) catch |err| switch (err) {
592 dwarf.flush(pt) catch |err| switch (err) {
593593 error.OutOfMemory => return error.OutOfMemory,
594594 else => |e| return diags.fail("failed to flush dwarf module: {s}", .{@errorName(e)}),
595595 };
......@@ -599,7 +599,7 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id)
599599 self.debug_strtab_dirty = false;
600600 }
601601
602 // The point of flushModule() is to commit changes, so in theory, nothing should
602 // The point of flush() is to commit changes, so in theory, nothing should
603603 // be dirty after this. However, it is possible for some things to remain
604604 // dirty because they fail to be written in the event of compile errors,
605605 // such as debug_line_header_dirty and debug_info_header_dirty.
......@@ -777,8 +777,7 @@ pub fn updateFunc(
777777 macho_file: *MachO,
778778 pt: Zcu.PerThread,
779779 func_index: InternPool.Index,
780 air: Air,
781 liveness: Air.Liveness,
780 mir: *const codegen.AnyMir,
782781) link.File.UpdateNavError!void {
783782 const tracy = trace(@src());
784783 defer tracy.end();
......@@ -796,13 +795,12 @@ pub fn updateFunc(
796795 var debug_wip_nav = if (self.dwarf) |*dwarf| try dwarf.initWipNav(pt, func.owner_nav, sym_index) else null;
797796 defer if (debug_wip_nav) |*wip_nav| wip_nav.deinit();
798797
799 try codegen.generateFunction(
798 try codegen.emitFunction(
800799 &macho_file.base,
801800 pt,
802801 zcu.navSrcLoc(func.owner_nav),
803802 func_index,
804 air,
805 liveness,
803 mir,
806804 &code_buffer,
807805 if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,
808806 );
......@@ -883,11 +881,7 @@ pub fn updateNav(
883881 const name = @"extern".name.toSlice(ip);
884882 const lib_name = @"extern".lib_name.toSlice(ip);
885883 const sym_index = try self.getGlobalSymbol(macho_file, name, lib_name);
886 if (!ip.isFunctionType(@"extern".ty)) {
887 const sym = &self.symbols.items[sym_index];
888 sym.flags.is_extern_ptr = true;
889 if (@"extern".is_threadlocal) sym.flags.tlv = true;
890 }
884 if (@"extern".is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) self.symbols.items[sym_index].flags.tlv = true;
891885 if (self.dwarf) |*dwarf| dwarf: {
892886 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf;
893887 defer debug_wip_nav.deinit();
......@@ -1160,7 +1154,6 @@ fn getNavOutputSection(
11601154) error{OutOfMemory}!u8 {
11611155 _ = self;
11621156 const ip = &zcu.intern_pool;
1163 const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
11641157 const nav_val = zcu.navValue(nav_index);
11651158 if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return macho_file.zig_text_sect_index.?;
11661159 const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
......@@ -1168,7 +1161,7 @@ fn getNavOutputSection(
11681161 .@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none },
11691162 else => .{ true, false, nav_val.toIntern() },
11701163 };
1171 if (any_non_single_threaded and is_threadlocal) {
1164 if (is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) {
11721165 for (code) |byte| {
11731166 if (byte != 0) break;
11741167 } else return macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(
......@@ -1537,7 +1530,7 @@ pub fn getOrCreateMetadataForLazySymbol(
15371530 }
15381531 state_ptr.* = .pending_flush;
15391532 const symbol_index = symbol_index_ptr.*;
1540 // anyerror needs to be deferred until flushModule
1533 // anyerror needs to be deferred until flush
15411534 if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(macho_file, pt, lazy_sym, symbol_index);
15421535 return symbol_index;
15431536}
......@@ -1813,7 +1806,6 @@ const target_util = @import("../../target.zig");
18131806const trace = @import("../../tracy.zig").trace;
18141807const std = @import("std");
18151808
1816const Air = @import("../../Air.zig");
18171809const Allocator = std.mem.Allocator;
18181810const Archive = @import("Archive.zig");
18191811const Atom = @import("Atom.zig");
src/link/Plan9.zig+14-34
......@@ -301,7 +301,6 @@ pub fn createEmpty(
301301 .stack_size = options.stack_size orelse 16777216,
302302 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
303303 .file = null,
304 .disable_lld_caching = options.disable_lld_caching,
305304 .build_id = options.build_id,
306305 },
307306 .sixtyfour_bit = sixtyfour_bit,
......@@ -387,8 +386,7 @@ pub fn updateFunc(
387386 self: *Plan9,
388387 pt: Zcu.PerThread,
389388 func_index: InternPool.Index,
390 air: Air,
391 liveness: Air.Liveness,
389 mir: *const codegen.AnyMir,
392390) link.File.UpdateNavError!void {
393391 if (build_options.skip_non_native and builtin.object_format != .plan9) {
394392 @panic("Attempted to compile for object format that was disabled by build configuration");
......@@ -413,13 +411,12 @@ pub fn updateFunc(
413411 };
414412 defer dbg_info_output.dbg_line.deinit();
415413
416 try codegen.generateFunction(
414 try codegen.emitFunction(
417415 &self.base,
418416 pt,
419417 zcu.navSrcLoc(func.owner_nav),
420418 func_index,
421 air,
422 liveness,
419 mir,
423420 &code_buffer,
424421 .{ .plan9 = &dbg_info_output },
425422 );
......@@ -494,7 +491,7 @@ fn updateFinish(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
494491 // write the symbol
495492 // we already have the got index
496493 const sym: aout.Sym = .{
497 .value = undefined, // the value of stuff gets filled in in flushModule
494 .value = undefined, // the value of stuff gets filled in in flush
498495 .type = atom.type,
499496 .name = try gpa.dupe(u8, nav.name.toSlice(ip)),
500497 };
......@@ -527,25 +524,6 @@ fn allocateGotIndex(self: *Plan9) usize {
527524 }
528525}
529526
530pub fn flush(
531 self: *Plan9,
532 arena: Allocator,
533 tid: Zcu.PerThread.Id,
534 prog_node: std.Progress.Node,
535) link.File.FlushError!void {
536 const comp = self.base.comp;
537 const diags = &comp.link_diags;
538 const use_lld = build_options.have_llvm and comp.config.use_lld;
539 assert(!use_lld);
540
541 switch (link.File.effectiveOutputMode(use_lld, comp.config.output_mode)) {
542 .Exe => {},
543 .Obj => return diags.fail("writing plan9 object files unimplemented", .{}),
544 .Lib => return diags.fail("writing plan9 lib files unimplemented", .{}),
545 }
546 return self.flushModule(arena, tid, prog_node);
547}
548
549527pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {
550528 if (delta_line > 0 and delta_line < 65) {
551529 const toappend = @as(u8, @intCast(delta_line));
......@@ -586,7 +564,7 @@ fn atomCount(self: *Plan9) usize {
586564 return data_nav_count + fn_nav_count + lazy_atom_count + extern_atom_count + uav_atom_count;
587565}
588566
589pub fn flushModule(
567pub fn flush(
590568 self: *Plan9,
591569 arena: Allocator,
592570 /// TODO: stop using this
......@@ -607,10 +585,16 @@ pub fn flushModule(
607585 const gpa = comp.gpa;
608586 const target = comp.root_mod.resolved_target.result;
609587
588 switch (comp.config.output_mode) {
589 .Exe => {},
590 .Obj => return diags.fail("writing plan9 object files unimplemented", .{}),
591 .Lib => return diags.fail("writing plan9 lib files unimplemented", .{}),
592 }
593
610594 const sub_prog_node = prog_node.start("Flush Module", 0);
611595 defer sub_prog_node.end();
612596
613 log.debug("flushModule", .{});
597 log.debug("flush", .{});
614598
615599 defer assert(self.hdr.entry != 0x0);
616600
......@@ -1039,7 +1023,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *Plan9, pt: Zcu.PerThread, lazy_sym: F
10391023 const atom = atom_ptr.*;
10401024 _ = try self.getAtomPtr(atom).getOrCreateSymbolTableEntry(self);
10411025 _ = self.getAtomPtr(atom).getOrCreateOffsetTableEntry(self);
1042 // anyerror needs to be deferred until flushModule
1026 // anyerror needs to be deferred until flush
10431027 if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbolAtom(pt, lazy_sym, atom);
10441028 return atom;
10451029}
......@@ -1182,11 +1166,7 @@ pub fn open(
11821166
11831167 const file = try emit.root_dir.handle.createFile(emit.sub_path, .{
11841168 .read = true,
1185 .mode = link.File.determineMode(
1186 use_lld,
1187 comp.config.output_mode,
1188 comp.config.link_mode,
1189 ),
1169 .mode = link.File.determineMode(comp.config.output_mode, comp.config.link_mode),
11901170 });
11911171 errdefer file.close();
11921172 self.base.file = file;
src/link/Queue.zig created+279
......@@ -0,0 +1,279 @@
1//! Stores and manages the queue of link tasks. Each task is either a `PrelinkTask` or a `ZcuTask`.
2//!
3//! There must be at most one link thread (the thread processing these tasks) active at a time. If
4//! `!comp.separateCodegenThreadOk()`, then ZCU tasks will be run on the main thread, bypassing this
5//! queue entirely.
6//!
7//! All prelink tasks must be processed before any ZCU tasks are processed. After all prelink tasks
8//! are run, but before any ZCU tasks are run, `prelink` must be called on the `link.File`.
9//!
10//! There will sometimes be a `ZcuTask` in the queue which is not yet ready because it depends on
11//! MIR which has not yet been generated by any codegen thread. In this case, we must pause
12//! processing of linker tasks until the MIR is ready. It would be incorrect to run any other link
13//! tasks first, since this would make builds unreproducible.
14
15mutex: std.Thread.Mutex,
16/// Validates that only one `flushTaskQueue` thread is running at a time.
17flush_safety: std.debug.SafetyLock,
18
19/// This is the number of prelink tasks which are expected but have not yet been enqueued.
20/// Guarded by `mutex`.
21pending_prelink_tasks: u32,
22
23/// Prelink tasks which have been enqueued and are not yet owned by the worker thread.
24/// Allocated into `gpa`, guarded by `mutex`.
25queued_prelink: std.ArrayListUnmanaged(PrelinkTask),
26/// The worker thread moves items from `queued_prelink` into this array in order to process them.
27/// Allocated into `gpa`, accessed only by the worker thread.
28wip_prelink: std.ArrayListUnmanaged(PrelinkTask),
29
30/// Like `queued_prelink`, but for ZCU tasks.
31/// Allocated into `gpa`, guarded by `mutex`.
32queued_zcu: std.ArrayListUnmanaged(ZcuTask),
33/// Like `wip_prelink`, but for ZCU tasks.
34/// Allocated into `gpa`, accessed only by the worker thread.
35wip_zcu: std.ArrayListUnmanaged(ZcuTask),
36
37/// When processing ZCU link tasks, we might have to block due to unpopulated MIR. When this
38/// happens, some tasks in `wip_zcu` have been run, and some are still pending. This is the
39/// index into `wip_zcu` which we have reached.
40wip_zcu_idx: usize,
41
42/// The sum of all `air_bytes` for all currently-queued `ZcuTask.link_func` tasks. Because
43/// MIR bytes are approximately proportional to AIR bytes, this acts to limit the amount of
44/// AIR and MIR which is queued for codegen and link respectively, to prevent excessive
45/// memory usage if analysis produces AIR faster than it can be processed by codegen/link.
46/// The cap is `max_air_bytes_in_flight`.
47/// Guarded by `mutex`.
48air_bytes_in_flight: u32,
49/// If nonzero, then a call to `enqueueZcu` is blocked waiting to add a `link_func` task, but
50/// cannot until `air_bytes_in_flight` is no greater than this value.
51/// Guarded by `mutex`.
52air_bytes_waiting: u32,
53/// After setting `air_bytes_waiting`, `enqueueZcu` will wait on this condition (with `mutex`).
54/// When `air_bytes_waiting` many bytes can be queued, this condition should be signaled.
55air_bytes_cond: std.Thread.Condition,
56
57/// Guarded by `mutex`.
58state: union(enum) {
59 /// The link thread is currently running or queued to run.
60 running,
61 /// The link thread is not running or queued, because it has exhausted all immediately available
62 /// tasks. It should be spawned when more tasks are enqueued. If `pending_prelink_tasks` is not
63 /// zero, we are specifically waiting for prelink tasks.
64 finished,
65 /// The link thread is not running or queued, because it is waiting for this MIR to be populated.
66 /// Once codegen completes, it must call `mirReady` which will restart the link thread.
67 wait_for_mir: *ZcuTask.LinkFunc.SharedMir,
68},
69
70/// In the worst observed case, MIR is around 50 times as large as AIR. More typically, the ratio is
71/// around 20. Going by that 50x multiplier, and assuming we want to consume no more than 500 MiB of
72/// memory on AIR/MIR, we see a limit of around 10 MiB of AIR in-flight.
73const max_air_bytes_in_flight = 10 * 1024 * 1024;
74
75/// The initial `Queue` state, containing no tasks, expecting no prelink tasks, and with no running worker thread.
76/// The `pending_prelink_tasks` and `queued_prelink` fields may be modified as needed before calling `start`.
77pub const empty: Queue = .{
78 .mutex = .{},
79 .flush_safety = .{},
80 .pending_prelink_tasks = 0,
81 .queued_prelink = .empty,
82 .wip_prelink = .empty,
83 .queued_zcu = .empty,
84 .wip_zcu = .empty,
85 .wip_zcu_idx = 0,
86 .state = .finished,
87 .air_bytes_in_flight = 0,
88 .air_bytes_waiting = 0,
89 .air_bytes_cond = .{},
90};
91/// `lf` is needed to correctly deinit any pending `ZcuTask`s.
92pub fn deinit(q: *Queue, comp: *Compilation) void {
93 const gpa = comp.gpa;
94 for (q.queued_zcu.items) |t| t.deinit(comp.zcu.?);
95 for (q.wip_zcu.items[q.wip_zcu_idx..]) |t| t.deinit(comp.zcu.?);
96 q.queued_prelink.deinit(gpa);
97 q.wip_prelink.deinit(gpa);
98 q.queued_zcu.deinit(gpa);
99 q.wip_zcu.deinit(gpa);
100}
101
102/// This is expected to be called exactly once, after which the caller must not directly access
103/// `queued_prelink` or `pending_prelink_tasks` any longer. This will spawn the link thread if
104/// necessary.
105pub fn start(q: *Queue, comp: *Compilation) void {
106 assert(q.state == .finished);
107 assert(q.queued_zcu.items.len == 0);
108 if (q.queued_prelink.items.len != 0) {
109 q.state = .running;
110 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
111 }
112}
113
114/// Called by codegen workers after they have populated a `ZcuTask.LinkFunc.SharedMir`. If the link
115/// thread was waiting for this MIR, it can resume.
116pub fn mirReady(q: *Queue, comp: *Compilation, mir: *ZcuTask.LinkFunc.SharedMir) void {
117 // We would like to assert that `mir` is not pending, but that would race with a worker thread
118 // potentially freeing it.
119 {
120 q.mutex.lock();
121 defer q.mutex.unlock();
122 switch (q.state) {
123 .finished, .running => return,
124 .wait_for_mir => |wait_for| if (wait_for != mir) return,
125 }
126 // We were waiting for `mir`, so we will restart the linker thread.
127 q.state = .running;
128 }
129 assert(mir.status.load(.monotonic) != .pending);
130 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
131}
132
133/// Enqueues all prelink tasks in `tasks`. Asserts that they were expected, i.e. that `tasks.len` is
134/// less than or equal to `q.pending_prelink_tasks`. Also asserts that `tasks.len` is not 0.
135pub fn enqueuePrelink(q: *Queue, comp: *Compilation, tasks: []const PrelinkTask) Allocator.Error!void {
136 {
137 q.mutex.lock();
138 defer q.mutex.unlock();
139 try q.queued_prelink.appendSlice(comp.gpa, tasks);
140 q.pending_prelink_tasks -= @intCast(tasks.len);
141 switch (q.state) {
142 .wait_for_mir => unreachable, // we've not started zcu tasks yet
143 .running => return,
144 .finished => {},
145 }
146 // Restart the linker thread, because it was waiting for a task
147 q.state = .running;
148 }
149 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
150}
151
152pub fn enqueueZcu(q: *Queue, comp: *Compilation, task: ZcuTask) Allocator.Error!void {
153 assert(comp.separateCodegenThreadOk());
154 {
155 q.mutex.lock();
156 defer q.mutex.unlock();
157 // If this is a `link_func` task, we might need to wait for `air_bytes_in_flight` to fall.
158 if (task == .link_func) {
159 const max_in_flight = max_air_bytes_in_flight -| task.link_func.air_bytes;
160 while (q.air_bytes_in_flight > max_in_flight) {
161 q.air_bytes_waiting = task.link_func.air_bytes;
162 q.air_bytes_cond.wait(&q.mutex);
163 q.air_bytes_waiting = 0;
164 }
165 q.air_bytes_in_flight += task.link_func.air_bytes;
166 }
167 try q.queued_zcu.append(comp.gpa, task);
168 switch (q.state) {
169 .running, .wait_for_mir => return,
170 .finished => if (q.pending_prelink_tasks != 0) return,
171 }
172 // Restart the linker thread, unless it would immediately be blocked
173 if (task == .link_func and task.link_func.mir.status.load(.monotonic) == .pending) {
174 q.state = .{ .wait_for_mir = task.link_func.mir };
175 return;
176 }
177 q.state = .running;
178 }
179 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
180}
181
182fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void {
183 q.flush_safety.lock(); // every `return` site should unlock this before unlocking `q.mutex`
184
185 if (std.debug.runtime_safety) {
186 q.mutex.lock();
187 defer q.mutex.unlock();
188 assert(q.state == .running);
189 }
190 prelink: while (true) {
191 assert(q.wip_prelink.items.len == 0);
192 {
193 q.mutex.lock();
194 defer q.mutex.unlock();
195 std.mem.swap(std.ArrayListUnmanaged(PrelinkTask), &q.queued_prelink, &q.wip_prelink);
196 if (q.wip_prelink.items.len == 0) {
197 if (q.pending_prelink_tasks == 0) {
198 break :prelink; // prelink is done
199 } else {
200 // We're expecting more prelink tasks so can't move on to ZCU tasks.
201 q.state = .finished;
202 q.flush_safety.unlock();
203 return;
204 }
205 }
206 }
207 for (q.wip_prelink.items) |task| {
208 link.doPrelinkTask(comp, task);
209 }
210 q.wip_prelink.clearRetainingCapacity();
211 }
212
213 // We've finished the prelink tasks, so run prelink if necessary.
214 if (comp.bin_file) |lf| {
215 if (!lf.post_prelink) {
216 if (lf.prelink()) |_| {
217 lf.post_prelink = true;
218 } else |err| switch (err) {
219 error.OutOfMemory => comp.link_diags.setAllocFailure(),
220 error.LinkFailure => {},
221 }
222 }
223 }
224
225 // Now we can run ZCU tasks.
226 while (true) {
227 if (q.wip_zcu.items.len == q.wip_zcu_idx) {
228 q.wip_zcu.clearRetainingCapacity();
229 q.wip_zcu_idx = 0;
230 q.mutex.lock();
231 defer q.mutex.unlock();
232 std.mem.swap(std.ArrayListUnmanaged(ZcuTask), &q.queued_zcu, &q.wip_zcu);
233 if (q.wip_zcu.items.len == 0) {
234 // We've exhausted all available tasks.
235 q.state = .finished;
236 q.flush_safety.unlock();
237 return;
238 }
239 }
240 const task = q.wip_zcu.items[q.wip_zcu_idx];
241 // If the task is a `link_func`, we might have to stop until its MIR is populated.
242 pending: {
243 if (task != .link_func) break :pending;
244 const status_ptr = &task.link_func.mir.status;
245 // First check without the mutex to optimize for the common case where MIR is ready.
246 if (status_ptr.load(.monotonic) != .pending) break :pending;
247 q.mutex.lock();
248 defer q.mutex.unlock();
249 if (status_ptr.load(.monotonic) != .pending) break :pending;
250 // We will stop for now, and get restarted once this MIR is ready.
251 q.state = .{ .wait_for_mir = task.link_func.mir };
252 q.flush_safety.unlock();
253 return;
254 }
255 link.doZcuTask(comp, tid, task);
256 task.deinit(comp.zcu.?);
257 if (task == .link_func) {
258 // Decrease `air_bytes_in_flight`, since we've finished processing this MIR.
259 q.mutex.lock();
260 defer q.mutex.unlock();
261 q.air_bytes_in_flight -= task.link_func.air_bytes;
262 if (q.air_bytes_waiting != 0 and
263 q.air_bytes_in_flight <= max_air_bytes_in_flight -| q.air_bytes_waiting)
264 {
265 q.air_bytes_cond.signal();
266 }
267 }
268 q.wip_zcu_idx += 1;
269 }
270}
271
272const std = @import("std");
273const assert = std.debug.assert;
274const Allocator = std.mem.Allocator;
275const Compilation = @import("../Compilation.zig");
276const link = @import("../link.zig");
277const PrelinkTask = link.PrelinkTask;
278const ZcuTask = link.ZcuTask;
279const Queue = @This();
src/link/SpirV.zig+3-26
......@@ -17,7 +17,7 @@
1717//! All regular functions.
1818
1919// Because SPIR-V requires re-compilation anyway, and so hot swapping will not work
20// anyway, we simply generate all the code in flushModule. This keeps
20// anyway, we simply generate all the code in flush. This keeps
2121// things considerably simpler.
2222
2323const SpirV = @This();
......@@ -83,7 +83,6 @@ pub fn createEmpty(
8383 .stack_size = options.stack_size orelse 0,
8484 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
8585 .file = null,
86 .disable_lld_caching = options.disable_lld_caching,
8786 .build_id = options.build_id,
8887 },
8988 .object = codegen.Object.init(gpa, comp.getTarget()),
......@@ -112,24 +111,6 @@ pub fn deinit(self: *SpirV) void {
112111 self.object.deinit();
113112}
114113
115pub fn updateFunc(
116 self: *SpirV,
117 pt: Zcu.PerThread,
118 func_index: InternPool.Index,
119 air: Air,
120 liveness: Air.Liveness,
121) link.File.UpdateNavError!void {
122 if (build_options.skip_non_native) {
123 @panic("Attempted to compile for architecture that was disabled by build configuration");
124 }
125
126 const ip = &pt.zcu.intern_pool;
127 const func = pt.zcu.funcInfo(func_index);
128 log.debug("lowering function {}", .{ip.getNav(func.owner_nav).name.fmt(ip)});
129
130 try self.object.updateFunc(pt, func_index, air, liveness);
131}
132
133114pub fn updateNav(self: *SpirV, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
134115 if (build_options.skip_non_native) {
135116 @panic("Attempted to compile for architecture that was disabled by build configuration");
......@@ -193,18 +174,14 @@ pub fn updateExports(
193174 // TODO: Export regular functions, variables, etc using Linkage attributes.
194175}
195176
196pub fn flush(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
197 return self.flushModule(arena, tid, prog_node);
198}
199
200pub fn flushModule(
177pub fn flush(
201178 self: *SpirV,
202179 arena: Allocator,
203180 tid: Zcu.PerThread.Id,
204181 prog_node: std.Progress.Node,
205182) link.File.FlushError!void {
206183 // The goal is to never use this because it's only needed if we need to
207 // write to InternPool, but flushModule is too late to be writing to the
184 // write to InternPool, but flush is too late to be writing to the
208185 // InternPool.
209186 _ = tid;
210187
src/link/Wasm.zig+143-559
......@@ -29,19 +29,16 @@ const leb = std.leb;
2929const log = std.log.scoped(.link);
3030const mem = std.mem;
3131
32const Air = @import("../Air.zig");
3332const Mir = @import("../arch/wasm/Mir.zig");
3433const CodeGen = @import("../arch/wasm/CodeGen.zig");
3534const abi = @import("../arch/wasm/abi.zig");
3635const Compilation = @import("../Compilation.zig");
3736const Dwarf = @import("Dwarf.zig");
3837const InternPool = @import("../InternPool.zig");
39const LlvmObject = @import("../codegen/llvm.zig").Object;
4038const Zcu = @import("../Zcu.zig");
4139const codegen = @import("../codegen.zig");
4240const dev = @import("../dev.zig");
4341const link = @import("../link.zig");
44const lldMain = @import("../main.zig").lldMain;
4542const trace = @import("../tracy.zig").trace;
4643const wasi_libc = @import("../libs/wasi_libc.zig");
4744const Value = @import("../Value.zig");
......@@ -75,14 +72,10 @@ global_base: ?u64,
7572initial_memory: ?u64,
7673/// When defined, sets the maximum memory size of the memory.
7774max_memory: ?u64,
78/// When true, will import the function table from the host environment.
79import_table: bool,
8075/// When true, will export the function table to the host environment.
8176export_table: bool,
8277/// Output name of the file
8378name: []const u8,
84/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
85llvm_object: ?LlvmObject.Ptr = null,
8679/// List of relocatable files to be linked into the final binary.
8780objects: std.ArrayListUnmanaged(Object) = .{},
8881
......@@ -288,7 +281,7 @@ mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
288281/// Corresponds to `mir_instructions`.
289282mir_extra: std.ArrayListUnmanaged(u32) = .empty,
290283/// All local types for all Zcu functions.
291all_zcu_locals: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
284mir_locals: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
292285
293286params_scratch: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
294287returns_scratch: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
......@@ -872,9 +865,24 @@ const ZcuDataStarts = struct {
872865};
873866
874867pub const ZcuFunc = union {
875 function: CodeGen.Function,
868 function: Function,
876869 tag_name: TagName,
877870
871 pub const Function = extern struct {
872 /// Index into `Wasm.mir_instructions`.
873 instructions_off: u32,
874 /// This is unused except for as a safety slice bound and could be removed.
875 instructions_len: u32,
876 /// Index into `Wasm.mir_extra`.
877 extra_off: u32,
878 /// This is unused except for as a safety slice bound and could be removed.
879 extra_len: u32,
880 /// Index into `Wasm.mir_locals`.
881 locals_off: u32,
882 locals_len: u32,
883 prologue: Mir.Prologue,
884 };
885
878886 pub const TagName = extern struct {
879887 symbol_name: String,
880888 type_index: FunctionType.Index,
......@@ -2938,28 +2946,20 @@ pub fn createEmpty(
29382946 const target = comp.root_mod.resolved_target.result;
29392947 assert(target.ofmt == .wasm);
29402948
2941 const use_lld = build_options.have_llvm and comp.config.use_lld;
29422949 const use_llvm = comp.config.use_llvm;
29432950 const output_mode = comp.config.output_mode;
29442951 const wasi_exec_model = comp.config.wasi_exec_model;
29452952
2946 // If using LLD to link, this code should produce an object file so that it
2947 // can be passed to LLD.
2948 // If using LLVM to generate the object file for the zig compilation unit,
2949 // we need a place to put the object file so that it can be subsequently
2950 // handled.
2951 const zcu_object_sub_path = if (!use_lld and !use_llvm)
2952 null
2953 else
2954 try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path});
2955
29562953 const wasm = try arena.create(Wasm);
29572954 wasm.* = .{
29582955 .base = .{
29592956 .tag = .wasm,
29602957 .comp = comp,
29612958 .emit = emit,
2962 .zcu_object_sub_path = zcu_object_sub_path,
2959 .zcu_object_basename = if (use_llvm)
2960 try std.fmt.allocPrint(arena, "{s}_zcu.o", .{fs.path.stem(emit.sub_path)})
2961 else
2962 null,
29632963 // Garbage collection is so crucial to WebAssembly that we design
29642964 // the linker around the assumption that it will be on in the vast
29652965 // majority of cases, and therefore express "no garbage collection"
......@@ -2973,13 +2973,11 @@ pub fn createEmpty(
29732973 },
29742974 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
29752975 .file = null,
2976 .disable_lld_caching = options.disable_lld_caching,
29772976 .build_id = options.build_id,
29782977 },
29792978 .name = undefined,
29802979 .string_table = .empty,
29812980 .string_bytes = .empty,
2982 .import_table = options.import_table,
29832981 .export_table = options.export_table,
29842982 .import_symbols = options.import_symbols,
29852983 .export_symbol_names = options.export_symbol_names,
......@@ -2992,9 +2990,6 @@ pub fn createEmpty(
29922990 .object_host_name = .none,
29932991 .preloaded_strings = undefined,
29942992 };
2995 if (use_llvm and comp.config.have_zcu) {
2996 wasm.llvm_object = try LlvmObject.create(arena, comp);
2997 }
29982993 errdefer wasm.base.destroy();
29992994
30002995 if (options.object_host_name) |name| wasm.object_host_name = (try wasm.internString(name)).toOptional();
......@@ -3010,17 +3005,7 @@ pub fn createEmpty(
30103005 .named => |name| (try wasm.internString(name)).toOptional(),
30113006 };
30123007
3013 if (use_lld and (use_llvm or !comp.config.have_zcu)) {
3014 // LLVM emits the object file (if any); LLD links it into the final product.
3015 return wasm;
3016 }
3017
3018 // What path should this Wasm linker code output to?
3019 // If using LLD to link, this code should produce an object file so that it
3020 // can be passed to LLD.
3021 const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path;
3022
3023 wasm.base.file = try emit.root_dir.handle.createFile(sub_path, .{
3008 wasm.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
30243009 .truncate = true,
30253010 .read = true,
30263011 .mode = if (fs.has_executable_bit)
......@@ -3031,7 +3016,7 @@ pub fn createEmpty(
30313016 else
30323017 0,
30333018 });
3034 wasm.name = sub_path;
3019 wasm.name = emit.sub_path;
30353020
30363021 return wasm;
30373022}
......@@ -3116,7 +3101,6 @@ fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {
31163101
31173102pub fn deinit(wasm: *Wasm) void {
31183103 const gpa = wasm.base.comp.gpa;
3119 if (wasm.llvm_object) |llvm_object| llvm_object.deinit();
31203104
31213105 wasm.navs_exe.deinit(gpa);
31223106 wasm.navs_obj.deinit(gpa);
......@@ -3132,7 +3116,7 @@ pub fn deinit(wasm: *Wasm) void {
31323116
31333117 wasm.mir_instructions.deinit(gpa);
31343118 wasm.mir_extra.deinit(gpa);
3135 wasm.all_zcu_locals.deinit(gpa);
3119 wasm.mir_locals.deinit(gpa);
31363120
31373121 if (wasm.dwarf) |*dwarf| dwarf.deinit();
31383122
......@@ -3192,34 +3176,94 @@ pub fn deinit(wasm: *Wasm) void {
31923176 wasm.missing_exports.deinit(gpa);
31933177}
31943178
3195pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index, air: Air, liveness: Air.Liveness) !void {
3179pub fn updateFunc(
3180 wasm: *Wasm,
3181 pt: Zcu.PerThread,
3182 func_index: InternPool.Index,
3183 any_mir: *const codegen.AnyMir,
3184) !void {
31963185 if (build_options.skip_non_native and builtin.object_format != .wasm) {
31973186 @panic("Attempted to compile for object format that was disabled by build configuration");
31983187 }
3199 if (wasm.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
32003188
32013189 dev.check(.wasm_backend);
32023190
3191 // This linker implementation only works with codegen backend `.stage2_wasm`.
3192 const mir = &any_mir.wasm;
32033193 const zcu = pt.zcu;
32043194 const gpa = zcu.gpa;
3205 try wasm.functions.ensureUnusedCapacity(gpa, 1);
3206 try wasm.zcu_funcs.ensureUnusedCapacity(gpa, 1);
3207
32083195 const ip = &zcu.intern_pool;
3196 const is_obj = zcu.comp.config.output_mode == .Obj;
3197 const target = &zcu.comp.root_mod.resolved_target.result;
32093198 const owner_nav = zcu.funcInfo(func_index).owner_nav;
32103199 log.debug("updateFunc {}", .{ip.getNav(owner_nav).fqn.fmt(ip)});
32113200
3201 // For Wasm, we do not lower the MIR to code just yet. That lowering happens during `flush`,
3202 // after garbage collection, which can affect function and global indexes, which affects the
3203 // LEB integer encoding, which affects the output binary size.
3204
3205 // However, we do move the MIR into a more efficient in-memory representation, where the arrays
3206 // for all functions are packed together rather than keeping them each in their own `Mir`.
3207 const mir_instructions_off: u32 = @intCast(wasm.mir_instructions.len);
3208 const mir_extra_off: u32 = @intCast(wasm.mir_extra.items.len);
3209 const mir_locals_off: u32 = @intCast(wasm.mir_locals.items.len);
3210 {
3211 // Copying MultiArrayList data is a little non-trivial. Resize, then memcpy both slices.
3212 const old_len = wasm.mir_instructions.len;
3213 try wasm.mir_instructions.resize(gpa, old_len + mir.instructions.len);
3214 const dest_slice = wasm.mir_instructions.slice().subslice(old_len, mir.instructions.len);
3215 const src_slice = mir.instructions;
3216 @memcpy(dest_slice.items(.tag), src_slice.items(.tag));
3217 @memcpy(dest_slice.items(.data), src_slice.items(.data));
3218 }
3219 try wasm.mir_extra.appendSlice(gpa, mir.extra);
3220 try wasm.mir_locals.appendSlice(gpa, mir.locals);
3221
3222 // We also need to populate some global state from `mir`.
3223 try wasm.zcu_indirect_function_set.ensureUnusedCapacity(gpa, mir.indirect_function_set.count());
3224 for (mir.indirect_function_set.keys()) |nav| wasm.zcu_indirect_function_set.putAssumeCapacity(nav, {});
3225 for (mir.func_tys.keys()) |func_ty| {
3226 const fn_info = zcu.typeToFunc(.fromInterned(func_ty)).?;
3227 _ = try wasm.internFunctionType(fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target);
3228 }
3229 wasm.error_name_table_ref_count += mir.error_name_table_ref_count;
3230 // We need to populate UAV data. In theory, we can lower the UAV values while we fill `mir.uavs`.
3231 // However, lowering the data might cause *more* UAVs to be created, and mixing them up would be
3232 // a headache. So instead, just write `undefined` placeholder code and use the `ZcuDataStarts`.
32123233 const zds: ZcuDataStarts = .init(wasm);
3234 for (mir.uavs.keys(), mir.uavs.values()) |uav_val, uav_align| {
3235 if (uav_align != .none) {
3236 const gop = try wasm.overaligned_uavs.getOrPut(gpa, uav_val);
3237 gop.value_ptr.* = if (gop.found_existing) gop.value_ptr.maxStrict(uav_align) else uav_align;
3238 }
3239 if (is_obj) {
3240 const gop = try wasm.uavs_obj.getOrPut(gpa, uav_val);
3241 if (!gop.found_existing) gop.value_ptr.* = undefined; // `zds` handles lowering
3242 } else {
3243 const gop = try wasm.uavs_exe.getOrPut(gpa, uav_val);
3244 if (!gop.found_existing) gop.value_ptr.* = .{
3245 .code = undefined, // `zds` handles lowering
3246 .count = 0,
3247 };
3248 gop.value_ptr.count += 1;
3249 }
3250 }
3251 try zds.finish(wasm, pt); // actually generates the UAVs
3252
3253 try wasm.functions.ensureUnusedCapacity(gpa, 1);
3254 try wasm.zcu_funcs.ensureUnusedCapacity(gpa, 1);
32133255
32143256 // This converts AIR to MIR but does not yet lower to wasm code.
3215 // That lowering happens during `flush`, after garbage collection, which
3216 // can affect function and global indexes, which affects the LEB integer
3217 // encoding, which affects the output binary size.
3218 const function = try CodeGen.function(wasm, pt, func_index, air, liveness);
3219 wasm.zcu_funcs.putAssumeCapacity(func_index, .{ .function = function });
3257 wasm.zcu_funcs.putAssumeCapacity(func_index, .{ .function = .{
3258 .instructions_off = mir_instructions_off,
3259 .instructions_len = @intCast(mir.instructions.len),
3260 .extra_off = mir_extra_off,
3261 .extra_len = @intCast(mir.extra.len),
3262 .locals_off = mir_locals_off,
3263 .locals_len = @intCast(mir.locals.len),
3264 .prologue = mir.prologue,
3265 } });
32203266 wasm.functions.putAssumeCapacity(.pack(wasm, .{ .zcu_func = @enumFromInt(wasm.zcu_funcs.entries.len - 1) }), {});
3221
3222 try zds.finish(wasm, pt);
32233267}
32243268
32253269// Generate code for the "Nav", storing it in memory to be later written to
......@@ -3228,7 +3272,6 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
32283272 if (build_options.skip_non_native and builtin.object_format != .wasm) {
32293273 @panic("Attempted to compile for object format that was disabled by build configuration");
32303274 }
3231 if (wasm.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav_index);
32323275 const zcu = pt.zcu;
32333276 const ip = &zcu.intern_pool;
32343277 const nav = ip.getNav(nav_index);
......@@ -3308,8 +3351,6 @@ pub fn deleteExport(
33083351 exported: Zcu.Exported,
33093352 name: InternPool.NullTerminatedString,
33103353) void {
3311 if (wasm.llvm_object != null) return;
3312
33133354 const zcu = wasm.base.comp.zcu.?;
33143355 const ip = &zcu.intern_pool;
33153356 const name_slice = name.toSlice(ip);
......@@ -3332,7 +3373,6 @@ pub fn updateExports(
33323373 if (build_options.skip_non_native and builtin.object_format != .wasm) {
33333374 @panic("Attempted to compile for object format that was disabled by build configuration");
33343375 }
3335 if (wasm.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
33363376
33373377 const zcu = pt.zcu;
33383378 const gpa = zcu.gpa;
......@@ -3379,21 +3419,6 @@ pub fn loadInput(wasm: *Wasm, input: link.Input) !void {
33793419 }
33803420}
33813421
3382pub fn flush(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
3383 const comp = wasm.base.comp;
3384 const use_lld = build_options.have_llvm and comp.config.use_lld;
3385 const diags = &comp.link_diags;
3386
3387 if (use_lld) {
3388 return wasm.linkWithLLD(arena, tid, prog_node) catch |err| switch (err) {
3389 error.OutOfMemory => return error.OutOfMemory,
3390 error.LinkFailure => return error.LinkFailure,
3391 else => |e| return diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),
3392 };
3393 }
3394 return wasm.flushModule(arena, tid, prog_node);
3395}
3396
33973422pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!void {
33983423 const tracy = trace(@src());
33993424 defer tracy.end();
......@@ -3785,37 +3810,25 @@ fn markTable(wasm: *Wasm, i: ObjectTableIndex) link.File.FlushError!void {
37853810 try wasm.tables.put(wasm.base.comp.gpa, .fromObjectTable(i), {});
37863811}
37873812
3788pub fn flushModule(
3813pub fn flush(
37893814 wasm: *Wasm,
37903815 arena: Allocator,
37913816 tid: Zcu.PerThread.Id,
37923817 prog_node: std.Progress.Node,
37933818) link.File.FlushError!void {
37943819 // The goal is to never use this because it's only needed if we need to
3795 // write to InternPool, but flushModule is too late to be writing to the
3820 // write to InternPool, but flush is too late to be writing to the
37963821 // InternPool.
37973822 _ = tid;
37983823 const comp = wasm.base.comp;
3799 const use_lld = build_options.have_llvm and comp.config.use_lld;
38003824 const diags = &comp.link_diags;
38013825 const gpa = comp.gpa;
38023826
3803 if (wasm.llvm_object) |llvm_object| {
3804 try wasm.base.emitLlvmObject(arena, llvm_object, prog_node);
3805 if (use_lld) return;
3806 }
3807
38083827 if (comp.verbose_link) Compilation.dump_argv(wasm.dump_argv_list.items);
38093828
3810 if (wasm.base.zcu_object_sub_path) |path| {
3811 const module_obj_path: Path = .{
3812 .root_dir = wasm.base.emit.root_dir,
3813 .sub_path = if (fs.path.dirname(wasm.base.emit.sub_path)) |dirname|
3814 try fs.path.join(arena, &.{ dirname, path })
3815 else
3816 path,
3817 };
3818 openParseObjectReportingFailure(wasm, module_obj_path);
3829 if (wasm.base.zcu_object_basename) |raw| {
3830 const zcu_obj_path: Path = try comp.resolveEmitPathFlush(arena, .temp, raw);
3831 openParseObjectReportingFailure(wasm, zcu_obj_path);
38193832 try prelink(wasm, prog_node);
38203833 }
38213834
......@@ -3850,432 +3863,6 @@ pub fn flushModule(
38503863 };
38513864}
38523865
3853fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
3854 dev.check(.lld_linker);
3855
3856 const tracy = trace(@src());
3857 defer tracy.end();
3858
3859 const comp = wasm.base.comp;
3860 const diags = &comp.link_diags;
3861 const shared_memory = comp.config.shared_memory;
3862 const export_memory = comp.config.export_memory;
3863 const import_memory = comp.config.import_memory;
3864 const target = comp.root_mod.resolved_target.result;
3865
3866 const gpa = comp.gpa;
3867
3868 const directory = wasm.base.emit.root_dir; // Just an alias to make it shorter to type.
3869 const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path});
3870
3871 // If there is no Zig code to compile, then we should skip flushing the output file because it
3872 // will not be part of the linker line anyway.
3873 const module_obj_path: ?[]const u8 = if (comp.zcu != null) blk: {
3874 try wasm.flushModule(arena, tid, prog_node);
3875
3876 if (fs.path.dirname(full_out_path)) |dirname| {
3877 break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? });
3878 } else {
3879 break :blk wasm.base.zcu_object_sub_path.?;
3880 }
3881 } else null;
3882
3883 const sub_prog_node = prog_node.start("LLD Link", 0);
3884 defer sub_prog_node.end();
3885
3886 const is_obj = comp.config.output_mode == .Obj;
3887 const compiler_rt_path: ?Path = blk: {
3888 if (comp.compiler_rt_lib) |lib| break :blk lib.full_object_path;
3889 if (comp.compiler_rt_obj) |obj| break :blk obj.full_object_path;
3890 break :blk null;
3891 };
3892 const ubsan_rt_path: ?Path = blk: {
3893 if (comp.ubsan_rt_lib) |lib| break :blk lib.full_object_path;
3894 if (comp.ubsan_rt_obj) |obj| break :blk obj.full_object_path;
3895 break :blk null;
3896 };
3897
3898 const id_symlink_basename = "lld.id";
3899
3900 var man: Cache.Manifest = undefined;
3901 defer if (!wasm.base.disable_lld_caching) man.deinit();
3902
3903 var digest: [Cache.hex_digest_len]u8 = undefined;
3904
3905 if (!wasm.base.disable_lld_caching) {
3906 man = comp.cache_parent.obtain();
3907
3908 // We are about to obtain this lock, so here we give other processes a chance first.
3909 wasm.base.releaseLock();
3910
3911 comptime assert(Compilation.link_hash_implementation_version == 14);
3912
3913 try link.hashInputs(&man, comp.link_inputs);
3914 for (comp.c_object_table.keys()) |key| {
3915 _ = try man.addFilePath(key.status.success.object_path, null);
3916 }
3917 try man.addOptionalFile(module_obj_path);
3918 try man.addOptionalFilePath(compiler_rt_path);
3919 try man.addOptionalFilePath(ubsan_rt_path);
3920 man.hash.addOptionalBytes(wasm.entry_name.slice(wasm));
3921 man.hash.add(wasm.base.stack_size);
3922 man.hash.add(wasm.base.build_id);
3923 man.hash.add(import_memory);
3924 man.hash.add(export_memory);
3925 man.hash.add(wasm.import_table);
3926 man.hash.add(wasm.export_table);
3927 man.hash.addOptional(wasm.initial_memory);
3928 man.hash.addOptional(wasm.max_memory);
3929 man.hash.add(shared_memory);
3930 man.hash.addOptional(wasm.global_base);
3931 man.hash.addListOfBytes(wasm.export_symbol_names);
3932 // strip does not need to go into the linker hash because it is part of the hash namespace
3933
3934 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
3935 _ = try man.hit();
3936 digest = man.final();
3937
3938 var prev_digest_buf: [digest.len]u8 = undefined;
3939 const prev_digest: []u8 = Cache.readSmallFile(
3940 directory.handle,
3941 id_symlink_basename,
3942 &prev_digest_buf,
3943 ) catch |err| blk: {
3944 log.debug("WASM LLD new_digest={s} error: {s}", .{ std.fmt.fmtSliceHexLower(&digest), @errorName(err) });
3945 // Handle this as a cache miss.
3946 break :blk prev_digest_buf[0..0];
3947 };
3948 if (mem.eql(u8, prev_digest, &digest)) {
3949 log.debug("WASM LLD digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});
3950 // Hot diggity dog! The output binary is already there.
3951 wasm.base.lock = man.toOwnedLock();
3952 return;
3953 }
3954 log.debug("WASM LLD prev_digest={s} new_digest={s}", .{ std.fmt.fmtSliceHexLower(prev_digest), std.fmt.fmtSliceHexLower(&digest) });
3955
3956 // We are about to change the output file to be different, so we invalidate the build hash now.
3957 directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
3958 error.FileNotFound => {},
3959 else => |e| return e,
3960 };
3961 }
3962
3963 if (is_obj) {
3964 // LLD's WASM driver does not support the equivalent of `-r` so we do a simple file copy
3965 // here. TODO: think carefully about how we can avoid this redundant operation when doing
3966 // build-obj. See also the corresponding TODO in linkAsArchive.
3967 const the_object_path = blk: {
3968 if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
3969
3970 if (comp.c_object_table.count() != 0)
3971 break :blk comp.c_object_table.keys()[0].status.success.object_path;
3972
3973 if (module_obj_path) |p|
3974 break :blk Path.initCwd(p);
3975
3976 // TODO I think this is unreachable. Audit this situation when solving the above TODO
3977 // regarding eliding redundant object -> object transformations.
3978 return error.NoObjectsToLink;
3979 };
3980 try fs.Dir.copyFile(
3981 the_object_path.root_dir.handle,
3982 the_object_path.sub_path,
3983 directory.handle,
3984 wasm.base.emit.sub_path,
3985 .{},
3986 );
3987 } else {
3988 // Create an LLD command line and invoke it.
3989 var argv = std.ArrayList([]const u8).init(gpa);
3990 defer argv.deinit();
3991 // We will invoke ourselves as a child process to gain access to LLD.
3992 // This is necessary because LLD does not behave properly as a library -
3993 // it calls exit() and does not reset all global data between invocations.
3994 const linker_command = "wasm-ld";
3995 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
3996 try argv.append("--error-limit=0");
3997
3998 if (comp.config.lto != .none) {
3999 switch (comp.root_mod.optimize_mode) {
4000 .Debug => {},
4001 .ReleaseSmall => try argv.append("-O2"),
4002 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
4003 }
4004 }
4005
4006 if (import_memory) {
4007 try argv.append("--import-memory");
4008 }
4009
4010 if (export_memory) {
4011 try argv.append("--export-memory");
4012 }
4013
4014 if (wasm.import_table) {
4015 assert(!wasm.export_table);
4016 try argv.append("--import-table");
4017 }
4018
4019 if (wasm.export_table) {
4020 assert(!wasm.import_table);
4021 try argv.append("--export-table");
4022 }
4023
4024 // For wasm-ld we only need to specify '--no-gc-sections' when the user explicitly
4025 // specified it as garbage collection is enabled by default.
4026 if (!wasm.base.gc_sections) {
4027 try argv.append("--no-gc-sections");
4028 }
4029
4030 if (comp.config.debug_format == .strip) {
4031 try argv.append("-s");
4032 }
4033
4034 if (wasm.initial_memory) |initial_memory| {
4035 const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory});
4036 try argv.append(arg);
4037 }
4038
4039 if (wasm.max_memory) |max_memory| {
4040 const arg = try std.fmt.allocPrint(arena, "--max-memory={d}", .{max_memory});
4041 try argv.append(arg);
4042 }
4043
4044 if (shared_memory) {
4045 try argv.append("--shared-memory");
4046 }
4047
4048 if (wasm.global_base) |global_base| {
4049 const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base});
4050 try argv.append(arg);
4051 } else {
4052 // We prepend it by default, so when a stack overflow happens the runtime will trap correctly,
4053 // rather than silently overwrite all global declarations. See https://github.com/ziglang/zig/issues/4496
4054 //
4055 // The user can overwrite this behavior by setting the global-base
4056 try argv.append("--stack-first");
4057 }
4058
4059 // Users are allowed to specify which symbols they want to export to the wasm host.
4060 for (wasm.export_symbol_names) |symbol_name| {
4061 const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name});
4062 try argv.append(arg);
4063 }
4064
4065 if (comp.config.rdynamic) {
4066 try argv.append("--export-dynamic");
4067 }
4068
4069 if (wasm.entry_name.slice(wasm)) |entry_name| {
4070 try argv.appendSlice(&.{ "--entry", entry_name });
4071 } else {
4072 try argv.append("--no-entry");
4073 }
4074
4075 try argv.appendSlice(&.{
4076 "-z",
4077 try std.fmt.allocPrint(arena, "stack-size={d}", .{wasm.base.stack_size}),
4078 });
4079
4080 switch (wasm.base.build_id) {
4081 .none => try argv.append("--build-id=none"),
4082 .fast, .uuid, .sha1 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
4083 @tagName(wasm.base.build_id),
4084 })),
4085 .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{
4086 std.fmt.fmtSliceHexLower(hs.toSlice()),
4087 })),
4088 .md5 => {},
4089 }
4090
4091 if (wasm.import_symbols) {
4092 try argv.append("--allow-undefined");
4093 }
4094
4095 if (comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic) {
4096 try argv.append("--shared");
4097 }
4098 if (comp.config.pie) {
4099 try argv.append("--pie");
4100 }
4101
4102 try argv.appendSlice(&.{ "-o", full_out_path });
4103
4104 if (target.cpu.arch == .wasm64) {
4105 try argv.append("-mwasm64");
4106 }
4107
4108 const is_exe_or_dyn_lib = comp.config.output_mode == .Exe or
4109 (comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic);
4110
4111 if (comp.config.link_libc and is_exe_or_dyn_lib) {
4112 if (target.os.tag == .wasi) {
4113 for (comp.wasi_emulated_libs) |crt_file| {
4114 try argv.append(try comp.crtFileAsString(
4115 arena,
4116 wasi_libc.emulatedLibCRFileLibName(crt_file),
4117 ));
4118 }
4119
4120 try argv.append(try comp.crtFileAsString(
4121 arena,
4122 wasi_libc.execModelCrtFileFullName(comp.config.wasi_exec_model),
4123 ));
4124 try argv.append(try comp.crtFileAsString(arena, "libc.a"));
4125 }
4126
4127 if (comp.zigc_static_lib) |zigc| {
4128 try argv.append(try zigc.full_object_path.toString(arena));
4129 }
4130
4131 if (comp.config.link_libcpp) {
4132 try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena));
4133 try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena));
4134 }
4135 }
4136
4137 // Positional arguments to the linker such as object files.
4138 var whole_archive = false;
4139 for (comp.link_inputs) |link_input| switch (link_input) {
4140 .object, .archive => |obj| {
4141 if (obj.must_link and !whole_archive) {
4142 try argv.append("-whole-archive");
4143 whole_archive = true;
4144 } else if (!obj.must_link and whole_archive) {
4145 try argv.append("-no-whole-archive");
4146 whole_archive = false;
4147 }
4148 try argv.append(try obj.path.toString(arena));
4149 },
4150 .dso => |dso| {
4151 try argv.append(try dso.path.toString(arena));
4152 },
4153 .dso_exact => unreachable,
4154 .res => unreachable,
4155 };
4156 if (whole_archive) {
4157 try argv.append("-no-whole-archive");
4158 whole_archive = false;
4159 }
4160
4161 for (comp.c_object_table.keys()) |key| {
4162 try argv.append(try key.status.success.object_path.toString(arena));
4163 }
4164 if (module_obj_path) |p| {
4165 try argv.append(p);
4166 }
4167
4168 if (compiler_rt_path) |p| {
4169 try argv.append(try p.toString(arena));
4170 }
4171
4172 if (ubsan_rt_path) |p| {
4173 try argv.append(try p.toStringZ(arena));
4174 }
4175
4176 if (comp.verbose_link) {
4177 // Skip over our own name so that the LLD linker name is the first argv item.
4178 Compilation.dump_argv(argv.items[1..]);
4179 }
4180
4181 if (std.process.can_spawn) {
4182 // If possible, we run LLD as a child process because it does not always
4183 // behave properly as a library, unfortunately.
4184 // https://github.com/ziglang/zig/issues/3825
4185 var child = std.process.Child.init(argv.items, arena);
4186 if (comp.clang_passthrough_mode) {
4187 child.stdin_behavior = .Inherit;
4188 child.stdout_behavior = .Inherit;
4189 child.stderr_behavior = .Inherit;
4190
4191 const term = child.spawnAndWait() catch |err| {
4192 log.err("failed to spawn (passthrough mode) LLD {s}: {s}", .{ argv.items[0], @errorName(err) });
4193 return error.UnableToSpawnWasm;
4194 };
4195 switch (term) {
4196 .Exited => |code| {
4197 if (code != 0) {
4198 std.process.exit(code);
4199 }
4200 },
4201 else => std.process.abort(),
4202 }
4203 } else {
4204 child.stdin_behavior = .Ignore;
4205 child.stdout_behavior = .Ignore;
4206 child.stderr_behavior = .Pipe;
4207
4208 try child.spawn();
4209
4210 const stderr = try child.stderr.?.reader().readAllAlloc(arena, std.math.maxInt(usize));
4211
4212 const term = child.wait() catch |err| {
4213 log.err("failed to spawn LLD {s}: {s}", .{ argv.items[0], @errorName(err) });
4214 return error.UnableToSpawnWasm;
4215 };
4216
4217 switch (term) {
4218 .Exited => |code| {
4219 if (code != 0) {
4220 diags.lockAndParseLldStderr(linker_command, stderr);
4221 return error.LinkFailure;
4222 }
4223 },
4224 else => {
4225 return diags.fail("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
4226 },
4227 }
4228
4229 if (stderr.len != 0) {
4230 log.warn("unexpected LLD stderr:\n{s}", .{stderr});
4231 }
4232 }
4233 } else {
4234 const exit_code = try lldMain(arena, argv.items, false);
4235 if (exit_code != 0) {
4236 if (comp.clang_passthrough_mode) {
4237 std.process.exit(exit_code);
4238 } else {
4239 return diags.fail("{s} returned exit code {d}:\n{s}", .{ argv.items[0], exit_code });
4240 }
4241 }
4242 }
4243
4244 // Give +x to the .wasm file if it is an executable and the OS is WASI.
4245 // Some systems may be configured to execute such binaries directly. Even if that
4246 // is not the case, it means we will get "exec format error" when trying to run
4247 // it, and then can react to that in the same way as trying to run an ELF file
4248 // from a foreign CPU architecture.
4249 if (fs.has_executable_bit and target.os.tag == .wasi and
4250 comp.config.output_mode == .Exe)
4251 {
4252 // TODO: what's our strategy for reporting linker errors from this function?
4253 // report a nice error here with the file path if it fails instead of
4254 // just returning the error code.
4255 // chmod does not interact with umask, so we use a conservative -rwxr--r-- here.
4256 std.posix.fchmodat(fs.cwd().fd, full_out_path, 0o744, 0) catch |err| switch (err) {
4257 error.OperationNotSupported => unreachable, // Not a symlink.
4258 else => |e| return e,
4259 };
4260 }
4261 }
4262
4263 if (!wasm.base.disable_lld_caching) {
4264 // Update the file with the digest. If it fails we can continue; it only
4265 // means that the next invocation will have an unnecessary cache miss.
4266 Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
4267 log.warn("failed to save linking hash digest symlink: {s}", .{@errorName(err)});
4268 };
4269 // Again failure here only means an unnecessary cache miss.
4270 man.writeManifest() catch |err| {
4271 log.warn("failed to write cache manifest when linking: {s}", .{@errorName(err)});
4272 };
4273 // We hang on to this lock so that the output file path can be used without
4274 // other processes clobbering it.
4275 wasm.base.lock = man.toOwnedLock();
4276 }
4277}
4278
42793866fn defaultEntrySymbolName(
42803867 preloaded_strings: *const PreloadedStrings,
42813868 wasi_exec_model: std.builtin.WasiExecModel,
......@@ -4465,58 +4052,54 @@ pub fn symbolNameIndex(wasm: *Wasm, name: String) Allocator.Error!SymbolTableInd
44654052 return @enumFromInt(gop.index);
44664053}
44674054
4468pub fn refUavObj(wasm: *Wasm, ip_index: InternPool.Index, orig_ptr_ty: InternPool.Index) !UavsObjIndex {
4469 const comp = wasm.base.comp;
4470 const zcu = comp.zcu.?;
4471 const ip = &zcu.intern_pool;
4472 const gpa = comp.gpa;
4473 assert(comp.config.output_mode == .Obj);
4474
4475 if (orig_ptr_ty != .none) {
4476 const abi_alignment = Zcu.Type.fromInterned(ip.typeOf(ip_index)).abiAlignment(zcu);
4477 const explicit_alignment = ip.indexToKey(orig_ptr_ty).ptr_type.flags.alignment;
4478 if (explicit_alignment.compare(.gt, abi_alignment)) {
4479 const gop = try wasm.overaligned_uavs.getOrPut(gpa, ip_index);
4480 gop.value_ptr.* = if (gop.found_existing) gop.value_ptr.maxStrict(explicit_alignment) else explicit_alignment;
4481 }
4482 }
4483
4484 const gop = try wasm.uavs_obj.getOrPut(gpa, ip_index);
4485 if (!gop.found_existing) gop.value_ptr.* = .{
4486 // Lowering the value is delayed to avoid recursion.
4487 .code = undefined,
4488 .relocs = undefined,
4489 };
4490 return @enumFromInt(gop.index);
4491}
4492
4493pub fn refUavExe(wasm: *Wasm, ip_index: InternPool.Index, orig_ptr_ty: InternPool.Index) !UavsExeIndex {
4055pub fn addUavReloc(
4056 wasm: *Wasm,
4057 reloc_offset: usize,
4058 uav_val: InternPool.Index,
4059 orig_ptr_ty: InternPool.Index,
4060 addend: u32,
4061) !void {
44944062 const comp = wasm.base.comp;
44954063 const zcu = comp.zcu.?;
44964064 const ip = &zcu.intern_pool;
44974065 const gpa = comp.gpa;
4498 assert(comp.config.output_mode != .Obj);
44994066
4500 if (orig_ptr_ty != .none) {
4501 const abi_alignment = Zcu.Type.fromInterned(ip.typeOf(ip_index)).abiAlignment(zcu);
4502 const explicit_alignment = ip.indexToKey(orig_ptr_ty).ptr_type.flags.alignment;
4503 if (explicit_alignment.compare(.gt, abi_alignment)) {
4504 const gop = try wasm.overaligned_uavs.getOrPut(gpa, ip_index);
4505 gop.value_ptr.* = if (gop.found_existing) gop.value_ptr.maxStrict(explicit_alignment) else explicit_alignment;
4506 }
4507 }
4508
4509 const gop = try wasm.uavs_exe.getOrPut(gpa, ip_index);
4510 if (gop.found_existing) {
4511 gop.value_ptr.count += 1;
4067 @"align": {
4068 const ptr_type = ip.indexToKey(orig_ptr_ty).ptr_type;
4069 const this_align = ptr_type.flags.alignment;
4070 if (this_align == .none) break :@"align";
4071 const abi_align = Zcu.Type.fromInterned(ptr_type.child).abiAlignment(zcu);
4072 if (this_align.compare(.lte, abi_align)) break :@"align";
4073 const gop = try wasm.overaligned_uavs.getOrPut(gpa, uav_val);
4074 gop.value_ptr.* = if (gop.found_existing) gop.value_ptr.maxStrict(this_align) else this_align;
4075 }
4076
4077 if (comp.config.output_mode == .Obj) {
4078 const gop = try wasm.uavs_obj.getOrPut(gpa, uav_val);
4079 if (!gop.found_existing) gop.value_ptr.* = undefined; // to avoid recursion, `ZcuDataStarts` will lower the value later
4080 try wasm.out_relocs.append(gpa, .{
4081 .offset = @intCast(reloc_offset),
4082 .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav_val) },
4083 .tag = switch (wasm.pointerSize()) {
4084 32 => .memory_addr_i32,
4085 64 => .memory_addr_i64,
4086 else => unreachable,
4087 },
4088 .addend = @intCast(addend),
4089 });
45124090 } else {
4513 gop.value_ptr.* = .{
4514 // Lowering the value is delayed to avoid recursion.
4515 .code = undefined,
4516 .count = 1,
4091 const gop = try wasm.uavs_exe.getOrPut(gpa, uav_val);
4092 if (!gop.found_existing) gop.value_ptr.* = .{
4093 .code = undefined, // to avoid recursion, `ZcuDataStarts` will lower the value later
4094 .count = 0,
45174095 };
4096 gop.value_ptr.count += 1;
4097 try wasm.uav_fixups.append(gpa, .{
4098 .uavs_exe_index = @enumFromInt(gop.index),
4099 .offset = @intCast(reloc_offset),
4100 .addend = addend,
4101 });
45184102 }
4519 return @enumFromInt(gop.index);
45204103}
45214104
45224105pub fn refNavObj(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsObjIndex {
......@@ -4550,10 +4133,11 @@ pub fn refNavExe(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsExeIndex {
45504133}
45514134
45524135/// Asserts it is called after `Flush.data_segments` is fully populated and sorted.
4553pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) u32 {
4136pub fn uavAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 {
45544137 assert(wasm.flush_buffer.memory_layout_finished);
45554138 const comp = wasm.base.comp;
45564139 assert(comp.config.output_mode != .Obj);
4140 const uav_index: UavsExeIndex = @enumFromInt(wasm.uavs_exe.getIndex(ip_index).?);
45574141 const ds_id: DataSegmentId = .pack(wasm, .{ .uav_exe = uav_index });
45584142 return wasm.flush_buffer.data_segments.get(ds_id).?;
45594143}
src/link/Wasm/Flush.zig+16-1
......@@ -9,6 +9,7 @@ const Alignment = Wasm.Alignment;
99const String = Wasm.String;
1010const Relocation = Wasm.Relocation;
1111const InternPool = @import("../../InternPool.zig");
12const Mir = @import("../../arch/wasm/Mir.zig");
1213
1314const build_options = @import("build_options");
1415
......@@ -868,7 +869,21 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
868869 .enum_type => {
869870 try emitTagNameFunction(wasm, binary_bytes, f.data_segments.get(.__zig_tag_name_table).?, i.value(wasm).tag_name.table_index, ip_index);
870871 },
871 else => try i.value(wasm).function.lower(wasm, binary_bytes),
872 else => {
873 const func = i.value(wasm).function;
874 const mir: Mir = .{
875 .instructions = wasm.mir_instructions.slice().subslice(func.instructions_off, func.instructions_len),
876 .extra = wasm.mir_extra.items[func.extra_off..][0..func.extra_len],
877 .locals = wasm.mir_locals.items[func.locals_off..][0..func.locals_len],
878 .prologue = func.prologue,
879 // These fields are unused by `lower`.
880 .uavs = undefined,
881 .indirect_function_set = undefined,
882 .func_tys = undefined,
883 .error_name_table_ref_count = undefined,
884 };
885 try mir.lower(wasm, binary_bytes);
886 },
872887 }
873888 },
874889 };
src/link/Xcoff.zig+21-28
......@@ -13,14 +13,12 @@ const Path = std.Build.Cache.Path;
1313const Zcu = @import("../Zcu.zig");
1414const InternPool = @import("../InternPool.zig");
1515const Compilation = @import("../Compilation.zig");
16const codegen = @import("../codegen.zig");
1617const link = @import("../link.zig");
1718const trace = @import("../tracy.zig").trace;
1819const build_options = @import("build_options");
19const Air = @import("../Air.zig");
20const LlvmObject = @import("../codegen/llvm.zig").Object;
2120
2221base: link.File,
23llvm_object: LlvmObject.Ptr,
2422
2523pub fn createEmpty(
2624 arena: Allocator,
......@@ -36,23 +34,20 @@ pub fn createEmpty(
3634 assert(!use_lld); // Caught by Compilation.Config.resolve.
3735 assert(target.os.tag == .aix); // Caught by Compilation.Config.resolve.
3836
39 const llvm_object = try LlvmObject.create(arena, comp);
4037 const xcoff = try arena.create(Xcoff);
4138 xcoff.* = .{
4239 .base = .{
4340 .tag = .xcoff,
4441 .comp = comp,
4542 .emit = emit,
46 .zcu_object_sub_path = emit.sub_path,
43 .zcu_object_basename = emit.sub_path,
4744 .gc_sections = options.gc_sections orelse false,
4845 .print_gc_sections = options.print_gc_sections,
4946 .stack_size = options.stack_size orelse 0,
5047 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
5148 .file = null,
52 .disable_lld_caching = options.disable_lld_caching,
5349 .build_id = options.build_id,
5450 },
55 .llvm_object = llvm_object,
5651 };
5752
5853 return xcoff;
......@@ -70,27 +65,27 @@ pub fn open(
7065}
7166
7267pub fn deinit(self: *Xcoff) void {
73 self.llvm_object.deinit();
68 _ = self;
7469}
7570
7671pub fn updateFunc(
7772 self: *Xcoff,
7873 pt: Zcu.PerThread,
7974 func_index: InternPool.Index,
80 air: Air,
81 liveness: Air.Liveness,
75 mir: *const codegen.AnyMir,
8276) link.File.UpdateNavError!void {
83 if (build_options.skip_non_native and builtin.object_format != .xcoff)
84 @panic("Attempted to compile for object format that was disabled by build configuration");
85
86 try self.llvm_object.updateFunc(pt, func_index, air, liveness);
77 _ = self;
78 _ = pt;
79 _ = func_index;
80 _ = mir;
81 unreachable; // we always use llvm
8782}
8883
8984pub fn updateNav(self: *Xcoff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
90 if (build_options.skip_non_native and builtin.object_format != .xcoff)
91 @panic("Attempted to compile for object format that was disabled by build configuration");
92
93 return self.llvm_object.updateNav(pt, nav);
85 _ = self;
86 _ = pt;
87 _ = nav;
88 unreachable; // we always use llvm
9489}
9590
9691pub fn updateExports(
......@@ -99,21 +94,19 @@ pub fn updateExports(
9994 exported: Zcu.Exported,
10095 export_indices: []const Zcu.Export.Index,
10196) !void {
102 if (build_options.skip_non_native and builtin.object_format != .xcoff)
103 @panic("Attempted to compile for object format that was disabled by build configuration");
104
105 return self.llvm_object.updateExports(pt, exported, export_indices);
97 _ = self;
98 _ = pt;
99 _ = exported;
100 _ = export_indices;
101 unreachable; // we always use llvm
106102}
107103
108104pub fn flush(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
109 return self.flushModule(arena, tid, prog_node);
110}
111
112pub fn flushModule(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
113105 if (build_options.skip_non_native and builtin.object_format != .xcoff)
114106 @panic("Attempted to compile for object format that was disabled by build configuration");
115107
108 _ = self;
109 _ = arena;
116110 _ = tid;
117
118 try self.base.emitLlvmObject(arena, self.llvm_object, prog_node);
111 _ = prog_node;
119112}
src/main.zig+123-258
......@@ -699,55 +699,30 @@ const Emit = union(enum) {
699699 yes_default_path,
700700 yes: []const u8,
701701
702 const Resolved = struct {
703 data: ?Compilation.EmitLoc,
704 dir: ?fs.Dir,
705
706 fn deinit(self: *Resolved) void {
707 if (self.dir) |*dir| {
708 dir.close();
709 }
710 }
711 };
712
713 fn resolve(emit: Emit, default_basename: []const u8, output_to_cache: bool) !Resolved {
714 var resolved: Resolved = .{ .data = null, .dir = null };
715 errdefer resolved.deinit();
716
717 switch (emit) {
718 .no => {},
719 .yes_default_path => {
720 resolved.data = Compilation.EmitLoc{
721 .directory = if (output_to_cache) null else .{
722 .path = null,
723 .handle = fs.cwd(),
724 },
725 .basename = default_basename,
726 };
727 },
728 .yes => |full_path| {
729 const basename = fs.path.basename(full_path);
730 if (fs.path.dirname(full_path)) |dirname| {
731 const handle = try fs.cwd().openDir(dirname, .{});
732 resolved = .{
733 .dir = handle,
734 .data = Compilation.EmitLoc{
735 .basename = basename,
736 .directory = .{
737 .path = dirname,
738 .handle = handle,
739 },
740 },
741 };
742 } else {
743 resolved.data = Compilation.EmitLoc{
744 .basename = basename,
745 .directory = .{ .path = null, .handle = fs.cwd() },
702 const OutputToCacheReason = enum { listen, @"zig run", @"zig test" };
703 fn resolve(emit: Emit, default_basename: []const u8, output_to_cache: ?OutputToCacheReason) Compilation.CreateOptions.Emit {
704 return switch (emit) {
705 .no => .no,
706 .yes_default_path => if (output_to_cache != null) .yes_cache else .{ .yes_path = default_basename },
707 .yes => |path| if (output_to_cache) |reason| {
708 switch (reason) {
709 .listen => fatal("--listen incompatible with explicit output path '{s}'", .{path}),
710 .@"zig run", .@"zig test" => fatal(
711 "'{s}' with explicit output path '{s}' requires explicit '-femit-bin=path' or '-fno-emit-bin'",
712 .{ @tagName(reason), path },
713 ),
714 }
715 } else e: {
716 // If there's a dirname, check that dir exists. This will give a more descriptive error than `Compilation` otherwise would.
717 if (fs.path.dirname(path)) |dir_path| {
718 var dir = fs.cwd().openDir(dir_path, .{}) catch |err| {
719 fatal("unable to open output directory '{s}': {s}", .{ dir_path, @errorName(err) });
746720 };
721 dir.close();
747722 }
723 break :e .{ .yes_path = path };
748724 },
749 }
750 return resolved;
725 };
751726 }
752727};
753728
......@@ -867,9 +842,9 @@ fn buildOutputType(
867842 var linker_allow_undefined_version: bool = false;
868843 var linker_enable_new_dtags: ?bool = null;
869844 var disable_c_depfile = false;
870 var linker_sort_section: ?link.File.Elf.SortSection = null;
845 var linker_sort_section: ?link.File.Lld.Elf.SortSection = null;
871846 var linker_gc_sections: ?bool = null;
872 var linker_compress_debug_sections: ?link.File.Elf.CompressDebugSections = null;
847 var linker_compress_debug_sections: ?link.File.Lld.Elf.CompressDebugSections = null;
873848 var linker_allow_shlib_undefined: ?bool = null;
874849 var allow_so_scripts: bool = false;
875850 var linker_bind_global_refs_locally: ?bool = null;
......@@ -921,7 +896,7 @@ fn buildOutputType(
921896 var debug_compiler_runtime_libs = false;
922897 var opt_incremental: ?bool = null;
923898 var install_name: ?[]const u8 = null;
924 var hash_style: link.File.Elf.HashStyle = .both;
899 var hash_style: link.File.Lld.Elf.HashStyle = .both;
925900 var entitlements: ?[]const u8 = null;
926901 var pagezero_size: ?u64 = null;
927902 var lib_search_strategy: link.UnresolvedInput.SearchStrategy = .paths_first;
......@@ -1196,11 +1171,11 @@ fn buildOutputType(
11961171 install_name = args_iter.nextOrFatal();
11971172 } else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) {
11981173 const param = arg["--compress-debug-sections=".len..];
1199 linker_compress_debug_sections = std.meta.stringToEnum(link.File.Elf.CompressDebugSections, param) orelse {
1174 linker_compress_debug_sections = std.meta.stringToEnum(link.File.Lld.Elf.CompressDebugSections, param) orelse {
12001175 fatal("expected --compress-debug-sections=[none|zlib|zstd], found '{s}'", .{param});
12011176 };
12021177 } else if (mem.eql(u8, arg, "--compress-debug-sections")) {
1203 linker_compress_debug_sections = link.File.Elf.CompressDebugSections.zlib;
1178 linker_compress_debug_sections = link.File.Lld.Elf.CompressDebugSections.zlib;
12041179 } else if (mem.eql(u8, arg, "-pagezero_size")) {
12051180 const next_arg = args_iter.nextOrFatal();
12061181 pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| {
......@@ -2368,7 +2343,7 @@ fn buildOutputType(
23682343 if (it.only_arg.len == 0) {
23692344 linker_compress_debug_sections = .zlib;
23702345 } else {
2371 linker_compress_debug_sections = std.meta.stringToEnum(link.File.Elf.CompressDebugSections, it.only_arg) orelse {
2346 linker_compress_debug_sections = std.meta.stringToEnum(link.File.Lld.Elf.CompressDebugSections, it.only_arg) orelse {
23722347 fatal("expected [none|zlib|zstd] after --compress-debug-sections, found '{s}'", .{it.only_arg});
23732348 };
23742349 }
......@@ -2505,7 +2480,7 @@ fn buildOutputType(
25052480 linker_print_map = true;
25062481 } else if (mem.eql(u8, arg, "--sort-section")) {
25072482 const arg1 = linker_args_it.nextOrFatal();
2508 linker_sort_section = std.meta.stringToEnum(link.File.Elf.SortSection, arg1) orelse {
2483 linker_sort_section = std.meta.stringToEnum(link.File.Lld.Elf.SortSection, arg1) orelse {
25092484 fatal("expected [name|alignment] after --sort-section, found '{s}'", .{arg1});
25102485 };
25112486 } else if (mem.eql(u8, arg, "--allow-shlib-undefined") or
......@@ -2551,7 +2526,7 @@ fn buildOutputType(
25512526 try linker_export_symbol_names.append(arena, linker_args_it.nextOrFatal());
25522527 } else if (mem.eql(u8, arg, "--compress-debug-sections")) {
25532528 const arg1 = linker_args_it.nextOrFatal();
2554 linker_compress_debug_sections = std.meta.stringToEnum(link.File.Elf.CompressDebugSections, arg1) orelse {
2529 linker_compress_debug_sections = std.meta.stringToEnum(link.File.Lld.Elf.CompressDebugSections, arg1) orelse {
25552530 fatal("expected [none|zlib|zstd] after --compress-debug-sections, found '{s}'", .{arg1});
25562531 };
25572532 } else if (mem.startsWith(u8, arg, "-z")) {
......@@ -2764,7 +2739,7 @@ fn buildOutputType(
27642739 mem.eql(u8, arg, "--hash-style"))
27652740 {
27662741 const next_arg = linker_args_it.nextOrFatal();
2767 hash_style = std.meta.stringToEnum(link.File.Elf.HashStyle, next_arg) orelse {
2742 hash_style = std.meta.stringToEnum(link.File.Lld.Elf.HashStyle, next_arg) orelse {
27682743 fatal("expected [sysv|gnu|both] after --hash-style, found '{s}'", .{
27692744 next_arg,
27702745 });
......@@ -2830,7 +2805,7 @@ fn buildOutputType(
28302805 .link => {
28312806 create_module.opts.output_mode = if (is_shared_lib) .Lib else .Exe;
28322807 if (emit_bin != .no) {
2833 emit_bin = if (out_path) |p| .{ .yes = p } else EmitBin.yes_a_out;
2808 emit_bin = if (out_path) |p| .{ .yes = p } else .yes_a_out;
28342809 }
28352810 if (emit_llvm) {
28362811 fatal("-emit-llvm cannot be used when linking", .{});
......@@ -3208,7 +3183,17 @@ fn buildOutputType(
32083183 var cleanup_emit_bin_dir: ?fs.Dir = null;
32093184 defer if (cleanup_emit_bin_dir) |*dir| dir.close();
32103185
3211 const output_to_cache = listen != .none;
3186 // For `zig run` and `zig test`, we don't want to put the binary in the cwd by default. So, if
3187 // the binary is requested with no explicit path (as is the default), we emit to the cache.
3188 const output_to_cache: ?Emit.OutputToCacheReason = switch (listen) {
3189 .stdio, .ip4 => .listen,
3190 .none => if (arg_mode == .run and emit_bin == .yes_default_path)
3191 .@"zig run"
3192 else if (arg_mode == .zig_test and emit_bin == .yes_default_path)
3193 .@"zig test"
3194 else
3195 null,
3196 };
32123197 const optional_version = if (have_version) version else null;
32133198
32143199 const root_name = if (provided_name) |n| n else main_mod.fully_qualified_name;
......@@ -3225,150 +3210,57 @@ fn buildOutputType(
32253210 },
32263211 };
32273212
3228 const a_out_basename = switch (target.ofmt) {
3229 .coff => "a.exe",
3230 else => "a.out",
3231 };
3232
3233 const emit_bin_loc: ?Compilation.EmitLoc = switch (emit_bin) {
3234 .no => null,
3235 .yes_default_path => Compilation.EmitLoc{
3236 .directory = blk: {
3237 switch (arg_mode) {
3238 .run, .zig_test => break :blk null,
3239 .build, .cc, .cpp, .translate_c, .zig_test_obj => {
3240 if (output_to_cache) {
3241 break :blk null;
3242 } else {
3243 break :blk .{ .path = null, .handle = fs.cwd() };
3244 }
3245 },
3246 }
3247 },
3248 .basename = if (clang_preprocessor_mode == .pch)
3249 try std.fmt.allocPrint(arena, "{s}.pch", .{root_name})
3250 else
3251 try std.zig.binNameAlloc(arena, .{
3213 const emit_bin_resolved: Compilation.CreateOptions.Emit = switch (emit_bin) {
3214 .no => .no,
3215 .yes_default_path => emit: {
3216 if (output_to_cache != null) break :emit .yes_cache;
3217 const name = switch (clang_preprocessor_mode) {
3218 .pch => try std.fmt.allocPrint(arena, "{s}.pch", .{root_name}),
3219 else => try std.zig.binNameAlloc(arena, .{
32523220 .root_name = root_name,
32533221 .target = target,
32543222 .output_mode = create_module.resolved_options.output_mode,
32553223 .link_mode = create_module.resolved_options.link_mode,
32563224 .version = optional_version,
32573225 }),
3226 };
3227 break :emit .{ .yes_path = name };
32583228 },
3259 .yes => |full_path| b: {
3260 const basename = fs.path.basename(full_path);
3261 if (fs.path.dirname(full_path)) |dirname| {
3262 const handle = fs.cwd().openDir(dirname, .{}) catch |err| {
3263 fatal("unable to open output directory '{s}': {s}", .{ dirname, @errorName(err) });
3264 };
3265 cleanup_emit_bin_dir = handle;
3266 break :b Compilation.EmitLoc{
3267 .basename = basename,
3268 .directory = .{
3269 .path = dirname,
3270 .handle = handle,
3271 },
3272 };
3273 } else {
3274 break :b Compilation.EmitLoc{
3275 .basename = basename,
3276 .directory = .{ .path = null, .handle = fs.cwd() },
3229 .yes => |path| if (output_to_cache != null) {
3230 assert(output_to_cache == .listen); // there was an explicit bin path
3231 fatal("--listen incompatible with explicit output path '{s}'", .{path});
3232 } else emit: {
3233 // If there's a dirname, check that dir exists. This will give a more descriptive error than `Compilation` otherwise would.
3234 if (fs.path.dirname(path)) |dir_path| {
3235 var dir = fs.cwd().openDir(dir_path, .{}) catch |err| {
3236 fatal("unable to open output directory '{s}': {s}", .{ dir_path, @errorName(err) });
32773237 };
3238 dir.close();
32783239 }
3240 break :emit .{ .yes_path = path };
32793241 },
3280 .yes_a_out => Compilation.EmitLoc{
3281 .directory = .{ .path = null, .handle = fs.cwd() },
3282 .basename = a_out_basename,
3242 .yes_a_out => emit: {
3243 assert(output_to_cache == null);
3244 break :emit .{ .yes_path = switch (target.ofmt) {
3245 .coff => "a.exe",
3246 else => "a.out",
3247 } };
32833248 },
32843249 };
32853250
32863251 const default_h_basename = try std.fmt.allocPrint(arena, "{s}.h", .{root_name});
3287 var emit_h_resolved = emit_h.resolve(default_h_basename, output_to_cache) catch |err| {
3288 switch (emit_h) {
3289 .yes => |p| {
3290 fatal("unable to open directory from argument '-femit-h', '{s}': {s}", .{
3291 p, @errorName(err),
3292 });
3293 },
3294 .yes_default_path => {
3295 fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{
3296 default_h_basename, @errorName(err),
3297 });
3298 },
3299 .no => unreachable,
3300 }
3301 };
3302 defer emit_h_resolved.deinit();
3252 const emit_h_resolved = emit_h.resolve(default_h_basename, output_to_cache);
33033253
33043254 const default_asm_basename = try std.fmt.allocPrint(arena, "{s}.s", .{root_name});
3305 var emit_asm_resolved = emit_asm.resolve(default_asm_basename, output_to_cache) catch |err| {
3306 switch (emit_asm) {
3307 .yes => |p| {
3308 fatal("unable to open directory from argument '-femit-asm', '{s}': {s}", .{
3309 p, @errorName(err),
3310 });
3311 },
3312 .yes_default_path => {
3313 fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{
3314 default_asm_basename, @errorName(err),
3315 });
3316 },
3317 .no => unreachable,
3318 }
3319 };
3320 defer emit_asm_resolved.deinit();
3255 const emit_asm_resolved = emit_asm.resolve(default_asm_basename, output_to_cache);
33213256
33223257 const default_llvm_ir_basename = try std.fmt.allocPrint(arena, "{s}.ll", .{root_name});
3323 var emit_llvm_ir_resolved = emit_llvm_ir.resolve(default_llvm_ir_basename, output_to_cache) catch |err| {
3324 switch (emit_llvm_ir) {
3325 .yes => |p| {
3326 fatal("unable to open directory from argument '-femit-llvm-ir', '{s}': {s}", .{
3327 p, @errorName(err),
3328 });
3329 },
3330 .yes_default_path => {
3331 fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{
3332 default_llvm_ir_basename, @errorName(err),
3333 });
3334 },
3335 .no => unreachable,
3336 }
3337 };
3338 defer emit_llvm_ir_resolved.deinit();
3258 const emit_llvm_ir_resolved = emit_llvm_ir.resolve(default_llvm_ir_basename, output_to_cache);
33393259
33403260 const default_llvm_bc_basename = try std.fmt.allocPrint(arena, "{s}.bc", .{root_name});
3341 var emit_llvm_bc_resolved = emit_llvm_bc.resolve(default_llvm_bc_basename, output_to_cache) catch |err| {
3342 switch (emit_llvm_bc) {
3343 .yes => |p| {
3344 fatal("unable to open directory from argument '-femit-llvm-bc', '{s}': {s}", .{
3345 p, @errorName(err),
3346 });
3347 },
3348 .yes_default_path => {
3349 fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{
3350 default_llvm_bc_basename, @errorName(err),
3351 });
3352 },
3353 .no => unreachable,
3354 }
3355 };
3356 defer emit_llvm_bc_resolved.deinit();
3261 const emit_llvm_bc_resolved = emit_llvm_bc.resolve(default_llvm_bc_basename, output_to_cache);
33573262
3358 var emit_docs_resolved = emit_docs.resolve("docs", output_to_cache) catch |err| {
3359 switch (emit_docs) {
3360 .yes => |p| {
3361 fatal("unable to open directory from argument '-femit-docs', '{s}': {s}", .{
3362 p, @errorName(err),
3363 });
3364 },
3365 .yes_default_path => {
3366 fatal("unable to open directory 'docs': {s}", .{@errorName(err)});
3367 },
3368 .no => unreachable,
3369 }
3370 };
3371 defer emit_docs_resolved.deinit();
3263 const emit_docs_resolved = emit_docs.resolve("docs", output_to_cache);
33723264
33733265 const is_exe_or_dyn_lib = switch (create_module.resolved_options.output_mode) {
33743266 .Obj => false,
......@@ -3378,7 +3270,7 @@ fn buildOutputType(
33783270 // Note that cmake when targeting Windows will try to execute
33793271 // zig cc to make an executable and output an implib too.
33803272 const implib_eligible = is_exe_or_dyn_lib and
3381 emit_bin_loc != null and target.os.tag == .windows;
3273 emit_bin_resolved != .no and target.os.tag == .windows;
33823274 if (!implib_eligible) {
33833275 if (!emit_implib_arg_provided) {
33843276 emit_implib = .no;
......@@ -3387,22 +3279,18 @@ fn buildOutputType(
33873279 }
33883280 }
33893281 const default_implib_basename = try std.fmt.allocPrint(arena, "{s}.lib", .{root_name});
3390 var emit_implib_resolved = switch (emit_implib) {
3391 .no => Emit.Resolved{ .data = null, .dir = null },
3392 .yes => |p| emit_implib.resolve(default_implib_basename, output_to_cache) catch |err| {
3393 fatal("unable to open directory from argument '-femit-implib', '{s}': {s}", .{
3394 p, @errorName(err),
3282 const emit_implib_resolved: Compilation.CreateOptions.Emit = switch (emit_implib) {
3283 .no => .no,
3284 .yes => emit_implib.resolve(default_implib_basename, output_to_cache),
3285 .yes_default_path => emit: {
3286 if (output_to_cache != null) break :emit .yes_cache;
3287 const p = try fs.path.join(arena, &.{
3288 fs.path.dirname(emit_bin_resolved.yes_path) orelse ".",
3289 default_implib_basename,
33953290 });
3396 },
3397 .yes_default_path => Emit.Resolved{
3398 .data = Compilation.EmitLoc{
3399 .directory = emit_bin_loc.?.directory,
3400 .basename = default_implib_basename,
3401 },
3402 .dir = null,
3291 break :emit .{ .yes_path = p };
34033292 },
34043293 };
3405 defer emit_implib_resolved.deinit();
34063294
34073295 var thread_pool: ThreadPool = undefined;
34083296 try thread_pool.init(.{
......@@ -3456,7 +3344,7 @@ fn buildOutputType(
34563344 src.src_path = try dirs.local_cache.join(arena, &.{sub_path});
34573345 }
34583346
3459 if (build_options.have_llvm and emit_asm != .no) {
3347 if (build_options.have_llvm and emit_asm_resolved != .no) {
34603348 // LLVM has no way to set this non-globally.
34613349 const argv = [_][*:0]const u8{ "zig (LLVM option parsing)", "--x86-asm-syntax=intel" };
34623350 @import("codegen/llvm/bindings.zig").ParseCommandLineOptions(argv.len, &argv);
......@@ -3472,23 +3360,11 @@ fn buildOutputType(
34723360 fatal("--debug-incremental requires -fincremental", .{});
34733361 }
34743362
3475 const disable_lld_caching = !output_to_cache;
3476
34773363 const cache_mode: Compilation.CacheMode = b: {
3364 // Once incremental compilation is the default, we'll want some smarter logic here,
3365 // considering things like the backend in use and whether there's a ZCU.
3366 if (output_to_cache == null) break :b .none;
34783367 if (incremental) break :b .incremental;
3479 if (disable_lld_caching) break :b .incremental;
3480 if (!create_module.resolved_options.have_zcu) break :b .whole;
3481
3482 // TODO: once we support incremental compilation for the LLVM backend
3483 // via saving the LLVM module into a bitcode file and restoring it,
3484 // along with compiler state, this clause can be removed so that
3485 // incremental cache mode is used for LLVM backend too.
3486 if (create_module.resolved_options.use_llvm) break :b .whole;
3487
3488 // Eventually, this default should be `.incremental`. However, since incremental
3489 // compilation is currently an opt-in feature, it makes a strictly worse default cache mode
3490 // than `.whole`.
3491 // https://github.com/ziglang/zig/issues/21165
34923368 break :b .whole;
34933369 };
34943370
......@@ -3510,13 +3386,13 @@ fn buildOutputType(
35103386 .main_mod = main_mod,
35113387 .root_mod = root_mod,
35123388 .std_mod = std_mod,
3513 .emit_bin = emit_bin_loc,
3514 .emit_h = emit_h_resolved.data,
3515 .emit_asm = emit_asm_resolved.data,
3516 .emit_llvm_ir = emit_llvm_ir_resolved.data,
3517 .emit_llvm_bc = emit_llvm_bc_resolved.data,
3518 .emit_docs = emit_docs_resolved.data,
3519 .emit_implib = emit_implib_resolved.data,
3389 .emit_bin = emit_bin_resolved,
3390 .emit_h = emit_h_resolved,
3391 .emit_asm = emit_asm_resolved,
3392 .emit_llvm_ir = emit_llvm_ir_resolved,
3393 .emit_llvm_bc = emit_llvm_bc_resolved,
3394 .emit_docs = emit_docs_resolved,
3395 .emit_implib = emit_implib_resolved,
35203396 .lib_directories = create_module.lib_directories.items,
35213397 .rpath_list = create_module.rpath_list.items,
35223398 .symbol_wrap_set = symbol_wrap_set,
......@@ -3599,7 +3475,6 @@ fn buildOutputType(
35993475 .test_filters = test_filters.items,
36003476 .test_name_prefix = test_name_prefix,
36013477 .test_runner_path = test_runner_path,
3602 .disable_lld_caching = disable_lld_caching,
36033478 .cache_mode = cache_mode,
36043479 .subsystem = subsystem,
36053480 .debug_compile_errors = debug_compile_errors,
......@@ -3744,13 +3619,8 @@ fn buildOutputType(
37443619 }) {
37453620 dev.checkAny(&.{ .run_command, .test_command });
37463621
3747 if (test_exec_args.items.len == 0 and target.ofmt == .c) default_exec_args: {
3622 if (test_exec_args.items.len == 0 and target.ofmt == .c and emit_bin_resolved != .no) {
37483623 // Default to using `zig run` to execute the produced .c code from `zig test`.
3749 const c_code_loc = emit_bin_loc orelse break :default_exec_args;
3750 const c_code_directory = c_code_loc.directory orelse comp.bin_file.?.emit.root_dir;
3751 const c_code_path = try fs.path.join(arena, &[_][]const u8{
3752 c_code_directory.path orelse ".", c_code_loc.basename,
3753 });
37543624 try test_exec_args.appendSlice(arena, &.{ self_exe_path, "run" });
37553625 if (dirs.zig_lib.path) |p| {
37563626 try test_exec_args.appendSlice(arena, &.{ "-I", p });
......@@ -3775,7 +3645,7 @@ fn buildOutputType(
37753645 if (create_module.dynamic_linker) |dl| {
37763646 try test_exec_args.appendSlice(arena, &.{ "--dynamic-linker", dl });
37773647 }
3778 try test_exec_args.append(arena, c_code_path);
3648 try test_exec_args.append(arena, null); // placeholder for the path of the emitted C source file
37793649 }
37803650
37813651 try runOrTest(
......@@ -4354,12 +4224,22 @@ fn runOrTest(
43544224 runtime_args_start: ?usize,
43554225 link_libc: bool,
43564226) !void {
4357 const lf = comp.bin_file orelse return;
4358 // A naive `directory.join` here will indeed get the correct path to the binary,
4359 // however, in the case of cwd, we actually want `./foo` so that the path can be executed.
4360 const exe_path = try fs.path.join(arena, &[_][]const u8{
4361 lf.emit.root_dir.path orelse ".", lf.emit.sub_path,
4362 });
4227 const raw_emit_bin = comp.emit_bin orelse return;
4228 const exe_path = switch (comp.cache_use) {
4229 .none => p: {
4230 if (fs.path.isAbsolute(raw_emit_bin)) break :p raw_emit_bin;
4231 // Use `fs.path.join` to make a file in the cwd is still executed properly.
4232 break :p try fs.path.join(arena, &.{
4233 ".",
4234 raw_emit_bin,
4235 });
4236 },
4237 .whole, .incremental => try comp.dirs.local_cache.join(arena, &.{
4238 "o",
4239 &Cache.binToHex(comp.digest.?),
4240 raw_emit_bin,
4241 }),
4242 };
43634243
43644244 var argv = std.ArrayList([]const u8).init(gpa);
43654245 defer argv.deinit();
......@@ -5087,16 +4967,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
50874967 };
50884968 };
50894969
5090 const exe_basename = try std.zig.binNameAlloc(arena, .{
5091 .root_name = "build",
5092 .target = resolved_target.result,
5093 .output_mode = .Exe,
5094 });
5095 const emit_bin: Compilation.EmitLoc = .{
5096 .directory = null, // Use the local zig-cache.
5097 .basename = exe_basename,
5098 };
5099
51004970 process.raiseFileDescriptorLimit();
51014971
51024972 const cwd_path = try introspect.getResolvedCwd(arena);
......@@ -5357,8 +5227,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
53575227 .config = config,
53585228 .root_mod = root_mod,
53595229 .main_mod = build_mod,
5360 .emit_bin = emit_bin,
5361 .emit_h = null,
5230 .emit_bin = .yes_cache,
53625231 .self_exe_path = self_exe_path,
53635232 .thread_pool = &thread_pool,
53645233 .verbose_cc = verbose_cc,
......@@ -5386,8 +5255,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
53865255 // Since incremental compilation isn't done yet, we use cache_mode = whole
53875256 // above, and thus the output file is already closed.
53885257 //try comp.makeBinFileExecutable();
5389 child_argv.items[argv_index_exe] =
5390 try dirs.local_cache.join(arena, &.{comp.cache_use.whole.bin_sub_path.?});
5258 child_argv.items[argv_index_exe] = try dirs.local_cache.join(arena, &.{
5259 "o",
5260 &Cache.binToHex(comp.digest.?),
5261 comp.emit_bin.?,
5262 });
53915263 }
53925264
53935265 if (process.can_spawn) {
......@@ -5504,16 +5376,6 @@ fn jitCmd(
55045376 .is_explicit_dynamic_linker = false,
55055377 };
55065378
5507 const exe_basename = try std.zig.binNameAlloc(arena, .{
5508 .root_name = options.cmd_name,
5509 .target = resolved_target.result,
5510 .output_mode = .Exe,
5511 });
5512 const emit_bin: Compilation.EmitLoc = .{
5513 .directory = null, // Use the global zig-cache.
5514 .basename = exe_basename,
5515 };
5516
55175379 const self_exe_path = fs.selfExePathAlloc(arena) catch |err| {
55185380 fatal("unable to find self exe path: {s}", .{@errorName(err)});
55195381 };
......@@ -5605,8 +5467,7 @@ fn jitCmd(
56055467 .config = config,
56065468 .root_mod = root_mod,
56075469 .main_mod = root_mod,
5608 .emit_bin = emit_bin,
5609 .emit_h = null,
5470 .emit_bin = .yes_cache,
56105471 .self_exe_path = self_exe_path,
56115472 .thread_pool = &thread_pool,
56125473 .cache_mode = .whole,
......@@ -5637,7 +5498,11 @@ fn jitCmd(
56375498 };
56385499 }
56395500
5640 const exe_path = try dirs.global_cache.join(arena, &.{comp.cache_use.whole.bin_sub_path.?});
5501 const exe_path = try dirs.global_cache.join(arena, &.{
5502 "o",
5503 &Cache.binToHex(comp.digest.?),
5504 comp.emit_bin.?,
5505 });
56415506 child_argv.appendAssumeCapacity(exe_path);
56425507 }
56435508
src/target.zig+4-2
......@@ -739,7 +739,7 @@ pub fn functionPointerMask(target: std.Target) ?u64 {
739739
740740pub fn supportsTailCall(target: std.Target, backend: std.builtin.CompilerBackend) bool {
741741 switch (backend) {
742 .stage1, .stage2_llvm => return @import("codegen/llvm.zig").supportsTailCall(target),
742 .stage2_llvm => return @import("codegen/llvm.zig").supportsTailCall(target),
743743 .stage2_c => return true,
744744 else => return false,
745745 }
......@@ -850,7 +850,9 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
850850 },
851851 .separate_thread => switch (backend) {
852852 .stage2_llvm => false,
853 else => true,
853 .stage2_c, .stage2_wasm, .stage2_x86_64 => true,
854 // TODO: most self-hosted backends should be able to support this without too much work.
855 else => false,
854856 },
855857 };
856858}
stage1/wasi.c+12-12
......@@ -517,7 +517,7 @@ uint32_t wasi_snapshot_preview1_fd_read(uint32_t fd, uint32_t iovs, uint32_t iov
517517 case wasi_filetype_character_device: break;
518518 case wasi_filetype_regular_file: break;
519519 case wasi_filetype_directory: return wasi_errno_inval;
520 default: panic("unimplemented");
520 default: panic("unimplemented: fd_read special file");
521521 }
522522
523523 size_t size = 0;
......@@ -629,7 +629,7 @@ uint32_t wasi_snapshot_preview1_fd_pwrite(uint32_t fd, uint32_t iovs, uint32_t i
629629 case wasi_filetype_character_device: break;
630630 case wasi_filetype_regular_file: break;
631631 case wasi_filetype_directory: return wasi_errno_inval;
632 default: panic("unimplemented");
632 default: panic("unimplemented: fd_pwrite special file");
633633 }
634634
635635 fpos_t pos;
......@@ -679,7 +679,7 @@ uint32_t wasi_snapshot_preview1_fd_filestat_set_times(uint32_t fd, uint64_t atim
679679 fprintf(stderr, "wasi_snapshot_preview1_fd_filestat_set_times(%u, %llu, %llu, 0x%X)\n", fd, (unsigned long long)atim, (unsigned long long)mtim, fst_flags);
680680#endif
681681
682 panic("unimplemented");
682 panic("unimplemented: fd_filestat_set_times");
683683 return wasi_errno_success;
684684}
685685
......@@ -703,7 +703,7 @@ uint32_t wasi_snapshot_preview1_environ_get(uint32_t environ, uint32_t environ_b
703703 fprintf(stderr, "wasi_snapshot_preview1_environ_get()\n");
704704#endif
705705
706 panic("unimplemented");
706 panic("unimplemented: environ_get");
707707 return wasi_errno_success;
708708}
709709
......@@ -757,7 +757,7 @@ uint32_t wasi_snapshot_preview1_fd_readdir(uint32_t fd, uint32_t buf, uint32_t b
757757 fprintf(stderr, "wasi_snapshot_preview1_fd_readdir(%u, 0x%X, %u, %llu)\n", fd, buf, buf_len, (unsigned long long)cookie);
758758#endif
759759
760 panic("unimplemented");
760 panic("unimplemented: fd_readdir");
761761 return wasi_errno_success;
762762}
763763
......@@ -774,7 +774,7 @@ uint32_t wasi_snapshot_preview1_fd_write(uint32_t fd, uint32_t iovs, uint32_t io
774774 case wasi_filetype_character_device: break;
775775 case wasi_filetype_regular_file: break;
776776 case wasi_filetype_directory: return wasi_errno_inval;
777 default: panic("unimplemented");
777 default: panic("unimplemented: fd_write special file");
778778 }
779779
780780 size_t size = 0;
......@@ -825,7 +825,7 @@ uint32_t wasi_snapshot_preview1_path_open(uint32_t fd, uint32_t dirflags, uint32
825825 fds[fd_len].fdflags = fdflags;
826826 switch (des[de].filetype) {
827827 case wasi_filetype_directory: fds[fd_len].stream = NULL; break;
828 default: panic("unimplemented");
828 default: panic("unimplemented: path_open non-directory DirEntry");
829829 }
830830 fds[fd_len].fs_rights_inheriting = fs_rights_inheriting;
831831
......@@ -943,7 +943,7 @@ uint32_t wasi_snapshot_preview1_path_unlink_file(uint32_t fd, uint32_t path, uin
943943 enum wasi_errno lookup_errno = DirEntry_lookup(fd, 0, path_ptr, path_len, &de);
944944 if (lookup_errno != wasi_errno_success) return lookup_errno;
945945 if (des[de].filetype == wasi_filetype_directory) return wasi_errno_isdir;
946 if (des[de].filetype != wasi_filetype_regular_file) panic("unimplemented");
946 if (des[de].filetype != wasi_filetype_regular_file) panic("unimplemented: path_unlink_file special file");
947947 DirEntry_unlink(de);
948948 return wasi_errno_success;
949949}
......@@ -961,7 +961,7 @@ uint32_t wasi_snapshot_preview1_fd_pread(uint32_t fd, uint32_t iovs, uint32_t io
961961 case wasi_filetype_character_device: break;
962962 case wasi_filetype_regular_file: break;
963963 case wasi_filetype_directory: return wasi_errno_inval;
964 default: panic("unimplemented");
964 default: panic("unimplemented: fd_pread special file");
965965 }
966966
967967 fpos_t pos;
......@@ -975,7 +975,7 @@ uint32_t wasi_snapshot_preview1_fd_pread(uint32_t fd, uint32_t iovs, uint32_t io
975975 if (fds[fd].stream != NULL)
976976 read_size = fread(&m[load32_align2(&iovs_ptr[i].ptr)], 1, len, fds[fd].stream);
977977 else
978 panic("unimplemented");
978 panic("unimplemented: fd_pread stream=NULL");
979979 size += read_size;
980980 if (read_size < len) break;
981981 }
......@@ -1000,7 +1000,7 @@ uint32_t wasi_snapshot_preview1_fd_seek(uint32_t fd, uint64_t in_offset, uint32_
10001000 case wasi_filetype_character_device: break;
10011001 case wasi_filetype_regular_file: break;
10021002 case wasi_filetype_directory: return wasi_errno_inval;
1003 default: panic("unimplemented");
1003 default: panic("unimplemented: fd_seek special file");
10041004 }
10051005
10061006 if (fds[fd].stream == NULL) return wasi_errno_success;
......@@ -1035,7 +1035,7 @@ uint32_t wasi_snapshot_preview1_poll_oneoff(uint32_t in, uint32_t out, uint32_t
10351035 fprintf(stderr, "wasi_snapshot_preview1_poll_oneoff(%u)\n", nsubscriptions);
10361036#endif
10371037
1038 panic("unimplemented");
1038 panic("unimplemented: poll_oneoff");
10391039 return wasi_errno_success;
10401040}
10411041
test/link/macho.zig+2-2
......@@ -211,7 +211,7 @@ fn testDuplicateDefinitions(b: *Build, opts: Options) *Step {
211211 expectLinkErrors(exe, test_step, .{ .exact = &.{
212212 "error: duplicate symbol definition: _strong",
213213 "note: defined by /?/a.o",
214 "note: defined by /?/main.o",
214 "note: defined by /?/main_zcu.o",
215215 } });
216216
217217 return test_step;
......@@ -2648,7 +2648,7 @@ fn testUnresolvedError(b: *Build, opts: Options) *Step {
26482648 expectLinkErrors(exe, test_step, .{ .exact = &.{
26492649 "error: undefined symbol: _foo",
26502650 "note: referenced by /?/a.o:_bar",
2651 "note: referenced by /?/main.o:_main.main",
2651 "note: referenced by /?/main_zcu.o:_main.main",
26522652 } });
26532653 } else {
26542654 expectLinkErrors(exe, test_step, .{ .exact = &.{
test/src/check-stack-trace.zig+1-1
......@@ -65,7 +65,7 @@ pub fn main() !void {
6565 // This actually violates the DWARF specification (DWARF5 § 3.1.1, lines 24-27).
6666 // The self-hosted backend uses the root Zig source file of the module (in compilance with the spec).
6767 if (std.mem.eql(u8, file_name, "test") or
68 std.mem.eql(u8, file_name, "test.exe.obj") or
68 std.mem.eql(u8, file_name, "test_zcu.obj") or
6969 std.mem.endsWith(u8, file_name, ".zig"))
7070 {
7171 try buf.appendSlice("[main_file]");
tools/incr-check.zig+1-1
......@@ -314,7 +314,7 @@ const Eval = struct {
314314 const digest = body[@sizeOf(EbpHdr)..][0..Cache.bin_digest_len];
315315 const result_dir = ".local-cache" ++ std.fs.path.sep_str ++ "o" ++ std.fs.path.sep_str ++ Cache.binToHex(digest.*);
316316
317 const bin_name = try std.zig.binNameAlloc(arena, .{
317 const bin_name = try std.zig.EmitArtifact.bin.cacheName(arena, .{
318318 .root_name = "root", // corresponds to the module name "root"
319319 .target = eval.target.resolved,
320320 .output_mode = .Exe,