aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Air.zig4
-rw-r--r--src/Air/print.zig5
-rw-r--r--src/Compilation.zig1108
-rw-r--r--src/InternPool.zig51
-rw-r--r--src/Sema.zig132
-rw-r--r--src/Sema/LowerZon.zig8
-rw-r--r--src/ThreadSafeQueue.zig72
-rw-r--r--src/Type.zig23
-rw-r--r--src/Zcu.zig103
-rw-r--r--src/Zcu/PerThread.zig405
-rw-r--r--src/arch/aarch64/CodeGen.zig71
-rw-r--r--src/arch/aarch64/Mir.zig41
-rw-r--r--src/arch/arm/CodeGen.zig74
-rw-r--r--src/arch/arm/Mir.zig41
-rw-r--r--src/arch/powerpc/CodeGen.zig10
-rw-r--r--src/arch/riscv64/CodeGen.zig77
-rw-r--r--src/arch/riscv64/Emit.zig4
-rw-r--r--src/arch/riscv64/Mir.zig48
-rw-r--r--src/arch/sparc64/CodeGen.zig75
-rw-r--r--src/arch/sparc64/Mir.zig37
-rw-r--r--src/arch/wasm/CodeGen.zig305
-rw-r--r--src/arch/wasm/Emit.zig39
-rw-r--r--src/arch/wasm/Mir.zig123
-rw-r--r--src/arch/x86_64/CodeGen.zig4197
-rw-r--r--src/arch/x86_64/Emit.zig938
-rw-r--r--src/arch/x86_64/Lower.zig426
-rw-r--r--src/arch/x86_64/Mir.zig324
-rw-r--r--src/arch/x86_64/bits.zig28
-rw-r--r--src/arch/x86_64/encoder.zig17
-rw-r--r--src/codegen.zig306
-rw-r--r--src/codegen/c.zig146
-rw-r--r--src/codegen/llvm.zig58
-rw-r--r--src/codegen/spirv.zig11
-rw-r--r--src/codegen/spirv/Section.zig2
-rw-r--r--src/dev.zig9
-rw-r--r--src/libs/freebsd.zig15
-rw-r--r--src/libs/glibc.zig15
-rw-r--r--src/libs/libcxx.zig32
-rw-r--r--src/libs/libtsan.zig10
-rw-r--r--src/libs/libunwind.zig17
-rw-r--r--src/libs/musl.zig5
-rw-r--r--src/libs/netbsd.zig15
-rw-r--r--src/link.zig680
-rw-r--r--src/link/C.zig146
-rw-r--r--src/link/Coff.zig721
-rw-r--r--src/link/Dwarf.zig227
-rw-r--r--src/link/Elf.zig828
-rw-r--r--src/link/Elf/Symbol.zig3
-rw-r--r--src/link/Elf/ZigObject.zig26
-rw-r--r--src/link/Goff.zig49
-rw-r--r--src/link/Lld.zig1757
-rw-r--r--src/link/MachO.zig83
-rw-r--r--src/link/MachO/DebugSymbols.zig2
-rw-r--r--src/link/MachO/Symbol.zig3
-rw-r--r--src/link/MachO/ZigObject.zig26
-rw-r--r--src/link/Plan9.zig48
-rw-r--r--src/link/Queue.zig279
-rw-r--r--src/link/SpirV.zig29
-rw-r--r--src/link/Wasm.zig702
-rw-r--r--src/link/Wasm/Flush.zig17
-rw-r--r--src/link/Xcoff.zig49
-rw-r--r--src/main.zig381
-rw-r--r--src/target.zig6
63 files changed, 7940 insertions, 7549 deletions
diff --git a/src/Air.zig b/src/Air.zig
index 4810766e71..74f4c57424 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -1153,9 +1153,7 @@ pub const Inst = struct {
ty: Type,
arg: struct {
ty: Ref,
- /// Index into `extra` of a null-terminated string representing the parameter name.
- /// This is `.none` if debug info is stripped.
- name: NullTerminatedString,
+ zir_param_index: u32,
},
ty_op: struct {
ty: Ref,
diff --git a/src/Air/print.zig b/src/Air/print.zig
index 343c640a63..7f5f396cae 100644
--- a/src/Air/print.zig
+++ b/src/Air/print.zig
@@ -363,10 +363,7 @@ const Writer = struct {
fn writeArg(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
const arg = w.air.instructions.items(.data)[@intFromEnum(inst)].arg;
try w.writeType(s, arg.ty.toType());
- switch (arg.name) {
- .none => {},
- _ => try s.print(", \"{}\"", .{std.zig.fmtEscapes(arg.name.toSlice(w.air))}),
- }
+ try s.print(", {d}", .{arg.zir_param_index});
}
fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 81d150b03f..065b717931 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -43,7 +43,6 @@ const Air = @import("Air.zig");
const Builtin = @import("Builtin.zig");
const LlvmObject = @import("codegen/llvm.zig").Object;
const dev = @import("dev.zig");
-const ThreadSafeQueue = @import("ThreadSafeQueue.zig").ThreadSafeQueue;
pub const Config = @import("Compilation/Config.zig");
@@ -56,8 +55,7 @@ gpa: Allocator,
arena: Allocator,
/// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
zcu: ?*Zcu,
-/// Contains different state depending on whether the Compilation uses
-/// incremental or whole cache mode.
+/// Contains different state depending on the `CacheMode` used by this `Compilation`.
cache_use: CacheUse,
/// All compilations have a root module because this is where some important
/// settings are stored, such as target and optimization mode. This module
@@ -68,17 +66,13 @@ root_mod: *Package.Module,
config: Config,
/// The main output file.
-/// In whole cache mode, this is null except for during the body of the update
-/// function. In incremental cache mode, this is a long-lived object.
-/// In both cases, this is `null` when `-fno-emit-bin` is used.
+/// In `CacheMode.whole`, this is null except for during the body of `update`.
+/// In `CacheMode.none` and `CacheMode.incremental`, this is long-lived.
+/// Regardless of cache mode, this is `null` when `-fno-emit-bin` is used.
bin_file: ?*link.File,
/// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin)
sysroot: ?[]const u8,
-/// This is `null` when not building a Windows DLL, or when `-fno-emit-implib` is used.
-implib_emit: ?Cache.Path,
-/// This is non-null when `-femit-docs` is provided.
-docs_emit: ?Cache.Path,
root_name: [:0]const u8,
compiler_rt_strat: RtStrat,
ubsan_rt_strat: RtStrat,
@@ -113,17 +107,7 @@ win32_resource_table: if (dev.env.supports(.win32_resource)) std.AutoArrayHashMa
} = .{},
link_diags: link.Diags,
-link_task_queue: ThreadSafeQueue(link.Task) = .empty,
-/// Ensure only 1 simultaneous call to `flushTaskQueue`.
-link_task_queue_safety: std.debug.SafetyLock = .{},
-/// If any tasks are queued up that depend on prelink being finished, they are moved
-/// here until prelink finishes.
-link_task_queue_postponed: std.ArrayListUnmanaged(link.Task) = .empty,
-/// Initialized with how many link input tasks are expected. After this reaches zero
-/// the linker will begin the prelink phase.
-/// Initialized in the Compilation main thread before the pipeline; modified only in
-/// the linker task thread.
-remaining_prelink_tasks: u32,
+link_task_queue: link.Queue = .empty,
/// Set of work that can be represented by only flags to determine whether the
/// work is queued or not.
@@ -270,12 +254,8 @@ mutex: if (builtin.single_threaded) struct {
test_filters: []const []const u8,
test_name_prefix: ?[]const u8,
-emit_asm: ?EmitLoc,
-emit_llvm_ir: ?EmitLoc,
-emit_llvm_bc: ?EmitLoc,
-
link_task_wait_group: WaitGroup = .{},
-work_queue_progress_node: std.Progress.Node = .none,
+link_prog_node: std.Progress.Node = std.Progress.Node.none,
llvm_opt_bisect_limit: c_int,
@@ -285,6 +265,31 @@ file_system_inputs: ?*std.ArrayListUnmanaged(u8),
/// This digest will be known after update() is called.
digest: ?[Cache.bin_digest_len]u8 = null,
+/// Non-`null` iff we are emitting a binary.
+/// Does not change for the lifetime of this `Compilation`.
+/// Cwd-relative if `cache_use == .none`. Otherwise, relative to our subdirectory in the cache.
+emit_bin: ?[]const u8,
+/// Non-`null` iff we are emitting assembly.
+/// Does not change for the lifetime of this `Compilation`.
+/// Cwd-relative if `cache_use == .none`. Otherwise, relative to our subdirectory in the cache.
+emit_asm: ?[]const u8,
+/// Non-`null` iff we are emitting an implib.
+/// Does not change for the lifetime of this `Compilation`.
+/// Cwd-relative if `cache_use == .none`. Otherwise, relative to our subdirectory in the cache.
+emit_implib: ?[]const u8,
+/// Non-`null` iff we are emitting LLVM IR.
+/// Does not change for the lifetime of this `Compilation`.
+/// Cwd-relative if `cache_use == .none`. Otherwise, relative to our subdirectory in the cache.
+emit_llvm_ir: ?[]const u8,
+/// Non-`null` iff we are emitting LLVM bitcode.
+/// Does not change for the lifetime of this `Compilation`.
+/// Cwd-relative if `cache_use == .none`. Otherwise, relative to our subdirectory in the cache.
+emit_llvm_bc: ?[]const u8,
+/// Non-`null` iff we are emitting documentation.
+/// Does not change for the lifetime of this `Compilation`.
+/// Cwd-relative if `cache_use == .none`. Otherwise, relative to our subdirectory in the cache.
+emit_docs: ?[]const u8,
+
const QueuedJobs = struct {
compiler_rt_lib: bool = false,
compiler_rt_obj: bool = false,
@@ -785,13 +790,6 @@ pub const CrtFile = struct {
lock: Cache.Lock,
full_object_path: Cache.Path,
- pub fn isObject(cf: CrtFile) bool {
- return switch (classifyFileExt(cf.full_object_path.sub_path)) {
- .object => true,
- else => false,
- };
- }
-
pub fn deinit(self: *CrtFile, gpa: Allocator) void {
self.lock.release();
gpa.free(self.full_object_path.sub_path);
@@ -846,19 +844,34 @@ pub const RcIncludes = enum {
};
const Job = union(enum) {
- /// Corresponds to the task in `link.Task`.
- /// Only needed for backends that haven't yet been updated to not race against Sema.
- codegen_nav: InternPool.Nav.Index,
- /// Corresponds to the task in `link.Task`.
- /// Only needed for backends that haven't yet been updated to not race against Sema.
- codegen_func: link.Task.CodegenFunc,
- /// Corresponds to the task in `link.Task`.
- /// Only needed for backends that haven't yet been updated to not race against Sema.
- codegen_type: InternPool.Index,
+ /// Given the generated AIR for a function, put it onto the code generation queue.
+ /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that
+ /// all types are resolved before the linker task is queued.
+ /// If the backend does not support `Zcu.Feature.separate_thread`, codegen and linking happen immediately.
+ /// Before queueing this `Job`, increase the estimated total item count for both
+ /// `comp.zcu.?.codegen_prog_node` and `comp.link_prog_node`.
+ codegen_func: struct {
+ func: InternPool.Index,
+ /// The AIR emitted from analyzing `func`; owned by this `Job` in `gpa`.
+ air: Air,
+ },
+ /// Queue a `link.ZcuTask` to emit this non-function `Nav` into the output binary.
+ /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that
+ /// all types are resolved before the linker task is queued.
+ /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately.
+ /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
+ link_nav: InternPool.Nav.Index,
+ /// Queue a `link.ZcuTask` to emit debug information for this container type.
+ /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that
+ /// all types are resolved before the linker task is queued.
+ /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately.
+ /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
+ link_type: InternPool.Index,
+ /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
update_line_number: InternPool.TrackedInst.Index,
/// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed.
/// This may be its first time being analyzed, or it may be outdated.
- /// If the unit is a function, a `codegen_func` job will then be queued.
+ /// If the unit is a test function, an `analyze_func` job will then be queued.
analyze_comptime_unit: InternPool.AnalUnit,
/// This function must be semantically analyzed.
/// This may be its first time being analyzed, or it may be outdated.
@@ -1322,14 +1335,6 @@ pub const MiscError = struct {
}
};
-pub const EmitLoc = struct {
- /// If this is `null` it means the file will be output to the cache directory.
- /// When provided, both the open file handle and the path name must outlive the `Compilation`.
- directory: ?Cache.Directory,
- /// This may not have sub-directories in it.
- basename: []const u8,
-};
-
pub const cache_helpers = struct {
pub fn addModule(hh: *Cache.HashHelper, mod: *const Package.Module) void {
addResolvedTarget(hh, mod.resolved_target);
@@ -1369,15 +1374,6 @@ pub const cache_helpers = struct {
hh.add(resolved_target.is_explicit_dynamic_linker);
}
- pub fn addEmitLoc(hh: *Cache.HashHelper, emit_loc: EmitLoc) void {
- hh.addBytes(emit_loc.basename);
- }
-
- pub fn addOptionalEmitLoc(hh: *Cache.HashHelper, optional_emit_loc: ?EmitLoc) void {
- hh.add(optional_emit_loc != null);
- addEmitLoc(hh, optional_emit_loc orelse return);
- }
-
pub fn addOptionalDebugFormat(hh: *Cache.HashHelper, x: ?Config.DebugFormat) void {
hh.add(x != null);
addDebugFormat(hh, x orelse return);
@@ -1424,7 +1420,38 @@ pub const ClangPreprocessorMode = enum {
pub const Framework = link.File.MachO.Framework;
pub const SystemLib = link.SystemLib;
-pub const CacheMode = enum { incremental, whole };
+pub const CacheMode = enum {
+ /// The results of this compilation are not cached. The compilation is always performed, and the
+ /// results are emitted directly to their output locations. Temporary files will be placed in a
+ /// temporary directory in the cache, but deleted after the compilation is done.
+ ///
+ /// This mode is typically used for direct CLI invocations like `zig build-exe`, because such
+ /// processes are typically low-level usages which would not make efficient use of the cache.
+ none,
+ /// The compilation is cached based only on the options given when creating the `Compilation`.
+ /// In particular, Zig source file contents are not included in the cache manifest. This mode
+ /// allows incremental compilation, because the old cached compilation state can be restored
+ /// and the old binary patched up with the changes. All files, including temporary files, are
+ /// stored in the cache directory like '<cache>/o/<hash>/'. Temporary files are not deleted.
+ ///
+ /// At the time of writing, incremental compilation is only supported with the `-fincremental`
+ /// command line flag, so this mode is rarely used. However, it is required in order to use
+ /// incremental compilation.
+ incremental,
+ /// The compilation is cached based on the `Compilation` options and every input, including Zig
+ /// source files, linker inputs, and `@embedFile` targets. If any of them change, we will see a
+ /// cache miss, and the entire compilation will be re-run. On a cache miss, we initially write
+ /// all output files to a directory under '<cache>/tmp/', because we don't know the final
+ /// manifest digest until the update is almost done. Once we can compute the final digest, this
+ /// directory is moved to '<cache>/o/<hash>/'. Temporary files are not deleted.
+ ///
+ /// At the time of writing, this is the most commonly used cache mode: it is used by the build
+ /// system (and any other parent using `--listen`) unless incremental compilation is enabled.
+ /// Once incremental compilation is more mature, it will be replaced by `incremental` in many
+ /// cases, but still has use cases, such as for release binaries, particularly globally cached
+ /// artifacts like compiler_rt.
+ whole,
+};
pub const ParentWholeCache = struct {
manifest: *Cache.Manifest,
@@ -1433,22 +1460,33 @@ pub const ParentWholeCache = struct {
};
const CacheUse = union(CacheMode) {
+ none: *None,
incremental: *Incremental,
whole: *Whole,
+ const None = struct {
+ /// User-requested artifacts are written directly to their output path in this cache mode.
+ /// However, if we need to emit any temporary files, they are placed in this directory.
+ /// We will recursively delete this directory at the end of this update. This field is
+ /// non-`null` only inside `update`.
+ tmp_artifact_directory: ?Cache.Directory,
+ };
+
+ const Incremental = struct {
+ /// All output files, including artifacts and incremental compilation metadata, are placed
+ /// in this directory, which is some 'o/<hash>' in a cache directory.
+ artifact_directory: Cache.Directory,
+ };
+
const Whole = struct {
- /// This is a pointer to a local variable inside `update()`.
- cache_manifest: ?*Cache.Manifest = null,
- cache_manifest_mutex: std.Thread.Mutex = .{},
- /// null means -fno-emit-bin.
- /// This is mutable memory allocated into the Compilation-lifetime arena (`arena`)
- /// of exactly the correct size for "o/[digest]/[basename]".
- /// The basename is of the outputted binary file in case we don't know the directory yet.
- bin_sub_path: ?[]u8,
- /// Same as `bin_sub_path` but for implibs.
- implib_sub_path: ?[]u8,
- docs_sub_path: ?[]u8,
+ /// Since we don't open the output file until `update`, we must save these options for then.
lf_open_opts: link.File.OpenOptions,
+ /// This is a pointer to a local variable inside `update`.
+ cache_manifest: ?*Cache.Manifest,
+ cache_manifest_mutex: std.Thread.Mutex,
+ /// This is non-`null` for most of the body of `update`. It is the temporary directory which
+ /// we initially emit our artifacts to. After the main part of the update is done, it will
+ /// be closed and moved to its final location, and this field set to `null`.
tmp_artifact_directory: ?Cache.Directory,
/// Prevents other processes from clobbering files in the output directory.
lock: ?Cache.Lock,
@@ -1467,17 +1505,16 @@ const CacheUse = union(CacheMode) {
}
};
- const Incremental = struct {
- /// Where build artifacts and incremental compilation metadata serialization go.
- artifact_directory: Cache.Directory,
- };
-
fn deinit(cu: CacheUse) void {
switch (cu) {
+ .none => |none| {
+ assert(none.tmp_artifact_directory == null);
+ },
.incremental => |incremental| {
incremental.artifact_directory.handle.close();
},
.whole => |whole| {
+ assert(whole.tmp_artifact_directory == null);
whole.releaseLock();
},
}
@@ -1504,28 +1541,14 @@ pub const CreateOptions = struct {
std_mod: ?*Package.Module = null,
root_name: []const u8,
sysroot: ?[]const u8 = null,
- /// `null` means to not emit a binary file.
- emit_bin: ?EmitLoc,
- /// `null` means to not emit a C header file.
- emit_h: ?EmitLoc = null,
- /// `null` means to not emit assembly.
- emit_asm: ?EmitLoc = null,
- /// `null` means to not emit LLVM IR.
- emit_llvm_ir: ?EmitLoc = null,
- /// `null` means to not emit LLVM module bitcode.
- emit_llvm_bc: ?EmitLoc = null,
- /// `null` means to not emit docs.
- emit_docs: ?EmitLoc = null,
- /// `null` means to not emit an import lib.
- emit_implib: ?EmitLoc = null,
- /// Normally when using LLD to link, Zig uses a file named "lld.id" in the
- /// same directory as the output binary which contains the hash of the link
- /// operation, allowing Zig to skip linking when the hash would be unchanged.
- /// In the case that the output binary is being emitted into a directory which
- /// is externally modified - essentially anything other than zig-cache - then
- /// this flag would be set to disable this machinery to avoid false positives.
- disable_lld_caching: bool = false,
- cache_mode: CacheMode = .incremental,
+ cache_mode: CacheMode,
+ emit_h: Emit = .no,
+ emit_bin: Emit,
+ emit_asm: Emit = .no,
+ emit_implib: Emit = .no,
+ emit_llvm_ir: Emit = .no,
+ emit_llvm_bc: Emit = .no,
+ emit_docs: Emit = .no,
/// This field is intended to be removed.
/// The ELF implementation no longer uses this data, however the MachO and COFF
/// implementations still do.
@@ -1591,9 +1614,9 @@ pub const CreateOptions = struct {
linker_tsaware: bool = false,
linker_nxcompat: bool = false,
linker_dynamicbase: bool = true,
- linker_compress_debug_sections: ?link.File.Elf.CompressDebugSections = null,
+ linker_compress_debug_sections: ?link.File.Lld.Elf.CompressDebugSections = null,
linker_module_definition_file: ?[]const u8 = null,
- linker_sort_section: ?link.File.Elf.SortSection = null,
+ linker_sort_section: ?link.File.Lld.Elf.SortSection = null,
major_subsystem_version: ?u16 = null,
minor_subsystem_version: ?u16 = null,
clang_passthrough_mode: bool = false,
@@ -1615,7 +1638,7 @@ pub const CreateOptions = struct {
/// building such dependencies themselves, this flag must be set to avoid
/// infinite recursion.
skip_linker_dependencies: bool = false,
- hash_style: link.File.Elf.HashStyle = .both,
+ hash_style: link.File.Lld.Elf.HashStyle = .both,
entry: Entry = .default,
force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .empty,
stack_size: ?u64 = null,
@@ -1663,6 +1686,38 @@ pub const CreateOptions = struct {
parent_whole_cache: ?ParentWholeCache = null,
pub const Entry = link.File.OpenOptions.Entry;
+
+ /// Which fields are valid depends on the `cache_mode` given.
+ pub const Emit = union(enum) {
+ /// Do not emit this file. Always valid.
+ no,
+ /// Emit this file into its default name in the cache directory.
+ /// Requires `cache_mode` to not be `.none`.
+ yes_cache,
+ /// Emit this file to the given path (absolute or cwd-relative).
+ /// Requires `cache_mode` to be `.none`.
+ yes_path: []const u8,
+
+ fn resolve(emit: Emit, arena: Allocator, opts: *const CreateOptions, ea: std.zig.EmitArtifact) Allocator.Error!?[]const u8 {
+ switch (emit) {
+ .no => return null,
+ .yes_cache => {
+ assert(opts.cache_mode != .none);
+ return try ea.cacheName(arena, .{
+ .root_name = opts.root_name,
+ .target = opts.root_mod.resolved_target.result,
+ .output_mode = opts.config.output_mode,
+ .link_mode = opts.config.link_mode,
+ .version = opts.version,
+ });
+ },
+ .yes_path => |path| {
+ assert(opts.cache_mode == .none);
+ return try arena.dupe(u8, path);
+ },
+ }
+ }
+ };
};
fn addModuleTableToCacheHash(
@@ -1870,13 +1925,18 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
cache.hash.add(options.config.link_libunwind);
cache.hash.add(output_mode);
cache_helpers.addDebugFormat(&cache.hash, options.config.debug_format);
- cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin);
- cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib);
- cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);
cache.hash.addBytes(options.root_name);
cache.hash.add(options.config.wasi_exec_model);
cache.hash.add(options.config.san_cov_trace_pc_guard);
cache.hash.add(options.debug_compiler_runtime_libs);
+ // The actual emit paths don't matter. They're only user-specified if we aren't using the
+ // cache! However, it does matter whether the files are emitted at all.
+ cache.hash.add(options.emit_bin != .no);
+ cache.hash.add(options.emit_asm != .no);
+ cache.hash.add(options.emit_implib != .no);
+ cache.hash.add(options.emit_llvm_ir != .no);
+ cache.hash.add(options.emit_llvm_bc != .no);
+ cache.hash.add(options.emit_docs != .no);
// TODO audit this and make sure everything is in it
const main_mod = options.main_mod orelse options.root_mod;
@@ -1926,7 +1986,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
try zcu.init(options.thread_pool.getIdCount());
break :blk zcu;
} else blk: {
- if (options.emit_h != null) return error.NoZigModuleForCHeader;
+ if (options.emit_h != .no) return error.NoZigModuleForCHeader;
break :blk null;
};
errdefer if (opt_zcu) |zcu| zcu.deinit();
@@ -1939,18 +1999,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
.arena = arena,
.zcu = opt_zcu,
.cache_use = undefined, // populated below
- .bin_file = null, // populated below
- .implib_emit = null, // handled below
- .docs_emit = null, // handled below
+ .bin_file = null, // populated below if necessary
.root_mod = options.root_mod,
.config = options.config,
.dirs = options.dirs,
- .emit_asm = options.emit_asm,
- .emit_llvm_ir = options.emit_llvm_ir,
- .emit_llvm_bc = options.emit_llvm_bc,
.work_queues = @splat(.init(gpa)),
- .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),
- .win32_resource_work_queue = if (dev.env.supports(.win32_resource)) std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa) else .{},
+ .c_object_work_queue = .init(gpa),
+ .win32_resource_work_queue = if (dev.env.supports(.win32_resource)) .init(gpa) else .{},
.c_source_files = options.c_source_files,
.rc_source_files = options.rc_source_files,
.cache_parent = cache,
@@ -2003,7 +2058,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
.file_system_inputs = options.file_system_inputs,
.parent_whole_cache = options.parent_whole_cache,
.link_diags = .init(gpa),
- .remaining_prelink_tasks = 0,
+ .emit_bin = try options.emit_bin.resolve(arena, &options, .bin),
+ .emit_asm = try options.emit_asm.resolve(arena, &options, .@"asm"),
+ .emit_implib = try options.emit_implib.resolve(arena, &options, .implib),
+ .emit_llvm_ir = try options.emit_llvm_ir.resolve(arena, &options, .llvm_ir),
+ .emit_llvm_bc = try options.emit_llvm_bc.resolve(arena, &options, .llvm_bc),
+ .emit_docs = try options.emit_docs.resolve(arena, &options, .docs),
};
// 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
.soname = options.soname,
.compatibility_version = options.compatibility_version,
.build_id = build_id,
- .disable_lld_caching = options.disable_lld_caching or options.cache_mode == .whole,
.subsystem = options.subsystem,
.hash_style = options.hash_style,
.enable_link_snapshots = options.enable_link_snapshots,
@@ -2089,6 +2148,17 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
};
switch (options.cache_mode) {
+ .none => {
+ const none = try arena.create(CacheUse.None);
+ none.* = .{ .tmp_artifact_directory = null };
+ comp.cache_use = .{ .none = none };
+ if (comp.emit_bin) |path| {
+ comp.bin_file = try link.File.open(arena, comp, .{
+ .root_dir = .cwd(),
+ .sub_path = path,
+ }, lf_open_opts);
+ }
+ },
.incremental => {
// Options that are specific to zig source files, that cannot be
// modified between incremental updates.
@@ -2102,7 +2172,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
hash.addListOfBytes(options.test_filters);
hash.addOptionalBytes(options.test_name_prefix);
hash.add(options.skip_linker_dependencies);
- hash.add(options.emit_h != null);
+ hash.add(options.emit_h != .no);
hash.add(error_limit);
// 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
};
comp.cache_use = .{ .incremental = incremental };
- if (options.emit_bin) |emit_bin| {
+ if (comp.emit_bin) |cache_rel_path| {
const emit: Cache.Path = .{
- .root_dir = emit_bin.directory orelse artifact_directory,
- .sub_path = emit_bin.basename,
+ .root_dir = artifact_directory,
+ .sub_path = cache_rel_path,
};
comp.bin_file = try link.File.open(arena, comp, emit, lf_open_opts);
}
-
- if (options.emit_implib) |emit_implib| {
- comp.implib_emit = .{
- .root_dir = emit_implib.directory orelse artifact_directory,
- .sub_path = emit_implib.basename,
- };
- }
-
- if (options.emit_docs) |emit_docs| {
- comp.docs_emit = .{
- .root_dir = emit_docs.directory orelse artifact_directory,
- .sub_path = emit_docs.basename,
- };
- }
},
.whole => {
- // For whole cache mode, we don't know where to put outputs from
- // the linker until the final cache hash, which is available after
- // the compilation is complete.
+ // For whole cache mode, we don't know where to put outputs from the linker until
+ // the final cache hash, which is available after the compilation is complete.
//
- // Therefore, bin_file is left null until the beginning of update(),
- // where it may find a cache hit, or use a temporary directory to
- // hold output artifacts.
+ // Therefore, `comp.bin_file` is left `null` (already done) until `update`, where
+ // it may find a cache hit, or else will use a temporary directory to hold output
+ // artifacts.
const whole = try arena.create(CacheUse.Whole);
whole.* = .{
- // This is kept here so that link.File.open can be called later.
.lf_open_opts = lf_open_opts,
- // This is so that when doing `CacheMode.whole`, the mechanism in update()
- // can use it for communicating the result directory via `bin_file.emit`.
- // This is used to distinguish between -fno-emit-bin and -femit-bin
- // for `CacheMode.whole`.
- // This memory will be overwritten with the real digest in update() but
- // the basename will be preserved.
- .bin_sub_path = try prepareWholeEmitSubPath(arena, options.emit_bin),
- .implib_sub_path = try prepareWholeEmitSubPath(arena, options.emit_implib),
- .docs_sub_path = try prepareWholeEmitSubPath(arena, options.emit_docs),
+ .cache_manifest = null,
+ .cache_manifest_mutex = .{},
.tmp_artifact_directory = null,
.lock = null,
};
@@ -2187,14 +2234,10 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
},
}
- // Handle the case of e.g. -fno-emit-bin -femit-llvm-ir.
- if (options.emit_bin == null and (comp.verbose_llvm_ir != null or
- comp.verbose_llvm_bc != null or
- (use_llvm and comp.emit_asm != null) or
- comp.emit_llvm_ir != null or
- comp.emit_llvm_bc != null))
- {
- if (opt_zcu) |zcu| zcu.llvm_object = try LlvmObject.create(arena, comp);
+ if (use_llvm) {
+ if (opt_zcu) |zcu| {
+ zcu.llvm_object = try LlvmObject.create(arena, comp);
+ }
}
break :comp comp;
@@ -2216,7 +2259,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
};
comp.c_object_table.putAssumeCapacityNoClobber(c_object, {});
}
- comp.remaining_prelink_tasks += @intCast(comp.c_object_table.count());
+ comp.link_task_queue.pending_prelink_tasks += @intCast(comp.c_object_table.count());
// Add a `Win32Resource` for each `rc_source_files` and one for `manifest_file`.
const win32_resource_count =
@@ -2227,7 +2270,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
// Add this after adding logic to updateWin32Resource to pass the
// result into link.loadInput. loadInput integration is not implemented
// for Windows linking logic yet.
- //comp.remaining_prelink_tasks += @intCast(win32_resource_count);
+ //comp.link_task_queue.pending_prelink_tasks += @intCast(win32_resource_count);
for (options.rc_source_files) |rc_source_file| {
const win32_resource = try gpa.create(Win32Resource);
errdefer gpa.destroy(win32_resource);
@@ -2251,12 +2294,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
}
}
- const have_bin_emit = switch (comp.cache_use) {
- .whole => |whole| whole.bin_sub_path != null,
- .incremental => comp.bin_file != null,
- };
-
- if (have_bin_emit and target.ofmt != .c) {
+ if (comp.emit_bin != null and target.ofmt != .c) {
if (!comp.skip_linker_dependencies) {
// If we need to build libc for the target, add work items for it.
// 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
const paths = try lci.resolveCrtPaths(arena, basenames, target);
const fields = @typeInfo(@TypeOf(paths)).@"struct".fields;
- try comp.link_task_queue.shared.ensureUnusedCapacity(gpa, fields.len + 1);
+ try comp.link_task_queue.queued_prelink.ensureUnusedCapacity(gpa, fields.len + 1);
inline for (fields) |field| {
if (@field(paths, field.name)) |path| {
- comp.link_task_queue.shared.appendAssumeCapacity(.{ .load_object = path });
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.queued_prelink.appendAssumeCapacity(.{ .load_object = path });
}
}
// Loads the libraries provided by `target_util.libcFullLinkFlags(target)`.
- comp.link_task_queue.shared.appendAssumeCapacity(.load_host_libc);
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.queued_prelink.appendAssumeCapacity(.load_host_libc);
} else if (target.isMuslLibC()) {
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
if (musl.needsCrt0(comp.config.output_mode, comp.config.link_mode, comp.config.pie)) |f| {
comp.queued_jobs.musl_crt_file[@intFromEnum(f)] = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
}
switch (comp.config.link_mode) {
.static => comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.libc_a)] = true,
.dynamic => comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.libc_so)] = true,
}
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
} else if (target.isGnuLibC()) {
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
if (glibc.needsCrt0(comp.config.output_mode)) |f| {
comp.queued_jobs.glibc_crt_file[@intFromEnum(f)] = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
}
comp.queued_jobs.glibc_shared_objects = true;
- comp.remaining_prelink_tasks += glibc.sharedObjectsCount(&target);
+ comp.link_task_queue.pending_prelink_tasks += glibc.sharedObjectsCount(&target);
comp.queued_jobs.glibc_crt_file[@intFromEnum(glibc.CrtFile.libc_nonshared_a)] = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
} else if (target.isFreeBSDLibC()) {
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
if (freebsd.needsCrt0(comp.config.output_mode)) |f| {
comp.queued_jobs.freebsd_crt_file[@intFromEnum(f)] = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
}
comp.queued_jobs.freebsd_shared_objects = true;
- comp.remaining_prelink_tasks += freebsd.sharedObjectsCount();
+ comp.link_task_queue.pending_prelink_tasks += freebsd.sharedObjectsCount();
} else if (target.isNetBSDLibC()) {
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
if (netbsd.needsCrt0(comp.config.output_mode)) |f| {
comp.queued_jobs.netbsd_crt_file[@intFromEnum(f)] = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
}
comp.queued_jobs.netbsd_shared_objects = true;
- comp.remaining_prelink_tasks += netbsd.sharedObjectsCount();
+ comp.link_task_queue.pending_prelink_tasks += netbsd.sharedObjectsCount();
} else if (target.isWasiLibC()) {
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
for (comp.wasi_emulated_libs) |crt_file| {
comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = true;
}
- comp.remaining_prelink_tasks += @intCast(comp.wasi_emulated_libs.len);
+ comp.link_task_queue.pending_prelink_tasks += @intCast(comp.wasi_emulated_libs.len);
comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.execModelCrtFile(comp.config.wasi_exec_model))] = true;
comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.CrtFile.libc_a)] = true;
- comp.remaining_prelink_tasks += 2;
+ comp.link_task_queue.pending_prelink_tasks += 2;
} else if (target.isMinGW()) {
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
const main_crt_file: mingw.CrtFile = if (is_dyn_lib) .dllcrt2_o else .crt2_o;
comp.queued_jobs.mingw_crt_file[@intFromEnum(main_crt_file)] = true;
comp.queued_jobs.mingw_crt_file[@intFromEnum(mingw.CrtFile.libmingw32_lib)] = true;
- comp.remaining_prelink_tasks += 2;
+ comp.link_task_queue.pending_prelink_tasks += 2;
// When linking mingw-w64 there are some import libs we always need.
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
target.isMinGW())
{
comp.queued_jobs.zigc_lib = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
}
}
@@ -2380,53 +2416,53 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
}
if (comp.wantBuildLibUnwindFromSource()) {
comp.queued_jobs.libunwind = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
}
if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.link_libcpp) {
comp.queued_jobs.libcxx = true;
comp.queued_jobs.libcxxabi = true;
- comp.remaining_prelink_tasks += 2;
+ comp.link_task_queue.pending_prelink_tasks += 2;
}
if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.any_sanitize_thread) {
comp.queued_jobs.libtsan = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
}
if (can_build_compiler_rt) {
if (comp.compiler_rt_strat == .lib) {
log.debug("queuing a job to build compiler_rt_lib", .{});
comp.queued_jobs.compiler_rt_lib = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
} else if (comp.compiler_rt_strat == .obj) {
log.debug("queuing a job to build compiler_rt_obj", .{});
// In this case we are making a static library, so we ask
// for a compiler-rt object to put in it.
comp.queued_jobs.compiler_rt_obj = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
}
if (comp.ubsan_rt_strat == .lib) {
log.debug("queuing a job to build ubsan_rt_lib", .{});
comp.queued_jobs.ubsan_rt_lib = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
} else if (comp.ubsan_rt_strat == .obj) {
log.debug("queuing a job to build ubsan_rt_obj", .{});
comp.queued_jobs.ubsan_rt_obj = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
}
if (is_exe_or_dyn_lib and comp.config.any_fuzz) {
log.debug("queuing a job to build libfuzzer", .{});
comp.queued_jobs.fuzzer_lib = true;
- comp.remaining_prelink_tasks += 1;
+ comp.link_task_queue.pending_prelink_tasks += 1;
}
}
}
- try comp.link_task_queue.shared.append(gpa, .load_explicitly_provided);
- comp.remaining_prelink_tasks += 1;
+ try comp.link_task_queue.queued_prelink.append(gpa, .load_explicitly_provided);
}
- log.debug("total prelink tasks: {d}", .{comp.remaining_prelink_tasks});
+ log.debug("queued prelink tasks: {d}", .{comp.link_task_queue.queued_prelink.items.len});
+ log.debug("pending prelink tasks: {d}", .{comp.link_task_queue.pending_prelink_tasks});
return comp;
}
@@ -2434,6 +2470,10 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
pub fn destroy(comp: *Compilation) void {
const gpa = comp.gpa;
+ // This needs to be destroyed first, because it might contain MIR which we only know
+ // how to interpret (which kind of MIR it is) from `comp.bin_file`.
+ comp.link_task_queue.deinit(comp);
+
if (comp.bin_file) |lf| lf.destroy();
if (comp.zcu) |zcu| zcu.deinit();
comp.cache_use.deinit();
@@ -2515,8 +2555,6 @@ pub fn destroy(comp: *Compilation) void {
comp.failed_win32_resources.deinit(gpa);
comp.link_diags.deinit();
- comp.link_task_queue.deinit(gpa);
- comp.link_task_queue_postponed.deinit(gpa);
comp.clearMiscFailures();
@@ -2550,8 +2588,28 @@ pub fn hotCodeSwap(
try lf.makeExecutable();
}
-fn cleanupAfterUpdate(comp: *Compilation) void {
+fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void {
switch (comp.cache_use) {
+ .none => |none| {
+ if (none.tmp_artifact_directory) |*tmp_dir| {
+ tmp_dir.handle.close();
+ none.tmp_artifact_directory = null;
+ if (dev.env == .bootstrap) {
+ // zig1 uses `CacheMode.none`, but it doesn't need to know how to delete
+ // temporary directories; it doesn't have a real cache directory anyway.
+ return;
+ }
+ const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
+ comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| {
+ log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{
+ comp.dirs.local_cache.path orelse ".",
+ std.fs.path.sep,
+ tmp_dir_sub_path,
+ @errorName(err),
+ });
+ };
+ }
+ },
.incremental => return,
.whole => |whole| {
if (whole.cache_manifest) |man| {
@@ -2562,10 +2620,18 @@ fn cleanupAfterUpdate(comp: *Compilation) void {
lf.destroy();
comp.bin_file = null;
}
- if (whole.tmp_artifact_directory) |*directory| {
- directory.handle.close();
- if (directory.path) |p| comp.gpa.free(p);
+ if (whole.tmp_artifact_directory) |*tmp_dir| {
+ tmp_dir.handle.close();
whole.tmp_artifact_directory = null;
+ const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
+ comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| {
+ log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{
+ comp.dirs.local_cache.path orelse ".",
+ std.fs.path.sep,
+ tmp_dir_sub_path,
+ @errorName(err),
+ });
+ };
}
},
}
@@ -2585,14 +2651,27 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
comp.clearMiscFailures();
comp.last_update_was_cache_hit = false;
- var man: Cache.Manifest = undefined;
- defer cleanupAfterUpdate(comp);
-
var tmp_dir_rand_int: u64 = undefined;
+ var man: Cache.Manifest = undefined;
+ defer cleanupAfterUpdate(comp, tmp_dir_rand_int);
// If using the whole caching strategy, we check for *everything* up front, including
// C source files.
+ log.debug("Compilation.update for {s}, CacheMode.{s}", .{ comp.root_name, @tagName(comp.cache_use) });
switch (comp.cache_use) {
+ .none => |none| {
+ assert(none.tmp_artifact_directory == null);
+ none.tmp_artifact_directory = d: {
+ tmp_dir_rand_int = std.crypto.random.int(u64);
+ const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
+ const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});
+ break :d .{
+ .path = path,
+ .handle = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}),
+ };
+ };
+ },
+ .incremental => {},
.whole => |whole| {
assert(comp.bin_file == null);
// 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 {
comp.last_update_was_cache_hit = true;
log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name});
const bin_digest = man.finalBin();
- const hex_digest = Cache.binToHex(bin_digest);
comp.digest = bin_digest;
- comp.wholeCacheModeSetBinFilePath(whole, &hex_digest);
assert(whole.lock == null);
whole.lock = man.toOwnedLock();
@@ -2651,52 +2728,23 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
log.debug("CacheMode.whole cache miss for {s}", .{comp.root_name});
// Compile the artifacts to a temporary directory.
- const tmp_artifact_directory: Cache.Directory = d: {
- const s = std.fs.path.sep_str;
+ whole.tmp_artifact_directory = d: {
tmp_dir_rand_int = std.crypto.random.int(u64);
- const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);
-
- const path = try comp.dirs.local_cache.join(gpa, &.{tmp_dir_sub_path});
- errdefer gpa.free(path);
-
- const handle = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{});
- errdefer handle.close();
-
+ const tmp_dir_sub_path = "tmp" ++ std.fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
+ const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});
break :d .{
.path = path,
- .handle = handle,
+ .handle = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}),
};
};
- whole.tmp_artifact_directory = tmp_artifact_directory;
-
- // Now that the directory is known, it is time to create the Emit
- // objects and call link.File.open.
-
- if (whole.implib_sub_path) |sub_path| {
- comp.implib_emit = .{
- .root_dir = tmp_artifact_directory,
- .sub_path = std.fs.path.basename(sub_path),
- };
- }
-
- if (whole.docs_sub_path) |sub_path| {
- comp.docs_emit = .{
- .root_dir = tmp_artifact_directory,
- .sub_path = std.fs.path.basename(sub_path),
- };
- }
-
- if (whole.bin_sub_path) |sub_path| {
+ if (comp.emit_bin) |sub_path| {
const emit: Cache.Path = .{
- .root_dir = tmp_artifact_directory,
- .sub_path = std.fs.path.basename(sub_path),
+ .root_dir = whole.tmp_artifact_directory.?,
+ .sub_path = sub_path,
};
comp.bin_file = try link.File.createEmpty(arena, comp, emit, whole.lf_open_opts);
}
},
- .incremental => {
- log.debug("Compilation.update for {s}, CacheMode.incremental", .{comp.root_name});
- },
}
// 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 {
}
}
+ // The linker progress node is set up here instead of in `performAllTheWork`, because
+ // we also want it around during `flush`.
+ const have_link_node = comp.bin_file != null;
+ if (have_link_node) {
+ comp.link_prog_node = main_progress_node.start("Linking", 0);
+ }
+ defer if (have_link_node) {
+ comp.link_prog_node.end();
+ comp.link_prog_node = .none;
+ };
+
try comp.performAllTheWork(main_progress_node);
if (comp.zcu) |zcu| {
@@ -2768,7 +2827,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
// The `test_functions` decl has been intentionally postponed until now,
// at which point we must populate it with the list of test functions that
// have been discovered and not filtered out.
- try pt.populateTestFunctions(main_progress_node);
+ try pt.populateTestFunctions();
}
try pt.processExports();
@@ -2795,11 +2854,18 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
return;
}
- // Flush below handles -femit-bin but there is still -femit-llvm-ir,
- // -femit-llvm-bc, and -femit-asm, in the case of C objects.
- comp.emitOthers();
+ if (comp.zcu == null and comp.config.output_mode == .Obj and comp.c_object_table.count() == 1) {
+ // This is `zig build-obj foo.c`. We can emit asm and LLVM IR/bitcode.
+ const c_obj_path = comp.c_object_table.keys()[0].status.success.object_path;
+ if (comp.emit_asm) |path| try comp.emitFromCObject(arena, c_obj_path, ".s", path);
+ if (comp.emit_llvm_ir) |path| try comp.emitFromCObject(arena, c_obj_path, ".ll", path);
+ if (comp.emit_llvm_bc) |path| try comp.emitFromCObject(arena, c_obj_path, ".bc", path);
+ }
switch (comp.cache_use) {
+ .none, .incremental => {
+ try flush(comp, arena, .main);
+ },
.whole => |whole| {
if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
if (comp.parent_whole_cache) |pwc| {
@@ -2811,18 +2877,6 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
const bin_digest = man.finalBin();
const hex_digest = Cache.binToHex(bin_digest);
- // Rename the temporary directory into place.
- // Close tmp dir and link.File to avoid open handle during rename.
- if (whole.tmp_artifact_directory) |*tmp_directory| {
- tmp_directory.handle.close();
- if (tmp_directory.path) |p| gpa.free(p);
- whole.tmp_artifact_directory = null;
- } else unreachable;
-
- const s = std.fs.path.sep_str;
- const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);
- const o_sub_path = "o" ++ s ++ hex_digest;
-
// Work around windows `AccessDenied` if any files within this
// directory are open by closing and reopening the file handles.
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 {
break :w .no;
};
+ // Rename the temporary directory into place.
+ // Close tmp dir and link.File to avoid open handle during rename.
+ whole.tmp_artifact_directory.?.handle.close();
+ whole.tmp_artifact_directory = null;
+ const s = std.fs.path.sep_str;
+ const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);
+ const o_sub_path = "o" ++ s ++ hex_digest;
renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| {
return comp.setMiscFailure(
.rename_results,
@@ -2859,7 +2920,6 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
);
};
comp.digest = bin_digest;
- comp.wholeCacheModeSetBinFilePath(whole, &hex_digest);
// The linker flush functions need to know the final output path
// 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 {
if (comp.bin_file) |lf| {
lf.emit = .{
.root_dir = comp.dirs.local_cache,
- .sub_path = whole.bin_sub_path.?,
+ .sub_path = try std.fs.path.join(arena, &.{ o_sub_path, comp.emit_bin.? }),
};
- // Has to be after the `wholeCacheModeSetBinFilePath` above.
switch (need_writable_dance) {
.no => {},
.lf_only => try lf.makeWritable(),
@@ -2881,10 +2940,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
}
}
- try flush(comp, arena, .{
- .root_dir = comp.dirs.local_cache,
- .sub_path = o_sub_path,
- }, .main, main_progress_node);
+ try flush(comp, arena, .main);
// Calling `flush` may have produced errors, in which case the
// cache manifest must not be written.
@@ -2903,11 +2959,6 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
assert(whole.lock == null);
whole.lock = man.toOwnedLock();
},
- .incremental => |incremental| {
- try flush(comp, arena, .{
- .root_dir = incremental.artifact_directory,
- }, .main, main_progress_node);
- },
}
}
@@ -2937,27 +2988,98 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat
fsi.appendSliceAssumeCapacity(path.sub_path);
}
+fn resolveEmitPath(comp: *Compilation, path: []const u8) Cache.Path {
+ return .{
+ .root_dir = switch (comp.cache_use) {
+ .none => .cwd(),
+ .incremental => |i| i.artifact_directory,
+ .whole => |w| w.tmp_artifact_directory.?,
+ },
+ .sub_path = path,
+ };
+}
+/// Like `resolveEmitPath`, but for calling during `flush`. The returned `Cache.Path` may reference
+/// memory from `arena`, and may reference `path` itself.
+/// If `kind == .temp`, then the returned path will be in a temporary or cache directory. This is
+/// useful for intermediate files, such as the ZCU object file emitted by the LLVM backend.
+pub fn resolveEmitPathFlush(
+ comp: *Compilation,
+ arena: Allocator,
+ kind: enum { temp, artifact },
+ path: []const u8,
+) Allocator.Error!Cache.Path {
+ switch (comp.cache_use) {
+ .none => |none| return .{
+ .root_dir = switch (kind) {
+ .temp => none.tmp_artifact_directory.?,
+ .artifact => .cwd(),
+ },
+ .sub_path = path,
+ },
+ .incremental, .whole => return .{
+ .root_dir = comp.dirs.local_cache,
+ .sub_path = try fs.path.join(arena, &.{
+ "o",
+ &Cache.binToHex(comp.digest.?),
+ path,
+ }),
+ },
+ }
+}
fn flush(
comp: *Compilation,
arena: Allocator,
- default_artifact_directory: Cache.Path,
tid: Zcu.PerThread.Id,
- prog_node: std.Progress.Node,
) !void {
+ if (comp.zcu) |zcu| {
+ if (zcu.llvm_object) |llvm_object| {
+ // Emit the ZCU object from LLVM now; it's required to flush the output file.
+ // If there's an output file, it wants to decide where the LLVM object goes!
+ const sub_prog_node = comp.link_prog_node.start("LLVM Emit Object", 0);
+ defer sub_prog_node.end();
+ try llvm_object.emit(.{
+ .pre_ir_path = comp.verbose_llvm_ir,
+ .pre_bc_path = comp.verbose_llvm_bc,
+
+ .bin_path = p: {
+ const lf = comp.bin_file orelse break :p null;
+ const p = try comp.resolveEmitPathFlush(arena, .temp, lf.zcu_object_basename.?);
+ break :p try p.toStringZ(arena);
+ },
+ .asm_path = p: {
+ const raw = comp.emit_asm orelse break :p null;
+ const p = try comp.resolveEmitPathFlush(arena, .artifact, raw);
+ break :p try p.toStringZ(arena);
+ },
+ .post_ir_path = p: {
+ const raw = comp.emit_llvm_ir orelse break :p null;
+ const p = try comp.resolveEmitPathFlush(arena, .artifact, raw);
+ break :p try p.toStringZ(arena);
+ },
+ .post_bc_path = p: {
+ const raw = comp.emit_llvm_bc orelse break :p null;
+ const p = try comp.resolveEmitPathFlush(arena, .artifact, raw);
+ break :p try p.toStringZ(arena);
+ },
+
+ .is_debug = comp.root_mod.optimize_mode == .Debug,
+ .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
+ .time_report = comp.time_report,
+ .sanitize_thread = comp.config.any_sanitize_thread,
+ .fuzz = comp.config.any_fuzz,
+ .lto = comp.config.lto,
+ });
+ }
+ }
if (comp.bin_file) |lf| {
// This is needed before reading the error flags.
- lf.flush(arena, tid, prog_node) catch |err| switch (err) {
+ lf.flush(arena, tid, comp.link_prog_node) catch |err| switch (err) {
error.LinkFailure => {}, // Already reported.
error.OutOfMemory => return error.OutOfMemory,
};
}
-
if (comp.zcu) |zcu| {
try link.File.C.flushEmitH(zcu);
-
- if (zcu.llvm_object) |llvm_object| {
- try emitLlvmObject(comp, arena, default_artifact_directory, null, llvm_object, prog_node);
- }
}
}
@@ -3009,45 +3131,6 @@ fn renameTmpIntoCache(
}
}
-/// Communicate the output binary location to parent Compilations.
-fn wholeCacheModeSetBinFilePath(
- comp: *Compilation,
- whole: *CacheUse.Whole,
- digest: *const [Cache.hex_digest_len]u8,
-) void {
- const digest_start = 2; // "o/[digest]/[basename]"
-
- if (whole.bin_sub_path) |sub_path| {
- @memcpy(sub_path[digest_start..][0..digest.len], digest);
- }
-
- if (whole.implib_sub_path) |sub_path| {
- @memcpy(sub_path[digest_start..][0..digest.len], digest);
-
- comp.implib_emit = .{
- .root_dir = comp.dirs.local_cache,
- .sub_path = sub_path,
- };
- }
-
- if (whole.docs_sub_path) |sub_path| {
- @memcpy(sub_path[digest_start..][0..digest.len], digest);
-
- comp.docs_emit = .{
- .root_dir = comp.dirs.local_cache,
- .sub_path = sub_path,
- };
- }
-}
-
-fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemory}!?[]u8 {
- const emit = opt_emit orelse return null;
- if (emit.directory != null) return null;
- const s = std.fs.path.sep_str;
- const format = "o" ++ s ++ ("x" ** Cache.hex_digest_len) ++ s ++ "{s}";
- return try std.fmt.allocPrint(arena, format, .{emit.basename});
-}
-
/// This is only observed at compile-time and used to emit a compile error
/// to remind the programmer to update multiple related pieces of code that
/// are in different locations. Bump this number when adding or deleting
@@ -3068,7 +3151,7 @@ fn addNonIncrementalStuffToCacheManifest(
man.hash.addListOfBytes(comp.test_filters);
man.hash.addOptionalBytes(comp.test_name_prefix);
man.hash.add(comp.skip_linker_dependencies);
- //man.hash.add(zcu.emit_h != null);
+ //man.hash.add(zcu.emit_h != .no);
man.hash.add(zcu.error_limit);
} else {
cache_helpers.addModule(&man.hash, comp.root_mod);
@@ -3114,10 +3197,6 @@ fn addNonIncrementalStuffToCacheManifest(
man.hash.addListOfBytes(comp.framework_dirs);
man.hash.addListOfBytes(comp.windows_libs.keys());
- cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_asm);
- cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir);
- cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc);
-
man.hash.addListOfBytes(comp.global_cc_argv);
const opts = comp.cache_use.whole.lf_open_opts;
@@ -3195,82 +3274,39 @@ fn addNonIncrementalStuffToCacheManifest(
man.hash.addOptional(opts.minor_subsystem_version);
}
-fn emitOthers(comp: *Compilation) void {
- if (comp.config.output_mode != .Obj or comp.zcu != null or
- comp.c_object_table.count() == 0)
- {
- return;
- }
- const obj_path = comp.c_object_table.keys()[0].status.success.object_path;
- const ext = std.fs.path.extension(obj_path.sub_path);
- const dirname = obj_path.sub_path[0 .. obj_path.sub_path.len - ext.len];
- // This obj path always ends with the object file extension, but if we change the
- // extension to .ll, .bc, or .s, then it will be the path to those things.
- const outs = [_]struct {
- emit: ?EmitLoc,
- ext: []const u8,
- }{
- .{ .emit = comp.emit_asm, .ext = ".s" },
- .{ .emit = comp.emit_llvm_ir, .ext = ".ll" },
- .{ .emit = comp.emit_llvm_bc, .ext = ".bc" },
- };
- for (outs) |out| {
- if (out.emit) |loc| {
- if (loc.directory) |directory| {
- const src_path = std.fmt.allocPrint(comp.gpa, "{s}{s}", .{
- dirname, out.ext,
- }) catch |err| {
- log.err("unable to copy {s}{s}: {s}", .{ dirname, out.ext, @errorName(err) });
- continue;
- };
- defer comp.gpa.free(src_path);
- obj_path.root_dir.handle.copyFile(src_path, directory.handle, loc.basename, .{}) catch |err| {
- log.err("unable to copy {s}: {s}", .{ src_path, @errorName(err) });
- };
- }
- }
- }
-}
-
-pub fn emitLlvmObject(
+fn emitFromCObject(
comp: *Compilation,
arena: Allocator,
- default_artifact_directory: Cache.Path,
- bin_emit_loc: ?EmitLoc,
- llvm_object: LlvmObject.Ptr,
- prog_node: std.Progress.Node,
-) !void {
- const sub_prog_node = prog_node.start("LLVM Emit Object", 0);
- defer sub_prog_node.end();
-
- try llvm_object.emit(.{
- .pre_ir_path = comp.verbose_llvm_ir,
- .pre_bc_path = comp.verbose_llvm_bc,
- .bin_path = try resolveEmitLoc(arena, default_artifact_directory, bin_emit_loc),
- .asm_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_asm),
- .post_ir_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_ir),
- .post_bc_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_bc),
-
- .is_debug = comp.root_mod.optimize_mode == .Debug,
- .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
- .time_report = comp.time_report,
- .sanitize_thread = comp.config.any_sanitize_thread,
- .fuzz = comp.config.any_fuzz,
- .lto = comp.config.lto,
- });
-}
+ c_obj_path: Cache.Path,
+ new_ext: []const u8,
+ unresolved_emit_path: []const u8,
+) Allocator.Error!void {
+ // The dirname and stem (i.e. everything but the extension), of the sub path of the C object.
+ // We'll append `new_ext` to it to get the path to the right thing (asm, LLVM IR, etc).
+ const c_obj_dir_and_stem: []const u8 = p: {
+ const p = c_obj_path.sub_path;
+ const ext_len = fs.path.extension(p).len;
+ break :p p[0 .. p.len - ext_len];
+ };
+ const src_path: Cache.Path = .{
+ .root_dir = c_obj_path.root_dir,
+ .sub_path = try std.fmt.allocPrint(arena, "{s}{s}", .{
+ c_obj_dir_and_stem,
+ new_ext,
+ }),
+ };
+ const emit_path = comp.resolveEmitPath(unresolved_emit_path);
-fn resolveEmitLoc(
- arena: Allocator,
- default_artifact_directory: Cache.Path,
- opt_loc: ?EmitLoc,
-) Allocator.Error!?[*:0]const u8 {
- const loc = opt_loc orelse return null;
- const slice = if (loc.directory) |directory|
- try directory.joinZ(arena, &.{loc.basename})
- else
- try default_artifact_directory.joinStringZ(arena, loc.basename);
- return slice.ptr;
+ src_path.root_dir.handle.copyFile(
+ src_path.sub_path,
+ emit_path.root_dir.handle,
+ emit_path.sub_path,
+ .{},
+ ) catch |err| log.err("unable to copy '{}' to '{}': {s}", .{
+ src_path,
+ emit_path,
+ @errorName(err),
+ });
}
/// Having the file open for writing is problematic as far as executing the
@@ -3512,7 +3548,7 @@ pub fn saveState(comp: *Compilation) !void {
// TODO handle the union safety field
//addBuf(&bufs, mem.sliceAsBytes(wasm.mir_instructions.items(.data)));
addBuf(&bufs, mem.sliceAsBytes(wasm.mir_extra.items));
- addBuf(&bufs, mem.sliceAsBytes(wasm.all_zcu_locals.items));
+ addBuf(&bufs, mem.sliceAsBytes(wasm.mir_locals.items));
addBuf(&bufs, mem.sliceAsBytes(wasm.tag_name_bytes.items));
addBuf(&bufs, mem.sliceAsBytes(wasm.tag_name_offs.items));
@@ -4156,28 +4192,15 @@ pub fn addWholeFileError(
}
}
-pub fn performAllTheWork(
+fn performAllTheWork(
comp: *Compilation,
main_progress_node: std.Progress.Node,
) JobError!void {
- comp.work_queue_progress_node = main_progress_node;
- defer comp.work_queue_progress_node = .none;
-
+ // Regardless of errors, `comp.zcu` needs to update its generation number.
defer if (comp.zcu) |zcu| {
- zcu.sema_prog_node.end();
- zcu.sema_prog_node = .none;
- zcu.codegen_prog_node.end();
- zcu.codegen_prog_node = .none;
-
zcu.generation += 1;
};
- try comp.performAllTheWorkInner(main_progress_node);
-}
-fn performAllTheWorkInner(
- comp: *Compilation,
- main_progress_node: std.Progress.Node,
-) JobError!void {
// Here we queue up all the AstGen tasks first, followed by C object compilation.
// We wait until the AstGen tasks are all completed before proceeding to the
// (at least for now) single-threaded main work queue. However, C object compilation
@@ -4189,11 +4212,13 @@ fn performAllTheWorkInner(
comp.link_task_wait_group.reset();
defer comp.link_task_wait_group.wait();
- if (comp.link_task_queue.start()) {
- comp.thread_pool.spawnWgId(&comp.link_task_wait_group, link.flushTaskQueue, .{comp});
- }
+ comp.link_prog_node.increaseEstimatedTotalItems(
+ comp.link_task_queue.queued_prelink.items.len + // already queued prelink tasks
+ comp.link_task_queue.pending_prelink_tasks, // prelink tasks which will be queued
+ );
+ comp.link_task_queue.start(comp);
- if (comp.docs_emit != null) {
+ if (comp.emit_docs != null) {
dev.check(.docs_emit);
comp.thread_pool.spawnWg(&work_queue_wait_group, workerDocsCopy, .{comp});
work_queue_wait_group.spawnManager(workerDocsWasm, .{ comp, main_progress_node });
@@ -4471,7 +4496,7 @@ fn performAllTheWorkInner(
};
}
},
- .incremental => {},
+ .none, .incremental => {},
}
if (any_fatal_files or
@@ -4499,15 +4524,31 @@ fn performAllTheWorkInner(
}
zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
- zcu.codegen_prog_node = if (comp.bin_file != null) main_progress_node.start("Code Generation", 0) else .none;
+ if (comp.bin_file != null) {
+ zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0);
+ }
+ // We increment `pending_codegen_jobs` so that it doesn't reach 0 until after analysis finishes.
+ // That prevents the "Code Generation" node from constantly disappearing and reappearing when
+ // we're probably going to analyze more functions at some point.
+ assert(zcu.pending_codegen_jobs.swap(1, .monotonic) == 0); // don't let this become 0 until analysis finishes
}
+ // When analysis ends, delete the progress nodes for "Semantic Analysis" and possibly "Code Generation".
+ defer if (comp.zcu) |zcu| {
+ zcu.sema_prog_node.end();
+ zcu.sema_prog_node = .none;
+ if (zcu.pending_codegen_jobs.rmw(.Sub, 1, .monotonic) == 1) {
+ // Decremented to 0, so all done.
+ zcu.codegen_prog_node.end();
+ zcu.codegen_prog_node = .none;
+ }
+ };
if (!comp.separateCodegenThreadOk()) {
// Waits until all input files have been parsed.
comp.link_task_wait_group.wait();
comp.link_task_wait_group.reset();
std.log.scoped(.link).debug("finished waiting for link_task_wait_group", .{});
- if (comp.remaining_prelink_tasks > 0) {
+ if (comp.link_task_queue.pending_prelink_tasks > 0) {
// Indicates an error occurred preventing prelink phase from completing.
return;
}
@@ -4552,26 +4593,91 @@ pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void {
fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
switch (job) {
- .codegen_nav => |nav_index| {
+ .codegen_func => |func| {
+ const zcu = comp.zcu.?;
+ const gpa = zcu.gpa;
+ var air = func.air;
+ errdefer {
+ zcu.codegen_prog_node.completeOne();
+ comp.link_prog_node.completeOne();
+ air.deinit(gpa);
+ }
+ if (!air.typesFullyResolved(zcu)) {
+ // Type resolution failed in a way which affects this function. This is a transitive
+ // failure, but it doesn't need recording, because this function semantically depends
+ // on the failed type, so when it is changed the function is updated.
+ zcu.codegen_prog_node.completeOne();
+ comp.link_prog_node.completeOne();
+ air.deinit(gpa);
+ return;
+ }
+ const shared_mir = try gpa.create(link.ZcuTask.LinkFunc.SharedMir);
+ shared_mir.* = .{
+ .status = .init(.pending),
+ .value = undefined,
+ };
+ assert(zcu.pending_codegen_jobs.rmw(.Add, 1, .monotonic) > 0); // the "Code Generation" node hasn't been ended
+ // This value is used as a heuristic to avoid queueing too much AIR/MIR at once (hence
+ // using a lot of memory). If this would cause too many AIR bytes to be in-flight, we
+ // will block on the `dispatchZcuLinkTask` call below.
+ const air_bytes: u32 = @intCast(air.instructions.len * 5 + air.extra.items.len * 4);
+ if (comp.separateCodegenThreadOk()) {
+ // `workerZcuCodegen` takes ownership of `air`.
+ comp.thread_pool.spawnWgId(&comp.link_task_wait_group, workerZcuCodegen, .{ comp, func.func, air, shared_mir });
+ comp.dispatchZcuLinkTask(tid, .{ .link_func = .{
+ .func = func.func,
+ .mir = shared_mir,
+ .air_bytes = air_bytes,
+ } });
+ } else {
+ {
+ const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
+ defer pt.deactivate();
+ pt.runCodegen(func.func, &air, shared_mir);
+ }
+ assert(shared_mir.status.load(.monotonic) != .pending);
+ comp.dispatchZcuLinkTask(tid, .{ .link_func = .{
+ .func = func.func,
+ .mir = shared_mir,
+ .air_bytes = air_bytes,
+ } });
+ air.deinit(gpa);
+ }
+ },
+ .link_nav => |nav_index| {
const zcu = comp.zcu.?;
const nav = zcu.intern_pool.getNav(nav_index);
if (nav.analysis != null) {
const unit: InternPool.AnalUnit = .wrap(.{ .nav_val = nav_index });
if (zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit)) {
+ comp.link_prog_node.completeOne();
return;
}
}
assert(nav.status == .fully_resolved);
- comp.dispatchCodegenTask(tid, .{ .codegen_nav = nav_index });
- },
- .codegen_func => |func| {
- comp.dispatchCodegenTask(tid, .{ .codegen_func = func });
+ if (!Air.valFullyResolved(zcu.navValue(nav_index), zcu)) {
+ // Type resolution failed in a way which affects this `Nav`. This is a transitive
+ // failure, but it doesn't need recording, because this `Nav` semantically depends
+ // on the failed type, so when it is changed the `Nav` will be updated.
+ comp.link_prog_node.completeOne();
+ return;
+ }
+ comp.dispatchZcuLinkTask(tid, .{ .link_nav = nav_index });
},
- .codegen_type => |ty| {
- comp.dispatchCodegenTask(tid, .{ .codegen_type = ty });
+ .link_type => |ty| {
+ const zcu = comp.zcu.?;
+ if (zcu.failed_types.fetchSwapRemove(ty)) |*entry| entry.value.deinit(zcu.gpa);
+ if (!Air.typeFullyResolved(.fromInterned(ty), zcu)) {
+ // Type resolution failed in a way which affects this type. This is a transitive
+ // failure, but it doesn't need recording, because this type semantically depends
+ // on the failed type, so when that is changed, this type will be updated.
+ comp.link_prog_node.completeOne();
+ return;
+ }
+ comp.dispatchZcuLinkTask(tid, .{ .link_type = ty });
},
.update_line_number => |ti| {
- comp.dispatchCodegenTask(tid, .{ .update_line_number = ti });
+ comp.dispatchZcuLinkTask(tid, .{ .update_line_number = ti });
},
.analyze_func => |func| {
const named_frame = tracy.namedFrame("analyze_func");
@@ -4663,18 +4769,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
}
}
-/// The reason for the double-queue here is that the first queue ensures any
-/// resolve_type_fully tasks are complete before this dispatch function is called.
-fn dispatchCodegenTask(comp: *Compilation, tid: usize, link_task: link.Task) void {
- if (comp.separateCodegenThreadOk()) {
- comp.queueLinkTasks(&.{link_task});
- } else {
- assert(comp.remaining_prelink_tasks == 0);
- link.doTask(comp, tid, link_task);
- }
-}
-
-fn separateCodegenThreadOk(comp: *const Compilation) bool {
+pub fn separateCodegenThreadOk(comp: *const Compilation) bool {
if (InternPool.single_threaded) return false;
const zcu = comp.zcu orelse return true;
return zcu.backendSupportsFeature(.separate_thread);
@@ -4694,12 +4789,12 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
const zcu = comp.zcu orelse
return comp.lockAndSetMiscFailure(.docs_copy, "no Zig code to document", .{});
- const emit = comp.docs_emit.?;
- var out_dir = emit.root_dir.handle.makeOpenPath(emit.sub_path, .{}) catch |err| {
+ const docs_path = comp.resolveEmitPath(comp.emit_docs.?);
+ var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| {
return comp.lockAndSetMiscFailure(
.docs_copy,
- "unable to create output directory '{}{s}': {s}",
- .{ emit.root_dir, emit.sub_path, @errorName(err) },
+ "unable to create output directory '{}': {s}",
+ .{ docs_path, @errorName(err) },
);
};
defer out_dir.close();
@@ -4718,8 +4813,8 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
var tar_file = out_dir.createFile("sources.tar", .{}) catch |err| {
return comp.lockAndSetMiscFailure(
.docs_copy,
- "unable to create '{}{s}/sources.tar': {s}",
- .{ emit.root_dir, emit.sub_path, @errorName(err) },
+ "unable to create '{}/sources.tar': {s}",
+ .{ docs_path, @errorName(err) },
);
};
defer tar_file.close();
@@ -4869,11 +4964,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
.parent = root_mod,
});
try root_mod.deps.put(arena, "Walk", walk_mod);
- const bin_basename = try std.zig.binNameAlloc(arena, .{
- .root_name = root_name,
- .target = resolved_target.result,
- .output_mode = output_mode,
- });
const sub_compilation = try Compilation.create(gpa, arena, .{
.dirs = dirs,
@@ -4885,10 +4975,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
.root_name = root_name,
.thread_pool = comp.thread_pool,
.libc_installation = comp.libc_installation,
- .emit_bin = .{
- .directory = null, // Put it in the cache directory.
- .basename = bin_basename,
- },
+ .emit_bin = .yes_cache,
.verbose_cc = comp.verbose_cc,
.verbose_link = comp.verbose_link,
.verbose_air = comp.verbose_air,
@@ -4903,27 +4990,31 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
try comp.updateSubCompilation(sub_compilation, .docs_wasm, prog_node);
- const emit = comp.docs_emit.?;
- var out_dir = emit.root_dir.handle.makeOpenPath(emit.sub_path, .{}) catch |err| {
+ var crt_file = try sub_compilation.toCrtFile();
+ defer crt_file.deinit(gpa);
+
+ const docs_bin_file = crt_file.full_object_path;
+ assert(docs_bin_file.sub_path.len > 0); // emitted binary is not a directory
+
+ const docs_path = comp.resolveEmitPath(comp.emit_docs.?);
+ var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| {
return comp.lockAndSetMiscFailure(
.docs_copy,
- "unable to create output directory '{}{s}': {s}",
- .{ emit.root_dir, emit.sub_path, @errorName(err) },
+ "unable to create output directory '{}': {s}",
+ .{ docs_path, @errorName(err) },
);
};
defer out_dir.close();
- sub_compilation.dirs.local_cache.handle.copyFile(
- sub_compilation.cache_use.whole.bin_sub_path.?,
+ crt_file.full_object_path.root_dir.handle.copyFile(
+ crt_file.full_object_path.sub_path,
out_dir,
"main.wasm",
.{},
) catch |err| {
- return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{}{s}' to '{}{s}': {s}", .{
- sub_compilation.dirs.local_cache,
- sub_compilation.cache_use.whole.bin_sub_path.?,
- emit.root_dir,
- emit.sub_path,
+ return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{}' to '{}': {s}", .{
+ crt_file.full_object_path,
+ docs_path,
@errorName(err),
});
};
@@ -5185,7 +5276,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
defer whole.cache_manifest_mutex.unlock();
try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);
},
- .incremental => {},
+ .incremental, .none => {},
}
const bin_digest = man.finalBin();
@@ -5261,6 +5352,21 @@ pub const RtOptions = struct {
allow_lto: bool = true,
};
+fn workerZcuCodegen(
+ tid: usize,
+ comp: *Compilation,
+ func_index: InternPool.Index,
+ orig_air: Air,
+ out: *link.ZcuTask.LinkFunc.SharedMir,
+) void {
+ var air = orig_air;
+ // We own `air` now, so we are responsbile for freeing it.
+ defer air.deinit(comp.gpa);
+ const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
+ defer pt.deactivate();
+ pt.runCodegen(func_index, &air, out);
+}
+
fn buildRt(
comp: *Compilation,
root_source_name: []const u8,
@@ -5515,9 +5621,9 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
defer man.deinit();
man.hash.add(comp.clang_preprocessor_mode);
- cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_asm);
- cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir);
- cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc);
+ man.hash.addOptionalBytes(comp.emit_asm);
+ man.hash.addOptionalBytes(comp.emit_llvm_ir);
+ man.hash.addOptionalBytes(comp.emit_llvm_bc);
try cache_helpers.hashCSource(&man, c_object.src);
@@ -5751,7 +5857,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);
}
},
- .incremental => {},
+ .incremental, .none => {},
}
}
@@ -5792,7 +5898,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
},
};
- comp.queueLinkTasks(&.{.{ .load_object = c_object.status.success.object_path }});
+ comp.queuePrelinkTasks(&.{.{ .load_object = c_object.status.success.object_path }});
}
fn 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
defer whole.cache_manifest_mutex.unlock();
try whole_cache_manifest.addFilePost(dep_file_path);
},
- .incremental => {},
+ .incremental, .none => {},
}
}
}
@@ -7167,12 +7273,6 @@ fn buildOutputFromZig(
.cc_argv = &.{},
.parent = null,
});
- const target = comp.getTarget();
- const bin_basename = try std.zig.binNameAlloc(arena, .{
- .root_name = root_name,
- .target = target,
- .output_mode = output_mode,
- });
const parent_whole_cache: ?ParentWholeCache = switch (comp.cache_use) {
.whole => |whole| .{
@@ -7185,7 +7285,7 @@ fn buildOutputFromZig(
3, // global cache is the same
},
},
- .incremental => null,
+ .incremental, .none => null,
};
const sub_compilation = try Compilation.create(gpa, arena, .{
@@ -7198,13 +7298,9 @@ fn buildOutputFromZig(
.root_name = root_name,
.thread_pool = comp.thread_pool,
.libc_installation = comp.libc_installation,
- .emit_bin = .{
- .directory = null, // Put it in the cache directory.
- .basename = bin_basename,
- },
+ .emit_bin = .yes_cache,
.function_sections = true,
.data_sections = true,
- .emit_h = null,
.verbose_cc = comp.verbose_cc,
.verbose_link = comp.verbose_link,
.verbose_air = comp.verbose_air,
@@ -7225,7 +7321,7 @@ fn buildOutputFromZig(
assert(out.* == null);
out.* = crt_file;
- comp.queueLinkTaskMode(crt_file.full_object_path, &config);
+ comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
}
pub const CrtFileOptions = struct {
@@ -7324,13 +7420,9 @@ pub fn build_crt_file(
.root_name = root_name,
.thread_pool = comp.thread_pool,
.libc_installation = comp.libc_installation,
- .emit_bin = .{
- .directory = null, // Put it in the cache directory.
- .basename = basename,
- },
+ .emit_bin = .yes_cache,
.function_sections = options.function_sections orelse false,
.data_sections = options.data_sections orelse false,
- .emit_h = null,
.c_source_files = c_source_files,
.verbose_cc = comp.verbose_cc,
.verbose_link = comp.verbose_link,
@@ -7349,7 +7441,7 @@ pub fn build_crt_file(
try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node);
const crt_file = try sub_compilation.toCrtFile();
- comp.queueLinkTaskMode(crt_file.full_object_path, &config);
+ comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
{
comp.mutex.lock();
@@ -7359,8 +7451,8 @@ pub fn build_crt_file(
}
}
-pub fn queueLinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Compilation.Config) void {
- comp.queueLinkTasks(switch (config.output_mode) {
+pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Compilation.Config) void {
+ comp.queuePrelinkTasks(switch (config.output_mode) {
.Exe => unreachable,
.Obj => &.{.{ .load_object = path }},
.Lib => &.{switch (config.link_mode) {
@@ -7372,19 +7464,41 @@ pub fn queueLinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Co
/// Only valid to call during `update`. Automatically handles queuing up a
/// linker worker task if there is not already one.
-pub fn queueLinkTasks(comp: *Compilation, tasks: []const link.Task) void {
- if (comp.link_task_queue.enqueue(comp.gpa, tasks) catch |err| switch (err) {
+pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) void {
+ comp.link_task_queue.enqueuePrelink(comp, tasks) catch |err| switch (err) {
error.OutOfMemory => return comp.setAllocFailure(),
- }) {
- comp.thread_pool.spawnWgId(&comp.link_task_wait_group, link.flushTaskQueue, .{comp});
+ };
+}
+
+/// The reason for the double-queue here is that the first queue ensures any
+/// resolve_type_fully tasks are complete before this dispatch function is called.
+fn dispatchZcuLinkTask(comp: *Compilation, tid: usize, task: link.ZcuTask) void {
+ if (!comp.separateCodegenThreadOk()) {
+ assert(tid == 0);
+ if (task == .link_func) {
+ assert(task.link_func.mir.status.load(.monotonic) != .pending);
+ }
+ link.doZcuTask(comp, tid, task);
+ task.deinit(comp.zcu.?);
+ return;
}
+ comp.link_task_queue.enqueueZcu(comp, task) catch |err| switch (err) {
+ error.OutOfMemory => {
+ task.deinit(comp.zcu.?);
+ comp.setAllocFailure();
+ },
+ };
}
pub fn toCrtFile(comp: *Compilation) Allocator.Error!CrtFile {
return .{
.full_object_path = .{
.root_dir = comp.dirs.local_cache,
- .sub_path = try comp.gpa.dupe(u8, comp.cache_use.whole.bin_sub_path.?),
+ .sub_path = try std.fs.path.join(comp.gpa, &.{
+ "o",
+ &Cache.binToHex(comp.digest.?),
+ comp.emit_bin.?,
+ }),
},
.lock = comp.cache_use.whole.moveLock(),
};
diff --git a/src/InternPool.zig b/src/InternPool.zig
index de1a434c02..7c3e52a8cf 100644
--- a/src/InternPool.zig
+++ b/src/InternPool.zig
@@ -3249,6 +3249,9 @@ pub const LoadedUnionType = struct {
name: NullTerminatedString,
/// Represents the declarations inside this union.
namespace: NamespaceIndex,
+ /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
+ /// Otherwise, this is `.none`.
+ name_nav: Nav.Index.Optional,
/// The enum tag type.
enum_tag_ty: Index,
/// List of field types in declaration order.
@@ -3567,6 +3570,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
.tid = unwrapped_index.tid,
.extra_index = data,
.name = type_union.data.name,
+ .name_nav = type_union.data.name_nav,
.namespace = type_union.data.namespace,
.enum_tag_ty = type_union.data.tag_ty,
.field_types = field_types,
@@ -3584,6 +3588,9 @@ pub const LoadedStructType = struct {
/// The name of this struct type.
name: NullTerminatedString,
namespace: NamespaceIndex,
+ /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
+ /// Otherwise, or if this is a file's root struct type, this is `.none`.
+ name_nav: Nav.Index.Optional,
/// Index of the `struct_decl` or `reify` ZIR instruction.
zir_index: TrackedInst.Index,
layout: std.builtin.Type.ContainerLayout,
@@ -4173,6 +4180,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
switch (item.tag) {
.type_struct => {
const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]);
+ const name_nav: Nav.Index.Optional = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?]);
const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]);
const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);
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 {
.tid = unwrapped_index.tid,
.extra_index = item.data,
.name = name,
+ .name_nav = name_nav,
.namespace = namespace,
.zir_index = zir_index,
.layout = if (flags.is_extern) .@"extern" else .auto,
@@ -4275,6 +4284,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
},
.type_struct_packed, .type_struct_packed_inits => {
const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?]);
+ const name_nav: Nav.Index.Optional = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?]);
const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]);
const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "fields_len").?];
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 {
.tid = unwrapped_index.tid,
.extra_index = item.data,
.name = name,
+ .name_nav = name_nav,
.namespace = namespace,
.zir_index = zir_index,
.layout = .@"packed",
@@ -4345,6 +4356,9 @@ pub const LoadedEnumType = struct {
name: NullTerminatedString,
/// Represents the declarations inside this enum.
namespace: NamespaceIndex,
+ /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
+ /// Otherwise, this is `.none`.
+ name_nav: Nav.Index.Optional,
/// An integer type which is used for the numerical value of the enum.
/// This field is present regardless of whether the enum has an
/// explicitly provided tag type or auto-numbered.
@@ -4428,6 +4442,7 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
} else extra.data.captures_len;
return .{
.name = extra.data.name,
+ .name_nav = extra.data.name_nav,
.namespace = extra.data.namespace,
.tag_ty = extra.data.int_tag_type,
.names = .{
@@ -4462,6 +4477,7 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
} else extra.data.captures_len;
return .{
.name = extra.data.name,
+ .name_nav = extra.data.name_nav,
.namespace = extra.data.namespace,
.tag_ty = extra.data.int_tag_type,
.names = .{
@@ -4493,6 +4509,9 @@ pub const LoadedOpaqueType = struct {
// TODO: the non-fqn will be needed by the new dwarf structure
/// The name of this opaque type.
name: NullTerminatedString,
+ /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
+ /// Otherwise, this is `.none`.
+ name_nav: Nav.Index.Optional,
/// Index of the `opaque_decl` or `reify` instruction.
zir_index: TrackedInst.Index,
captures: CaptureValue.Slice,
@@ -4509,6 +4528,7 @@ pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType {
extra.data.captures_len;
return .{
.name = extra.data.name,
+ .name_nav = extra.data.name_nav,
.namespace = extra.data.namespace,
.zir_index = extra.data.zir_index,
.captures = .{
@@ -6022,6 +6042,7 @@ pub const Tag = enum(u8) {
/// 4. field align: Alignment for each field; declaration order
pub const TypeUnion = struct {
name: NullTerminatedString,
+ name_nav: Nav.Index.Optional,
flags: Flags,
/// This could be provided through the tag type, but it is more convenient
/// to store it directly. This is also necessary for `dumpStatsFallible` to
@@ -6061,6 +6082,7 @@ pub const Tag = enum(u8) {
/// 5. init: Index for each fields_len // if tag is type_struct_packed_inits
pub const TypeStructPacked = struct {
name: NullTerminatedString,
+ name_nav: Nav.Index.Optional,
zir_index: TrackedInst.Index,
fields_len: u32,
namespace: NamespaceIndex,
@@ -6108,6 +6130,7 @@ pub const Tag = enum(u8) {
/// 8. field_offset: u32 // for each field in declared order, undef until layout_resolved
pub const TypeStruct = struct {
name: NullTerminatedString,
+ name_nav: Nav.Index.Optional,
zir_index: TrackedInst.Index,
namespace: NamespaceIndex,
fields_len: u32,
@@ -6151,6 +6174,7 @@ pub const Tag = enum(u8) {
/// 0. capture: CaptureValue // for each `captures_len`
pub const TypeOpaque = struct {
name: NullTerminatedString,
+ name_nav: Nav.Index.Optional,
/// Contains the declarations inside this opaque.
namespace: NamespaceIndex,
/// The index of the `opaque_decl` instruction.
@@ -6429,6 +6453,7 @@ pub const Array = struct {
/// 4. tag value: Index for each fields_len; declaration order
pub const EnumExplicit = struct {
name: NullTerminatedString,
+ name_nav: Nav.Index.Optional,
/// `std.math.maxInt(u32)` indicates this type is reified.
captures_len: u32,
namespace: NamespaceIndex,
@@ -6454,6 +6479,7 @@ pub const EnumExplicit = struct {
/// 3. field name: NullTerminatedString for each fields_len; declaration order
pub const EnumAuto = struct {
name: NullTerminatedString,
+ name_nav: Nav.Index.Optional,
/// `std.math.maxInt(u32)` indicates this type is reified.
captures_len: u32,
namespace: NamespaceIndex,
@@ -8666,6 +8692,7 @@ pub fn getUnionType(
.size = std.math.maxInt(u32),
.padding = std.math.maxInt(u32),
.name = undefined, // set by `finish`
+ .name_nav = undefined, // set by `finish`
.namespace = undefined, // set by `finish`
.tag_ty = ini.enum_tag_ty,
.zir_index = switch (ini.key) {
@@ -8717,6 +8744,7 @@ pub fn getUnionType(
.tid = tid,
.index = gop.put(),
.type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?,
+ .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?,
.namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?,
} };
}
@@ -8726,15 +8754,20 @@ pub const WipNamespaceType = struct {
index: Index,
type_name_extra_index: u32,
namespace_extra_index: u32,
+ name_nav_extra_index: u32,
pub fn setName(
wip: WipNamespaceType,
ip: *InternPool,
type_name: NullTerminatedString,
+ /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise.
+ /// This is also `.none` if we use `.parent` because we are the root struct type for a file.
+ name_nav: Nav.Index.Optional,
) void {
const extra = ip.getLocalShared(wip.tid).extra.acquire();
const extra_items = extra.view().items(.@"0");
extra_items[wip.type_name_extra_index] = @intFromEnum(type_name);
+ extra_items[wip.name_nav_extra_index] = @intFromEnum(name_nav);
}
pub fn finish(
@@ -8843,6 +8876,7 @@ pub fn getStructType(
ini.fields_len); // inits
const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{
.name = undefined, // set by `finish`
+ .name_nav = undefined, // set by `finish`
.zir_index = zir_index,
.fields_len = ini.fields_len,
.namespace = undefined, // set by `finish`
@@ -8887,6 +8921,7 @@ pub fn getStructType(
.tid = tid,
.index = gop.put(),
.type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?,
+ .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?,
.namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?,
} };
},
@@ -8909,6 +8944,7 @@ pub fn getStructType(
1); // names_map
const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{
.name = undefined, // set by `finish`
+ .name_nav = undefined, // set by `finish`
.zir_index = zir_index,
.namespace = undefined, // set by `finish`
.fields_len = ini.fields_len,
@@ -8977,6 +9013,7 @@ pub fn getStructType(
.tid = tid,
.index = gop.put(),
.type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?,
+ .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?,
.namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?,
} };
}
@@ -9766,6 +9803,7 @@ pub const WipEnumType = struct {
tag_ty_index: u32,
type_name_extra_index: u32,
namespace_extra_index: u32,
+ name_nav_extra_index: u32,
names_map: MapIndex,
names_start: u32,
values_map: OptionalMapIndex,
@@ -9775,10 +9813,13 @@ pub const WipEnumType = struct {
wip: WipEnumType,
ip: *InternPool,
type_name: NullTerminatedString,
+ /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise.
+ name_nav: Nav.Index.Optional,
) void {
const extra = ip.getLocalShared(wip.tid).extra.acquire();
const extra_items = extra.view().items(.@"0");
extra_items[wip.type_name_extra_index] = @intFromEnum(type_name);
+ extra_items[wip.name_nav_extra_index] = @intFromEnum(name_nav);
}
pub fn prepare(
@@ -9893,6 +9934,7 @@ pub fn getEnumType(
const extra_index = addExtraAssumeCapacity(extra, EnumAuto{
.name = undefined, // set by `prepare`
+ .name_nav = undefined, // set by `prepare`
.captures_len = switch (ini.key) {
inline .declared, .declared_owned_captures => |d| @intCast(d.captures.len),
.reified => std.math.maxInt(u32),
@@ -9921,6 +9963,7 @@ pub fn getEnumType(
.index = gop.put(),
.tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?,
.type_name_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name").?,
+ .name_nav_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name_nav").?,
.namespace_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "namespace").?,
.names_map = names_map,
.names_start = @intCast(names_start),
@@ -9950,6 +9993,7 @@ pub fn getEnumType(
const extra_index = addExtraAssumeCapacity(extra, EnumExplicit{
.name = undefined, // set by `prepare`
+ .name_nav = undefined, // set by `prepare`
.captures_len = switch (ini.key) {
inline .declared, .declared_owned_captures => |d| @intCast(d.captures.len),
.reified => std.math.maxInt(u32),
@@ -9987,6 +10031,7 @@ pub fn getEnumType(
.index = gop.put(),
.tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?,
.type_name_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name").?,
+ .name_nav_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name_nav").?,
.namespace_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "namespace").?,
.names_map = names_map,
.names_start = @intCast(names_start),
@@ -10055,6 +10100,7 @@ pub fn getGeneratedTagEnumType(
.tag = .type_enum_auto,
.data = addExtraAssumeCapacity(extra, EnumAuto{
.name = ini.name,
+ .name_nav = .none,
.captures_len = 0,
.namespace = namespace,
.int_tag_type = ini.tag_ty,
@@ -10088,6 +10134,7 @@ pub fn getGeneratedTagEnumType(
},
.data = addExtraAssumeCapacity(extra, EnumExplicit{
.name = ini.name,
+ .name_nav = .none,
.captures_len = 0,
.namespace = namespace,
.int_tag_type = ini.tag_ty,
@@ -10161,6 +10208,7 @@ pub fn getOpaqueType(
});
const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{
.name = undefined, // set by `finish`
+ .name_nav = undefined, // set by `finish`
.namespace = undefined, // set by `finish`
.zir_index = switch (ini.key) {
inline else => |x| x.zir_index,
@@ -10183,6 +10231,7 @@ pub fn getOpaqueType(
.tid = tid,
.index = gop.put(),
.type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?,
+ .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name_nav").?,
.namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?,
},
};
@@ -10299,6 +10348,7 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 {
extra.appendAssumeCapacity(.{switch (field.type) {
Index,
Nav.Index,
+ Nav.Index.Optional,
NamespaceIndex,
OptionalNamespaceIndex,
MapIndex,
@@ -10361,6 +10411,7 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat
@field(result, field.name) = switch (field.type) {
Index,
Nav.Index,
+ Nav.Index.Optional,
NamespaceIndex,
OptionalNamespaceIndex,
MapIndex,
diff --git a/src/Sema.zig b/src/Sema.zig
index 17e70214c3..bb0c24efdb 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -2963,13 +2963,14 @@ fn zirStructDecl(
};
errdefer wip_ty.cancel(ip, pt.tid);
- wip_ty.setName(ip, try sema.createTypeName(
+ const type_name = try sema.createTypeName(
block,
small.name_strategy,
"struct",
inst,
wip_ty.index,
- ));
+ );
+ wip_ty.setName(ip, type_name.name, type_name.nav);
const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
.parent = block.namespace.toOptional(),
@@ -2991,7 +2992,8 @@ fn zirStructDecl(
if (zcu.comp.config.use_llvm) break :codegen_type;
if (block.ownerModule().strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
- try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
+ zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
}
try sema.declareDependency(.{ .interned = wip_ty.index });
try sema.addTypeReferenceEntry(src, wip_ty.index);
@@ -3007,7 +3009,10 @@ pub fn createTypeName(
inst: ?Zir.Inst.Index,
/// This is used purely to give the type a unique name in the `anon` case.
type_index: InternPool.Index,
-) !InternPool.NullTerminatedString {
+) !struct {
+ name: InternPool.NullTerminatedString,
+ nav: InternPool.Nav.Index.Optional,
+} {
const pt = sema.pt;
const zcu = pt.zcu;
const gpa = zcu.gpa;
@@ -3015,7 +3020,10 @@ pub fn createTypeName(
switch (name_strategy) {
.anon => {}, // handled after switch
- .parent => return block.type_name_ctx,
+ .parent => return .{
+ .name = block.type_name_ctx,
+ .nav = sema.owner.unwrap().nav_val.toOptional(),
+ },
.func => func_strat: {
const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail);
const zir_tags = sema.code.instructions.items(.tag);
@@ -3057,7 +3065,10 @@ pub fn createTypeName(
};
try writer.writeByte(')');
- return ip.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls);
+ return .{
+ .name = try ip.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls),
+ .nav = .none,
+ };
},
.dbg_var => {
// 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(
const zir_data = sema.code.instructions.items(.data);
for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) {
.dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) {
- return ip.getOrPutStringFmt(gpa, pt.tid, "{}.{s}", .{
- block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),
- }, .no_embedded_nulls);
+ return .{
+ .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.{s}", .{
+ block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),
+ }, .no_embedded_nulls),
+ .nav = .none,
+ };
},
else => {},
};
@@ -3086,9 +3100,12 @@ pub fn createTypeName(
// types appropriately. However, `@typeName` becomes a problem then. If we remove
// that builtin from the language, we can consider this.
- return ip.getOrPutStringFmt(gpa, pt.tid, "{}__{s}_{d}", .{
- block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index),
- }, .no_embedded_nulls);
+ return .{
+ .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}__{s}_{d}", .{
+ block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index),
+ }, .no_embedded_nulls),
+ .nav = .none,
+ };
}
fn zirEnumDecl(
@@ -3209,7 +3226,7 @@ fn zirEnumDecl(
inst,
wip_ty.index,
);
- wip_ty.setName(ip, type_name);
+ wip_ty.setName(ip, type_name.name, type_name.nav);
const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
.parent = block.namespace.toOptional(),
@@ -3236,7 +3253,7 @@ fn zirEnumDecl(
inst,
tracked_inst,
new_namespace_index,
- type_name,
+ type_name.name,
small,
body,
tag_type_ref,
@@ -3250,7 +3267,8 @@ fn zirEnumDecl(
if (zcu.comp.config.use_llvm) break :codegen_type;
if (block.ownerModule().strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
- try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
+ zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
}
return Air.internedToRef(wip_ty.index);
}
@@ -3340,13 +3358,14 @@ fn zirUnionDecl(
};
errdefer wip_ty.cancel(ip, pt.tid);
- wip_ty.setName(ip, try sema.createTypeName(
+ const type_name = try sema.createTypeName(
block,
small.name_strategy,
"union",
inst,
wip_ty.index,
- ));
+ );
+ wip_ty.setName(ip, type_name.name, type_name.nav);
const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
.parent = block.namespace.toOptional(),
@@ -3368,7 +3387,8 @@ fn zirUnionDecl(
if (zcu.comp.config.use_llvm) break :codegen_type;
if (block.ownerModule().strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
- try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
+ zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
}
try sema.declareDependency(.{ .interned = wip_ty.index });
try sema.addTypeReferenceEntry(src, wip_ty.index);
@@ -3432,13 +3452,14 @@ fn zirOpaqueDecl(
};
errdefer wip_ty.cancel(ip, pt.tid);
- wip_ty.setName(ip, try sema.createTypeName(
+ const type_name = try sema.createTypeName(
block,
small.name_strategy,
"opaque",
inst,
wip_ty.index,
- ));
+ );
+ wip_ty.setName(ip, type_name.name, type_name.nav);
const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
.parent = block.namespace.toOptional(),
@@ -3455,7 +3476,8 @@ fn zirOpaqueDecl(
if (zcu.comp.config.use_llvm) break :codegen_type;
if (block.ownerModule().strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
- try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
+ zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
}
try sema.addTypeReferenceEntry(src, wip_ty.index);
if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
@@ -20052,7 +20074,8 @@ fn structInitAnon(
}, false)) {
.wip => |wip| ty: {
errdefer wip.cancel(ip, pt.tid);
- wip.setName(ip, try sema.createTypeName(block, .anon, "struct", inst, wip.index));
+ const type_name = try sema.createTypeName(block, .anon, "struct", inst, wip.index);
+ wip.setName(ip, type_name.name, type_name.nav);
const struct_type = ip.loadStructType(wip.index);
@@ -20076,7 +20099,8 @@ fn structInitAnon(
codegen_type: {
if (zcu.comp.config.use_llvm) break :codegen_type;
if (block.ownerModule().strip) break :codegen_type;
- try zcu.comp.queueJob(.{ .codegen_type = wip.index });
+ zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try zcu.comp.queueJob(.{ .link_type = wip.index });
}
if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index);
break :ty wip.finish(ip, new_namespace_index);
@@ -21112,13 +21136,14 @@ fn zirReify(
};
errdefer wip_ty.cancel(ip, pt.tid);
- wip_ty.setName(ip, try sema.createTypeName(
+ const type_name = try sema.createTypeName(
block,
name_strategy,
"opaque",
inst,
wip_ty.index,
- ));
+ );
+ wip_ty.setName(ip, type_name.name, type_name.nav);
const new_namespace_index = try pt.createNamespace(.{
.parent = block.namespace.toOptional(),
@@ -21317,13 +21342,14 @@ fn reifyEnum(
return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{});
}
- wip_ty.setName(ip, try sema.createTypeName(
+ const type_name = try sema.createTypeName(
block,
name_strategy,
"enum",
inst,
wip_ty.index,
- ));
+ );
+ wip_ty.setName(ip, type_name.name, type_name.nav);
const new_namespace_index = try pt.createNamespace(.{
.parent = block.namespace.toOptional(),
@@ -21386,7 +21412,8 @@ fn reifyEnum(
if (zcu.comp.config.use_llvm) break :codegen_type;
if (block.ownerModule().strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
- try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
+ zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
}
return Air.internedToRef(wip_ty.index);
}
@@ -21488,7 +21515,7 @@ fn reifyUnion(
inst,
wip_ty.index,
);
- wip_ty.setName(ip, type_name);
+ wip_ty.setName(ip, type_name.name, type_name.nav);
const field_types = try sema.arena.alloc(InternPool.Index, fields_len);
const field_aligns = if (any_aligns) try sema.arena.alloc(InternPool.Alignment, fields_len) else undefined;
@@ -21581,7 +21608,7 @@ fn reifyUnion(
}
}
- const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), wip_ty.index, type_name);
+ const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), wip_ty.index, type_name.name);
break :tag_ty .{ enum_tag_ty, false };
};
errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error
@@ -21640,7 +21667,8 @@ fn reifyUnion(
if (zcu.comp.config.use_llvm) break :codegen_type;
if (block.ownerModule().strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
- try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
+ zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
}
try sema.declareDependency(.{ .interned = wip_ty.index });
try sema.addTypeReferenceEntry(src, wip_ty.index);
@@ -21843,13 +21871,14 @@ fn reifyStruct(
};
errdefer wip_ty.cancel(ip, pt.tid);
- wip_ty.setName(ip, try sema.createTypeName(
+ const type_name = try sema.createTypeName(
block,
name_strategy,
"struct",
inst,
wip_ty.index,
- ));
+ );
+ wip_ty.setName(ip, type_name.name, type_name.nav);
const struct_type = ip.loadStructType(wip_ty.index);
@@ -21994,7 +22023,8 @@ fn reifyStruct(
if (zcu.comp.config.use_llvm) break :codegen_type;
if (block.ownerModule().strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
- try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
+ zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
}
try sema.declareDependency(.{ .interned = wip_ty.index });
try sema.addTypeReferenceEntry(src, wip_ty.index);
@@ -35022,7 +35052,7 @@ pub fn resolveUnionAlignment(
union_type.setAlignment(ip, max_align);
}
-/// This logic must be kept in sync with `Zcu.getUnionLayout`.
+/// This logic must be kept in sync with `Type.getUnionLayout`.
pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
const pt = sema.pt;
const ip = &pt.zcu.intern_pool;
@@ -35056,24 +35086,32 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
var max_align: Alignment = .@"1";
for (0..union_type.field_types.len) |field_index| {
const field_ty: Type = .fromInterned(union_type.field_types.get(ip)[field_index]);
-
- if (try field_ty.comptimeOnlySema(pt) or field_ty.zigTypeTag(pt.zcu) == .noreturn) continue; // TODO: should this affect alignment?
-
- max_size = @max(max_size, field_ty.abiSizeSema(pt) catch |err| switch (err) {
- error.AnalysisFail => {
- const msg = sema.err orelse return err;
- try sema.addFieldErrNote(ty, field_index, msg, "while checking this field", .{});
- return err;
- },
- else => return err,
- });
+ if (field_ty.isNoReturn(pt.zcu)) continue;
+
+ // We need to call `hasRuntimeBits` before calling `abiSize` to prevent reachable `unreachable`s,
+ // but `hasRuntimeBits` only resolves field types and so may infinite recurse on a layout wip type,
+ // so we must resolve the layout manually first, instead of waiting for `abiSize` to do it for us.
+ // This is arguably just hacking around bugs in both `abiSize` for not allowing arbitrary types to
+ // be queried, enabling failures to be handled with the emission of a compile error, and also in
+ // `hasRuntimeBits` for ever being able to infinite recurse in the first place.
+ try field_ty.resolveLayout(pt);
+
+ if (try field_ty.hasRuntimeBitsSema(pt)) {
+ max_size = @max(max_size, field_ty.abiSizeSema(pt) catch |err| switch (err) {
+ error.AnalysisFail => {
+ const msg = sema.err orelse return err;
+ try sema.addFieldErrNote(ty, field_index, msg, "while checking this field", .{});
+ return err;
+ },
+ else => return err,
+ });
+ }
const explicit_align = union_type.fieldAlign(ip, field_index);
const field_align = if (explicit_align != .none)
explicit_align
else
try field_ty.abiAlignmentSema(pt);
-
max_align = max_align.max(field_align);
}
diff --git a/src/Sema/LowerZon.zig b/src/Sema/LowerZon.zig
index 77065a07e8..8dfb710ac0 100644
--- a/src/Sema/LowerZon.zig
+++ b/src/Sema/LowerZon.zig
@@ -157,13 +157,14 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter
)) {
.wip => |wip| ty: {
errdefer wip.cancel(ip, pt.tid);
- wip.setName(ip, try self.sema.createTypeName(
+ const type_name = try self.sema.createTypeName(
self.block,
.anon,
"struct",
self.base_node_inst.resolve(ip),
wip.index,
- ));
+ );
+ wip.setName(ip, type_name.name, type_name.nav);
const struct_type = ip.loadStructType(wip.index);
@@ -194,7 +195,8 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter
codegen_type: {
if (pt.zcu.comp.config.use_llvm) break :codegen_type;
if (self.block.ownerModule().strip) break :codegen_type;
- try pt.zcu.comp.queueJob(.{ .codegen_type = wip.index });
+ pt.zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try pt.zcu.comp.queueJob(.{ .link_type = wip.index });
}
break :ty wip.finish(ip, new_namespace_index);
},
diff --git a/src/ThreadSafeQueue.zig b/src/ThreadSafeQueue.zig
deleted file mode 100644
index 74bbdc418f..0000000000
--- a/src/ThreadSafeQueue.zig
+++ /dev/null
@@ -1,72 +0,0 @@
-const std = @import("std");
-const assert = std.debug.assert;
-const Allocator = std.mem.Allocator;
-
-pub fn ThreadSafeQueue(comptime T: type) type {
- return struct {
- worker_owned: std.ArrayListUnmanaged(T),
- /// Protected by `mutex`.
- shared: std.ArrayListUnmanaged(T),
- mutex: std.Thread.Mutex,
- state: State,
-
- const Self = @This();
-
- pub const State = enum { wait, run };
-
- pub const empty: Self = .{
- .worker_owned = .empty,
- .shared = .empty,
- .mutex = .{},
- .state = .wait,
- };
-
- pub fn deinit(self: *Self, gpa: Allocator) void {
- self.worker_owned.deinit(gpa);
- self.shared.deinit(gpa);
- self.* = undefined;
- }
-
- /// Must be called from the worker thread.
- pub fn check(self: *Self) ?[]T {
- assert(self.worker_owned.items.len == 0);
- {
- self.mutex.lock();
- defer self.mutex.unlock();
- assert(self.state == .run);
- if (self.shared.items.len == 0) {
- self.state = .wait;
- return null;
- }
- std.mem.swap(std.ArrayListUnmanaged(T), &self.worker_owned, &self.shared);
- }
- const result = self.worker_owned.items;
- self.worker_owned.clearRetainingCapacity();
- return result;
- }
-
- /// Adds items to the queue, returning true if and only if the worker
- /// thread is waiting. Thread-safe.
- /// Not safe to call from the worker thread.
- pub fn enqueue(self: *Self, gpa: Allocator, items: []const T) error{OutOfMemory}!bool {
- self.mutex.lock();
- defer self.mutex.unlock();
- try self.shared.appendSlice(gpa, items);
- return switch (self.state) {
- .run => false,
- .wait => {
- self.state = .run;
- return true;
- },
- };
- }
-
- /// Safe only to call exactly once when initially starting the worker.
- pub fn start(self: *Self) bool {
- assert(self.state == .wait);
- if (self.shared.items.len == 0) return false;
- self.state = .run;
- return true;
- }
- };
-}
diff --git a/src/Type.zig b/src/Type.zig
index 00f1c70129..eafdd65531 100644
--- a/src/Type.zig
+++ b/src/Type.zig
@@ -177,6 +177,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
switch (ip.indexToKey(ty.toIntern())) {
+ .undef => return writer.writeAll("@as(type, undefined)"),
.int_type => |int_type| {
const sign_char: u8 = switch (int_type.signedness) {
.signed => 'i',
@@ -398,7 +399,6 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
},
// values, not types
- .undef,
.simple_value,
.variable,
.@"extern",
@@ -3915,29 +3915,32 @@ fn resolveUnionInner(
pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) Zcu.UnionLayout {
const ip = &zcu.intern_pool;
assert(loaded_union.haveLayout(ip));
- var most_aligned_field: u32 = undefined;
- var most_aligned_field_size: u64 = undefined;
- var biggest_field: u32 = undefined;
+ var most_aligned_field: u32 = 0;
+ var most_aligned_field_align: InternPool.Alignment = .@"1";
+ var most_aligned_field_size: u64 = 0;
+ var biggest_field: u32 = 0;
var payload_size: u64 = 0;
var payload_align: InternPool.Alignment = .@"1";
- for (loaded_union.field_types.get(ip), 0..) |field_ty, field_index| {
- if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue;
+ for (loaded_union.field_types.get(ip), 0..) |field_ty_ip_index, field_index| {
+ const field_ty: Type = .fromInterned(field_ty_ip_index);
+ if (field_ty.isNoReturn(zcu)) continue;
const explicit_align = loaded_union.fieldAlign(ip, field_index);
const field_align = if (explicit_align != .none)
explicit_align
else
- Type.fromInterned(field_ty).abiAlignment(zcu);
- const field_size = Type.fromInterned(field_ty).abiSize(zcu);
+ field_ty.abiAlignment(zcu);
+ const field_size = field_ty.abiSize(zcu);
if (field_size > payload_size) {
payload_size = field_size;
biggest_field = @intCast(field_index);
}
- if (field_align.compare(.gte, payload_align)) {
- payload_align = field_align;
+ if (field_size > 0 and field_align.compare(.gte, most_aligned_field_align)) {
most_aligned_field = @intCast(field_index);
+ most_aligned_field_align = field_align;
most_aligned_field_size = field_size;
}
+ payload_align = payload_align.max(field_align);
}
const have_tag = loaded_union.flagsUnordered(ip).runtime_tag.hasTag();
if (!have_tag or !Type.fromInterned(loaded_union.enum_tag_ty).hasRuntimeBits(zcu)) {
diff --git a/src/Zcu.zig b/src/Zcu.zig
index 7223e5a55e..513492e818 100644
--- a/src/Zcu.zig
+++ b/src/Zcu.zig
@@ -56,9 +56,8 @@ comptime {
/// General-purpose allocator. Used for both temporary and long-term storage.
gpa: Allocator,
comp: *Compilation,
-/// Usually, the LlvmObject is managed by linker code, however, in the case
-/// that -fno-emit-bin is specified, the linker code never executes, so we
-/// store the LlvmObject here.
+/// If the ZCU is emitting an LLVM object (i.e. we are using the LLVM backend), then this is the
+/// `LlvmObject` we are emitting to.
llvm_object: ?LlvmObject.Ptr,
/// Pointer to externally managed resource.
@@ -67,8 +66,18 @@ root_mod: *Package.Module,
/// `root_mod` is the test runner, and `main_mod` is the user's source file which has the tests.
main_mod: *Package.Module,
std_mod: *Package.Module,
-sema_prog_node: std.Progress.Node = std.Progress.Node.none,
-codegen_prog_node: std.Progress.Node = std.Progress.Node.none,
+sema_prog_node: std.Progress.Node = .none,
+codegen_prog_node: std.Progress.Node = .none,
+/// The number of codegen jobs which are pending or in-progress. Whichever thread drops this value
+/// to 0 is responsible for ending `codegen_prog_node`. While semantic analysis is happening, this
+/// value bottoms out at 1 instead of 0, to ensure that it can only drop to 0 after analysis is
+/// completed (since semantic analysis could trigger more codegen work).
+pending_codegen_jobs: std.atomic.Value(u32) = .init(0),
+
+/// This is the progress node *under* `sema_prog_node` which is currently running.
+/// When we have to pause to analyze something else, we just temporarily rename this node.
+/// Eventually, when we thread semantic analysis, we will want one of these per thread.
+cur_sema_prog_node: std.Progress.Node = .none,
/// Used by AstGen worker to load and store ZIR cache.
global_zir_cache: Cache.Directory,
@@ -172,6 +181,8 @@ transitive_failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .emp
/// This `Nav` succeeded analysis, but failed codegen.
/// This may be a simple "value" `Nav`, or it may be a function.
/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
+/// While multiple threads are active (most of the time!), this is guarded by `zcu.comp.mutex`, as
+/// codegen and linking run on a separate thread.
failed_codegen: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, *ErrorMsg) = .empty,
failed_types: std.AutoArrayHashMapUnmanaged(InternPool.Index, *ErrorMsg) = .empty,
/// Keep track of `@compileLog`s per `AnalUnit`.
@@ -267,16 +278,6 @@ resolved_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) = n
/// Reset to `false` at the start of each update in `Compilation.update`.
skip_analysis_this_update: bool = false,
-stage1_flags: packed struct {
- have_winmain: bool = false,
- have_wwinmain: bool = false,
- have_winmain_crt_startup: bool = false,
- have_wwinmain_crt_startup: bool = false,
- have_dllmain_crt_startup: bool = false,
- have_c_main: bool = false,
- reserved: u2 = 0,
-} = .{},
-
test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
global_assembly: std.AutoArrayHashMapUnmanaged(AnalUnit, []u8) = .empty,
@@ -3828,7 +3829,36 @@ pub const Feature = enum {
is_named_enum_value,
error_set_has_value,
field_reordering,
- /// If the backend supports running from another thread.
+ /// In theory, backends are supposed to work like this:
+ ///
+ /// * The AIR emitted by `Sema` is converted into MIR by `codegen.generateFunction`. This pass
+ /// is "pure", in that it does not depend on or modify any external mutable state.
+ ///
+ /// * That MIR is sent to the linker, which calls `codegen.emitFunction` to convert the MIR to
+ /// finalized machine code. This process is permitted to query and modify linker state.
+ ///
+ /// * The linker stores the resulting machine code in the binary as needed.
+ ///
+ /// The first stage described above can run in parallel to the rest of the compiler, and even to
+ /// other code generation work; we can run as many codegen threads as we want in parallel because
+ /// of the fact that this pass is pure. Emit and link must be single-threaded, but are generally
+ /// very fast, so that isn't a problem.
+ ///
+ /// Unfortunately, some code generation implementations currently query and/or mutate linker state
+ /// or even (in the case of the LLVM backend) semantic analysis state. Such backends cannot be run
+ /// in parallel with each other, with linking, or (potentially) with semantic analysis.
+ ///
+ /// Additionally, some backends continue to need the AIR in the "emit" stage, despite this pass
+ /// operating on MIR. This complicates memory management under the threading model above.
+ ///
+ /// These are both **bugs** in backend implementations, left over from legacy code. However, they
+ /// are difficult to fix. So, this `Feature` currently guards correct threading of code generation:
+ ///
+ /// * With this feature enabled, the backend is threaded as described above. The "emit" stage does
+ /// not have access to AIR (it will be `undefined`; see `codegen.emitFunction`).
+ ///
+ /// * With this feature disabled, semantic analysis, code generation, and linking all occur on the
+ /// same thread, and the "emit" stage has access to AIR.
separate_thread,
};
@@ -4577,22 +4607,29 @@ pub fn codegenFail(
comptime format: []const u8,
args: anytype,
) CodegenFailError {
- const gpa = zcu.gpa;
- try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1);
- const msg = try Zcu.ErrorMsg.create(gpa, zcu.navSrcLoc(nav_index), format, args);
- zcu.failed_codegen.putAssumeCapacityNoClobber(nav_index, msg);
- return error.CodegenFail;
+ const msg = try Zcu.ErrorMsg.create(zcu.gpa, zcu.navSrcLoc(nav_index), format, args);
+ return zcu.codegenFailMsg(nav_index, msg);
}
+/// Takes ownership of `msg`, even on OOM.
pub fn codegenFailMsg(zcu: *Zcu, nav_index: InternPool.Nav.Index, msg: *ErrorMsg) CodegenFailError {
const gpa = zcu.gpa;
{
+ zcu.comp.mutex.lock();
+ defer zcu.comp.mutex.unlock();
errdefer msg.deinit(gpa);
try zcu.failed_codegen.putNoClobber(gpa, nav_index, msg);
}
return error.CodegenFail;
}
+/// Asserts that `zcu.failed_codegen` contains the key `nav`, with the necessary lock held.
+pub fn assertCodegenFailed(zcu: *Zcu, nav: InternPool.Nav.Index) void {
+ zcu.comp.mutex.lock();
+ defer zcu.comp.mutex.unlock();
+ assert(zcu.failed_codegen.contains(nav));
+}
+
pub fn codegenFailType(
zcu: *Zcu,
ty_index: InternPool.Index,
@@ -4726,3 +4763,27 @@ fn explainWhyFileIsInModule(
import = importer_ref.import;
}
}
+
+const SemaProgNode = struct {
+ /// `null` means we created the node, so should end it.
+ old_name: ?[std.Progress.Node.max_name_len]u8,
+ pub fn end(spn: SemaProgNode, zcu: *Zcu) void {
+ if (spn.old_name) |old_name| {
+ zcu.sema_prog_node.completeOne(); // we're just renaming, but it's effectively completion
+ zcu.cur_sema_prog_node.setName(&old_name);
+ } else {
+ zcu.cur_sema_prog_node.end();
+ zcu.cur_sema_prog_node = .none;
+ }
+ }
+};
+pub fn startSemaProgNode(zcu: *Zcu, name: []const u8) SemaProgNode {
+ if (zcu.cur_sema_prog_node.index != .none) {
+ const old_name = zcu.cur_sema_prog_node.getName();
+ zcu.cur_sema_prog_node.setName(name);
+ return .{ .old_name = old_name };
+ } else {
+ zcu.cur_sema_prog_node = zcu.sema_prog_node.start(name, 0);
+ return .{ .old_name = null };
+ }
+}
diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig
index 8b35d8d799..4d90878420 100644
--- a/src/Zcu/PerThread.zig
+++ b/src/Zcu/PerThread.zig
@@ -27,6 +27,7 @@ const Type = @import("../Type.zig");
const Value = @import("../Value.zig");
const Zcu = @import("../Zcu.zig");
const Compilation = @import("../Compilation.zig");
+const codegen = @import("../codegen.zig");
const Zir = std.zig.Zir;
const Zoir = std.zig.Zoir;
const ZonGen = std.zig.ZonGen;
@@ -795,8 +796,8 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
info.deps.clearRetainingCapacity();
}
- const unit_prog_node = zcu.sema_prog_node.start("comptime", 0);
- defer unit_prog_node.end();
+ const unit_prog_node = zcu.startSemaProgNode("comptime");
+ defer unit_prog_node.end(zcu);
return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) {
error.AnalysisFail => {
@@ -975,8 +976,8 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu
info.deps.clearRetainingCapacity();
}
- const unit_prog_node = zcu.sema_prog_node.start(nav.fqn.toSlice(ip), 0);
- defer unit_prog_node.end();
+ const unit_prog_node = zcu.startSemaProgNode(nav.fqn.toSlice(ip));
+ defer unit_prog_node.end(zcu);
const invalidate_value: bool, const new_failed: bool = if (pt.analyzeNavVal(nav_id)) |result| res: {
break :res .{
@@ -1320,7 +1321,8 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
}
// This job depends on any resolve_type_fully jobs queued up before it.
- try zcu.comp.queueJob(.{ .codegen_nav = nav_id });
+ zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try zcu.comp.queueJob(.{ .link_nav = nav_id });
}
switch (old_nav.status) {
@@ -1395,8 +1397,8 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc
info.deps.clearRetainingCapacity();
}
- const unit_prog_node = zcu.sema_prog_node.start(nav.fqn.toSlice(ip), 0);
- defer unit_prog_node.end();
+ const unit_prog_node = zcu.startSemaProgNode(nav.fqn.toSlice(ip));
+ defer unit_prog_node.end(zcu);
const invalidate_type: bool, const new_failed: bool = if (pt.analyzeNavType(nav_id)) |result| res: {
break :res .{
@@ -1616,8 +1618,8 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter
info.deps.clearRetainingCapacity();
}
- const func_prog_node = zcu.sema_prog_node.start(ip.getNav(func.owner_nav).fqn.toSlice(ip), 0);
- defer func_prog_node.end();
+ const func_prog_node = zcu.startSemaProgNode(ip.getNav(func.owner_nav).fqn.toSlice(ip));
+ defer func_prog_node.end(zcu);
const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index)) |result|
.{ prev_failed or result.ies_outdated, false }
@@ -1716,6 +1718,8 @@ fn analyzeFuncBody(
}
// This job depends on any resolve_type_fully jobs queued up before it.
+ zcu.codegen_prog_node.increaseEstimatedTotalItems(1);
+ comp.link_prog_node.increaseEstimatedTotalItems(1);
try comp.queueJob(.{ .codegen_func = .{
.func = func_index,
.air = air,
@@ -1724,87 +1728,6 @@ fn analyzeFuncBody(
return .{ .ies_outdated = ies_outdated };
}
-/// Takes ownership of `air`, even on error.
-/// If any types referenced by `air` are unresolved, marks the codegen as failed.
-pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) Allocator.Error!void {
- const zcu = pt.zcu;
- const gpa = zcu.gpa;
- const ip = &zcu.intern_pool;
- const comp = zcu.comp;
-
- const func = zcu.funcInfo(func_index);
- const nav_index = func.owner_nav;
- const nav = ip.getNav(nav_index);
-
- const codegen_prog_node = zcu.codegen_prog_node.start(nav.fqn.toSlice(ip), 0);
- defer codegen_prog_node.end();
-
- if (!air.typesFullyResolved(zcu)) {
- // A type we depend on failed to resolve. This is a transitive failure.
- // Correcting this failure will involve changing a type this function
- // depends on, hence triggering re-analysis of this function, so this
- // interacts correctly with incremental compilation.
- return;
- }
-
- legalize: {
- try air.legalize(pt, @import("../codegen.zig").legalizeFeatures(pt, nav_index) orelse break :legalize);
- }
-
- var liveness = try Air.Liveness.analyze(zcu, air.*, ip);
- defer liveness.deinit(gpa);
-
- if (build_options.enable_debug_extensions and comp.verbose_air) {
- std.debug.print("# Begin Function AIR: {}:\n", .{nav.fqn.fmt(ip)});
- air.dump(pt, liveness);
- std.debug.print("# End Function AIR: {}\n\n", .{nav.fqn.fmt(ip)});
- }
-
- if (std.debug.runtime_safety) {
- var verify: Air.Liveness.Verify = .{
- .gpa = gpa,
- .zcu = zcu,
- .air = air.*,
- .liveness = liveness,
- .intern_pool = ip,
- };
- defer verify.deinit();
-
- verify.verify() catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- else => {
- try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
- gpa,
- zcu.navSrcLoc(nav_index),
- "invalid liveness: {s}",
- .{@errorName(err)},
- ));
- return;
- },
- };
- }
-
- if (comp.bin_file) |lf| {
- lf.updateFunc(pt, func_index, air.*, liveness) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
- error.Overflow, error.RelocationNotByteAligned => {
- try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
- gpa,
- zcu.navSrcLoc(nav_index),
- "unable to codegen: {s}",
- .{@errorName(err)},
- ));
- // Not a retryable failure.
- },
- };
- } else if (zcu.llvm_object) |llvm_object| {
- llvm_object.updateFunc(pt, func_index, air.*, liveness) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- };
- }
-}
-
pub fn semaMod(pt: Zcu.PerThread, mod: *Module) !void {
dev.check(.sema);
const file_index = pt.zcu.module_roots.get(mod).?.unwrap().?;
@@ -1867,7 +1790,7 @@ fn createFileRootStruct(
};
errdefer wip_ty.cancel(ip, pt.tid);
- wip_ty.setName(ip, try file.internFullyQualifiedName(pt));
+ wip_ty.setName(ip, try file.internFullyQualifiedName(pt), .none);
ip.namespacePtr(namespace_index).owner_type = wip_ty.index;
if (zcu.comp.incremental) {
@@ -1877,10 +1800,10 @@ fn createFileRootStruct(
try pt.scanNamespace(namespace_index, decls);
try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
codegen_type: {
- if (zcu.comp.config.use_llvm) break :codegen_type;
if (file.mod.?.strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
- try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
+ zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
}
zcu.setFileRootType(file_index, wip_ty.index);
if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
@@ -2574,7 +2497,7 @@ fn newEmbedFile(
cache: {
const whole = switch (zcu.comp.cache_use) {
.whole => |whole| whole,
- .incremental => break :cache,
+ .incremental, .none => break :cache,
};
const man = whole.cache_manifest orelse break :cache;
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
runtime_params_len;
var runtime_param_index: usize = 0;
- for (fn_info.param_body[0..src_params_len]) |inst| {
+ for (fn_info.param_body[0..src_params_len], 0..) |inst, zir_param_index| {
const gop = sema.inst_map.getOrPutAssumeCapacity(inst);
if (gop.found_existing) continue; // provided above by comptime arg
- const param_inst_info = sema.code.instructions.get(@intFromEnum(inst));
- const param_name: Zir.NullTerminatedString = switch (param_inst_info.tag) {
- .param_anytype => param_inst_info.data.str_tok.start,
- .param => sema.code.extraData(Zir.Inst.Param, param_inst_info.data.pl_tok.payload_index).data.name,
- else => unreachable,
- };
-
const param_ty = fn_ty_info.param_types.get(ip)[runtime_param_index];
runtime_param_index += 1;
@@ -3004,10 +2920,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
.tag = .arg,
.data = .{ .arg = .{
.ty = Air.internedToRef(param_ty),
- .name = if (inner_block.ownerModule().strip)
- .none
- else
- try sema.appendAirString(sema.code.nullTerminatedString(param_name)),
+ .zir_param_index = @intCast(zir_param_index),
} },
});
}
@@ -3189,7 +3102,9 @@ pub fn processExports(pt: Zcu.PerThread) !void {
// This export might already have been sent to the linker on a previous update, in which case we need to delete it.
// The linker export API should be modified to eliminate this call. #23616
if (zcu.comp.bin_file) |lf| {
- lf.deleteExport(exp.exported, exp.opts.name);
+ if (zcu.llvm_object == null) {
+ lf.deleteExport(exp.exported, exp.opts.name);
+ }
}
continue;
}
@@ -3213,8 +3128,10 @@ pub fn processExports(pt: Zcu.PerThread) !void {
// This export might already have been sent to the linker on a previous update, in which case we need to delete it.
// The linker export API should be modified to eliminate this loop. #23616
if (zcu.comp.bin_file) |lf| {
- for (exports) |exp| {
- lf.deleteExport(exp.exported, exp.opts.name);
+ if (zcu.llvm_object == null) {
+ for (exports) |exp| {
+ lf.deleteExport(exp.exported, exp.opts.name);
+ }
}
}
continue;
@@ -3309,46 +3226,49 @@ fn processExportsInner(
.uav => {},
}
- if (zcu.comp.bin_file) |lf| {
- try zcu.handleUpdateExports(export_indices, lf.updateExports(pt, exported, export_indices));
- } else if (zcu.llvm_object) |llvm_object| {
+ if (zcu.llvm_object) |llvm_object| {
try zcu.handleUpdateExports(export_indices, llvm_object.updateExports(pt, exported, export_indices));
+ } else if (zcu.comp.bin_file) |lf| {
+ try zcu.handleUpdateExports(export_indices, lf.updateExports(pt, exported, export_indices));
}
}
-pub fn populateTestFunctions(
- pt: Zcu.PerThread,
- main_progress_node: std.Progress.Node,
-) Allocator.Error!void {
+pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
+
+ // Our job is to correctly set the value of the `test_functions` declaration if it has been
+ // analyzed and sent to codegen, It usually will have been, because the test runner will
+ // reference it, and `std.builtin` shouldn't have type errors. However, if it hasn't been
+ // analyzed, we will just terminate early, since clearly the test runner hasn't referenced
+ // `test_functions` so there's no point populating it. More to the the point, we potentially
+ // *can't* populate it without doing some type resolution, and... let's try to leave Sema in
+ // the past here.
+
const builtin_mod = zcu.builtin_modules.get(zcu.root_mod.getBuiltinOptions(zcu.comp.config).hash()).?;
const builtin_file_index = zcu.module_roots.get(builtin_mod).?.unwrap().?;
- pt.ensureFileAnalyzed(builtin_file_index) catch |err| switch (err) {
- error.AnalysisFail => unreachable, // builtin module is generated so cannot be corrupt
- error.OutOfMemory => |e| return e,
- };
- const builtin_root_type = Type.fromInterned(zcu.fileRootType(builtin_file_index));
- const builtin_namespace = builtin_root_type.getNamespace(zcu).unwrap().?;
+ const builtin_root_type = zcu.fileRootType(builtin_file_index);
+ if (builtin_root_type == .none) return; // `@import("builtin")` never analyzed
+ const builtin_namespace = Type.fromInterned(builtin_root_type).getNamespace(zcu).unwrap().?;
+ // We know that the namespace has a `test_functions`...
const nav_index = zcu.namespacePtr(builtin_namespace).pub_decls.getKeyAdapted(
try ip.getOrPutString(gpa, pt.tid, "test_functions", .no_embedded_nulls),
Zcu.Namespace.NameAdapter{ .zcu = zcu },
).?;
+ // ...but it might not be populated, so let's check that!
+ if (zcu.failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or
+ zcu.transitive_failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or
+ ip.getNav(nav_index).status != .fully_resolved)
{
- // We have to call `ensureNavValUpToDate` here in case `builtin.test_functions`
- // was not referenced by start code.
- zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
- defer {
- zcu.sema_prog_node.end();
- zcu.sema_prog_node = std.Progress.Node.none;
- }
- pt.ensureNavValUpToDate(nav_index) catch |err| switch (err) {
- error.AnalysisFail => return,
- error.OutOfMemory => return error.OutOfMemory,
- };
+ // The value of `builtin.test_functions` was either never referenced, or failed analysis.
+ // Either way, we don't need to do anything.
+ return;
}
+ // Okay, `builtin.test_functions` is (potentially) referenced and valid. Our job now is to swap
+ // its placeholder `&.{}` value for the actual list of all test functions.
+
const test_fns_val = zcu.navValue(nav_index);
const test_fn_ty = test_fns_val.typeOf(zcu).slicePtrFieldType(zcu).childType(zcu);
@@ -3450,81 +3370,8 @@ pub fn populateTestFunctions(
} });
ip.mutateVarInit(test_fns_val.toIntern(), new_init);
}
- {
- zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0);
- defer {
- zcu.codegen_prog_node.end();
- zcu.codegen_prog_node = std.Progress.Node.none;
- }
-
- try pt.linkerUpdateNav(nav_index);
- }
-}
-
-pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{OutOfMemory}!void {
- const zcu = pt.zcu;
- const comp = zcu.comp;
- const gpa = zcu.gpa;
- const ip = &zcu.intern_pool;
-
- const nav = zcu.intern_pool.getNav(nav_index);
- const codegen_prog_node = zcu.codegen_prog_node.start(nav.fqn.toSlice(ip), 0);
- defer codegen_prog_node.end();
-
- if (!Air.valFullyResolved(zcu.navValue(nav_index), zcu)) {
- // The value of this nav failed to resolve. This is a transitive failure.
- // TODO: do we need to mark this failure anywhere? I don't think so, since compilation
- // will fail due to the type error anyway.
- } else if (comp.bin_file) |lf| {
- lf.updateNav(pt, nav_index) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
- error.Overflow, error.RelocationNotByteAligned => {
- try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
- gpa,
- zcu.navSrcLoc(nav_index),
- "unable to codegen: {s}",
- .{@errorName(err)},
- ));
- // Not a retryable failure.
- },
- };
- } else if (zcu.llvm_object) |llvm_object| {
- llvm_object.updateNav(pt, nav_index) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- };
- }
-}
-
-pub fn linkerUpdateContainerType(pt: Zcu.PerThread, ty: InternPool.Index) error{OutOfMemory}!void {
- const zcu = pt.zcu;
- const gpa = zcu.gpa;
- const comp = zcu.comp;
- const ip = &zcu.intern_pool;
-
- const codegen_prog_node = zcu.codegen_prog_node.start(Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), 0);
- defer codegen_prog_node.end();
-
- if (zcu.failed_types.fetchSwapRemove(ty)) |*entry| entry.value.deinit(gpa);
-
- if (!Air.typeFullyResolved(Type.fromInterned(ty), zcu)) {
- // This type failed to resolve. This is a transitive failure.
- return;
- }
-
- if (comp.bin_file) |lf| lf.updateContainerType(pt, ty) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.TypeFailureReported => assert(zcu.failed_types.contains(ty)),
- };
-}
-
-pub fn linkerUpdateLineNumber(pt: Zcu.PerThread, ti: InternPool.TrackedInst.Index) !void {
- if (pt.zcu.comp.bin_file) |lf| {
- lf.updateLineNumber(pt, ti) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- else => |e| log.err("update line number failed: {s}", .{@errorName(e)}),
- };
- }
+ // The linker thread is not running, so we actually need to dispatch this task directly.
+ @import("../link.zig").linkTestFunctionsNav(pt, nav_index);
}
/// 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!
const result = try pt.zcu.intern_pool.getExtern(pt.zcu.gpa, pt.tid, key);
if (result.new_nav.unwrap()) |nav| {
// This job depends on any resolve_type_fully jobs queued up before it.
- try pt.zcu.comp.queueJob(.{ .codegen_nav = nav });
+ pt.zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try pt.zcu.comp.queueJob(.{ .link_nav = nav });
if (pt.zcu.comp.debugIncremental()) try pt.zcu.incremental_debug_state.newNav(pt.zcu, nav);
}
return result.index;
@@ -4122,17 +3970,17 @@ fn recreateStructType(
};
errdefer wip_ty.cancel(ip, pt.tid);
- wip_ty.setName(ip, struct_obj.name);
+ wip_ty.setName(ip, struct_obj.name, struct_obj.name_nav);
try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = key.zir_index });
zcu.namespacePtr(struct_obj.namespace).owner_type = wip_ty.index;
// No need to re-scan the namespace -- `zirStructDecl` will ultimately do that if the type is still alive.
try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
codegen_type: {
- if (zcu.comp.config.use_llvm) break :codegen_type;
if (file.mod.?.strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
- try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
+ zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
}
if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
@@ -4215,17 +4063,17 @@ fn recreateUnionType(
};
errdefer wip_ty.cancel(ip, pt.tid);
- wip_ty.setName(ip, union_obj.name);
+ wip_ty.setName(ip, union_obj.name, union_obj.name_nav);
try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = key.zir_index });
zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;
// No need to re-scan the namespace -- `zirUnionDecl` will ultimately do that if the type is still alive.
try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
codegen_type: {
- if (zcu.comp.config.use_llvm) break :codegen_type;
if (file.mod.?.strip) break :codegen_type;
// This job depends on any resolve_type_fully jobs queued up before it.
- try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
+ zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
+ try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
}
if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
@@ -4325,7 +4173,7 @@ fn recreateEnumType(
var done = true;
errdefer if (!done) wip_ty.cancel(ip, pt.tid);
- wip_ty.setName(ip, enum_obj.name);
+ wip_ty.setName(ip, enum_obj.name, enum_obj.name_nav);
zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;
// 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
try info.deps.append(gpa, dependee);
}
}
+
+/// Performs code generation, which comes after `Sema` but before `link` in the pipeline.
+/// This part of the pipeline is self-contained/"pure", so can be run in parallel with most
+/// other code. This function is currently run either on the main thread, or on a separate
+/// codegen thread, depending on whether the backend supports `Zcu.Feature.separate_thread`.
+pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air, out: *@import("../link.zig").ZcuTask.LinkFunc.SharedMir) void {
+ const zcu = pt.zcu;
+ if (runCodegenInner(pt, func_index, air)) |mir| {
+ out.value = mir;
+ out.status.store(.ready, .release);
+ } else |err| switch (err) {
+ error.OutOfMemory => {
+ zcu.comp.setAllocFailure();
+ out.status.store(.failed, .monotonic);
+ },
+ error.CodegenFail => {
+ zcu.assertCodegenFailed(zcu.funcInfo(func_index).owner_nav);
+ out.status.store(.failed, .monotonic);
+ },
+ error.NoLinkFile => {
+ assert(zcu.comp.bin_file == null);
+ out.status.store(.failed, .monotonic);
+ },
+ error.BackendDoesNotProduceMir => {
+ const backend = target_util.zigBackend(zcu.root_mod.resolved_target.result, zcu.comp.config.use_llvm);
+ switch (backend) {
+ else => unreachable, // assertion failure
+ .stage2_spirv64,
+ .stage2_llvm,
+ => {},
+ }
+ out.status.store(.failed, .monotonic);
+ },
+ }
+ zcu.comp.link_task_queue.mirReady(zcu.comp, out);
+ if (zcu.pending_codegen_jobs.rmw(.Sub, 1, .monotonic) == 1) {
+ // Decremented to 0, so all done.
+ zcu.codegen_prog_node.end();
+ zcu.codegen_prog_node = .none;
+ }
+}
+fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) error{
+ OutOfMemory,
+ CodegenFail,
+ NoLinkFile,
+ BackendDoesNotProduceMir,
+}!codegen.AnyMir {
+ const zcu = pt.zcu;
+ const gpa = zcu.gpa;
+ const ip = &zcu.intern_pool;
+ const comp = zcu.comp;
+
+ const nav = zcu.funcInfo(func_index).owner_nav;
+ const fqn = ip.getNav(nav).fqn;
+
+ const codegen_prog_node = zcu.codegen_prog_node.start(fqn.toSlice(ip), 0);
+ defer codegen_prog_node.end();
+
+ if (codegen.legalizeFeatures(pt, nav)) |features| {
+ try air.legalize(pt, features);
+ }
+
+ var liveness: Air.Liveness = try .analyze(zcu, air.*, ip);
+ defer liveness.deinit(gpa);
+
+ if (build_options.enable_debug_extensions and comp.verbose_air) {
+ std.debug.lockStdErr();
+ defer std.debug.unlockStdErr();
+ const stderr = std.io.getStdErr().writer();
+ stderr.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)}) catch {};
+ air.write(stderr, pt, liveness);
+ stderr.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)}) catch {};
+ }
+
+ if (std.debug.runtime_safety) {
+ var verify: Air.Liveness.Verify = .{
+ .gpa = gpa,
+ .zcu = zcu,
+ .air = air.*,
+ .liveness = liveness,
+ .intern_pool = ip,
+ };
+ defer verify.deinit();
+
+ verify.verify() catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ else => return zcu.codegenFail(nav, "invalid liveness: {s}", .{@errorName(err)}),
+ };
+ }
+
+ // The LLVM backend is special, because we only need to do codegen. There is no equivalent to the
+ // "emit" step because LLVM does not support incremental linking. Our linker (LLD or self-hosted)
+ // will just see the ZCU object file which LLVM ultimately emits.
+ if (zcu.llvm_object) |llvm_object| {
+ assert(pt.tid == .main); // LLVM has a lot of shared state
+ try llvm_object.updateFunc(pt, func_index, air, &liveness);
+ return error.BackendDoesNotProduceMir;
+ }
+
+ const lf = comp.bin_file orelse return error.NoLinkFile;
+
+ // TODO: self-hosted codegen should always have a type of MIR; codegen should produce that MIR,
+ // and the linker should consume it. However, our SPIR-V backend is currently tightly coupled
+ // with our SPIR-V linker, so needs to work more like the LLVM backend. This should be fixed to
+ // unblock threaded codegen for SPIR-V.
+ if (lf.cast(.spirv)) |spirv_file| {
+ assert(pt.tid == .main); // SPIR-V has a lot of shared state
+ spirv_file.object.updateFunc(pt, func_index, air, &liveness) catch |err| {
+ switch (err) {
+ error.OutOfMemory => comp.link_diags.setAllocFailure(),
+ }
+ return error.CodegenFail;
+ };
+ return error.BackendDoesNotProduceMir;
+ }
+
+ return codegen.generateFunction(lf, pt, zcu.navSrcLoc(nav), func_index, air, &liveness) catch |err| switch (err) {
+ error.OutOfMemory,
+ error.CodegenFail,
+ => |e| return e,
+ error.Overflow,
+ error.RelocationNotByteAligned,
+ => return zcu.codegenFail(nav, "unable to codegen: {s}", .{@errorName(err)}),
+ };
+}
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig
index 00cceb0c67..4aaf6bf85c 100644
--- a/src/arch/aarch64/CodeGen.zig
+++ b/src/arch/aarch64/CodeGen.zig
@@ -49,7 +49,6 @@ pt: Zcu.PerThread,
air: Air,
liveness: Air.Liveness,
bin_file: *link.File,
-debug_output: link.File.DebugInfoOutput,
target: *const std.Target,
func_index: InternPool.Index,
owner_nav: InternPool.Nav.Index,
@@ -185,6 +184,9 @@ const DbgInfoReloc = struct {
}
fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
+ // TODO: Add a pseudo-instruction or something to defer this work until Emit.
+ // We aren't allowed to interact with linker state here.
+ if (true) return;
switch (function.debug_output) {
.dwarf => |dw| {
const loc: link.File.Dwarf.Loc = switch (reloc.mcv) {
@@ -213,6 +215,9 @@ const DbgInfoReloc = struct {
}
fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
+ // TODO: Add a pseudo-instruction or something to defer this work until Emit.
+ // We aren't allowed to interact with linker state here.
+ if (true) return;
switch (function.debug_output) {
.dwarf => |dwarf| {
const loc: link.File.Dwarf.Loc = switch (reloc.mcv) {
@@ -326,11 +331,9 @@ pub fn generate(
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
- code: *std.ArrayListUnmanaged(u8),
- debug_output: link.File.DebugInfoOutput,
-) CodeGenError!void {
+ air: *const Air,
+ liveness: *const Air.Liveness,
+) CodeGenError!Mir {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const func = zcu.funcInfo(func_index);
@@ -349,9 +352,8 @@ pub fn generate(
var function: Self = .{
.gpa = gpa,
.pt = pt,
- .air = air,
- .liveness = liveness,
- .debug_output = debug_output,
+ .air = air.*,
+ .liveness = liveness.*,
.target = target,
.bin_file = lf,
.func_index = func_index,
@@ -395,29 +397,13 @@ pub fn generate(
var mir: Mir = .{
.instructions = function.mir_instructions.toOwnedSlice(),
- .extra = try function.mir_extra.toOwnedSlice(gpa),
- };
- defer mir.deinit(gpa);
-
- var emit: Emit = .{
- .mir = mir,
- .bin_file = lf,
- .debug_output = debug_output,
- .target = target,
- .src_loc = src_loc,
- .code = code,
- .prev_di_pc = 0,
- .prev_di_line = func.lbrace_line,
- .prev_di_column = func.lbrace_column,
- .stack_size = function.max_end_stack,
+ .extra = &.{}, // fallible, so assign after errdefer
+ .max_end_stack = function.max_end_stack,
.saved_regs_stack_space = function.saved_regs_stack_space,
};
- defer emit.deinit();
-
- emit.emitMir() catch |err| switch (err) {
- error.EmitFail => return function.failMsg(emit.err_msg.?),
- else => |e| return e,
- };
+ errdefer mir.deinit(gpa);
+ mir.extra = try function.mir_extra.toOwnedSlice(gpa);
+ return mir;
}
fn 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 {
while (self.args[arg_index] == .none) arg_index += 1;
self.arg_index = arg_index + 1;
- const ty = self.typeOfIndex(inst);
- const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
- const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
- if (name != .none) try self.dbg_info_relocs.append(self.gpa, .{
- .tag = tag,
- .ty = ty,
- .name = name.toSlice(self.air),
- .mcv = self.args[arg_index],
- });
+ const zcu = self.pt.zcu;
+ const func_zir = zcu.funcInfo(self.func_index).zir_body_inst.resolveFull(&zcu.intern_pool).?;
+ const file = zcu.fileByIndex(func_zir.file);
+ if (!file.mod.?.strip) {
+ const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
+ const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
+ const ty = self.typeOfIndex(inst);
+ const zir = &file.zir.?;
+ const name = zir.nullTerminatedString(zir.getParamName(zir.getParamBody(func_zir.inst)[arg.zir_param_index]).?);
+ try self.dbg_info_relocs.append(self.gpa, .{
+ .tag = tag,
+ .ty = ty,
+ .name = name,
+ .mcv = self.args[arg_index],
+ });
+ }
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
return self.finishAir(inst, result, .{ .none, .none, .none });
diff --git a/src/arch/aarch64/Mir.zig b/src/arch/aarch64/Mir.zig
index edf05f625e..88089c8488 100644
--- a/src/arch/aarch64/Mir.zig
+++ b/src/arch/aarch64/Mir.zig
@@ -13,6 +13,14 @@ const assert = std.debug.assert;
const bits = @import("bits.zig");
const Register = bits.Register;
+const InternPool = @import("../../InternPool.zig");
+const Emit = @import("Emit.zig");
+const codegen = @import("../../codegen.zig");
+const link = @import("../../link.zig");
+const Zcu = @import("../../Zcu.zig");
+
+max_end_stack: u32,
+saved_regs_stack_space: u32,
instructions: std.MultiArrayList(Inst).Slice,
/// 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 {
mir.* = undefined;
}
+pub fn emit(
+ mir: Mir,
+ lf: *link.File,
+ pt: Zcu.PerThread,
+ src_loc: Zcu.LazySrcLoc,
+ func_index: InternPool.Index,
+ code: *std.ArrayListUnmanaged(u8),
+ debug_output: link.File.DebugInfoOutput,
+) codegen.CodeGenError!void {
+ const zcu = pt.zcu;
+ const func = zcu.funcInfo(func_index);
+ const nav = func.owner_nav;
+ const mod = zcu.navFileScope(nav).mod.?;
+ var e: Emit = .{
+ .mir = mir,
+ .bin_file = lf,
+ .debug_output = debug_output,
+ .target = &mod.resolved_target.result,
+ .src_loc = src_loc,
+ .code = code,
+ .prev_di_pc = 0,
+ .prev_di_line = func.lbrace_line,
+ .prev_di_column = func.lbrace_column,
+ .stack_size = mir.max_end_stack,
+ .saved_regs_stack_space = mir.saved_regs_stack_space,
+ };
+ defer e.deinit();
+ e.emitMir() catch |err| switch (err) {
+ error.EmitFail => return zcu.codegenFailMsg(nav, e.err_msg.?),
+ else => |e1| return e1,
+ };
+}
+
/// Returns the requested data, as well as the new index which is at the start of the
/// trailers for the object.
pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end: usize } {
diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig
index 421ba7d753..09304bf1de 100644
--- a/src/arch/arm/CodeGen.zig
+++ b/src/arch/arm/CodeGen.zig
@@ -50,7 +50,6 @@ pt: Zcu.PerThread,
air: Air,
liveness: Air.Liveness,
bin_file: *link.File,
-debug_output: link.File.DebugInfoOutput,
target: *const std.Target,
func_index: InternPool.Index,
err_msg: ?*ErrorMsg,
@@ -264,6 +263,9 @@ const DbgInfoReloc = struct {
}
fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
+ // TODO: Add a pseudo-instruction or something to defer this work until Emit.
+ // We aren't allowed to interact with linker state here.
+ if (true) return;
switch (function.debug_output) {
.dwarf => |dw| {
const loc: link.File.Dwarf.Loc = switch (reloc.mcv) {
@@ -292,6 +294,9 @@ const DbgInfoReloc = struct {
}
fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
+ // TODO: Add a pseudo-instruction or something to defer this work until Emit.
+ // We aren't allowed to interact with linker state here.
+ if (true) return;
switch (function.debug_output) {
.dwarf => |dw| {
const loc: link.File.Dwarf.Loc = switch (reloc.mcv) {
@@ -335,11 +340,9 @@ pub fn generate(
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
- code: *std.ArrayListUnmanaged(u8),
- debug_output: link.File.DebugInfoOutput,
-) CodeGenError!void {
+ air: *const Air,
+ liveness: *const Air.Liveness,
+) CodeGenError!Mir {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const func = zcu.funcInfo(func_index);
@@ -358,11 +361,10 @@ pub fn generate(
var function: Self = .{
.gpa = gpa,
.pt = pt,
- .air = air,
- .liveness = liveness,
+ .air = air.*,
+ .liveness = liveness.*,
.target = target,
.bin_file = lf,
- .debug_output = debug_output,
.func_index = func_index,
.err_msg = null,
.args = undefined, // populated after `resolveCallingConventionValues`
@@ -402,31 +404,15 @@ pub fn generate(
return function.fail("failed to generate debug info: {s}", .{@errorName(err)});
}
- var mir = Mir{
+ var mir: Mir = .{
.instructions = function.mir_instructions.toOwnedSlice(),
- .extra = try function.mir_extra.toOwnedSlice(gpa),
- };
- defer mir.deinit(gpa);
-
- var emit = Emit{
- .mir = mir,
- .bin_file = lf,
- .debug_output = debug_output,
- .target = target,
- .src_loc = src_loc,
- .code = code,
- .prev_di_pc = 0,
- .prev_di_line = func.lbrace_line,
- .prev_di_column = func.lbrace_column,
- .stack_size = function.max_end_stack,
+ .extra = &.{}, // fallible, so assign after errdefer
+ .max_end_stack = function.max_end_stack,
.saved_regs_stack_space = function.saved_regs_stack_space,
};
- defer emit.deinit();
-
- emit.emitMir() catch |err| switch (err) {
- error.EmitFail => return function.failMsg(emit.err_msg.?),
- else => |e| return e,
- };
+ errdefer mir.deinit(gpa);
+ mir.extra = try function.mir_extra.toOwnedSlice(gpa);
+ return mir;
}
fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
@@ -4205,16 +4191,22 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
while (self.args[arg_index] == .none) arg_index += 1;
self.arg_index = arg_index + 1;
- const ty = self.typeOfIndex(inst);
- const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
-
- const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
- if (name != .none) try self.dbg_info_relocs.append(self.gpa, .{
- .tag = tag,
- .ty = ty,
- .name = name.toSlice(self.air),
- .mcv = self.args[arg_index],
- });
+ const zcu = self.pt.zcu;
+ const func_zir = zcu.funcInfo(self.func_index).zir_body_inst.resolveFull(&zcu.intern_pool).?;
+ const file = zcu.fileByIndex(func_zir.file);
+ if (!file.mod.?.strip) {
+ const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
+ const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
+ const ty = self.typeOfIndex(inst);
+ const zir = &file.zir.?;
+ const name = zir.nullTerminatedString(zir.getParamName(zir.getParamBody(func_zir.inst)[arg.zir_param_index]).?);
+ try self.dbg_info_relocs.append(self.gpa, .{
+ .tag = tag,
+ .ty = ty,
+ .name = name,
+ .mcv = self.args[arg_index],
+ });
+ }
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
return self.finishAir(inst, result, .{ .none, .none, .none });
diff --git a/src/arch/arm/Mir.zig b/src/arch/arm/Mir.zig
index 5e651b7939..5b7585a2ca 100644
--- a/src/arch/arm/Mir.zig
+++ b/src/arch/arm/Mir.zig
@@ -13,6 +13,14 @@ const assert = std.debug.assert;
const bits = @import("bits.zig");
const Register = bits.Register;
+const InternPool = @import("../../InternPool.zig");
+const Emit = @import("Emit.zig");
+const codegen = @import("../../codegen.zig");
+const link = @import("../../link.zig");
+const Zcu = @import("../../Zcu.zig");
+
+max_end_stack: u32,
+saved_regs_stack_space: u32,
instructions: std.MultiArrayList(Inst).Slice,
/// 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 {
mir.* = undefined;
}
+pub fn emit(
+ mir: Mir,
+ lf: *link.File,
+ pt: Zcu.PerThread,
+ src_loc: Zcu.LazySrcLoc,
+ func_index: InternPool.Index,
+ code: *std.ArrayListUnmanaged(u8),
+ debug_output: link.File.DebugInfoOutput,
+) codegen.CodeGenError!void {
+ const zcu = pt.zcu;
+ const func = zcu.funcInfo(func_index);
+ const nav = func.owner_nav;
+ const mod = zcu.navFileScope(nav).mod.?;
+ var e: Emit = .{
+ .mir = mir,
+ .bin_file = lf,
+ .debug_output = debug_output,
+ .target = &mod.resolved_target.result,
+ .src_loc = src_loc,
+ .code = code,
+ .prev_di_pc = 0,
+ .prev_di_line = func.lbrace_line,
+ .prev_di_column = func.lbrace_column,
+ .stack_size = mir.max_end_stack,
+ .saved_regs_stack_space = mir.saved_regs_stack_space,
+ };
+ defer e.deinit();
+ e.emitMir() catch |err| switch (err) {
+ error.EmitFail => return zcu.codegenFailMsg(nav, e.err_msg.?),
+ else => |e1| return e1,
+ };
+}
+
/// Returns the requested data, as well as the new index which is at the start of the
/// trailers for the object.
pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end: usize } {
diff --git a/src/arch/powerpc/CodeGen.zig b/src/arch/powerpc/CodeGen.zig
index 0cfee67ebd..4964fe19f4 100644
--- a/src/arch/powerpc/CodeGen.zig
+++ b/src/arch/powerpc/CodeGen.zig
@@ -19,19 +19,15 @@ pub fn generate(
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
- code: *std.ArrayListUnmanaged(u8),
- debug_output: link.File.DebugInfoOutput,
-) codegen.CodeGenError!void {
+ air: *const Air,
+ liveness: *const Air.Liveness,
+) codegen.CodeGenError!noreturn {
_ = bin_file;
_ = pt;
_ = src_loc;
_ = func_index;
_ = air;
_ = liveness;
- _ = code;
- _ = debug_output;
unreachable;
}
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig
index 9fc51bd2d3..c82061a5dd 100644
--- a/src/arch/riscv64/CodeGen.zig
+++ b/src/arch/riscv64/CodeGen.zig
@@ -68,9 +68,9 @@ gpa: Allocator,
mod: *Package.Module,
target: *const std.Target,
-debug_output: link.File.DebugInfoOutput,
args: []MCValue,
ret_mcv: InstTracking,
+func_index: InternPool.Index,
fn_type: Type,
arg_index: usize,
src_loc: Zcu.LazySrcLoc,
@@ -746,13 +746,10 @@ pub fn generate(
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
- code: *std.ArrayListUnmanaged(u8),
- debug_output: link.File.DebugInfoOutput,
-) CodeGenError!void {
+ air: *const Air,
+ liveness: *const Air.Liveness,
+) CodeGenError!Mir {
const zcu = pt.zcu;
- const comp = zcu.comp;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
const func = zcu.funcInfo(func_index);
@@ -769,16 +766,16 @@ pub fn generate(
var function: Func = .{
.gpa = gpa,
- .air = air,
+ .air = air.*,
.pt = pt,
.mod = mod,
.bin_file = bin_file,
- .liveness = liveness,
+ .liveness = liveness.*,
.target = &mod.resolved_target.result,
- .debug_output = debug_output,
.owner = .{ .nav_index = func.owner_nav },
.args = undefined, // populated after `resolveCallingConventionValues`
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
+ .func_index = func_index,
.fn_type = fn_type,
.arg_index = 0,
.branch_stack = &branch_stack,
@@ -855,33 +852,8 @@ pub fn generate(
.instructions = function.mir_instructions.toOwnedSlice(),
.frame_locs = function.frame_locs.toOwnedSlice(),
};
- defer mir.deinit(gpa);
-
- var emit: Emit = .{
- .lower = .{
- .pt = pt,
- .allocator = gpa,
- .mir = mir,
- .cc = fn_info.cc,
- .src_loc = src_loc,
- .output_mode = comp.config.output_mode,
- .link_mode = comp.config.link_mode,
- .pic = mod.pic,
- },
- .bin_file = bin_file,
- .debug_output = debug_output,
- .code = code,
- .prev_di_pc = 0,
- .prev_di_line = func.lbrace_line,
- .prev_di_column = func.lbrace_column,
- };
- defer emit.deinit();
-
- emit.emitMir() catch |err| switch (err) {
- error.LowerFail, error.EmitFail => return function.failMsg(emit.lower.err_msg.?),
- error.InvalidInstruction => |e| return function.fail("emit MIR failed: {s} (Zig compiler bug)", .{@errorName(e)}),
- else => |e| return e,
- };
+ errdefer mir.deinit(gpa);
+ return mir;
}
pub fn generateLazy(
@@ -904,10 +876,10 @@ pub fn generateLazy(
.bin_file = bin_file,
.liveness = undefined,
.target = &mod.resolved_target.result,
- .debug_output = debug_output,
.owner = .{ .lazy_sym = lazy_sym },
.args = undefined, // populated after `resolveCallingConventionValues`
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
+ .func_index = undefined,
.fn_type = undefined,
.arg_index = 0,
.branch_stack = undefined,
@@ -3631,9 +3603,7 @@ fn airRuntimeNavPtr(func: *Func, inst: Air.Inst.Index) !void {
const tlv_sym_index = if (func.bin_file.cast(.elf)) |elf_file| sym: {
const zo = elf_file.zigObjectPtr().?;
if (nav.getExtern(ip)) |e| {
- const sym = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip));
- zo.symbol(sym).flags.is_extern_ptr = true;
- break :sym sym;
+ break :sym try elf_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip));
}
break :sym try zo.getOrCreateMetadataForNav(zcu, ty_nav.nav);
} 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 {
return func.fail("TODO implement codegen airFieldParentPtr", .{});
}
-fn genArgDbgInfo(func: *const Func, inst: Air.Inst.Index, mcv: MCValue) InnerError!void {
- const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
- const ty = arg.ty.toType();
- if (arg.name == .none) return;
+fn genArgDbgInfo(func: *const Func, name: []const u8, ty: Type, mcv: MCValue) InnerError!void {
+ assert(!func.mod.strip);
+ // TODO: Add a pseudo-instruction or something to defer this work until Emit.
+ // We aren't allowed to interact with linker state here.
+ if (true) return;
switch (func.debug_output) {
.dwarf => |dw| switch (mcv) {
.register => |reg| dw.genLocalDebugInfo(
.local_arg,
- arg.name.toSlice(func.air),
+ name,
ty,
.{ .reg = reg.dwarfNum() },
) 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
}
fn airArg(func: *Func, inst: Air.Inst.Index) InnerError!void {
+ const zcu = func.pt.zcu;
+
var arg_index = func.arg_index;
// we skip over args that have no bits
@@ -4793,7 +4766,14 @@ fn airArg(func: *Func, inst: Air.Inst.Index) InnerError!void {
try func.genCopy(arg_ty, dst_mcv, src_mcv);
- try func.genArgDbgInfo(inst, src_mcv);
+ const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
+ // can delete `func.func_index` if this logic is moved to emit
+ const func_zir = zcu.funcInfo(func.func_index).zir_body_inst.resolveFull(&zcu.intern_pool).?;
+ const file = zcu.fileByIndex(func_zir.file);
+ const zir = &file.zir.?;
+ const name = zir.nullTerminatedString(zir.getParamName(zir.getParamBody(func_zir.inst)[arg.zir_param_index]).?);
+
+ try func.genArgDbgInfo(name, arg_ty, src_mcv);
break :result dst_mcv;
};
@@ -5273,6 +5253,9 @@ fn genVarDbgInfo(
mcv: MCValue,
name: []const u8,
) !void {
+ // TODO: Add a pseudo-instruction or something to defer this work until Emit.
+ // We aren't allowed to interact with linker state here.
+ if (true) return;
switch (func.debug_output) {
.dwarf => |dwarf| {
const loc: link.File.Dwarf.Loc = switch (mcv) {
diff --git a/src/arch/riscv64/Emit.zig b/src/arch/riscv64/Emit.zig
index 095cfc278b..0561eb2019 100644
--- a/src/arch/riscv64/Emit.zig
+++ b/src/arch/riscv64/Emit.zig
@@ -50,8 +50,8 @@ pub fn emitMir(emit: *Emit) Error!void {
const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;
const sym = zo.symbol(symbol.sym_index);
- if (sym.flags.is_extern_ptr and emit.lower.pic) {
- return emit.fail("emit GOT relocation for symbol '{s}'", .{sym.name(elf_file)});
+ if (emit.lower.pic) {
+ return emit.fail("know when to emit GOT relocation for symbol '{s}'", .{sym.name(elf_file)});
}
const hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
diff --git a/src/arch/riscv64/Mir.zig b/src/arch/riscv64/Mir.zig
index 2ae62fd9b2..2ad75e4677 100644
--- a/src/arch/riscv64/Mir.zig
+++ b/src/arch/riscv64/Mir.zig
@@ -109,6 +109,48 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
mir.* = undefined;
}
+pub fn emit(
+ mir: Mir,
+ lf: *link.File,
+ pt: Zcu.PerThread,
+ src_loc: Zcu.LazySrcLoc,
+ func_index: InternPool.Index,
+ code: *std.ArrayListUnmanaged(u8),
+ debug_output: link.File.DebugInfoOutput,
+) codegen.CodeGenError!void {
+ const zcu = pt.zcu;
+ const comp = zcu.comp;
+ const gpa = comp.gpa;
+ const func = zcu.funcInfo(func_index);
+ const fn_info = zcu.typeToFunc(.fromInterned(func.ty)).?;
+ const nav = func.owner_nav;
+ const mod = zcu.navFileScope(nav).mod.?;
+ var e: Emit = .{
+ .lower = .{
+ .pt = pt,
+ .allocator = gpa,
+ .mir = mir,
+ .cc = fn_info.cc,
+ .src_loc = src_loc,
+ .output_mode = comp.config.output_mode,
+ .link_mode = comp.config.link_mode,
+ .pic = mod.pic,
+ },
+ .bin_file = lf,
+ .debug_output = debug_output,
+ .code = code,
+ .prev_di_pc = 0,
+ .prev_di_line = func.lbrace_line,
+ .prev_di_column = func.lbrace_column,
+ };
+ defer e.deinit();
+ e.emitMir() catch |err| switch (err) {
+ error.LowerFail, error.EmitFail => return zcu.codegenFailMsg(nav, e.lower.err_msg.?),
+ error.InvalidInstruction => return zcu.codegenFail(nav, "emit MIR failed: {s} (Zig compiler bug)", .{@errorName(err)}),
+ else => |err1| return err1,
+ };
+}
+
pub const FrameLoc = struct {
base: Register,
disp: i32,
@@ -202,3 +244,9 @@ const FrameIndex = bits.FrameIndex;
const FrameAddr = @import("CodeGen.zig").FrameAddr;
const IntegerBitSet = std.bit_set.IntegerBitSet;
const Mnemonic = @import("mnem.zig").Mnemonic;
+
+const InternPool = @import("../../InternPool.zig");
+const Emit = @import("Emit.zig");
+const codegen = @import("../../codegen.zig");
+const link = @import("../../link.zig");
+const Zcu = @import("../../Zcu.zig");
diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig
index ad9884dcdb..b35f45dd64 100644
--- a/src/arch/sparc64/CodeGen.zig
+++ b/src/arch/sparc64/CodeGen.zig
@@ -57,8 +57,6 @@ liveness: Air.Liveness,
bin_file: *link.File,
target: *const std.Target,
func_index: InternPool.Index,
-code: *std.ArrayListUnmanaged(u8),
-debug_output: link.File.DebugInfoOutput,
err_msg: ?*ErrorMsg,
args: []MCValue,
ret_mcv: MCValue,
@@ -268,11 +266,9 @@ pub fn generate(
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
- code: *std.ArrayListUnmanaged(u8),
- debug_output: link.File.DebugInfoOutput,
-) CodeGenError!void {
+ air: *const Air,
+ liveness: *const Air.Liveness,
+) CodeGenError!Mir {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const func = zcu.funcInfo(func_index);
@@ -291,13 +287,11 @@ pub fn generate(
var function: Self = .{
.gpa = gpa,
.pt = pt,
- .air = air,
- .liveness = liveness,
+ .air = air.*,
+ .liveness = liveness.*,
.target = target,
.bin_file = lf,
.func_index = func_index,
- .code = code,
- .debug_output = debug_output,
.err_msg = null,
.args = undefined, // populated after `resolveCallingConventionValues`
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
@@ -330,29 +324,13 @@ pub fn generate(
else => |e| return e,
};
- var mir = Mir{
+ var mir: Mir = .{
.instructions = function.mir_instructions.toOwnedSlice(),
- .extra = try function.mir_extra.toOwnedSlice(gpa),
- };
- defer mir.deinit(gpa);
-
- var emit: Emit = .{
- .mir = mir,
- .bin_file = lf,
- .debug_output = debug_output,
- .target = target,
- .src_loc = src_loc,
- .code = code,
- .prev_di_pc = 0,
- .prev_di_line = func.lbrace_line,
- .prev_di_column = func.lbrace_column,
- };
- defer emit.deinit();
-
- emit.emitMir() catch |err| switch (err) {
- error.EmitFail => return function.failMsg(emit.err_msg.?),
- else => |e| return e,
+ .extra = &.{}, // fallible, so populated after errdefer
};
+ errdefer mir.deinit(gpa);
+ mir.extra = try function.mir_extra.toOwnedSlice(gpa);
+ return mir;
}
fn gen(self: *Self) !void {
@@ -1017,23 +995,29 @@ fn airArg(self: *Self, inst: Air.Inst.Index) InnerError!void {
self.arg_index += 1;
const ty = self.typeOfIndex(inst);
-
- const arg = self.args[arg_index];
- const mcv = blk: {
- switch (arg) {
+ const mcv: MCValue = blk: {
+ switch (self.args[arg_index]) {
.stack_offset => |off| {
const abi_size = math.cast(u32, ty.abiSize(zcu)) orelse {
return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(pt)});
};
const offset = off + abi_size;
- break :blk MCValue{ .stack_offset = offset };
+ break :blk .{ .stack_offset = offset };
},
- else => break :blk arg,
+ else => |mcv| break :blk mcv,
}
};
- self.genArgDbgInfo(inst, mcv) catch |err|
- return self.fail("failed to generate debug info for parameter: {s}", .{@errorName(err)});
+ const func_zir = zcu.funcInfo(self.func_index).zir_body_inst.resolveFull(&zcu.intern_pool).?;
+ const file = zcu.fileByIndex(func_zir.file);
+ if (!file.mod.?.strip) {
+ const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
+ const zir = &file.zir.?;
+ const name = zir.nullTerminatedString(zir.getParamName(zir.getParamBody(func_zir.inst)[arg.zir_param_index]).?);
+
+ self.genArgDbgInfo(name, ty, mcv) catch |err|
+ return self.fail("failed to generate debug info for parameter: {s}", .{@errorName(err)});
+ }
if (self.liveness.isUnused(inst))
return self.finishAirBookkeeping();
@@ -3561,16 +3545,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Air.
self.finishAirBookkeeping();
}
-fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
- const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
- const ty = arg.ty.toType();
- if (arg.name == .none) return;
-
+fn genArgDbgInfo(self: Self, name: []const u8, ty: Type, mcv: MCValue) !void {
+ // TODO: Add a pseudo-instruction or something to defer this work until Emit.
+ // We aren't allowed to interact with linker state here.
+ if (true) return;
switch (self.debug_output) {
.dwarf => |dw| switch (mcv) {
.register => |reg| try dw.genLocalDebugInfo(
.local_arg,
- arg.name.toSlice(self.air),
+ name,
ty,
.{ .reg = reg.dwarfNum() },
),
diff --git a/src/arch/sparc64/Mir.zig b/src/arch/sparc64/Mir.zig
index e9086db7a5..842ac10fed 100644
--- a/src/arch/sparc64/Mir.zig
+++ b/src/arch/sparc64/Mir.zig
@@ -12,7 +12,11 @@ const assert = std.debug.assert;
const Mir = @This();
const bits = @import("bits.zig");
-const Air = @import("../../Air.zig");
+const InternPool = @import("../../InternPool.zig");
+const Emit = @import("Emit.zig");
+const codegen = @import("../../codegen.zig");
+const link = @import("../../link.zig");
+const Zcu = @import("../../Zcu.zig");
const Instruction = bits.Instruction;
const ASI = bits.Instruction.ASI;
@@ -370,6 +374,37 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
mir.* = undefined;
}
+pub fn emit(
+ mir: Mir,
+ lf: *link.File,
+ pt: Zcu.PerThread,
+ src_loc: Zcu.LazySrcLoc,
+ func_index: InternPool.Index,
+ code: *std.ArrayListUnmanaged(u8),
+ debug_output: link.File.DebugInfoOutput,
+) codegen.CodeGenError!void {
+ const zcu = pt.zcu;
+ const func = zcu.funcInfo(func_index);
+ const nav = func.owner_nav;
+ const mod = zcu.navFileScope(nav).mod.?;
+ var e: Emit = .{
+ .mir = mir,
+ .bin_file = lf,
+ .debug_output = debug_output,
+ .target = &mod.resolved_target.result,
+ .src_loc = src_loc,
+ .code = code,
+ .prev_di_pc = 0,
+ .prev_di_line = func.lbrace_line,
+ .prev_di_column = func.lbrace_column,
+ };
+ defer e.deinit();
+ e.emitMir() catch |err| switch (err) {
+ error.EmitFail => return zcu.codegenFailMsg(nav, e.err_msg.?),
+ else => |err1| return err1,
+ };
+}
+
/// Returns the requested data, as well as the new index which is at the start of the
/// trailers for the object.
pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end: usize } {
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index 264b1e732d..2936025a49 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -3,7 +3,6 @@ const builtin = @import("builtin");
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const testing = std.testing;
-const leb = std.leb;
const mem = std.mem;
const log = std.log.scoped(.codegen);
@@ -18,12 +17,10 @@ const Compilation = @import("../../Compilation.zig");
const link = @import("../../link.zig");
const Air = @import("../../Air.zig");
const Mir = @import("Mir.zig");
-const Emit = @import("Emit.zig");
const abi = @import("abi.zig");
const Alignment = InternPool.Alignment;
const errUnionPayloadOffset = codegen.errUnionPayloadOffset;
const errUnionErrorOffset = codegen.errUnionErrorOffset;
-const Wasm = link.File.Wasm;
const target_util = @import("../../target.zig");
const libcFloatPrefix = target_util.libcFloatPrefix;
@@ -78,17 +75,24 @@ simd_immediates: std.ArrayListUnmanaged([16]u8) = .empty,
/// The Target we're emitting (used to call intInfo)
target: *const std.Target,
ptr_size: enum { wasm32, wasm64 },
-wasm: *link.File.Wasm,
pt: Zcu.PerThread,
/// List of MIR Instructions
-mir_instructions: *std.MultiArrayList(Mir.Inst),
+mir_instructions: std.MultiArrayList(Mir.Inst),
/// Contains extra data for MIR
-mir_extra: *std.ArrayListUnmanaged(u32),
-start_mir_extra_off: u32,
-start_locals_off: u32,
+mir_extra: std.ArrayListUnmanaged(u32),
/// List of all locals' types generated throughout this declaration
/// used to emit locals count at start of 'code' section.
-locals: *std.ArrayListUnmanaged(std.wasm.Valtype),
+mir_locals: std.ArrayListUnmanaged(std.wasm.Valtype),
+/// Set of all UAVs referenced by this function. Key is the UAV value, value is the alignment.
+/// `.none` means naturally aligned. An explicit alignment is never less than the natural alignment.
+mir_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
+/// Set of all functions whose address this function has taken and which therefore might be called
+/// via a `call_indirect` function.
+mir_indirect_function_set: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
+/// Set of all function types used by this function. These must be interned by the linker.
+mir_func_tys: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
+/// The number of `error_name_table_ref` instructions emitted.
+error_name_table_ref_count: u32,
/// When a function is executing, we store the the current stack pointer's value within this local.
/// This value is then used to restore the stack pointer to the original value at the return of the function.
initial_stack_value: WValue = .none,
@@ -219,7 +223,7 @@ const WValue = union(enum) {
if (local_value < reserved + 2) return; // reserved locals may never be re-used. Also accounts for 2 stack locals.
const index = local_value - reserved;
- const valtype = gen.locals.items[gen.start_locals_off + index];
+ const valtype = gen.mir_locals.items[index];
switch (valtype) {
.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
.i64 => gen.free_locals_i64.append(gen.gpa, local_value) catch return,
@@ -716,6 +720,12 @@ pub fn deinit(cg: *CodeGen) void {
cg.free_locals_f32.deinit(gpa);
cg.free_locals_f64.deinit(gpa);
cg.free_locals_v128.deinit(gpa);
+ cg.mir_instructions.deinit(gpa);
+ cg.mir_extra.deinit(gpa);
+ cg.mir_locals.deinit(gpa);
+ cg.mir_uavs.deinit(gpa);
+ cg.mir_indirect_function_set.deinit(gpa);
+ cg.mir_func_tys.deinit(gpa);
cg.* = undefined;
}
@@ -876,7 +886,7 @@ fn addTag(cg: *CodeGen, tag: Mir.Inst.Tag) error{OutOfMemory}!void {
}
fn addExtended(cg: *CodeGen, opcode: std.wasm.MiscOpcode) error{OutOfMemory}!void {
- const extra_index = cg.extraLen();
+ const extra_index: u32 = @intCast(cg.mir_extra.items.len);
try cg.mir_extra.append(cg.gpa, @intFromEnum(opcode));
try cg.addInst(.{ .tag = .misc_prefix, .data = .{ .payload = extra_index } });
}
@@ -889,10 +899,6 @@ fn addLocal(cg: *CodeGen, tag: Mir.Inst.Tag, local: u32) error{OutOfMemory}!void
try cg.addInst(.{ .tag = tag, .data = .{ .local = local } });
}
-fn addFuncTy(cg: *CodeGen, tag: Mir.Inst.Tag, i: Wasm.FunctionType.Index) error{OutOfMemory}!void {
- try cg.addInst(.{ .tag = tag, .data = .{ .func_ty = i } });
-}
-
/// Accepts an unsigned 32bit integer rather than a signed integer to
/// prevent us from having to bitcast multiple times as most values
/// within codegen are represented as unsigned rather than signed.
@@ -911,7 +917,7 @@ fn addImm64(cg: *CodeGen, imm: u64) error{OutOfMemory}!void {
/// Accepts the index into the list of 128bit-immediates
fn addImm128(cg: *CodeGen, index: u32) error{OutOfMemory}!void {
const simd_values = cg.simd_immediates.items[index];
- const extra_index = cg.extraLen();
+ const extra_index: u32 = @intCast(cg.mir_extra.items.len);
// tag + 128bit value
try cg.mir_extra.ensureUnusedCapacity(cg.gpa, 5);
cg.mir_extra.appendAssumeCapacity(@intFromEnum(std.wasm.SimdOpcode.v128_const));
@@ -956,15 +962,13 @@ fn addExtra(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 {
/// Returns the index into `mir_extra`
fn addExtraAssumeCapacity(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 {
const fields = std.meta.fields(@TypeOf(extra));
- const result = cg.extraLen();
+ const result: u32 = @intCast(cg.mir_extra.items.len);
inline for (fields) |field| {
cg.mir_extra.appendAssumeCapacity(switch (field.type) {
u32 => @field(extra, field.name),
i32 => @bitCast(@field(extra, field.name)),
InternPool.Index,
InternPool.Nav.Index,
- Wasm.UavsObjIndex,
- Wasm.UavsExeIndex,
=> @intFromEnum(@field(extra, field.name)),
else => |field_type| @compileError("Unsupported field type " ++ @typeName(field_type)),
});
@@ -1034,18 +1038,12 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
.float32 => |val| try cg.addInst(.{ .tag = .f32_const, .data = .{ .float32 = val } }),
.float64 => |val| try cg.addFloat64(val),
.nav_ref => |nav_ref| {
- const wasm = cg.wasm;
- const comp = wasm.base.comp;
- const zcu = comp.zcu.?;
+ const zcu = cg.pt.zcu;
const ip = &zcu.intern_pool;
if (ip.getNav(nav_ref.nav_index).isFn(ip)) {
assert(nav_ref.offset == 0);
- const gop = try wasm.zcu_indirect_function_set.getOrPut(comp.gpa, nav_ref.nav_index);
- if (!gop.found_existing) gop.value_ptr.* = {};
- try cg.addInst(.{
- .tag = .func_ref,
- .data = .{ .indirect_function_table_index = @enumFromInt(gop.index) },
- });
+ try cg.mir_indirect_function_set.put(cg.gpa, nav_ref.nav_index, {});
+ try cg.addInst(.{ .tag = .func_ref, .data = .{ .nav_index = nav_ref.nav_index } });
} else if (nav_ref.offset == 0) {
try cg.addInst(.{ .tag = .nav_ref, .data = .{ .nav_index = nav_ref.nav_index } });
} else {
@@ -1061,41 +1059,37 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
}
},
.uav_ref => |uav| {
- const wasm = cg.wasm;
- const comp = wasm.base.comp;
- const is_obj = comp.config.output_mode == .Obj;
- const zcu = comp.zcu.?;
+ const zcu = cg.pt.zcu;
const ip = &zcu.intern_pool;
- if (ip.isFunctionType(ip.typeOf(uav.ip_index))) {
- assert(uav.offset == 0);
- const owner_nav = ip.toFunc(uav.ip_index).owner_nav;
- const gop = try wasm.zcu_indirect_function_set.getOrPut(comp.gpa, owner_nav);
- if (!gop.found_existing) gop.value_ptr.* = {};
- try cg.addInst(.{
- .tag = .func_ref,
- .data = .{ .indirect_function_table_index = @enumFromInt(gop.index) },
- });
- } else if (uav.offset == 0) {
+ assert(!ip.isFunctionType(ip.typeOf(uav.ip_index)));
+ const gop = try cg.mir_uavs.getOrPut(cg.gpa, uav.ip_index);
+ const this_align: Alignment = a: {
+ if (uav.orig_ptr_ty == .none) break :a .none;
+ const ptr_type = ip.indexToKey(uav.orig_ptr_ty).ptr_type;
+ const this_align = ptr_type.flags.alignment;
+ if (this_align == .none) break :a .none;
+ const abi_align = Type.fromInterned(ptr_type.child).abiAlignment(zcu);
+ if (this_align.compare(.lte, abi_align)) break :a .none;
+ break :a this_align;
+ };
+ if (!gop.found_existing or
+ gop.value_ptr.* == .none or
+ (this_align != .none and this_align.compare(.gt, gop.value_ptr.*)))
+ {
+ gop.value_ptr.* = this_align;
+ }
+ if (uav.offset == 0) {
try cg.addInst(.{
.tag = .uav_ref,
- .data = if (is_obj) .{
- .uav_obj = try wasm.refUavObj(uav.ip_index, uav.orig_ptr_ty),
- } else .{
- .uav_exe = try wasm.refUavExe(uav.ip_index, uav.orig_ptr_ty),
- },
+ .data = .{ .ip_index = uav.ip_index },
});
} else {
try cg.addInst(.{
.tag = .uav_ref_off,
- .data = .{
- .payload = if (is_obj) try cg.addExtra(Mir.UavRefOffObj{
- .uav_obj = try wasm.refUavObj(uav.ip_index, uav.orig_ptr_ty),
- .offset = uav.offset,
- }) else try cg.addExtra(Mir.UavRefOffExe{
- .uav_exe = try wasm.refUavExe(uav.ip_index, uav.orig_ptr_ty),
- .offset = uav.offset,
- }),
- },
+ .data = .{ .payload = try cg.addExtra(@as(Mir.UavRefOff, .{
+ .value = uav.ip_index,
+ .offset = uav.offset,
+ })) },
});
}
},
@@ -1157,106 +1151,12 @@ fn allocLocal(cg: *CodeGen, ty: Type) InnerError!WValue {
/// to use a zero-initialized local.
fn ensureAllocLocal(cg: *CodeGen, ty: Type) InnerError!WValue {
const zcu = cg.pt.zcu;
- try cg.locals.append(cg.gpa, typeToValtype(ty, zcu, cg.target));
+ try cg.mir_locals.append(cg.gpa, typeToValtype(ty, zcu, cg.target));
const initial_index = cg.local_index;
cg.local_index += 1;
return .{ .local = .{ .value = initial_index, .references = 1 } };
}
-pub const Function = extern struct {
- /// Index into `Wasm.mir_instructions`.
- mir_off: u32,
- /// This is unused except for as a safety slice bound and could be removed.
- mir_len: u32,
- /// Index into `Wasm.mir_extra`.
- mir_extra_off: u32,
- /// This is unused except for as a safety slice bound and could be removed.
- mir_extra_len: u32,
- locals_off: u32,
- locals_len: u32,
- prologue: Prologue,
-
- pub const Prologue = extern struct {
- flags: Flags,
- sp_local: u32,
- stack_size: u32,
- bottom_stack_local: u32,
-
- pub const Flags = packed struct(u32) {
- stack_alignment: Alignment,
- padding: u26 = 0,
- };
-
- pub const none: Prologue = .{
- .sp_local = 0,
- .flags = .{ .stack_alignment = .none },
- .stack_size = 0,
- .bottom_stack_local = 0,
- };
-
- pub fn isNone(p: *const Prologue) bool {
- return p.flags.stack_alignment != .none;
- }
- };
-
- pub fn lower(f: *Function, wasm: *Wasm, code: *std.ArrayListUnmanaged(u8)) Allocator.Error!void {
- const gpa = wasm.base.comp.gpa;
-
- // Write the locals in the prologue of the function body.
- const locals = wasm.all_zcu_locals.items[f.locals_off..][0..f.locals_len];
- try code.ensureUnusedCapacity(gpa, 5 + locals.len * 6 + 38);
-
- std.leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(locals.len))) catch unreachable;
- for (locals) |local| {
- std.leb.writeUleb128(code.fixedWriter(), @as(u32, 1)) catch unreachable;
- code.appendAssumeCapacity(@intFromEnum(local));
- }
-
- // Stack management section of function prologue.
- const stack_alignment = f.prologue.flags.stack_alignment;
- if (stack_alignment.toByteUnits()) |align_bytes| {
- const sp_global: Wasm.GlobalIndex = .stack_pointer;
- // load stack pointer
- code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_get));
- std.leb.writeULEB128(code.fixedWriter(), @intFromEnum(sp_global)) catch unreachable;
- // store stack pointer so we can restore it when we return from the function
- code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_tee));
- leb.writeUleb128(code.fixedWriter(), f.prologue.sp_local) catch unreachable;
- // get the total stack size
- const aligned_stack: i32 = @intCast(stack_alignment.forward(f.prologue.stack_size));
- code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));
- leb.writeIleb128(code.fixedWriter(), aligned_stack) catch unreachable;
- // subtract it from the current stack pointer
- code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_sub));
- // Get negative stack alignment
- const neg_stack_align = @as(i32, @intCast(align_bytes)) * -1;
- code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));
- leb.writeIleb128(code.fixedWriter(), neg_stack_align) catch unreachable;
- // Bitwise-and the value to get the new stack pointer to ensure the
- // pointers are aligned with the abi alignment.
- code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_and));
- // The bottom will be used to calculate all stack pointer offsets.
- code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_tee));
- leb.writeUleb128(code.fixedWriter(), f.prologue.bottom_stack_local) catch unreachable;
- // Store the current stack pointer value into the global stack pointer so other function calls will
- // start from this value instead and not overwrite the current stack.
- code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_set));
- std.leb.writeULEB128(code.fixedWriter(), @intFromEnum(sp_global)) catch unreachable;
- }
-
- var emit: Emit = .{
- .mir = .{
- .instruction_tags = wasm.mir_instructions.items(.tag)[f.mir_off..][0..f.mir_len],
- .instruction_datas = wasm.mir_instructions.items(.data)[f.mir_off..][0..f.mir_len],
- .extra = wasm.mir_extra.items[f.mir_extra_off..][0..f.mir_extra_len],
- },
- .wasm = wasm,
- .code = code,
- };
- try emit.lowerToCode();
- }
-};
-
pub const Error = error{
OutOfMemory,
/// Compiler was asked to operate on a number larger than supported.
@@ -1265,13 +1165,16 @@ pub const Error = error{
CodegenFail,
};
-pub fn function(
- wasm: *Wasm,
+pub fn generate(
+ bin_file: *link.File,
pt: Zcu.PerThread,
+ src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
-) Error!Function {
+ air: *const Air,
+ liveness: *const Air.Liveness,
+) Error!Mir {
+ _ = src_loc;
+ _ = bin_file;
const zcu = pt.zcu;
const gpa = zcu.gpa;
const cg = zcu.funcInfo(func_index);
@@ -1279,10 +1182,8 @@ pub fn function(
const target = &file_scope.mod.?.resolved_target.result;
const fn_ty = zcu.navValue(cg.owner_nav).typeOf(zcu);
const fn_info = zcu.typeToFunc(fn_ty).?;
- const ip = &zcu.intern_pool;
- const fn_ty_index = try wasm.internFunctionType(fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target);
- const returns = fn_ty_index.ptr(wasm).returns.slice(wasm);
- const any_returns = returns.len != 0;
+ const ret_ty: Type = .fromInterned(fn_info.return_type);
+ const any_returns = !firstParamSRet(fn_info.cc, ret_ty, zcu, target) and ret_ty.hasRuntimeBitsIgnoreComptime(zcu);
var cc_result = try resolveCallingConventionValues(zcu, fn_ty, target);
defer cc_result.deinit(gpa);
@@ -1290,8 +1191,8 @@ pub fn function(
var code_gen: CodeGen = .{
.gpa = gpa,
.pt = pt,
- .air = air,
- .liveness = liveness,
+ .air = air.*,
+ .liveness = liveness.*,
.owner_nav = cg.owner_nav,
.target = target,
.ptr_size = switch (target.cpu.arch) {
@@ -1299,31 +1200,33 @@ pub fn function(
.wasm64 => .wasm64,
else => unreachable,
},
- .wasm = wasm,
.func_index = func_index,
.args = cc_result.args,
.return_value = cc_result.return_value,
.local_index = cc_result.local_index,
- .mir_instructions = &wasm.mir_instructions,
- .mir_extra = &wasm.mir_extra,
- .locals = &wasm.all_zcu_locals,
- .start_mir_extra_off = @intCast(wasm.mir_extra.items.len),
- .start_locals_off = @intCast(wasm.all_zcu_locals.items.len),
+ .mir_instructions = .empty,
+ .mir_extra = .empty,
+ .mir_locals = .empty,
+ .mir_uavs = .empty,
+ .mir_indirect_function_set = .empty,
+ .mir_func_tys = .empty,
+ .error_name_table_ref_count = 0,
};
defer code_gen.deinit();
- return functionInner(&code_gen, any_returns) catch |err| switch (err) {
- error.CodegenFail => return error.CodegenFail,
+ try code_gen.mir_func_tys.putNoClobber(gpa, fn_ty.toIntern(), {});
+
+ return generateInner(&code_gen, any_returns) catch |err| switch (err) {
+ error.CodegenFail,
+ error.OutOfMemory,
+ error.Overflow,
+ => |e| return e,
else => |e| return code_gen.fail("failed to generate function: {s}", .{@errorName(e)}),
};
}
-fn functionInner(cg: *CodeGen, any_returns: bool) InnerError!Function {
- const wasm = cg.wasm;
+fn generateInner(cg: *CodeGen, any_returns: bool) InnerError!Mir {
const zcu = cg.pt.zcu;
-
- const start_mir_off: u32 = @intCast(wasm.mir_instructions.len);
-
try cg.branches.append(cg.gpa, .{});
// clean up outer branch
defer {
@@ -1347,20 +1250,25 @@ fn functionInner(cg: *CodeGen, any_returns: bool) InnerError!Function {
try cg.addTag(.end);
try cg.addTag(.dbg_epilogue_begin);
- return .{
- .mir_off = start_mir_off,
- .mir_len = @intCast(wasm.mir_instructions.len - start_mir_off),
- .mir_extra_off = cg.start_mir_extra_off,
- .mir_extra_len = cg.extraLen(),
- .locals_off = cg.start_locals_off,
- .locals_len = @intCast(wasm.all_zcu_locals.items.len - cg.start_locals_off),
+ var mir: Mir = .{
+ .instructions = cg.mir_instructions.toOwnedSlice(),
+ .extra = &.{}, // fallible so assigned after errdefer
+ .locals = &.{}, // fallible so assigned after errdefer
.prologue = if (cg.initial_stack_value == .none) .none else .{
.sp_local = cg.initial_stack_value.local.value,
.flags = .{ .stack_alignment = cg.stack_alignment },
.stack_size = cg.stack_size,
.bottom_stack_local = cg.bottom_stack_value.local.value,
},
+ .uavs = cg.mir_uavs.move(),
+ .indirect_function_set = cg.mir_indirect_function_set.move(),
+ .func_tys = cg.mir_func_tys.move(),
+ .error_name_table_ref_count = cg.error_name_table_ref_count,
};
+ errdefer mir.deinit(cg.gpa);
+ mir.extra = try cg.mir_extra.toOwnedSlice(cg.gpa);
+ mir.locals = try cg.mir_locals.toOwnedSlice(cg.gpa);
+ return mir;
}
const CallWValues = struct {
@@ -1969,7 +1877,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
.dbg_inline_block => cg.airDbgInlineBlock(inst),
.dbg_var_ptr => cg.airDbgVar(inst, .local_var, true),
.dbg_var_val => cg.airDbgVar(inst, .local_var, false),
- .dbg_arg_inline => cg.airDbgVar(inst, .local_arg, false),
+ .dbg_arg_inline => cg.airDbgVar(inst, .arg, false),
.call => cg.airCall(inst, .auto),
.call_always_tail => cg.airCall(inst, .always_tail),
@@ -2220,7 +2128,6 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
}
fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) InnerError!void {
- const wasm = cg.wasm;
if (modifier == .always_tail) return cg.fail("TODO implement tail calls for wasm", .{});
const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
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
const operand = try cg.resolveInst(pl_op.operand);
try cg.emitWValue(operand);
- const fn_type_index = try wasm.internFunctionType(fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), cg.target);
- try cg.addFuncTy(.call_indirect, fn_type_index);
+ try cg.mir_func_tys.put(cg.gpa, fn_ty.toIntern(), {});
+ try cg.addInst(.{
+ .tag = .call_indirect,
+ .data = .{ .ip_index = fn_ty.toIntern() },
+ });
}
const result_value = result_value: {
@@ -2449,7 +2359,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
try cg.emitWValue(lhs);
try cg.lowerToStack(rhs);
// TODO: Add helper functions for simd opcodes
- const extra_index = cg.extraLen();
+ const extra_index: u32 = @intCast(cg.mir_extra.items.len);
// stores as := opcode, offset, alignment (opcode::memarg)
try cg.mir_extra.appendSlice(cg.gpa, &[_]u32{
@intFromEnum(std.wasm.SimdOpcode.v128_store),
@@ -2574,7 +2484,7 @@ fn load(cg: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue
if (ty.zigTypeTag(zcu) == .vector) {
// TODO: Add helper functions for simd opcodes
- const extra_index = cg.extraLen();
+ const extra_index: u32 = @intCast(cg.mir_extra.items.len);
// stores as := opcode, offset, alignment (opcode::memarg)
try cg.mir_extra.appendSlice(cg.gpa, &[_]u32{
@intFromEnum(std.wasm.SimdOpcode.v128_load),
@@ -4971,7 +4881,7 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
try cg.emitWValue(array);
- const extra_index = cg.extraLen();
+ const extra_index: u32 = @intCast(cg.mir_extra.items.len);
try cg.mir_extra.appendSlice(cg.gpa, &operands);
try cg.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
@@ -5123,7 +5033,7 @@ fn airSplat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
else => break :blk, // Cannot make use of simd-instructions
};
try cg.emitWValue(operand);
- const extra_index: u32 = cg.extraLen();
+ const extra_index: u32 = @intCast(cg.mir_extra.items.len);
// stores as := opcode, offset, alignment (opcode::memarg)
try cg.mir_extra.appendSlice(cg.gpa, &[_]u32{
opcode,
@@ -5142,7 +5052,7 @@ fn airSplat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
else => break :blk, // Cannot make use of simd-instructions
};
try cg.emitWValue(operand);
- const extra_index = cg.extraLen();
+ const extra_index: u32 = @intCast(cg.mir_extra.items.len);
try cg.mir_extra.append(cg.gpa, opcode);
try cg.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
return cg.finishAir(inst, .stack, &.{ty_op.operand});
@@ -5246,7 +5156,7 @@ fn airShuffleTwo(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
}
try cg.emitWValue(operand_a);
try cg.emitWValue(operand_b);
- const extra_index = cg.extraLen();
+ const extra_index: u32 = @intCast(cg.mir_extra.items.len);
try cg.mir_extra.appendSlice(cg.gpa, &.{
@intFromEnum(std.wasm.SimdOpcode.i8x16_shuffle),
@bitCast(lane_map[0..4].*),
@@ -6016,9 +5926,8 @@ fn airErrorName(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const name_ty = Type.slice_const_u8_sentinel_0;
const abi_size = name_ty.abiSize(pt.zcu);
- cg.wasm.error_name_table_ref_count += 1;
-
// Lowers to a i32.const or i64.const with the error table memory address.
+ cg.error_name_table_ref_count += 1;
try cg.addTag(.error_name_table_ref);
try cg.emitWValue(operand);
switch (cg.ptr_size) {
@@ -6046,7 +5955,7 @@ fn airPtrSliceFieldPtr(cg: *CodeGen, inst: Air.Inst.Index, offset: u32) InnerErr
/// NOTE: Allocates place for result on virtual stack, when integer size > 64 bits
fn intZeroValue(cg: *CodeGen, ty: Type) InnerError!WValue {
- const zcu = cg.wasm.base.comp.zcu.?;
+ const zcu = cg.pt.zcu;
const int_info = ty.intInfo(zcu);
const wasm_bits = toWasmBits(int_info.bits) orelse {
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 {
fn airDbgVar(
cg: *CodeGen,
inst: Air.Inst.Index,
- local_tag: link.File.Dwarf.WipNav.LocalTag,
+ local_tag: link.File.Dwarf.WipNav.LocalVarTag,
is_ptr: bool,
) InnerError!void {
_ = is_ptr;
@@ -7673,7 +7582,3 @@ fn floatCmpIntrinsic(op: std.math.CompareOperator, bits: u16) Mir.Intrinsic {
},
};
}
-
-fn extraLen(cg: *const CodeGen) u32 {
- return @intCast(cg.mir_extra.items.len - cg.start_mir_extra_off);
-}
diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig
index 28159f3336..8024f2db9e 100644
--- a/src/arch/wasm/Emit.zig
+++ b/src/arch/wasm/Emit.zig
@@ -31,8 +31,8 @@ pub fn lowerToCode(emit: *Emit) Error!void {
const target = &comp.root_mod.resolved_target.result;
const is_wasm32 = target.cpu.arch == .wasm32;
- const tags = mir.instruction_tags;
- const datas = mir.instruction_datas;
+ const tags = mir.instructions.items(.tag);
+ const datas = mir.instructions.items(.data);
var inst: u32 = 0;
loop: switch (tags[inst]) {
@@ -50,18 +50,19 @@ pub fn lowerToCode(emit: *Emit) Error!void {
},
.uav_ref => {
if (is_obj) {
- try uavRefOffObj(wasm, code, .{ .uav_obj = datas[inst].uav_obj, .offset = 0 }, is_wasm32);
+ try uavRefObj(wasm, code, datas[inst].ip_index, 0, is_wasm32);
} else {
- try uavRefOffExe(wasm, code, .{ .uav_exe = datas[inst].uav_exe, .offset = 0 }, is_wasm32);
+ try uavRefExe(wasm, code, datas[inst].ip_index, 0, is_wasm32);
}
inst += 1;
continue :loop tags[inst];
},
.uav_ref_off => {
+ const extra = mir.extraData(Mir.UavRefOff, datas[inst].payload).data;
if (is_obj) {
- try uavRefOffObj(wasm, code, mir.extraData(Mir.UavRefOffObj, datas[inst].payload).data, is_wasm32);
+ try uavRefObj(wasm, code, extra.value, extra.offset, is_wasm32);
} else {
- try uavRefOffExe(wasm, code, mir.extraData(Mir.UavRefOffExe, datas[inst].payload).data, is_wasm32);
+ try uavRefExe(wasm, code, extra.value, extra.offset, is_wasm32);
}
inst += 1;
continue :loop tags[inst];
@@ -77,11 +78,14 @@ pub fn lowerToCode(emit: *Emit) Error!void {
continue :loop tags[inst];
},
.func_ref => {
+ const indirect_func_idx: Wasm.ZcuIndirectFunctionSetIndex = @enumFromInt(
+ wasm.zcu_indirect_function_set.getIndex(datas[inst].nav_index).?,
+ );
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));
if (is_obj) {
@panic("TODO");
} else {
- leb.writeUleb128(code.fixedWriter(), 1 + @intFromEnum(datas[inst].indirect_function_table_index)) catch unreachable;
+ leb.writeUleb128(code.fixedWriter(), 1 + @intFromEnum(indirect_func_idx)) catch unreachable;
}
inst += 1;
continue :loop tags[inst];
@@ -101,6 +105,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {
continue :loop tags[inst];
},
.error_name_table_ref => {
+ wasm.error_name_table_ref_count += 1;
try code.ensureUnusedCapacity(gpa, 11);
const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
code.appendAssumeCapacity(@intFromEnum(opcode));
@@ -176,7 +181,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {
.call_indirect => {
try code.ensureUnusedCapacity(gpa, 11);
- const func_ty_index = datas[inst].func_ty;
+ const fn_info = comp.zcu.?.typeToFunc(.fromInterned(datas[inst].ip_index)).?;
+ const func_ty_index = wasm.getExistingFunctionType(
+ fn_info.cc,
+ fn_info.param_types.get(&comp.zcu.?.intern_pool),
+ .fromInterned(fn_info.return_type),
+ target,
+ ).?;
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.call_indirect));
if (is_obj) {
try wasm.out_relocs.append(gpa, .{
@@ -912,7 +923,7 @@ fn encodeMemArg(code: *std.ArrayListUnmanaged(u8), mem_arg: Mir.MemArg) void {
leb.writeUleb128(code.fixedWriter(), mem_arg.offset) catch unreachable;
}
-fn uavRefOffObj(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.UavRefOffObj, is_wasm32: bool) !void {
+fn uavRefObj(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void {
const comp = wasm.base.comp;
const gpa = comp.gpa;
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
try wasm.out_relocs.append(gpa, .{
.offset = @intCast(code.items.len),
- .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(data.uav_obj.key(wasm).*) },
+ .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(value) },
.tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,
- .addend = data.offset,
+ .addend = offset,
});
code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);
}
-fn uavRefOffExe(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.UavRefOffExe, is_wasm32: bool) !void {
+fn uavRefExe(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void {
const comp = wasm.base.comp;
const gpa = comp.gpa;
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
try code.ensureUnusedCapacity(gpa, 11);
code.appendAssumeCapacity(@intFromEnum(opcode));
- const addr = wasm.uavAddr(data.uav_exe);
- leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable;
+ const addr = wasm.uavAddr(value);
+ leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + offset))) catch unreachable;
}
fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff, is_wasm32: bool) !void {
diff --git a/src/arch/wasm/Mir.zig b/src/arch/wasm/Mir.zig
index 5c8c558926..3aee13acd7 100644
--- a/src/arch/wasm/Mir.zig
+++ b/src/arch/wasm/Mir.zig
@@ -9,16 +9,53 @@
const Mir = @This();
const InternPool = @import("../../InternPool.zig");
const Wasm = @import("../../link/Wasm.zig");
+const Emit = @import("Emit.zig");
+const Alignment = InternPool.Alignment;
const builtin = @import("builtin");
const std = @import("std");
const assert = std.debug.assert;
+const leb = std.leb;
-instruction_tags: []const Inst.Tag,
-instruction_datas: []const Inst.Data,
+instructions: std.MultiArrayList(Inst).Slice,
/// A slice of indexes where the meaning of the data is determined by the
/// `Inst.Tag` value.
extra: []const u32,
+locals: []const std.wasm.Valtype,
+prologue: Prologue,
+
+/// Not directly used by `Emit`, but the linker needs this to merge it with a global set.
+/// Value is the explicit alignment if greater than natural alignment, `.none` otherwise.
+uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
+/// Not directly used by `Emit`, but the linker needs this to merge it with a global set.
+indirect_function_set: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
+/// Not directly used by `Emit`, but the linker needs this to ensure these types are interned.
+func_tys: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
+/// Not directly used by `Emit`, but the linker needs this to add it to its own refcount.
+error_name_table_ref_count: u32,
+
+pub const Prologue = extern struct {
+ flags: Flags,
+ sp_local: u32,
+ stack_size: u32,
+ bottom_stack_local: u32,
+
+ pub const Flags = packed struct(u32) {
+ stack_alignment: Alignment,
+ padding: u26 = 0,
+ };
+
+ pub const none: Prologue = .{
+ .sp_local = 0,
+ .flags = .{ .stack_alignment = .none },
+ .stack_size = 0,
+ .bottom_stack_local = 0,
+ };
+
+ pub fn isNone(p: *const Prologue) bool {
+ return p.flags.stack_alignment != .none;
+ }
+};
pub const Inst = struct {
/// The opcode that represents this instruction
@@ -80,7 +117,7 @@ pub const Inst = struct {
/// Lowers to an i32_const which is the index of the function in the
/// table section.
///
- /// Uses `indirect_function_table_index`.
+ /// Uses `nav_index`.
func_ref,
/// Inserts debug information about the current line and column
/// of the source code
@@ -123,7 +160,7 @@ pub const Inst = struct {
/// Calls a function pointer by its function signature
/// and index into the function table.
///
- /// Uses `func_ty`
+ /// Uses `ip_index`; the `InternPool.Index` is the function type.
call_indirect,
/// Calls a function by its index.
///
@@ -611,11 +648,7 @@ pub const Inst = struct {
ip_index: InternPool.Index,
nav_index: InternPool.Nav.Index,
- func_ty: Wasm.FunctionType.Index,
intrinsic: Intrinsic,
- uav_obj: Wasm.UavsObjIndex,
- uav_exe: Wasm.UavsExeIndex,
- indirect_function_table_index: Wasm.ZcuIndirectFunctionSetIndex,
comptime {
switch (builtin.mode) {
@@ -626,10 +659,66 @@ pub const Inst = struct {
};
};
-pub fn deinit(self: *Mir, gpa: std.mem.Allocator) void {
- self.instructions.deinit(gpa);
- gpa.free(self.extra);
- self.* = undefined;
+pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
+ mir.instructions.deinit(gpa);
+ gpa.free(mir.extra);
+ gpa.free(mir.locals);
+ mir.uavs.deinit(gpa);
+ mir.indirect_function_set.deinit(gpa);
+ mir.func_tys.deinit(gpa);
+ mir.* = undefined;
+}
+
+pub fn lower(mir: *const Mir, wasm: *Wasm, code: *std.ArrayListUnmanaged(u8)) std.mem.Allocator.Error!void {
+ const gpa = wasm.base.comp.gpa;
+
+ // Write the locals in the prologue of the function body.
+ try code.ensureUnusedCapacity(gpa, 5 + mir.locals.len * 6 + 38);
+
+ std.leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(mir.locals.len))) catch unreachable;
+ for (mir.locals) |local| {
+ std.leb.writeUleb128(code.fixedWriter(), @as(u32, 1)) catch unreachable;
+ code.appendAssumeCapacity(@intFromEnum(local));
+ }
+
+ // Stack management section of function prologue.
+ const stack_alignment = mir.prologue.flags.stack_alignment;
+ if (stack_alignment.toByteUnits()) |align_bytes| {
+ const sp_global: Wasm.GlobalIndex = .stack_pointer;
+ // load stack pointer
+ code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_get));
+ std.leb.writeULEB128(code.fixedWriter(), @intFromEnum(sp_global)) catch unreachable;
+ // store stack pointer so we can restore it when we return from the function
+ code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_tee));
+ leb.writeUleb128(code.fixedWriter(), mir.prologue.sp_local) catch unreachable;
+ // get the total stack size
+ const aligned_stack: i32 = @intCast(stack_alignment.forward(mir.prologue.stack_size));
+ code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));
+ leb.writeIleb128(code.fixedWriter(), aligned_stack) catch unreachable;
+ // subtract it from the current stack pointer
+ code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_sub));
+ // Get negative stack alignment
+ const neg_stack_align = @as(i32, @intCast(align_bytes)) * -1;
+ code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));
+ leb.writeIleb128(code.fixedWriter(), neg_stack_align) catch unreachable;
+ // Bitwise-and the value to get the new stack pointer to ensure the
+ // pointers are aligned with the abi alignment.
+ code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_and));
+ // The bottom will be used to calculate all stack pointer offsets.
+ code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_tee));
+ leb.writeUleb128(code.fixedWriter(), mir.prologue.bottom_stack_local) catch unreachable;
+ // Store the current stack pointer value into the global stack pointer so other function calls will
+ // start from this value instead and not overwrite the current stack.
+ code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_set));
+ std.leb.writeULEB128(code.fixedWriter(), @intFromEnum(sp_global)) catch unreachable;
+ }
+
+ var emit: Emit = .{
+ .mir = mir.*,
+ .wasm = wasm,
+ .code = code,
+ };
+ try emit.lowerToCode();
}
pub 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
Wasm.UavsObjIndex,
Wasm.UavsExeIndex,
InternPool.Nav.Index,
+ InternPool.Index,
=> @enumFromInt(self.extra[i]),
else => |field_type| @compileError("Unsupported field type " ++ @typeName(field_type)),
};
@@ -695,13 +785,8 @@ pub const MemArg = struct {
alignment: u32,
};
-pub const UavRefOffObj = struct {
- uav_obj: Wasm.UavsObjIndex,
- offset: i32,
-};
-
-pub const UavRefOffExe = struct {
- uav_exe: Wasm.UavsExeIndex,
+pub const UavRefOff = struct {
+ value: InternPool.Index,
offset: i32,
};
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index b38492d500..c652d48f3e 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -124,13 +124,13 @@ gpa: Allocator,
pt: Zcu.PerThread,
air: Air,
liveness: Air.Liveness,
-bin_file: *link.File,
-debug_output: link.File.DebugInfoOutput,
target: *const std.Target,
-owner: Owner,
+owner: union(enum) {
+ nav_index: InternPool.Nav.Index,
+ lazy_sym: link.File.LazySymbol,
+},
inline_func: InternPool.Index,
mod: *Module,
-arg_index: u32,
args: []MCValue,
va_info: union {
sysv: struct {
@@ -152,6 +152,14 @@ eflags_inst: ?Air.Inst.Index = null,
mir_instructions: std.MultiArrayList(Mir.Inst) = .empty,
/// MIR extra data
mir_extra: std.ArrayListUnmanaged(u32) = .empty,
+mir_string_bytes: std.ArrayListUnmanaged(u8) = .empty,
+mir_strings: std.HashMapUnmanaged(
+ u32,
+ void,
+ std.hash_map.StringIndexContext,
+ std.hash_map.default_max_load_percentage,
+) = .empty,
+mir_locals: std.ArrayListUnmanaged(Mir.Local) = .empty,
mir_table: std.ArrayListUnmanaged(Mir.Inst.Index) = .empty,
/// The value is an offset into the `Function` `code` from the beginning.
@@ -194,41 +202,6 @@ loop_switches: std.AutoHashMapUnmanaged(Air.Inst.Index, struct {
next_temp_index: Temp.Index = @enumFromInt(0),
temp_type: [Temp.Index.max]Type = undefined,
-const Owner = union(enum) {
- nav_index: InternPool.Nav.Index,
- lazy_sym: link.File.LazySymbol,
-
- fn getSymbolIndex(owner: Owner, ctx: *CodeGen) !u32 {
- const pt = ctx.pt;
- switch (owner) {
- .nav_index => |nav_index| if (ctx.bin_file.cast(.elf)) |elf_file| {
- return elf_file.zigObjectPtr().?.getOrCreateMetadataForNav(pt.zcu, nav_index);
- } else if (ctx.bin_file.cast(.macho)) |macho_file| {
- return macho_file.getZigObject().?.getOrCreateMetadataForNav(macho_file, nav_index);
- } else if (ctx.bin_file.cast(.coff)) |coff_file| {
- const atom = try coff_file.getOrCreateAtomForNav(nav_index);
- return coff_file.getAtom(atom).getSymbolIndex().?;
- } else if (ctx.bin_file.cast(.plan9)) |p9_file| {
- return p9_file.seeNav(pt, nav_index);
- } else unreachable,
- .lazy_sym => |lazy_sym| if (ctx.bin_file.cast(.elf)) |elf_file| {
- return elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
- ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
- } else if (ctx.bin_file.cast(.macho)) |macho_file| {
- return macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym) catch |err|
- ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
- } else if (ctx.bin_file.cast(.coff)) |coff_file| {
- const atom = coff_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
- return ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
- return coff_file.getAtom(atom).getSymbolIndex().?;
- } else if (ctx.bin_file.cast(.plan9)) |p9_file| {
- return p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
- return ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
- } else unreachable,
- }
- }
-};
-
const MaskInfo = packed struct {
kind: enum(u1) { sign, all },
inverted: bool = false,
@@ -269,37 +242,22 @@ pub const MCValue = union(enum) {
/// The value is in memory at a hard-coded address.
/// If the type is a pointer, it means the pointer address is stored at this memory location.
memory: u64,
- /// The value is in memory at an address not-yet-allocated by the linker.
- /// This traditionally corresponds to a relocation emitted in a relocatable object file.
- load_symbol: bits.SymbolOffset,
- /// The address of the memory location not-yet-allocated by the linker.
- lea_symbol: bits.SymbolOffset,
- /// The value is in memory at an address not-yet-allocated by the linker.
- /// This must use a non-got pc-relative relocation.
- load_pcrel: bits.SymbolOffset,
- /// The address of the memory location not-yet-allocated by the linker.
- /// This must use a non-got pc-relative relocation.
- lea_pcrel: bits.SymbolOffset,
/// The value is in memory at a constant offset from the address in a register.
indirect: bits.RegisterOffset,
- /// The value is in memory.
- /// Payload is a symbol index.
- load_direct: u32,
- /// The value is a pointer to a value in memory.
- /// Payload is a symbol index.
- lea_direct: u32,
- /// The value is in memory referenced indirectly via GOT.
- /// Payload is a symbol index.
- load_got: u32,
- /// The value is a pointer to a value referenced indirectly via GOT.
- /// Payload is a symbol index.
- lea_got: u32,
/// The value stored at an offset from a frame index
/// Payload is a frame address.
load_frame: bits.FrameAddr,
/// The address of an offset from a frame index
/// Payload is a frame address.
lea_frame: bits.FrameAddr,
+ load_nav: InternPool.Nav.Index,
+ lea_nav: InternPool.Nav.Index,
+ load_uav: InternPool.Key.Ptr.BaseAddr.Uav,
+ lea_uav: InternPool.Key.Ptr.BaseAddr.Uav,
+ load_lazy_sym: link.File.LazySymbol,
+ lea_lazy_sym: link.File.LazySymbol,
+ load_extern_func: Mir.NullTerminatedString,
+ lea_extern_func: Mir.NullTerminatedString,
/// Supports integer_per_element abi
elementwise_args: packed struct { regs: u3, frame_off: i29, frame_index: FrameIndex },
/// This indicates that we have already allocated a frame index for this instruction,
@@ -319,11 +277,14 @@ pub const MCValue = union(enum) {
.register_mask,
.eflags,
.register_overflow,
- .lea_symbol,
- .lea_pcrel,
- .lea_direct,
- .lea_got,
.lea_frame,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .lea_extern_func,
+ .load_extern_func,
.elementwise_args,
.reserved_frame,
.air_ref,
@@ -333,11 +294,8 @@ pub const MCValue = union(enum) {
.register_triple,
.register_quadruple,
.memory,
- .load_symbol,
- .load_pcrel,
- .load_got,
- .load_direct,
.indirect,
+ .load_nav,
=> true,
.load_frame => |frame_addr| !frame_addr.index.isNamed(),
};
@@ -353,7 +311,14 @@ pub const MCValue = union(enum) {
fn isMemory(mcv: MCValue) bool {
return switch (mcv) {
- .memory, .indirect, .load_frame, .load_symbol => true,
+ .memory,
+ .indirect,
+ .load_frame,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
+ => true,
else => false,
};
}
@@ -423,7 +388,7 @@ pub const MCValue = union(enum) {
fn address(mcv: MCValue) MCValue {
return switch (mcv) {
- .none,
+ .none => .none,
.unreach,
.dead,
.undef,
@@ -436,11 +401,11 @@ pub const MCValue = union(enum) {
.register_offset,
.register_overflow,
.register_mask,
- .lea_symbol,
- .lea_pcrel,
- .lea_direct,
- .lea_got,
.lea_frame,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
.elementwise_args,
.reserved_frame,
.air_ref,
@@ -450,17 +415,17 @@ pub const MCValue = union(enum) {
0 => .{ .register = reg_off.reg },
else => .{ .register_offset = reg_off },
},
- .load_direct => |sym_index| .{ .lea_direct = sym_index },
- .load_got => |sym_index| .{ .lea_got = sym_index },
.load_frame => |frame_addr| .{ .lea_frame = frame_addr },
- .load_symbol => |sym_off| .{ .lea_symbol = sym_off },
- .load_pcrel => |sym_off| .{ .lea_pcrel = sym_off },
+ .load_nav => |nav| .{ .lea_nav = nav },
+ .load_uav => |uav| .{ .lea_uav = uav },
+ .load_lazy_sym => |lazy_sym| .{ .lea_lazy_sym = lazy_sym },
+ .load_extern_func => |extern_func| .{ .lea_extern_func = extern_func },
};
}
fn deref(mcv: MCValue) MCValue {
return switch (mcv) {
- .none,
+ .none => .none,
.unreach,
.dead,
.undef,
@@ -472,11 +437,11 @@ pub const MCValue = union(enum) {
.register_mask,
.memory,
.indirect,
- .load_direct,
- .load_got,
.load_frame,
- .load_symbol,
- .load_pcrel,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
.elementwise_args,
.reserved_frame,
.air_ref,
@@ -484,17 +449,17 @@ pub const MCValue = union(enum) {
.immediate => |addr| .{ .memory = addr },
.register => |reg| .{ .indirect = .{ .reg = reg } },
.register_offset => |reg_off| .{ .indirect = reg_off },
- .lea_direct => |sym_index| .{ .load_direct = sym_index },
- .lea_got => |sym_index| .{ .load_got = sym_index },
.lea_frame => |frame_addr| .{ .load_frame = frame_addr },
- .lea_symbol => |sym_index| .{ .load_symbol = sym_index },
- .lea_pcrel => |sym_index| .{ .load_pcrel = sym_index },
+ .lea_nav => |nav| .{ .load_nav = nav },
+ .lea_uav => |uav| .{ .load_uav = uav },
+ .lea_lazy_sym => |lazy_sym| .{ .load_lazy_sym = lazy_sym },
+ .lea_extern_func => |extern_func| .{ .load_extern_func = extern_func },
};
}
fn offset(mcv: MCValue, off: i32) MCValue {
return switch (mcv) {
- .none,
+ .none => .none,
.unreach,
.dead,
.undef,
@@ -510,15 +475,15 @@ pub const MCValue = union(enum) {
.register_mask,
.memory,
.indirect,
- .load_direct,
- .lea_direct,
- .load_got,
- .lea_got,
.load_frame,
- .load_symbol,
- .lea_symbol,
- .load_pcrel,
- .lea_pcrel,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .load_extern_func,
+ .lea_extern_func,
=> switch (off) {
0 => mcv,
else => unreachable, // not offsettable
@@ -536,7 +501,7 @@ pub const MCValue = union(enum) {
fn mem(mcv: MCValue, function: *CodeGen, mod_rm: Memory.Mod.Rm) !Memory {
return switch (mcv) {
- .none,
+ .none => .{ .mod = .{ .rm = mod_rm } },
.unreach,
.dead,
.undef,
@@ -549,15 +514,13 @@ pub const MCValue = union(enum) {
.register_offset,
.register_overflow,
.register_mask,
- .load_direct,
- .lea_direct,
- .load_got,
- .lea_got,
.lea_frame,
.elementwise_args,
.reserved_frame,
- .lea_symbol,
- .lea_pcrel,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
=> unreachable,
.memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| .{
.base = .{ .reg = .ds },
@@ -586,30 +549,10 @@ pub const MCValue = union(enum) {
.disp = frame_addr.off + mod_rm.disp,
} },
},
- .load_symbol => |sym_off| {
- assert(sym_off.off == 0);
- return .{
- .base = .{ .reloc = sym_off.sym_index },
- .mod = .{ .rm = .{
- .size = mod_rm.size,
- .index = mod_rm.index,
- .scale = mod_rm.scale,
- .disp = sym_off.off + mod_rm.disp,
- } },
- };
- },
- .load_pcrel => |sym_off| {
- assert(sym_off.off == 0);
- return .{
- .base = .{ .pcrel = sym_off.sym_index },
- .mod = .{ .rm = .{
- .size = mod_rm.size,
- .index = mod_rm.index,
- .scale = mod_rm.scale,
- .disp = sym_off.off + mod_rm.disp,
- } },
- };
- },
+ .load_nav => |nav| .{ .base = .{ .nav = nav }, .mod = .{ .rm = mod_rm } },
+ .load_uav => |uav| .{ .base = .{ .uav = uav }, .mod = .{ .rm = mod_rm } },
+ .load_lazy_sym => |lazy_sym| .{ .base = .{ .lazy_sym = lazy_sym }, .mod = .{ .rm = mod_rm } },
+ .load_extern_func => |extern_func| .{ .base = .{ .extern_func = extern_func }, .mod = .{ .rm = mod_rm } },
.air_ref => |ref| (try function.resolveInst(ref)).mem(function, mod_rm),
};
}
@@ -643,20 +586,20 @@ pub const MCValue = union(enum) {
@as(u8, if (pl.info.inverted) '!' else ' '),
@tagName(pl.reg),
}),
- .load_symbol => |pl| try writer.print("[sym:{} + 0x{x}]", .{ pl.sym_index, pl.off }),
- .lea_symbol => |pl| try writer.print("sym:{} + 0x{x}", .{ pl.sym_index, pl.off }),
- .load_pcrel => |pl| try writer.print("[sym@pcrel:{} + 0x{x}]", .{ pl.sym_index, pl.off }),
- .lea_pcrel => |pl| try writer.print("sym@pcrel:{} + 0x{x}", .{ pl.sym_index, pl.off }),
.indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
- .load_direct => |pl| try writer.print("[direct:{d}]", .{pl}),
- .lea_direct => |pl| try writer.print("direct:{d}", .{pl}),
- .load_got => |pl| try writer.print("[got:{d}]", .{pl}),
- .lea_got => |pl| try writer.print("got:{d}", .{pl}),
.load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),
+ .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),
+ .load_nav => |pl| try writer.print("[nav:{d}]", .{@intFromEnum(pl)}),
+ .lea_nav => |pl| try writer.print("nav:{d}", .{@intFromEnum(pl)}),
+ .load_uav => |pl| try writer.print("[uav:{d}]", .{@intFromEnum(pl.val)}),
+ .lea_uav => |pl| try writer.print("uav:{d}", .{@intFromEnum(pl.val)}),
+ .load_lazy_sym => |pl| try writer.print("[lazy:{s}:{d}]", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
+ .lea_lazy_sym => |pl| try writer.print("lazy:{s}:{d}", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
+ .load_extern_func => |pl| try writer.print("[extern:{d}]", .{@intFromEnum(pl)}),
+ .lea_extern_func => |pl| try writer.print("extern:{d}", .{@intFromEnum(pl)}),
.elementwise_args => |pl| try writer.print("elementwise:{d}:[{} + 0x{x}]", .{
pl.regs, pl.frame_index, pl.frame_off,
}),
- .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),
.reserved_frame => |pl| try writer.print("(dead:{})", .{pl}),
.air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}),
}
@@ -676,16 +619,16 @@ const InstTracking = struct {
.undef,
.immediate,
.memory,
- .load_direct,
- .lea_direct,
- .load_got,
- .lea_got,
.load_frame,
.lea_frame,
- .load_symbol,
- .lea_symbol,
- .load_pcrel,
- .lea_pcrel,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .load_extern_func,
+ .lea_extern_func,
=> result,
.dead,
.elementwise_args,
@@ -779,15 +722,15 @@ const InstTracking = struct {
.undef,
.immediate,
.memory,
- .load_direct,
- .lea_direct,
- .load_got,
- .lea_got,
.lea_frame,
- .load_symbol,
- .lea_symbol,
- .load_pcrel,
- .lea_pcrel,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .load_extern_func,
+ .lea_extern_func,
=> assert(std.meta.eql(self.long, target.long)),
.dead,
.eflags,
@@ -972,31 +915,28 @@ pub fn generate(
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
- code: *std.ArrayListUnmanaged(u8),
- debug_output: link.File.DebugInfoOutput,
-) codegen.CodeGenError!void {
+ air: *const Air,
+ liveness: *const Air.Liveness,
+) codegen.CodeGenError!Mir {
+ _ = bin_file;
const zcu = pt.zcu;
- const comp = zcu.comp;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
const func = zcu.funcInfo(func_index);
+ const func_zir = func.zir_body_inst.resolveFull(ip).?;
+ const file = zcu.fileByIndex(func_zir.file);
const fn_type: Type = .fromInterned(func.ty);
- const mod = zcu.navFileScope(func.owner_nav).mod.?;
+ const mod = file.mod.?;
var function: CodeGen = .{
.gpa = gpa,
.pt = pt,
- .air = air,
- .liveness = liveness,
+ .air = air.*,
+ .liveness = liveness.*,
.target = &mod.resolved_target.result,
.mod = mod,
- .bin_file = bin_file,
- .debug_output = debug_output,
.owner = .{ .nav_index = func.owner_nav },
.inline_func = func_index,
- .arg_index = undefined,
.args = undefined, // populated after `resolveCallingConventionValues`
.va_info = undefined, // populated after `resolveCallingConventionValues`
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
@@ -1016,6 +956,9 @@ pub fn generate(
function.inst_tracking.deinit(gpa);
function.epilogue_relocs.deinit(gpa);
function.mir_instructions.deinit(gpa);
+ function.mir_string_bytes.deinit(gpa);
+ function.mir_strings.deinit(gpa);
+ function.mir_locals.deinit(gpa);
function.mir_extra.deinit(gpa);
function.mir_table.deinit(gpa);
}
@@ -1083,14 +1026,14 @@ pub fn generate(
);
}
- function.gen() catch |err| switch (err) {
+ function.gen(&file.zir.?, func_zir.inst, func.comptime_args, call_info.air_arg_count) catch |err| switch (err) {
error.CodegenFail => return error.CodegenFail,
error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
else => |e| return e,
};
// Drop them off at the rbrace.
- if (debug_output != .none) _ = try function.addInst(.{
+ if (!mod.strip) _ = try function.addInst(.{
.tag = .pseudo,
.ops = .pseudo_dbg_line_line_column,
.data = .{ .line_column = .{
@@ -1100,48 +1043,31 @@ pub fn generate(
});
var mir: Mir = .{
- .instructions = function.mir_instructions.toOwnedSlice(),
- .extra = try function.mir_extra.toOwnedSlice(gpa),
- .table = try function.mir_table.toOwnedSlice(gpa),
- .frame_locs = function.frame_locs.toOwnedSlice(),
+ .instructions = .empty,
+ .extra = &.{},
+ .string_bytes = &.{},
+ .locals = &.{},
+ .table = &.{},
+ .frame_locs = .empty,
};
- defer mir.deinit(gpa);
-
- var emit: Emit = .{
- .air = function.air,
- .lower = .{
- .bin_file = bin_file,
- .target = function.target,
- .allocator = gpa,
- .mir = mir,
- .cc = fn_info.cc,
- .src_loc = src_loc,
- .output_mode = comp.config.output_mode,
- .link_mode = comp.config.link_mode,
- .pic = mod.pic,
- },
- .atom_index = function.owner.getSymbolIndex(&function) catch |err| switch (err) {
- error.CodegenFail => return error.CodegenFail,
- else => |e| return e,
- },
- .debug_output = debug_output,
- .code = code,
- .prev_di_loc = .{
- .line = func.lbrace_line,
- .column = func.lbrace_column,
- .is_stmt = switch (debug_output) {
- .dwarf => |dwarf| dwarf.dwarf.debug_line.header.default_is_stmt,
- .plan9 => undefined,
- .none => undefined,
- },
- },
- .prev_di_pc = 0,
- };
- emit.emitMir() catch |err| switch (err) {
- error.LowerFail, error.EmitFail => return function.failMsg(emit.lower.err_msg.?),
+ errdefer mir.deinit(gpa);
+ mir.instructions = function.mir_instructions.toOwnedSlice();
+ mir.extra = try function.mir_extra.toOwnedSlice(gpa);
+ mir.string_bytes = try function.mir_string_bytes.toOwnedSlice(gpa);
+ mir.locals = try function.mir_locals.toOwnedSlice(gpa);
+ mir.table = try function.mir_table.toOwnedSlice(gpa);
+ mir.frame_locs = function.frame_locs.toOwnedSlice();
+ return mir;
+}
- error.InvalidInstruction, error.CannotEncode => |e| return function.fail("emit MIR failed: {s} (Zig compiler bug)", .{@errorName(e)}),
- else => |e| return function.fail("emit MIR failed: {s}", .{@errorName(e)}),
+pub fn getTmpMir(cg: *CodeGen) Mir {
+ return .{
+ .instructions = cg.mir_instructions.slice(),
+ .extra = cg.mir_extra.items,
+ .string_bytes = cg.mir_string_bytes.items,
+ .locals = cg.mir_locals.items,
+ .table = cg.mir_table.items,
+ .frame_locs = cg.frame_locs.slice(),
};
}
@@ -1153,10 +1079,9 @@ pub fn generateLazy(
code: *std.ArrayListUnmanaged(u8),
debug_output: link.File.DebugInfoOutput,
) codegen.CodeGenError!void {
- const comp = bin_file.comp;
- const gpa = comp.gpa;
+ const gpa = pt.zcu.gpa;
// This function is for generating global code, so we use the root module.
- const mod = comp.root_mod;
+ const mod = pt.zcu.comp.root_mod;
var function: CodeGen = .{
.gpa = gpa,
.pt = pt,
@@ -1164,11 +1089,8 @@ pub fn generateLazy(
.liveness = undefined,
.target = &mod.resolved_target.result,
.mod = mod,
- .bin_file = bin_file,
- .debug_output = debug_output,
.owner = .{ .lazy_sym = lazy_sym },
.inline_func = undefined,
- .arg_index = undefined,
.args = undefined,
.va_info = undefined,
.ret_mcv = undefined,
@@ -1179,6 +1101,9 @@ pub fn generateLazy(
defer {
function.inst_tracking.deinit(gpa);
function.mir_instructions.deinit(gpa);
+ function.mir_string_bytes.deinit(gpa);
+ function.mir_strings.deinit(gpa);
+ function.mir_locals.deinit(gpa);
function.mir_extra.deinit(gpa);
function.mir_table.deinit(gpa);
}
@@ -1194,42 +1119,7 @@ pub fn generateLazy(
else => |e| return e,
};
- var mir: Mir = .{
- .instructions = function.mir_instructions.toOwnedSlice(),
- .extra = try function.mir_extra.toOwnedSlice(gpa),
- .table = try function.mir_table.toOwnedSlice(gpa),
- .frame_locs = function.frame_locs.toOwnedSlice(),
- };
- defer mir.deinit(gpa);
-
- var emit: Emit = .{
- .air = function.air,
- .lower = .{
- .bin_file = bin_file,
- .target = function.target,
- .allocator = gpa,
- .mir = mir,
- .cc = .auto,
- .src_loc = src_loc,
- .output_mode = comp.config.output_mode,
- .link_mode = comp.config.link_mode,
- .pic = mod.pic,
- },
- .atom_index = function.owner.getSymbolIndex(&function) catch |err| switch (err) {
- error.CodegenFail => return error.CodegenFail,
- else => |e| return e,
- },
- .debug_output = debug_output,
- .code = code,
- .prev_di_loc = undefined, // no debug info yet
- .prev_di_pc = undefined, // no debug info yet
- };
- emit.emitMir() catch |err| switch (err) {
- error.LowerFail, error.EmitFail => return function.failMsg(emit.lower.err_msg.?),
- error.InvalidInstruction => return function.fail("failed to find a viable x86 instruction (Zig compiler bug)", .{}),
- error.CannotEncode => return function.fail("failed to encode x86 instruction (Zig compiler bug)", .{}),
- else => |e| return function.fail("failed to emit MIR: {s}", .{@errorName(e)}),
- };
+ try function.getTmpMir().emitLazy(bin_file, pt, src_loc, lazy_sym, code, debug_output);
}
const FormatNavData = struct {
@@ -1277,23 +1167,12 @@ fn formatWipMir(
_: std.fmt.FormatOptions,
writer: anytype,
) @TypeOf(writer).Error!void {
- const comp = data.self.bin_file.comp;
- const mod = comp.root_mod;
var lower: Lower = .{
- .bin_file = data.self.bin_file,
.target = data.self.target,
.allocator = data.self.gpa,
- .mir = .{
- .instructions = data.self.mir_instructions.slice(),
- .extra = data.self.mir_extra.items,
- .table = data.self.mir_table.items,
- .frame_locs = (std.MultiArrayList(Mir.FrameLoc){}).slice(),
- },
+ .mir = data.self.getTmpMir(),
.cc = .auto,
.src_loc = data.self.src_loc,
- .output_mode = comp.config.output_mode,
- .link_mode = comp.config.link_mode,
- .pic = mod.pic,
};
var first = true;
for ((lower.lowerMir(data.inst) catch |err| switch (err) {
@@ -1329,7 +1208,9 @@ fn formatWipMir(
.pseudo_dbg_epilogue_begin_none,
.pseudo_dbg_enter_block_none,
.pseudo_dbg_leave_block_none,
+ .pseudo_dbg_arg_none,
.pseudo_dbg_var_args_none,
+ .pseudo_dbg_var_none,
.pseudo_dead_none,
=> {},
.pseudo_dbg_line_stmt_line_column, .pseudo_dbg_line_line_column => try writer.print(
@@ -1337,57 +1218,40 @@ fn formatWipMir(
mir_inst.data.line_column,
),
.pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try writer.print(" {}", .{
- ip.getNav(ip.indexToKey(mir_inst.data.func).func.owner_nav).name.fmt(ip),
+ ip.getNav(ip.indexToKey(mir_inst.data.ip_index).func.owner_nav).name.fmt(ip),
}),
- .pseudo_dbg_local_a => try writer.print(" {}", .{mir_inst.data.a.air_inst}),
- .pseudo_dbg_local_ai_s => try writer.print(" {}, {d}", .{
- mir_inst.data.ai.air_inst,
- @as(i32, @bitCast(mir_inst.data.ai.i)),
+ .pseudo_dbg_arg_i_s, .pseudo_dbg_var_i_s => try writer.print(" {d}", .{
+ @as(i32, @bitCast(mir_inst.data.i.i)),
}),
- .pseudo_dbg_local_ai_u => try writer.print(" {}, {d}", .{
- mir_inst.data.ai.air_inst,
- mir_inst.data.ai.i,
+ .pseudo_dbg_arg_i_u, .pseudo_dbg_var_i_u => try writer.print(" {d}", .{
+ mir_inst.data.i.i,
}),
- .pseudo_dbg_local_ai_64 => try writer.print(" {}, {d}", .{
- mir_inst.data.ai.air_inst,
- lower.mir.extraData(Mir.Imm64, mir_inst.data.ai.i).data.decode(),
+ .pseudo_dbg_arg_i_64, .pseudo_dbg_var_i_64 => try writer.print(" {d}", .{
+ mir_inst.data.i64,
}),
- .pseudo_dbg_local_as => {
- const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
- .base = .{ .reloc = mir_inst.data.as.sym_index },
- }) };
- try writer.print(" {}, {}", .{ mir_inst.data.as.air_inst, mem_op.fmt(.m) });
- },
- .pseudo_dbg_local_aso => {
- const sym_off = lower.mir.extraData(bits.SymbolOffset, mir_inst.data.ax.payload).data;
+ .pseudo_dbg_arg_ro, .pseudo_dbg_var_ro => {
const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
- .base = .{ .reloc = sym_off.sym_index },
- .disp = sym_off.off,
+ .base = .{ .reg = mir_inst.data.ro.reg },
+ .disp = mir_inst.data.ro.off,
}) };
- try writer.print(" {}, {}", .{ mir_inst.data.ax.air_inst, mem_op.fmt(.m) });
+ try writer.print(" {}", .{mem_op.fmt(.m)});
},
- .pseudo_dbg_local_aro => {
- const air_off = lower.mir.extraData(Mir.AirOffset, mir_inst.data.rx.payload).data;
+ .pseudo_dbg_arg_fa, .pseudo_dbg_var_fa => {
const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
- .base = .{ .reg = mir_inst.data.rx.r1 },
- .disp = air_off.off,
+ .base = .{ .frame = mir_inst.data.fa.index },
+ .disp = mir_inst.data.fa.off,
}) };
- try writer.print(" {}, {}", .{ air_off.air_inst, mem_op.fmt(.m) });
+ try writer.print(" {}", .{mem_op.fmt(.m)});
},
- .pseudo_dbg_local_af => {
- const frame_addr = lower.mir.extraData(bits.FrameAddr, mir_inst.data.ax.payload).data;
- const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
- .base = .{ .frame = frame_addr.index },
- .disp = frame_addr.off,
- }) };
- try writer.print(" {}, {}", .{ mir_inst.data.ax.air_inst, mem_op.fmt(.m) });
- },
- .pseudo_dbg_local_am => {
+ .pseudo_dbg_arg_m, .pseudo_dbg_var_m => {
const mem_op: encoder.Instruction.Operand = .{
- .mem = lower.mir.extraData(Mir.Memory, mir_inst.data.ax.payload).data.decode(),
+ .mem = lower.mir.extraData(Mir.Memory, mir_inst.data.x.payload).data.decode(),
};
- try writer.print(" {}, {}", .{ mir_inst.data.ax.air_inst, mem_op.fmt(.m) });
+ try writer.print(" {}", .{mem_op.fmt(.m)});
},
+ .pseudo_dbg_arg_val, .pseudo_dbg_var_val => try writer.print(" {}", .{
+ Value.fromInterned(mir_inst.data.ip_index).fmtValue(data.self.pt),
+ }),
}
}
}
@@ -1440,6 +1304,22 @@ fn addExtraAssumeCapacity(self: *CodeGen, extra: anytype) u32 {
return result;
}
+fn addString(cg: *CodeGen, string: []const u8) Allocator.Error!Mir.NullTerminatedString {
+ try cg.mir_string_bytes.ensureUnusedCapacity(cg.gpa, string.len + 1);
+ try cg.mir_strings.ensureUnusedCapacityContext(cg.gpa, 1, .{ .bytes = &cg.mir_string_bytes });
+
+ const mir_string_gop = cg.mir_strings.getOrPutAssumeCapacityAdapted(
+ string,
+ std.hash_map.StringIndexAdapter{ .bytes = &cg.mir_string_bytes },
+ );
+ if (!mir_string_gop.found_existing) {
+ mir_string_gop.key_ptr.* = @intCast(cg.mir_string_bytes.items.len);
+ cg.mir_string_bytes.appendSliceAssumeCapacity(string);
+ cg.mir_string_bytes.appendAssumeCapacity(0);
+ }
+ return @enumFromInt(mir_string_gop.key_ptr.*);
+}
+
fn asmOps(self: *CodeGen, tag: Mir.Inst.FixedTag, ops: [4]Operand) !void {
return switch (ops[0]) {
.none => self.asmOpOnly(tag),
@@ -1678,124 +1558,6 @@ fn asmPlaceholder(self: *CodeGen) !Mir.Inst.Index {
});
}
-const MirTagAir = enum { dbg_local };
-
-fn asmAir(self: *CodeGen, tag: MirTagAir, inst: Air.Inst.Index) !void {
- _ = try self.addInst(.{
- .tag = .pseudo,
- .ops = switch (tag) {
- .dbg_local => .pseudo_dbg_local_a,
- },
- .data = .{ .a = .{ .air_inst = inst } },
- });
-}
-
-fn asmAirImmediate(self: *CodeGen, tag: MirTagAir, inst: Air.Inst.Index, imm: Immediate) !void {
- switch (imm) {
- .signed => |s| _ = try self.addInst(.{
- .tag = .pseudo,
- .ops = switch (tag) {
- .dbg_local => .pseudo_dbg_local_ai_s,
- },
- .data = .{ .ai = .{
- .air_inst = inst,
- .i = @bitCast(s),
- } },
- }),
- .unsigned => |u| _ = if (std.math.cast(u32, u)) |small| try self.addInst(.{
- .tag = .pseudo,
- .ops = switch (tag) {
- .dbg_local => .pseudo_dbg_local_ai_u,
- },
- .data = .{ .ai = .{
- .air_inst = inst,
- .i = small,
- } },
- }) else try self.addInst(.{
- .tag = .pseudo,
- .ops = switch (tag) {
- .dbg_local => .pseudo_dbg_local_ai_64,
- },
- .data = .{ .ai = .{
- .air_inst = inst,
- .i = try self.addExtra(Mir.Imm64.encode(u)),
- } },
- }),
- .reloc => |sym_off| _ = if (sym_off.off == 0) try self.addInst(.{
- .tag = .pseudo,
- .ops = switch (tag) {
- .dbg_local => .pseudo_dbg_local_as,
- },
- .data = .{ .as = .{
- .air_inst = inst,
- .sym_index = sym_off.sym_index,
- } },
- }) else try self.addInst(.{
- .tag = .pseudo,
- .ops = switch (tag) {
- .dbg_local => .pseudo_dbg_local_aso,
- },
- .data = .{ .ax = .{
- .air_inst = inst,
- .payload = try self.addExtra(sym_off),
- } },
- }),
- }
-}
-
-fn asmAirRegisterImmediate(
- self: *CodeGen,
- tag: MirTagAir,
- inst: Air.Inst.Index,
- reg: Register,
- imm: Immediate,
-) !void {
- _ = try self.addInst(.{
- .tag = .pseudo,
- .ops = switch (tag) {
- .dbg_local => .pseudo_dbg_local_aro,
- },
- .data = .{ .rx = .{
- .r1 = reg,
- .payload = try self.addExtra(Mir.AirOffset{
- .air_inst = inst,
- .off = imm.signed,
- }),
- } },
- });
-}
-
-fn asmAirFrameAddress(
- self: *CodeGen,
- tag: MirTagAir,
- inst: Air.Inst.Index,
- frame_addr: bits.FrameAddr,
-) !void {
- _ = try self.addInst(.{
- .tag = .pseudo,
- .ops = switch (tag) {
- .dbg_local => .pseudo_dbg_local_af,
- },
- .data = .{ .ax = .{
- .air_inst = inst,
- .payload = try self.addExtra(frame_addr),
- } },
- });
-}
-
-fn asmAirMemory(self: *CodeGen, tag: MirTagAir, inst: Air.Inst.Index, m: Memory) !void {
- _ = try self.addInst(.{
- .tag = .pseudo,
- .ops = switch (tag) {
- .dbg_local => .pseudo_dbg_local_am,
- },
- .data = .{ .ax = .{
- .air_inst = inst,
- .payload = try self.addExtra(Mir.Memory.encode(m)),
- } },
- });
-}
-
fn asmOpOnly(self: *CodeGen, tag: Mir.Inst.FixedTag) !void {
_ = try self.addInst(.{
.tag = tag[1],
@@ -1873,21 +1635,36 @@ fn asmImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, imm: Immediate) !void {
.ops = switch (imm) {
.signed => .i_s,
.unsigned => .i_u,
- .reloc => .rel,
+ .nav => .nav,
+ .uav => .uav,
+ .lazy_sym => .lazy_sym,
+ .extern_func => .extern_func,
},
.data = switch (imm) {
- .reloc => |sym_off| reloc: {
- assert(tag[0] == ._);
- break :reloc .{ .reloc = sym_off };
- },
.signed, .unsigned => .{ .i = .{
.fixes = tag[0],
.i = switch (imm) {
.signed => |s| @bitCast(s),
.unsigned => |u| @intCast(u),
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
},
} },
+ .nav => |nav| switch (tag[0]) {
+ ._ => .{ .nav = nav },
+ else => unreachable,
+ },
+ .uav => |uav| switch (tag[0]) {
+ ._ => .{ .uav = uav },
+ else => unreachable,
+ },
+ .lazy_sym => |lazy_sym| switch (tag[0]) {
+ ._ => .{ .lazy_sym = lazy_sym },
+ else => unreachable,
+ },
+ .extern_func => |extern_func| switch (tag[0]) {
+ ._ => .{ .extern_func = extern_func },
+ else => unreachable,
+ },
},
});
}
@@ -1902,7 +1679,7 @@ fn asmImmediateRegister(self: *CodeGen, tag: Mir.Inst.FixedTag, imm: Immediate,
.i = @as(u8, switch (imm) {
.signed => |s| @bitCast(@as(i8, @intCast(s))),
.unsigned => |u| @intCast(u),
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
}),
} },
});
@@ -1917,12 +1694,12 @@ fn asmImmediateImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, imm1: Immediate
.i1 = switch (imm1) {
.signed => |s| @bitCast(@as(i16, @intCast(s))),
.unsigned => |u| @intCast(u),
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
},
.i2 = switch (imm2) {
.signed => |s| @bitCast(@as(i8, @intCast(s))),
.unsigned => |u| @intCast(u),
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
},
} },
});
@@ -1947,7 +1724,7 @@ fn asmRegisterImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, reg: Register, i
.{ .ri_u, small }
else
.{ .ri_64, try self.addExtra(Mir.Imm64.encode(imm.unsigned)) },
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
};
_ = try self.addInst(.{
.tag = tag[1],
@@ -2019,7 +1796,7 @@ fn asmRegisterRegisterRegisterImmediate(
.i = switch (imm) {
.signed => |s| @bitCast(@as(i8, @intCast(s))),
.unsigned => |u| @intCast(u),
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
},
} },
});
@@ -2037,7 +1814,7 @@ fn asmRegisterRegisterImmediate(
.ops = switch (imm) {
.signed => .rri_s,
.unsigned => .rri_u,
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
},
.data = .{ .rri = .{
.fixes = tag[0],
@@ -2046,7 +1823,7 @@ fn asmRegisterRegisterImmediate(
.i = switch (imm) {
.signed => |s| @bitCast(s),
.unsigned => |u| @intCast(u),
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
},
} },
});
@@ -2144,7 +1921,7 @@ fn asmRegisterMemoryImmediate(
if (switch (imm) {
.signed => |s| if (std.math.cast(i16, s)) |x| @as(u16, @bitCast(x)) else null,
.unsigned => |u| std.math.cast(u16, u),
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
}) |small_imm| {
_ = try self.addInst(.{
.tag = tag[1],
@@ -2160,7 +1937,7 @@ fn asmRegisterMemoryImmediate(
const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
.signed => |s| @bitCast(s),
.unsigned => |u| @as(u32, @intCast(u)),
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
} });
assert(payload + 1 == try self.addExtra(Mir.Memory.encode(m)));
_ = try self.addInst(.{
@@ -2168,7 +1945,7 @@ fn asmRegisterMemoryImmediate(
.ops = switch (imm) {
.signed => .rmi_s,
.unsigned => .rmi_u,
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
},
.data = .{ .rx = .{
.fixes = tag[0],
@@ -2216,7 +1993,7 @@ fn asmMemoryImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, m: Memory, imm: Im
const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
.signed => |s| @bitCast(s),
.unsigned => |u| @intCast(u),
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
} });
assert(payload + 1 == try self.addExtra(Mir.Memory.encode(m)));
_ = try self.addInst(.{
@@ -2224,7 +2001,7 @@ fn asmMemoryImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, m: Memory, imm: Im
.ops = switch (imm) {
.signed => .mi_s,
.unsigned => .mi_u,
- .reloc => unreachable,
+ .nav, .uav, .lazy_sym, .extern_func => unreachable,
},
.data = .{ .x = .{
.fixes = tag[0],
@@ -2271,7 +2048,13 @@ fn asmMemoryRegisterImmediate(
});
}
-fn gen(self: *CodeGen) InnerError!void {
+fn gen(
+ self: *CodeGen,
+ zir: *const std.zig.Zir,
+ func_zir_inst: std.zig.Zir.Inst.Index,
+ comptime_args: InternPool.Index.Slice,
+ air_arg_count: u32,
+) InnerError!void {
const pt = self.pt;
const zcu = pt.zcu;
const fn_info = zcu.typeToFunc(self.fn_type).?;
@@ -2339,9 +2122,9 @@ fn gen(self: *CodeGen) InnerError!void {
else => |cc| return self.fail("{s} does not support var args", .{@tagName(cc)}),
};
- if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_prologue_end_none);
+ if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_prologue_end_none);
- try self.genBody(self.air.getMainBody());
+ try self.genMainBody(zir, func_zir_inst, comptime_args, air_arg_count);
const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: {
var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1);
@@ -2356,7 +2139,7 @@ fn gen(self: *CodeGen) InnerError!void {
}
for (self.epilogue_relocs.items) |epilogue_reloc| self.performReloc(epilogue_reloc);
- if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);
+ if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);
const backpatch_stack_dealloc = try self.asmPlaceholder();
const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder();
try self.asmRegister(.{ ._, .pop }, .rbp);
@@ -2475,21 +2258,88 @@ fn gen(self: *CodeGen) InnerError!void {
});
}
} else {
- if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_prologue_end_none);
- try self.genBody(self.air.getMainBody());
- if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);
+ if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_prologue_end_none);
+ try self.genMainBody(zir, func_zir_inst, comptime_args, air_arg_count);
+ if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);
+ }
+}
+
+fn genMainBody(
+ cg: *CodeGen,
+ zir: *const std.zig.Zir,
+ func_zir_inst: std.zig.Zir.Inst.Index,
+ comptime_args: InternPool.Index.Slice,
+ air_arg_count: u32,
+) InnerError!void {
+ const pt = cg.pt;
+ const zcu = pt.zcu;
+ const ip = &zcu.intern_pool;
+
+ const main_body = cg.air.getMainBody();
+ const air_args_body = main_body[0..air_arg_count];
+ try cg.genBody(air_args_body);
+
+ if (!cg.mod.strip) {
+ var air_arg_index: usize = 0;
+ const fn_info = zcu.typeToFunc(cg.fn_type).?;
+ var fn_param_index: usize = 0;
+ var zir_param_index: usize = 0;
+ for (zir.getParamBody(func_zir_inst)) |zir_param_inst| {
+ const name = switch (zir.getParamName(zir_param_inst) orelse break) {
+ .empty => .none,
+ else => |zir_name| try cg.addString(zir.nullTerminatedString(zir_name)),
+ };
+ defer zir_param_index += 1;
+
+ if (comptime_args.len > 0) switch (comptime_args.get(ip)[zir_param_index]) {
+ .none => {},
+ else => |comptime_arg| {
+ try cg.mir_locals.append(cg.gpa, .{ .name = name, .type = ip.typeOf(comptime_arg) });
+ _ = try cg.addInst(.{
+ .tag = .pseudo,
+ .ops = .pseudo_dbg_arg_val,
+ .data = .{ .ip_index = comptime_arg },
+ });
+ continue;
+ },
+ };
+
+ const arg_ty = fn_info.param_types.get(ip)[fn_param_index];
+ try cg.mir_locals.append(cg.gpa, .{ .name = name, .type = arg_ty });
+ fn_param_index += 1;
+
+ if (air_arg_index == air_args_body.len) {
+ try cg.asmPseudo(.pseudo_dbg_arg_none);
+ continue;
+ }
+ const air_arg_inst = air_args_body[air_arg_index];
+ const air_arg_data = cg.air.instructions.items(.data)[air_arg_index].arg;
+ if (air_arg_data.zir_param_index != zir_param_index) {
+ try cg.asmPseudo(.pseudo_dbg_arg_none);
+ continue;
+ }
+ air_arg_index += 1;
+ try cg.genLocalDebugInfo(
+ .arg,
+ .fromInterned(arg_ty),
+ cg.getResolvedInstValue(air_arg_inst).short,
+ );
+ }
+ if (fn_info.is_var_args) try cg.asmPseudo(.pseudo_dbg_var_args_none);
}
+
+ try cg.genBody(main_body[air_arg_count..]);
}
-fn checkInvariantsAfterAirInst(self: *CodeGen) void {
- assert(!self.register_manager.lockedRegsExist());
+fn checkInvariantsAfterAirInst(cg: *CodeGen) void {
+ assert(!cg.register_manager.lockedRegsExist());
if (std.debug.runtime_safety) {
// check consistency of tracked registers
- var it = self.register_manager.free_registers.iterator(.{ .kind = .unset });
+ var it = cg.register_manager.free_registers.iterator(.{ .kind = .unset });
while (it.next()) |index| {
- const tracked_inst = self.register_manager.registers[index];
- const tracking = self.getResolvedInstValue(tracked_inst);
+ const tracked_inst = cg.register_manager.registers[index];
+ const tracking = cg.getResolvedInstValue(tracked_inst);
for (tracking.getRegs()) |reg| {
if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
} else unreachable; // tracked register not in use
@@ -2497,10 +2347,10 @@ fn checkInvariantsAfterAirInst(self: *CodeGen) void {
}
}
-fn genBodyBlock(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
- if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_enter_block_none);
- try self.genBody(body);
- if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_leave_block_none);
+fn genBodyBlock(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
+ if (!cg.mod.strip) try cg.asmPseudo(.pseudo_dbg_enter_block_none);
+ try cg.genBody(body);
+ if (!cg.mod.strip) try cg.asmPseudo(.pseudo_dbg_leave_block_none);
}
fn 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 {
const air_datas = cg.air.instructions.items(.data);
const use_old = cg.target.ofmt == .coff;
- cg.arg_index = 0;
- for (body) |inst| switch (air_tags[@intFromEnum(inst)]) {
- .arg => {
- wip_mir_log.debug("{}", .{cg.fmtAir(inst)});
- verbose_tracking_log.debug("{}", .{cg.fmtTracking()});
-
- cg.reused_operands = .initEmpty();
- try cg.inst_tracking.ensureUnusedCapacity(cg.gpa, 1);
-
- try cg.airArg(inst);
-
- try cg.resetTemps(@enumFromInt(0));
- cg.checkInvariantsAfterAirInst();
- },
- else => break,
- };
-
- if (cg.arg_index == 0) try cg.airDbgVarArgs();
- cg.arg_index = 0;
for (body) |inst| {
if (cg.liveness.isUnused(inst) and !cg.air.mustLower(inst, ip)) continue;
wip_mir_log.debug("{}", .{cg.fmtAir(inst)});
@@ -2544,20 +2375,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.shuffle_one, .shuffle_two => @panic("x86_64 TODO: shuffle_one/shuffle_two"),
// zig fmt: on
- .arg => if (cg.debug_output != .none) {
- // skip zero-bit arguments as they don't have a corresponding arg instruction
- var arg_index = cg.arg_index;
- while (cg.args[arg_index] == .none) arg_index += 1;
- cg.arg_index = arg_index + 1;
-
- const name = air_datas[@intFromEnum(inst)].arg.name;
- if (name != .none) try cg.genLocalDebugInfo(inst, cg.getResolvedInstValue(inst).short);
- if (cg.liveness.isUnused(inst)) try cg.processDeath(inst);
-
- for (cg.args[arg_index + 1 ..]) |arg| {
- if (arg != .none) break;
- } else try cg.airDbgVarArgs();
- },
+ .arg => try cg.airArg(inst),
.add, .add_optimized, .add_wrap => |air_tag| if (use_old) try cg.airBinOp(inst, switch (air_tag) {
else => unreachable,
.add, .add_optimized => .add,
@@ -3577,7 +3395,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -3709,7 +3527,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -3745,7 +3563,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -3782,7 +3600,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -3822,7 +3640,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -4307,7 +4125,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -4339,7 +4157,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -4374,7 +4192,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -4409,7 +4227,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -14009,7 +13827,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__subhf3" } },
.unused,
.unused,
.unused,
@@ -14141,7 +13959,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__subhf3" } },
.unused,
.unused,
.unused,
@@ -14177,7 +13995,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__subhf3" } },
.unused,
.unused,
.unused,
@@ -14214,7 +14032,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__subhf3" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -14254,7 +14072,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__subhf3" } },
.unused,
.unused,
.unused,
@@ -14756,7 +14574,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__subtf3" } },
.unused,
.unused,
.unused,
@@ -14788,7 +14606,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__subtf3" } },
.unused,
.unused,
.unused,
@@ -14823,7 +14641,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__subtf3" } },
.unused,
.unused,
.unused,
@@ -14858,7 +14676,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__subtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__subtf3" } },
.unused,
.unused,
.unused,
@@ -23539,7 +23357,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -23671,7 +23489,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -23707,7 +23525,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -23744,7 +23562,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -23784,7 +23602,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -24269,7 +24087,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -24301,7 +24119,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -24336,7 +24154,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -24371,7 +24189,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -26231,7 +26049,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -26363,7 +26181,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -26399,7 +26217,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -26436,7 +26254,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -26476,7 +26294,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -26961,7 +26779,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -26993,7 +26811,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -27028,7 +26846,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -27063,7 +26881,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -32371,7 +32189,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
.unused,
.unused,
.unused,
@@ -32503,7 +32321,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
.unused,
.unused,
.unused,
@@ -32539,7 +32357,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
.unused,
.unused,
.unused,
@@ -32576,7 +32394,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -32616,7 +32434,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
.unused,
.unused,
.unused,
@@ -33119,7 +32937,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
.unused,
.unused,
.unused,
@@ -33151,7 +32969,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
.unused,
.unused,
.unused,
@@ -33186,7 +33004,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
.unused,
.unused,
.unused,
@@ -33221,7 +33039,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
.unused,
.unused,
.unused,
@@ -33305,8 +33123,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunch" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunch" } },
.unused,
.unused,
.unused,
@@ -33447,8 +33265,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunch" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunch" } },
.unused,
.unused,
.unused,
@@ -33484,8 +33302,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunch" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunch" } },
.unused,
.unused,
.unused,
@@ -33522,8 +33340,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunch" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunch" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -33563,8 +33381,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunch" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunch" } },
.unused,
.unused,
.unused,
@@ -33632,7 +33450,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "truncf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "truncf" } },
.unused,
.unused,
.unused,
@@ -33696,7 +33514,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "truncf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "truncf" } },
.unused,
.unused,
.unused,
@@ -33845,7 +33663,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "trunc" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "trunc" } },
.unused,
.unused,
.unused,
@@ -33875,8 +33693,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divdf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "trunc" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divdf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "trunc" } },
.unused,
.unused,
.unused,
@@ -34023,7 +33841,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "trunc" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "trunc" } },
.unused,
.unused,
.unused,
@@ -34059,8 +33877,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divdf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "trunc" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divdf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "trunc" } },
.unused,
.unused,
.unused,
@@ -34097,7 +33915,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f80, .kind = .{ .reg = .st6 } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncx" } },
.unused,
.unused,
.unused,
@@ -34131,7 +33949,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f80, .kind = .{ .reg = .st6 } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncx" } },
.unused,
.unused,
.unused,
@@ -34165,8 +33983,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "truncq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
.unused,
.unused,
.unused,
@@ -34198,8 +34016,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "truncq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
.unused,
.unused,
.unused,
@@ -34234,8 +34052,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "truncq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
.unused,
.unused,
.unused,
@@ -34270,8 +34088,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "truncq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "truncq" } },
.unused,
.unused,
.unused,
@@ -34361,12 +34179,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "__trunch",
.down => "__floorh",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -34501,12 +34319,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "__trunch",
.down => "__floorh",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -34542,12 +34360,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "__trunch",
.down => "__floorh",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -34584,12 +34402,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "__trunch",
.down => "__floorh",
- } } } },
+ } } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -34629,12 +34447,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "__trunch",
.down => "__floorh",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -34702,11 +34520,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "truncf",
.down => "floorf",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -34770,11 +34588,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "truncf",
.down => "floorf",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -34923,11 +34741,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "trunc",
.down => "floor",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -34957,12 +34775,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divdf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = "__divdf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "trunc",
.down => "floor",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -35109,11 +34927,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "trunc",
.down => "floor",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -35149,12 +34967,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divdf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = "__divdf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "trunc",
.down => "floor",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -35191,11 +35009,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f80, .kind = .{ .reg = .st6 } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "__truncx",
.down => "__floorx",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -35227,11 +35045,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "__truncx",
.down => "__floorx",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -35264,11 +35082,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "__truncx",
.down => "__floorx",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -35302,11 +35120,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f80, .kind = .{ .reg = .st6 } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "__truncx",
.down => "__floorx",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -35340,12 +35158,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "truncq",
.down => "floorq",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -35377,12 +35195,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "truncq",
.down => "floorq",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -35417,12 +35235,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "truncq",
.down => "floorq",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -35457,12 +35275,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.zero => "truncq",
.down => "floorq",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -35649,9 +35467,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .i128, .kind = .{ .param_gpr_pair = .{ .cc = .ccc, .at = 0 } } },
.{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__modti3" } },
.{ .type = .i64, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divti3" } },
.unused,
.unused,
.unused,
@@ -35700,9 +35518,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
.{ .type = .i32, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divei4" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divei4" } },
.{ .kind = .{ .mem_of_type = .dst0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modei4" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__modei4" } },
.unused,
.unused,
.unused,
@@ -35781,8 +35599,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floorh" } },
.unused,
.unused,
.unused,
@@ -35923,8 +35741,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floorh" } },
.unused,
.unused,
.unused,
@@ -35960,8 +35778,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floorh" } },
.unused,
.unused,
.unused,
@@ -35998,8 +35816,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floorh" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -36039,8 +35857,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divhf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divhf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floorh" } },
.unused,
.unused,
.unused,
@@ -36108,7 +35926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floorf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "floorf" } },
.unused,
.unused,
.unused,
@@ -36172,7 +35990,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floorf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "floorf" } },
.unused,
.unused,
.unused,
@@ -36321,7 +36139,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floor" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "floor" } },
.unused,
.unused,
.unused,
@@ -36351,8 +36169,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divdf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floor" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divdf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "floor" } },
.unused,
.unused,
.unused,
@@ -36499,7 +36317,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floor" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "floor" } },
.unused,
.unused,
.unused,
@@ -36535,8 +36353,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divdf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floor" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divdf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "floor" } },
.unused,
.unused,
.unused,
@@ -36573,7 +36391,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f80, .kind = .{ .reg = .st6 } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floorx" } },
.unused,
.unused,
.unused,
@@ -36607,7 +36425,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f80, .kind = .{ .reg = .st6 } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floorx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floorx" } },
.unused,
.unused,
.unused,
@@ -36641,8 +36459,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floorq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
.unused,
.unused,
.unused,
@@ -36674,8 +36492,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floorq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
.unused,
.unused,
.unused,
@@ -36710,8 +36528,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floorq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
.unused,
.unused,
.unused,
@@ -36746,8 +36564,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divtf3" } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "floorq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } },
+ .{ .type = .usize, .kind = .{ .extern_func = "floorq" } },
.unused,
.unused,
.unused,
@@ -36903,7 +36721,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__modti3" } },
.unused,
.unused,
.unused,
@@ -36932,7 +36750,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__umodti3" } },
.unused,
.unused,
.unused,
@@ -36965,7 +36783,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modei4" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__modei4" } },
.unused,
.unused,
.unused,
@@ -36998,7 +36816,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodei4" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__umodei4" } },
.unused,
.unused,
.unused,
@@ -37362,7 +37180,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__modti3" } },
.{ .type = .u64, .kind = .{ .ret_gpr = .{ .cc = .ccc, .at = 0 } } },
.unused,
.unused,
@@ -37400,7 +37218,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__umodti3" } },
.{ .type = .u64, .kind = .{ .ret_gpr = .{ .cc = .ccc, .at = 0 } } },
.unused,
.unused,
@@ -37438,7 +37256,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modei4" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__modei4" } },
.unused,
.unused,
.unused,
@@ -37474,7 +37292,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodei4" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__umodei4" } },
.unused,
.unused,
.unused,
@@ -37505,7 +37323,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.unused,
.unused,
.unused,
@@ -37537,7 +37355,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.unused,
.unused,
.unused,
@@ -37573,7 +37391,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.unused,
.unused,
.unused,
@@ -37610,7 +37428,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -37650,7 +37468,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.unused,
.unused,
.unused,
@@ -37686,7 +37504,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
.unused,
.unused,
.unused,
@@ -37718,7 +37536,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
.unused,
.unused,
.unused,
@@ -37753,7 +37571,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
.unused,
.unused,
.unused,
@@ -37785,7 +37603,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
.unused,
.unused,
.unused,
@@ -37817,7 +37635,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
.unused,
.unused,
.unused,
@@ -37852,7 +37670,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
.unused,
.unused,
.unused,
@@ -37887,7 +37705,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
.unused,
.unused,
.unused,
@@ -37923,7 +37741,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.unused,
.unused,
.unused,
@@ -37956,7 +37774,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.unused,
.unused,
.unused,
@@ -37989,7 +37807,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.unused,
.unused,
.unused,
@@ -38023,7 +37841,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.unused,
.unused,
.unused,
@@ -38061,7 +37879,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.unused,
.unused,
.unused,
@@ -38099,7 +37917,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.unused,
.unused,
.unused,
@@ -38134,7 +37952,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
.unused,
.unused,
.unused,
@@ -38166,7 +37984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
.unused,
.unused,
.unused,
@@ -38201,7 +38019,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
.unused,
.unused,
.unused,
@@ -38236,7 +38054,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
.unused,
.unused,
.unused,
@@ -38571,7 +38389,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__modti3" } },
.{ .type = .i64, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -38610,7 +38428,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__modti3" } },
.unused,
.unused,
.unused,
@@ -38650,7 +38468,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__umodti3" } },
.unused,
.unused,
.unused,
@@ -38684,7 +38502,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
.{ .type = .i64, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__modei4" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__modei4" } },
.unused,
.unused,
.unused,
@@ -38741,7 +38559,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__umodei4" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__umodei4" } },
.unused,
.unused,
.unused,
@@ -38771,7 +38589,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
@@ -38812,7 +38630,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
@@ -38853,10 +38671,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -38891,10 +38709,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -38929,10 +38747,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -38967,10 +38785,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -39005,10 +38823,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f32, .kind = .mem },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .ax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -39043,10 +38861,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f32, .kind = .mem },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .ax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -39084,7 +38902,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
@@ -39132,7 +38950,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
@@ -39180,10 +38998,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -39225,10 +39043,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -39270,10 +39088,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -39315,10 +39133,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -39360,10 +39178,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -39406,10 +39224,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f16, .kind = .{ .reg = .dx } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -39453,9 +39271,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f32, .kind = .mem },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -39502,9 +39320,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodh" } },
.{ .type = .f32, .kind = .mem },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -39547,7 +39365,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f32, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
.{ .type = .f32, .kind = .{ .reg = .edx } },
.{ .type = .f32, .kind = .{ .reg = .eax } },
.unused,
@@ -39585,7 +39403,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f32, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
.{ .type = .f32, .kind = .{ .reg = .edx } },
.{ .type = .f32, .kind = .{ .reg = .eax } },
.unused,
@@ -39623,7 +39441,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f32, .kind = .mem },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f32, .kind = .{ .reg = .eax } },
.unused,
@@ -39663,7 +39481,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .{ .reg = .xmm1 } },
.{ .type = .f32, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
.{ .type = .f32, .kind = .{ .reg = .edx } },
.{ .type = .f32, .kind = .{ .reg = .eax } },
.unused,
@@ -39707,7 +39525,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .{ .reg = .xmm1 } },
.{ .type = .f32, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
.{ .type = .f32, .kind = .{ .reg = .edx } },
.{ .type = .f32, .kind = .{ .reg = .eax } },
.unused,
@@ -39750,7 +39568,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodf" } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f32, .kind = .{ .reg = .eax } },
.unused,
@@ -39790,7 +39608,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f64, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
.{ .type = .f64, .kind = .{ .reg = .rcx } },
.{ .type = .f64, .kind = .{ .reg = .rdx } },
.{ .type = .f64, .kind = .{ .reg = .rax } },
@@ -39829,7 +39647,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f64, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
.{ .type = .f64, .kind = .{ .reg = .rcx } },
.{ .type = .f64, .kind = .{ .reg = .rdx } },
.{ .type = .f64, .kind = .{ .reg = .rax } },
@@ -39868,7 +39686,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f64, .kind = .mem },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
.{ .type = .f64, .kind = .mem },
.{ .type = .f64, .kind = .{ .reg = .rdx } },
.{ .type = .f64, .kind = .{ .reg = .rax } },
@@ -39913,7 +39731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
.{ .type = .f64, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
.{ .type = .f64, .kind = .{ .reg = .rcx } },
.{ .type = .f64, .kind = .{ .reg = .rdx } },
.{ .type = .f64, .kind = .{ .reg = .rax } },
@@ -39958,7 +39776,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
.{ .type = .f64, .kind = .{ .rc = .general_purpose } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
.{ .type = .f64, .kind = .{ .reg = .rcx } },
.{ .type = .f64, .kind = .{ .reg = .rdx } },
.{ .type = .f64, .kind = .{ .reg = .rax } },
@@ -40002,7 +39820,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmod" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmod" } },
.{ .type = .f64, .kind = .{ .reg = .rdx } },
.{ .type = .f64, .kind = .mem },
.{ .type = .f64, .kind = .{ .reg = .rax } },
@@ -40050,7 +39868,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .reg = .rax } },
.unused,
@@ -40093,7 +39911,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .reg = .rax } },
.unused,
@@ -40136,7 +39954,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .reg = .rax } },
.unused,
@@ -40179,7 +39997,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .reg = .rax } },
.unused,
@@ -40222,7 +40040,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .reg = .rax } },
.unused,
@@ -40265,7 +40083,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .reg = .rax } },
.unused,
@@ -40309,7 +40127,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .reg = .rax } },
.unused,
@@ -40357,7 +40175,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .reg = .rax } },
.unused,
@@ -40405,7 +40223,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .reg = .rax } },
.unused,
@@ -40453,7 +40271,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .reg = .rax } },
.unused,
@@ -40501,7 +40319,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .reg = .rax } },
.unused,
@@ -40549,7 +40367,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmodx" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmodx" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.{ .type = .f80, .kind = .{ .reg = .rax } },
.unused,
@@ -40595,11 +40413,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f128, .kind = .mem },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
.{ .type = .f128, .kind = .{ .reg = .rcx } },
.{ .type = .f128, .kind = .{ .reg = .rdx } },
.{ .type = .f128, .kind = .{ .reg = .rax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -40636,11 +40454,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f128, .kind = .mem },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
.{ .type = .f128, .kind = .{ .reg = .rcx } },
.{ .type = .f128, .kind = .{ .reg = .rdx } },
.{ .type = .f128, .kind = .{ .reg = .rax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -40677,11 +40495,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f128, .kind = .mem },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
.{ .type = .f128, .kind = .{ .reg = .rcx } },
.{ .type = .f128, .kind = .{ .reg = .rdx } },
.{ .type = .f128, .kind = .{ .reg = .rax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -40719,11 +40537,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f128, .kind = .mem },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
.{ .type = .f128, .kind = .{ .reg = .rdx } },
.{ .type = .f128, .kind = .mem },
.{ .type = .f128, .kind = .{ .reg = .rax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -40761,11 +40579,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
.{ .type = .f128, .kind = .{ .reg = .rcx } },
.{ .type = .f128, .kind = .{ .reg = .rdx } },
.{ .type = .f128, .kind = .{ .reg = .rax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -40807,11 +40625,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
.{ .type = .f128, .kind = .{ .reg = .rcx } },
.{ .type = .f128, .kind = .{ .reg = .rdx } },
.{ .type = .f128, .kind = .{ .reg = .rax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -40853,11 +40671,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
.{ .type = .f128, .kind = .{ .reg = .rcx } },
.{ .type = .f128, .kind = .{ .reg = .rdx } },
.{ .type = .f128, .kind = .{ .reg = .rax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -40900,11 +40718,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmodq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } },
.{ .type = .f128, .kind = .{ .reg = .rdx } },
.{ .type = .f128, .kind = .mem },
.{ .type = .f128, .kind = .{ .reg = .rax } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -43994,7 +43812,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
.unused,
.unused,
.unused,
@@ -44132,7 +43950,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
.unused,
.unused,
.unused,
@@ -44168,7 +43986,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
.unused,
.unused,
.unused,
@@ -44205,7 +44023,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -44245,7 +44063,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
.unused,
.unused,
.unused,
@@ -44660,7 +44478,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmax" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmax" } },
.unused,
.unused,
.unused,
@@ -44915,7 +44733,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmax" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmax" } },
.unused,
.unused,
.unused,
@@ -45204,7 +45022,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
.unused,
.unused,
.unused,
@@ -45236,7 +45054,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
.unused,
.unused,
.unused,
@@ -45271,7 +45089,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
.unused,
.unused,
.unused,
@@ -45306,7 +45124,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
.unused,
.unused,
.unused,
@@ -48153,7 +47971,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
.unused,
.unused,
.unused,
@@ -48291,7 +48109,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
.unused,
.unused,
.unused,
@@ -48327,7 +48145,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
.unused,
.unused,
.unused,
@@ -48364,7 +48182,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -48404,7 +48222,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
.unused,
.unused,
.unused,
@@ -48819,7 +48637,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmin" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmin" } },
.unused,
.unused,
.unused,
@@ -49074,7 +48892,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmin" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmin" } },
.unused,
.unused,
.unused,
@@ -49351,7 +49169,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
.unused,
.unused,
.unused,
@@ -49383,7 +49201,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
.unused,
.unused,
.unused,
@@ -49418,7 +49236,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
.unused,
.unused,
.unused,
@@ -49453,7 +49271,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
.unused,
.unused,
.unused,
@@ -64179,9 +63997,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.block => {
const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
const block = cg.air.extraData(Air.Block, ty_pl.payload);
- if (cg.debug_output != .none) try cg.asmPseudo(.pseudo_dbg_enter_block_none);
+ if (!cg.mod.strip) try cg.asmPseudo(.pseudo_dbg_enter_block_none);
try cg.lowerBlock(inst, @ptrCast(cg.air.extra.items[block.end..][0..block.data.body_len]));
- if (cg.debug_output != .none) try cg.asmPseudo(.pseudo_dbg_leave_block_none);
+ if (!cg.mod.strip) try cg.asmPseudo(.pseudo_dbg_leave_block_none);
},
.loop => if (use_old) try cg.airLoop(inst) else {
const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
@@ -72393,7 +72211,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__sqrth" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__sqrth" } },
.unused,
.unused,
.unused,
@@ -72475,7 +72293,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__sqrth" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__sqrth" } },
.unused,
.unused,
.unused,
@@ -72506,7 +72324,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__sqrth" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__sqrth" } },
.unused,
.unused,
.unused,
@@ -72537,7 +72355,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__sqrth" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__sqrth" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -72571,7 +72389,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__sqrth" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__sqrth" } },
.unused,
.unused,
.unused,
@@ -72643,7 +72461,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "sqrtf" } },
.unused,
.unused,
.unused,
@@ -72759,7 +72577,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "sqrtf" } },
.unused,
.unused,
.unused,
@@ -72789,7 +72607,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "sqrtf" } },
.unused,
.unused,
.unused,
@@ -72859,7 +72677,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrt" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "sqrt" } },
.unused,
.unused,
.unused,
@@ -72975,7 +72793,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrt" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "sqrt" } },
.unused,
.unused,
.unused,
@@ -73005,7 +72823,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrt" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "sqrt" } },
.unused,
.unused,
.unused,
@@ -73035,7 +72853,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrt" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "sqrt" } },
.unused,
.unused,
.unused,
@@ -73119,7 +72937,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
.unused,
.unused,
.unused,
@@ -73146,7 +72964,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
.unused,
.unused,
.unused,
@@ -73176,7 +72994,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
.unused,
.unused,
.unused,
@@ -73206,7 +73024,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "sqrtq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } },
.unused,
.unused,
.unused,
@@ -73250,7 +73068,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "h" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "h" } },
.unused,
.unused,
.unused,
@@ -73277,7 +73095,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "h" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "h" } },
.unused,
.unused,
.unused,
@@ -73308,7 +73126,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "h" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "h" } },
.unused,
.unused,
.unused,
@@ -73339,7 +73157,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "h" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "h" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -73373,7 +73191,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "h" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "h" } },
.unused,
.unused,
.unused,
@@ -73403,7 +73221,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "f" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f" } },
.unused,
.unused,
.unused,
@@ -73430,7 +73248,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "f" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f" } },
.unused,
.unused,
.unused,
@@ -73460,7 +73278,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "f" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f" } },
.unused,
.unused,
.unused,
@@ -73488,7 +73306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) } } },
+ .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) } },
.unused,
.unused,
.unused,
@@ -73515,7 +73333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) } } },
+ .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) } },
.unused,
.unused,
.unused,
@@ -73545,7 +73363,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) } } },
+ .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) } },
.unused,
.unused,
.unused,
@@ -73575,7 +73393,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) } } },
+ .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) } },
.unused,
.unused,
.unused,
@@ -73606,7 +73424,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "x" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "x" } },
.unused,
.unused,
.unused,
@@ -73633,7 +73451,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "x" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "x" } },
.unused,
.unused,
.unused,
@@ -73660,7 +73478,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "x" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "x" } },
.unused,
.unused,
.unused,
@@ -73688,7 +73506,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "x" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "x" } },
.unused,
.unused,
.unused,
@@ -73720,7 +73538,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "x" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "x" } },
.unused,
.unused,
.unused,
@@ -73752,7 +73570,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__" ++ @tagName(name) ++ "x" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__" ++ @tagName(name) ++ "x" } },
.unused,
.unused,
.unused,
@@ -73781,7 +73599,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "q" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
.unused,
.unused,
.unused,
@@ -73808,7 +73626,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "q" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
.unused,
.unused,
.unused,
@@ -73838,7 +73656,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "q" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
.unused,
.unused,
.unused,
@@ -73868,7 +73686,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(name) ++ "q" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } },
.unused,
.unused,
.unused,
@@ -75486,12 +75304,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "__floorh",
.up => "__ceilh",
.zero => "__trunch",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -75573,12 +75391,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "__floorh",
.up => "__ceilh",
.zero => "__trunch",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -75609,12 +75427,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "__floorh",
.up => "__ceilh",
.zero => "__trunch",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -75645,12 +75463,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "__floorh",
.up => "__ceilh",
.zero => "__trunch",
- } } } },
+ } } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -75684,12 +75502,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "__floorh",
.up => "__ceilh",
.zero => "__trunch",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -75761,12 +75579,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "floorf",
.up => "ceilf",
.zero => "truncf",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -75888,12 +75706,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "floorf",
.up => "ceilf",
.zero => "truncf",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -75923,12 +75741,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "floorf",
.up => "ceilf",
.zero => "truncf",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -75998,12 +75816,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "floor",
.up => "ceil",
.zero => "trunc",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76125,12 +75943,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "floor",
.up => "ceil",
.zero => "trunc",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76160,12 +75978,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "floor",
.up => "ceil",
.zero => "trunc",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76195,12 +76013,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "floor",
.up => "ceil",
.zero => "trunc",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76231,12 +76049,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "__floorx",
.up => "__ceilx",
.zero => "__truncx",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76263,12 +76081,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "__floorx",
.up => "__ceilx",
.zero => "__truncx",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76295,12 +76113,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "__floorx",
.up => "__ceilx",
.zero => "__truncx",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76328,12 +76146,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "__floorx",
.up => "__ceilx",
.zero => "__truncx",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76365,12 +76183,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "__floorx",
.up => "__ceilx",
.zero => "__truncx",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76402,12 +76220,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "__floorx",
.up => "__ceilx",
.zero => "__truncx",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76436,12 +76254,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "floorq",
.up => "ceilq",
.zero => "truncq",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76468,12 +76286,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "floorq",
.up => "ceilq",
.zero => "truncq",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76503,12 +76321,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "floorq",
.up => "ceilq",
.zero => "truncq",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -76538,12 +76356,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (direction) {
+ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) {
else => unreachable,
.down => "floorq",
.up => "ceilq",
.zero => "truncq",
- } } } },
+ } } },
.unused,
.unused,
.unused,
@@ -77175,7 +76993,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -77518,7 +77336,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -77679,7 +77497,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -78046,7 +77864,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -78715,7 +78533,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -78759,7 +78577,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -78803,7 +78621,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -78848,7 +78666,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -78893,7 +78711,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -78940,7 +78758,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -78987,7 +78805,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -79040,7 +78858,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -79093,7 +78911,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -79147,7 +78965,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -79201,7 +79019,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -79257,7 +79075,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -80084,7 +79902,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -80128,7 +79946,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -80172,7 +79990,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -80216,7 +80034,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -80260,7 +80078,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -80304,7 +80122,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -80348,7 +80166,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -80401,7 +80219,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -80454,7 +80272,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -80507,7 +80325,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -80560,7 +80378,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -80613,7 +80431,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -83223,7 +83041,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -83267,7 +83085,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -83311,7 +83129,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -83356,7 +83174,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -83401,7 +83219,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -83448,7 +83266,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -83495,7 +83313,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -83548,7 +83366,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -83601,7 +83419,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -83655,7 +83473,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -83709,7 +83527,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -83765,7 +83583,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmphf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmphf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -84606,7 +84424,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -84650,7 +84468,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -84694,7 +84512,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -84738,7 +84556,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -84782,7 +84600,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -84826,7 +84644,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u32, .kind = .{ .reg = .edx } },
@@ -84870,7 +84688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -84923,7 +84741,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -84976,7 +84794,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -85029,7 +84847,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -85082,7 +84900,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -85135,7 +84953,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__cmptf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__cmptf2" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .u8, .kind = .{ .reg = .cl } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
@@ -85191,7 +85009,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.switch_dispatch => try cg.airSwitchDispatch(inst),
.@"try", .try_cold => try cg.airTry(inst),
.try_ptr, .try_ptr_cold => try cg.airTryPtr(inst),
- .dbg_stmt => if (cg.debug_output != .none) {
+ .dbg_stmt => if (!cg.mod.strip) {
const dbg_stmt = air_datas[@intFromEnum(inst)].dbg_stmt;
_ = try cg.addInst(.{
.tag = .pseudo,
@@ -85202,7 +85020,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} },
});
},
- .dbg_empty_stmt => if (cg.debug_output != .none) {
+ .dbg_empty_stmt => if (!cg.mod.strip) {
if (cg.mir_instructions.len > 0) {
const prev_mir_op = &cg.mir_instructions.items(.ops)[cg.mir_instructions.len - 1];
if (prev_mir_op.* == .pseudo_dbg_line_line_column)
@@ -85216,23 +85034,27 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
const old_inline_func = cg.inline_func;
defer cg.inline_func = old_inline_func;
cg.inline_func = dbg_inline_block.data.func;
- if (cg.debug_output != .none) _ = try cg.addInst(.{
+ if (!cg.mod.strip) _ = try cg.addInst(.{
.tag = .pseudo,
.ops = .pseudo_dbg_enter_inline_func,
- .data = .{ .func = dbg_inline_block.data.func },
+ .data = .{ .ip_index = dbg_inline_block.data.func },
});
try cg.lowerBlock(inst, @ptrCast(cg.air.extra.items[dbg_inline_block.end..][0..dbg_inline_block.data.body_len]));
- if (cg.debug_output != .none) _ = try cg.addInst(.{
+ if (!cg.mod.strip) _ = try cg.addInst(.{
.tag = .pseudo,
.ops = .pseudo_dbg_leave_inline_func,
- .data = .{ .func = old_inline_func },
+ .data = .{ .ip_index = old_inline_func },
});
},
- .dbg_var_ptr,
- .dbg_var_val,
- .dbg_arg_inline,
- => if (use_old) try cg.airDbgVar(inst) else if (cg.debug_output != .none) {
+ .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => |air_tag| if (use_old) try cg.airDbgVar(inst) else if (!cg.mod.strip) {
const pl_op = air_datas[@intFromEnum(inst)].pl_op;
+ const air_name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
+ const op_ty = cg.typeOf(pl_op.operand);
+ const local_ty = switch (air_tag) {
+ else => unreachable,
+ .dbg_var_ptr => op_ty.childType(zcu),
+ .dbg_var_val, .dbg_arg_inline => op_ty,
+ };
var ops = try cg.tempsFromOperands(inst, .{pl_op.operand});
var mcv = ops[0].tracking(cg).short;
switch (mcv) {
@@ -85247,7 +85069,19 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
},
}
- try cg.genLocalDebugInfo(inst, ops[0].tracking(cg).short);
+
+ try cg.mir_locals.append(cg.gpa, .{
+ .name = switch (air_name) {
+ .none => switch (air_tag) {
+ else => unreachable,
+ .dbg_arg_inline => .none,
+ },
+ else => try cg.addString(air_name.toSlice(cg.air)),
+ },
+ .type = local_ty.toIntern(),
+ });
+
+ try cg.genLocalDebugInfo(air_tag, local_ty, ops[0].tracking(cg).short);
try ops[0].die(cg);
},
.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 {
.ret => try cg.airRet(inst, false),
.ret_safe => try cg.airRet(inst, true),
.ret_load => try cg.airRetLoad(inst),
- .store, .store_safe => |air_tag| if (use_old) try cg.airStore(inst, switch (air_tag) {
- else => unreachable,
- .store => false,
- .store_safe => true,
- }) else fallback: {
+ .store, .store_safe => |air_tag| fallback: {
const bin_op = air_datas[@intFromEnum(inst)].bin_op;
const ptr_ty = cg.typeOf(bin_op.lhs);
const ptr_info = ptr_ty.ptrInfo(zcu);
@@ -85513,7 +85343,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncsfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncsfhf2" } },
.unused,
.unused,
.unused,
@@ -85570,7 +85400,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncsfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncsfhf2" } },
.unused,
.unused,
.unused,
@@ -85601,7 +85431,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncsfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncsfhf2" } },
.unused,
.unused,
.unused,
@@ -85632,7 +85462,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncsfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncsfhf2" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -85664,7 +85494,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncsfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncsfhf2" } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
@@ -85695,7 +85525,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncdfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncdfhf2" } },
.unused,
.unused,
.unused,
@@ -85723,7 +85553,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncdfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncdfhf2" } },
.unused,
.unused,
.unused,
@@ -85754,7 +85584,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncdfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncdfhf2" } },
.unused,
.unused,
.unused,
@@ -85785,7 +85615,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncdfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncdfhf2" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -85817,7 +85647,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncdfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncdfhf2" } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
@@ -86034,7 +85864,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .size = 16, .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
.unused,
.unused,
.unused,
@@ -86062,7 +85892,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .size = 16, .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
.unused,
.unused,
.unused,
@@ -86090,7 +85920,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .size = 16, .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
.unused,
.unused,
.unused,
@@ -86120,7 +85950,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
.unused,
.unused,
.unused,
@@ -86152,7 +85982,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
.unused,
.unused,
.unused,
@@ -86184,7 +86014,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -86217,7 +86047,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__truncxfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__truncxfhf2" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -86358,7 +86188,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfhf2" } },
.unused,
.unused,
.unused,
@@ -86386,7 +86216,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfhf2" } },
.unused,
.unused,
.unused,
@@ -86417,7 +86247,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfhf2" } },
.unused,
.unused,
.unused,
@@ -86448,7 +86278,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfhf2" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -86480,7 +86310,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfhf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfhf2" } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
@@ -86511,7 +86341,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfsf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfsf2" } },
.unused,
.unused,
.unused,
@@ -86539,7 +86369,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfsf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfsf2" } },
.unused,
.unused,
.unused,
@@ -86570,7 +86400,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfsf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfsf2" } },
.unused,
.unused,
.unused,
@@ -86601,7 +86431,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfsf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfsf2" } },
.unused,
.unused,
.unused,
@@ -86630,7 +86460,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfdf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfdf2" } },
.unused,
.unused,
.unused,
@@ -86658,7 +86488,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfdf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfdf2" } },
.unused,
.unused,
.unused,
@@ -86689,7 +86519,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfdf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfdf2" } },
.unused,
.unused,
.unused,
@@ -86720,7 +86550,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfdf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfdf2" } },
.unused,
.unused,
.unused,
@@ -86749,7 +86579,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfxf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfxf2" } },
.unused,
.unused,
.unused,
@@ -86777,7 +86607,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfxf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfxf2" } },
.unused,
.unused,
.unused,
@@ -86809,7 +86639,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfxf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfxf2" } },
.unused,
.unused,
.unused,
@@ -86841,7 +86671,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__trunctfxf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__trunctfxf2" } },
.unused,
.unused,
.unused,
@@ -86921,7 +86751,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfsf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhfsf2" } },
.unused,
.unused,
.unused,
@@ -86978,7 +86808,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfsf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhfsf2" } },
.unused,
.unused,
.unused,
@@ -87010,7 +86840,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfsf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhfsf2" } },
.unused,
.unused,
.unused,
@@ -87044,7 +86874,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfsf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhfsf2" } },
.unused,
.unused,
.unused,
@@ -87141,7 +86971,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfdf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhfdf2" } },
.unused,
.unused,
.unused,
@@ -87202,7 +87032,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfdf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhfdf2" } },
.unused,
.unused,
.unused,
@@ -87234,7 +87064,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfdf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhfdf2" } },
.unused,
.unused,
.unused,
@@ -87268,7 +87098,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfdf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhfdf2" } },
.unused,
.unused,
.unused,
@@ -87324,7 +87154,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfxf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhfxf2" } },
.unused,
.unused,
.unused,
@@ -87352,7 +87182,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfxf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhfxf2" } },
.unused,
.unused,
.unused,
@@ -87385,7 +87215,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfxf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhfxf2" } },
.unused,
.unused,
.unused,
@@ -87420,7 +87250,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhfxf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhfxf2" } },
.unused,
.unused,
.unused,
@@ -87450,7 +87280,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhftf2" } },
.unused,
.unused,
.unused,
@@ -87478,7 +87308,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhftf2" } },
.unused,
.unused,
.unused,
@@ -87510,7 +87340,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhftf2" } },
.unused,
.unused,
.unused,
@@ -87544,7 +87374,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendhftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendhftf2" } },
.unused,
.unused,
.unused,
@@ -87811,7 +87641,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendsftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendsftf2" } },
.unused,
.unused,
.unused,
@@ -87839,7 +87669,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendsftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendsftf2" } },
.unused,
.unused,
.unused,
@@ -87870,7 +87700,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendsftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendsftf2" } },
.unused,
.unused,
.unused,
@@ -87901,7 +87731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendsftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendsftf2" } },
.unused,
.unused,
.unused,
@@ -87984,7 +87814,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extenddftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extenddftf2" } },
.unused,
.unused,
.unused,
@@ -88012,7 +87842,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extenddftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extenddftf2" } },
.unused,
.unused,
.unused,
@@ -88043,7 +87873,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extenddftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extenddftf2" } },
.unused,
.unused,
.unused,
@@ -88074,7 +87904,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extenddftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extenddftf2" } },
.unused,
.unused,
.unused,
@@ -88105,7 +87935,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .size = 16, .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendxftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendxftf2" } },
.unused,
.unused,
.unused,
@@ -88133,7 +87963,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .size = 16, .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendxftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendxftf2" } },
.unused,
.unused,
.unused,
@@ -88161,7 +87991,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .size = 16, .alignment = .@"16" },
.extra_temps = .{
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendxftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendxftf2" } },
.unused,
.unused,
.unused,
@@ -88191,7 +88021,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendxftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendxftf2" } },
.unused,
.unused,
.unused,
@@ -88223,7 +88053,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendxftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendxftf2" } },
.unused,
.unused,
.unused,
@@ -88255,7 +88085,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__extendxftf2" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__extendxftf2" } },
.unused,
.unused,
.unused,
@@ -99006,9 +98836,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => {
const elem_size = res_ty.abiSize(zcu);
- const base = try cg.tempAllocReg(.usize, abi.RegisterClass.gp);
+ var base = try cg.tempAllocReg(.usize, abi.RegisterClass.gp);
while (try ops[0].toBase(false, cg) or
- try ops[1].toRegClass(true, .general_purpose, cg))
+ try ops[1].toRegClass(true, .general_purpose, cg) or
+ try base.toRegClass(true, .general_purpose, cg))
{}
const base_reg = base.tracking(cg).short.register.to64();
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 {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.unused,
.unused,
.unused,
@@ -99475,7 +99306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfsi" } },
.unused,
.unused,
.unused,
@@ -99501,7 +99332,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfdi" } },
.unused,
.unused,
.unused,
@@ -99527,7 +99358,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfdi" } },
.unused,
.unused,
.unused,
@@ -99553,7 +99384,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfti" } },
.unused,
.unused,
.unused,
@@ -99579,7 +99410,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfti" } },
.unused,
.unused,
.unused,
@@ -99605,7 +99436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfdi" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .u32, .kind = .{ .reg = .ecx } },
@@ -99636,7 +99467,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfdi" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .u32, .kind = .{ .reg = .ecx } },
@@ -99730,7 +99561,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -99762,7 +99593,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -99794,7 +99625,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -99826,7 +99657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -99860,7 +99691,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.unused,
.unused,
.unused,
@@ -99893,7 +99724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.unused,
.unused,
.unused,
@@ -100014,7 +99845,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -100046,7 +99877,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -100080,7 +99911,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.unused,
.unused,
.unused,
@@ -100173,7 +100004,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -100205,7 +100036,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfsi" } },
.{ .type = .u32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -100237,7 +100068,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -100269,7 +100100,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfsi" } },
.{ .type = .u32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -100303,7 +100134,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .i32, .kind = .{ .reg = .eax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfsi" } },
.unused,
.unused,
.unused,
@@ -100336,7 +100167,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u32, .kind = .{ .reg = .eax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfsi" } },
.unused,
.unused,
.unused,
@@ -100399,7 +100230,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfdi" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -100431,7 +100262,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfdi" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -100463,7 +100294,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfdi" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -100495,7 +100326,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfdi" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -100529,7 +100360,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .i64, .kind = .{ .reg = .rax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfdi" } },
.unused,
.unused,
.unused,
@@ -100562,7 +100393,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfdi" } },
.unused,
.unused,
.unused,
@@ -100593,7 +100424,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -100626,7 +100457,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -100659,7 +100490,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -100692,7 +100523,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -100727,7 +100558,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfti" } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
.unused,
@@ -100761,7 +100592,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfti" } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
.unused,
@@ -100796,7 +100627,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfei" } },
.unused,
.unused,
.unused,
@@ -100831,7 +100662,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfei" } },
.unused,
.unused,
.unused,
@@ -100866,7 +100697,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfei" } },
.unused,
.unused,
.unused,
@@ -100901,7 +100732,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfei" } },
.unused,
.unused,
.unused,
@@ -100937,7 +100768,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixhfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixhfei" } },
.unused,
.unused,
.unused,
@@ -100973,7 +100804,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunshfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunshfei" } },
.unused,
.unused,
.unused,
@@ -101115,7 +100946,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfti" } },
.unused,
.unused,
.unused,
@@ -101141,7 +100972,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
.unused,
.unused,
.unused,
@@ -101170,7 +101001,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .i64, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.{ .type = .vector_4_f32, .kind = .{ .smax_mem = .{} } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .u32, .kind = .{ .reg = .ecx } },
@@ -101211,7 +101042,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .i64, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.{ .type = .vector_4_f32, .kind = .{ .smax_mem = .{} } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .u32, .kind = .{ .reg = .ecx } },
@@ -101252,7 +101083,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.{ .type = .vector_4_f32, .kind = .{ .smax_mem = .{} } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
.{ .type = .u32, .kind = .{ .reg = .ecx } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
@@ -101290,7 +101121,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
@@ -101500,7 +101331,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -101531,7 +101362,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -101562,7 +101393,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -101593,7 +101424,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -101796,7 +101627,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -101827,7 +101658,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -101940,7 +101771,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -101971,7 +101802,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfsi" } },
.{ .type = .u32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -102002,7 +101833,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -102033,7 +101864,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfsi" } },
.{ .type = .u32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -102122,7 +101953,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfdi" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -102153,7 +101984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfdi" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -102184,7 +102015,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfdi" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -102215,7 +102046,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfdi" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -102246,7 +102077,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -102278,7 +102109,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -102310,7 +102141,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -102342,7 +102173,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -102377,7 +102208,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfei" } },
.unused,
.unused,
.unused,
@@ -102411,7 +102242,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfei" } },
.unused,
.unused,
.unused,
@@ -102445,7 +102276,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfei" } },
.unused,
.unused,
.unused,
@@ -102479,7 +102310,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunssfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunssfei" } },
.unused,
.unused,
.unused,
@@ -102818,7 +102649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfti" } },
.unused,
.unused,
.unused,
@@ -102844,7 +102675,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfti" } },
.unused,
.unused,
.unused,
@@ -102872,7 +102703,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfei" } },
.unused,
.unused,
.unused,
@@ -102900,7 +102731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfei" } },
.unused,
.unused,
.unused,
@@ -103205,7 +103036,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -103236,7 +103067,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -103267,7 +103098,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -103298,7 +103129,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -103329,7 +103160,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -103361,7 +103192,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixsfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixsfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -103692,7 +103523,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -103723,7 +103554,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -103754,7 +103585,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -103952,7 +103783,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -103983,7 +103814,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfsi" } },
.{ .type = .u32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -104014,7 +103845,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -104045,7 +103876,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfsi" } },
.{ .type = .u32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -104076,7 +103907,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -104108,7 +103939,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfsi" } },
.{ .type = .u32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -104233,7 +104064,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfdi" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -104264,7 +104095,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfdi" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -104295,7 +104126,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfdi" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -104326,7 +104157,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfdi" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -104357,7 +104188,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfdi" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -104389,7 +104220,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfdi" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -104421,7 +104252,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -104453,7 +104284,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -104485,7 +104316,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -104517,7 +104348,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -104549,7 +104380,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -104582,7 +104413,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -104618,7 +104449,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfei" } },
.unused,
.unused,
.unused,
@@ -104652,7 +104483,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfei" } },
.unused,
.unused,
.unused,
@@ -104686,7 +104517,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfei" } },
.unused,
.unused,
.unused,
@@ -104720,7 +104551,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfei" } },
.unused,
.unused,
.unused,
@@ -104754,7 +104585,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixdfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixdfei" } },
.unused,
.unused,
.unused,
@@ -104789,7 +104620,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsdfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsdfei" } },
.unused,
.unused,
.unused,
@@ -105810,7 +105641,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -105842,7 +105673,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -105874,7 +105705,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -105905,7 +105736,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixxfti" } },
.unused,
.unused,
.unused,
@@ -105933,7 +105764,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
.unused,
.unused,
.unused,
@@ -105961,7 +105792,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixxfti" } },
.unused,
.unused,
.unused,
@@ -105989,7 +105820,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
.unused,
.unused,
.unused,
@@ -106017,7 +105848,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixxfti" } },
.unused,
.unused,
.unused,
@@ -106045,7 +105876,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
.unused,
.unused,
.unused,
@@ -106074,7 +105905,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixxfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -106107,7 +105938,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -106140,7 +105971,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixxfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -106173,7 +106004,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -106206,7 +106037,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixxfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -106239,7 +106070,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -106273,7 +106104,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixxfei" } },
.unused,
.unused,
.unused,
@@ -106303,7 +106134,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfei" } },
.unused,
.unused,
.unused,
@@ -106333,7 +106164,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixxfei" } },
.unused,
.unused,
.unused,
@@ -106363,7 +106194,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfei" } },
.unused,
.unused,
.unused,
@@ -106393,7 +106224,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixxfei" } },
.unused,
.unused,
.unused,
@@ -106423,7 +106254,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfei" } },
.unused,
.unused,
.unused,
@@ -106455,7 +106286,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixxfei" } },
.unused,
.unused,
.unused,
@@ -106490,7 +106321,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfei" } },
.unused,
.unused,
.unused,
@@ -106525,7 +106356,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixxfei" } },
.unused,
.unused,
.unused,
@@ -106560,7 +106391,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfei" } },
.unused,
.unused,
.unused,
@@ -106595,7 +106426,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixxfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixxfei" } },
.unused,
.unused,
.unused,
@@ -106630,7 +106461,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunsxfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunsxfei" } },
.unused,
.unused,
.unused,
@@ -106662,7 +106493,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -106695,7 +106526,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -106728,7 +106559,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -106761,7 +106592,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -106794,7 +106625,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -106827,7 +106658,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -106859,7 +106690,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -106890,7 +106721,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -106921,7 +106752,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -106950,7 +106781,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.unused,
.unused,
.unused,
@@ -106976,7 +106807,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfsi" } },
.unused,
.unused,
.unused,
@@ -107004,7 +106835,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -107035,7 +106866,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfsi" } },
.{ .type = .u32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -107066,7 +106897,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -107097,7 +106928,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfsi" } },
.{ .type = .u32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -107128,7 +106959,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfsi" } },
.{ .type = .i32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -107159,7 +106990,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfsi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfsi" } },
.{ .type = .u32, .kind = .{ .reg = .eax } },
.unused,
.unused,
@@ -107188,7 +107019,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfdi" } },
.unused,
.unused,
.unused,
@@ -107214,7 +107045,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfdi" } },
.unused,
.unused,
.unused,
@@ -107242,7 +107073,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfdi" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -107273,7 +107104,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfdi" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -107304,7 +107135,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfdi" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -107335,7 +107166,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfdi" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -107366,7 +107197,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfdi" } },
.{ .type = .i64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -107397,7 +107228,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfdi" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfdi" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.unused,
.unused,
@@ -107426,7 +107257,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfti" } },
.unused,
.unused,
.unused,
@@ -107452,7 +107283,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfti" } },
.unused,
.unused,
.unused,
@@ -107480,7 +107311,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -107512,7 +107343,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -107544,7 +107375,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -107576,7 +107407,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -107608,7 +107439,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .i64, .kind = .{ .reg = .rdx } },
.unused,
@@ -107640,7 +107471,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfti" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfti" } },
.{ .type = .u64, .kind = .{ .reg = .rax } },
.{ .type = .u64, .kind = .{ .reg = .rdx } },
.unused,
@@ -107672,7 +107503,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfei" } },
.unused,
.unused,
.unused,
@@ -107700,7 +107531,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfei" } },
.unused,
.unused,
.unused,
@@ -107731,7 +107562,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfei" } },
.unused,
.unused,
.unused,
@@ -107765,7 +107596,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfei" } },
.unused,
.unused,
.unused,
@@ -107799,7 +107630,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfei" } },
.unused,
.unused,
.unused,
@@ -107833,7 +107664,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfei" } },
.unused,
.unused,
.unused,
@@ -107867,7 +107698,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixtfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixtfei" } },
.unused,
.unused,
.unused,
@@ -107901,7 +107732,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fixunstfei" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fixunstfei" } },
.unused,
.unused,
.unused,
@@ -108149,7 +107980,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.unused,
.unused,
.unused,
@@ -108176,7 +108007,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.unused,
.unused,
.unused,
@@ -108203,7 +108034,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.unused,
.unused,
.unused,
@@ -108230,7 +108061,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.unused,
.unused,
.unused,
@@ -108257,7 +108088,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.unused,
.unused,
.unused,
@@ -108283,7 +108114,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.unused,
.unused,
.unused,
@@ -108309,7 +108140,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatdihf" } },
.unused,
.unused,
.unused,
@@ -108335,7 +108166,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatundihf" } },
.unused,
.unused,
.unused,
@@ -108361,7 +108192,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattihf" } },
.unused,
.unused,
.unused,
@@ -108387,7 +108218,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntihf" } },
.unused,
.unused,
.unused,
@@ -108415,7 +108246,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateihf" } },
.unused,
.unused,
.unused,
@@ -108443,7 +108274,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneihf" } },
.unused,
.unused,
.unused,
@@ -108647,7 +108478,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -108678,7 +108509,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -108709,7 +108540,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -108740,7 +108571,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -108771,7 +108602,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -108803,7 +108634,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -108835,7 +108666,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -108868,7 +108699,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -108901,7 +108732,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -108932,7 +108763,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -108963,7 +108794,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -108994,7 +108825,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109025,7 +108856,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109057,7 +108888,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109089,7 +108920,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -109122,7 +108953,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -109331,7 +109162,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109362,7 +109193,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109393,7 +109224,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109425,7 +109256,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -109458,7 +109289,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109489,7 +109320,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109520,7 +109351,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109552,7 +109383,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -109669,7 +109500,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109700,7 +109531,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109731,7 +109562,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109763,7 +109594,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -109796,7 +109627,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109827,7 +109658,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109858,7 +109689,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109890,7 +109721,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -109954,7 +109785,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatdihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -109985,7 +109816,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatdihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110016,7 +109847,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatdihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110048,7 +109879,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatdihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -110081,7 +109912,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatundihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110112,7 +109943,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatundihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110143,7 +109974,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatundihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110175,7 +110006,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatundihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -110209,7 +110040,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110241,7 +110072,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110273,7 +110104,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110306,7 +110137,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -110340,7 +110171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110372,7 +110203,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110404,7 +110235,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110437,7 +110268,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -110472,7 +110303,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110506,7 +110337,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110540,7 +110371,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110575,7 +110406,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -110611,7 +110442,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110645,7 +110476,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110679,7 +110510,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -110714,7 +110545,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneihf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneihf" } },
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .mem },
.unused,
@@ -111138,7 +110969,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattisf" } },
.unused,
.unused,
.unused,
@@ -111164,7 +110995,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntisf" } },
.unused,
.unused,
.unused,
@@ -111192,7 +111023,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateisf" } },
.unused,
.unused,
.unused,
@@ -111220,7 +111051,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneisf" } },
.unused,
.unused,
.unused,
@@ -111506,7 +111337,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -111537,7 +111368,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -111568,7 +111399,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -111599,7 +111430,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -111630,7 +111461,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -111661,7 +111492,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -111692,7 +111523,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -111723,7 +111554,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112012,7 +111843,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112043,7 +111874,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112074,7 +111905,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112105,7 +111936,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112288,7 +112119,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112319,7 +112150,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112350,7 +112181,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112381,7 +112212,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112472,7 +112303,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatdisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112503,7 +112334,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatdisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112534,7 +112365,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatundisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112565,7 +112396,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatundisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112597,7 +112428,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112629,7 +112460,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112661,7 +112492,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112693,7 +112524,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112726,7 +112557,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112760,7 +112591,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112794,7 +112625,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -112828,7 +112659,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneisf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneisf" } },
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -113468,7 +113299,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattidf" } },
.unused,
.unused,
.unused,
@@ -113494,7 +113325,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntidf" } },
.unused,
.unused,
.unused,
@@ -113522,7 +113353,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateidf" } },
.unused,
.unused,
.unused,
@@ -113550,7 +113381,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneidf" } },
.unused,
.unused,
.unused,
@@ -113844,7 +113675,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -113875,7 +113706,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -113906,7 +113737,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -113937,7 +113768,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -113968,7 +113799,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -113999,7 +113830,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114030,7 +113861,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114061,7 +113892,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114092,7 +113923,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114123,7 +113954,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114154,7 +113985,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114185,7 +114016,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114478,7 +114309,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114509,7 +114340,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114540,7 +114371,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114571,7 +114402,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114602,7 +114433,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114633,7 +114464,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114787,7 +114618,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114818,7 +114649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114849,7 +114680,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114880,7 +114711,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114911,7 +114742,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -114942,7 +114773,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115033,7 +114864,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatdidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115064,7 +114895,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatdidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115095,7 +114926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatdidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115126,7 +114957,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatundidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115157,7 +114988,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatundidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115188,7 +115019,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatundidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115220,7 +115051,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115252,7 +115083,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115284,7 +115115,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115316,7 +115147,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115348,7 +115179,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115380,7 +115211,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115413,7 +115244,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115447,7 +115278,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115481,7 +115312,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115515,7 +115346,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115549,7 +115380,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115583,7 +115414,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneidf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneidf" } },
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -115830,7 +115661,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattixf" } },
.unused,
.unused,
.unused,
@@ -115856,7 +115687,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntixf" } },
.unused,
.unused,
.unused,
@@ -115884,7 +115715,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateixf" } },
.unused,
.unused,
.unused,
@@ -115912,7 +115743,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneixf" } },
.unused,
.unused,
.unused,
@@ -116073,7 +115904,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116107,7 +115938,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116141,7 +115972,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116175,7 +116006,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116237,7 +116068,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116269,7 +116100,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116330,7 +116161,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116362,7 +116193,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116423,7 +116254,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatdixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatdixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116455,7 +116286,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatundixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatundixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116488,7 +116319,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116521,7 +116352,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116555,7 +116386,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116590,7 +116421,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneixf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneixf" } },
.{ .type = .f80, .kind = .{ .reg = .st7 } },
.unused,
.unused,
@@ -116623,7 +116454,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.unused,
.unused,
.unused,
@@ -116651,7 +116482,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.unused,
.unused,
.unused,
@@ -116679,7 +116510,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.unused,
.unused,
.unused,
@@ -116707,7 +116538,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.unused,
.unused,
.unused,
@@ -116733,7 +116564,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.unused,
.unused,
.unused,
@@ -116759,7 +116590,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.unused,
.unused,
.unused,
@@ -116785,7 +116616,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatditf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatditf" } },
.unused,
.unused,
.unused,
@@ -116811,7 +116642,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunditf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunditf" } },
.unused,
.unused,
.unused,
@@ -116837,7 +116668,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattitf" } },
.unused,
.unused,
.unused,
@@ -116863,7 +116694,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
.unused,
.unused,
.unused,
@@ -116891,7 +116722,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateitf" } },
.unused,
.unused,
.unused,
@@ -116919,7 +116750,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneitf" } },
.unused,
.unused,
.unused,
@@ -116948,7 +116779,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -116981,7 +116812,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117014,7 +116845,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117047,7 +116878,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117080,7 +116911,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117113,7 +116944,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117146,7 +116977,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117179,7 +117010,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117212,7 +117043,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117245,7 +117076,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117278,7 +117109,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117311,7 +117142,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117343,7 +117174,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117374,7 +117205,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117405,7 +117236,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117436,7 +117267,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117467,7 +117298,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117498,7 +117329,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117529,7 +117360,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117560,7 +117391,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117591,7 +117422,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117622,7 +117453,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117653,7 +117484,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117684,7 +117515,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u32, .kind = .{ .reg = .edi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunsitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunsitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117715,7 +117546,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatditf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatditf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117746,7 +117577,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatditf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatditf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117777,7 +117608,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .i64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatditf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatditf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117808,7 +117639,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunditf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunditf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117839,7 +117670,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunditf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunditf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117870,7 +117701,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatunditf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatunditf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117902,7 +117733,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117934,7 +117765,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117966,7 +117797,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .i64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floattitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floattitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -117998,7 +117829,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -118030,7 +117861,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -118062,7 +117893,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .reg = .rdi } },
.{ .type = .u64, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuntitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -118095,7 +117926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -118129,7 +117960,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -118163,7 +117994,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floateitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floateitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -118197,7 +118028,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -118231,7 +118062,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -118265,7 +118096,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .reg = .rdi } },
.{ .type = .usize, .kind = .{ .reg = .rsi } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__floatuneitf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__floatuneitf" } },
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.unused,
.unused,
@@ -131980,7 +131811,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
.unused,
.unused,
.unused,
@@ -132013,7 +131844,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
.unused,
.unused,
.unused,
@@ -132048,7 +131879,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
.unused,
.unused,
.unused,
@@ -133648,7 +133479,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
.unused,
.unused,
.unused,
@@ -133679,7 +133510,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
.unused,
.unused,
.unused,
@@ -133710,7 +133541,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
.unused,
.unused,
.unused,
@@ -142100,7 +141931,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
.unused,
.unused,
.unused,
@@ -142133,7 +141964,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
.unused,
.unused,
.unused,
@@ -142168,7 +141999,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
.unused,
.unused,
.unused,
@@ -143776,7 +143607,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
.unused,
.unused,
.unused,
@@ -143807,7 +143638,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
.unused,
.unused,
.unused,
@@ -143838,7 +143669,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
.unused,
.unused,
.unused,
@@ -147771,7 +147602,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -147804,7 +147635,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -147839,7 +147670,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -148356,7 +148187,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -148387,7 +148218,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -148418,7 +148249,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -151430,7 +151261,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -151463,7 +151294,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -151498,7 +151329,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -151895,7 +151726,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -151926,7 +151757,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -151957,7 +151788,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -152469,7 +152300,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
.unused,
.unused,
.unused,
@@ -152502,7 +152333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
.unused,
.unused,
.unused,
@@ -152537,7 +152368,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fminh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fminh" } },
.unused,
.unused,
.unused,
@@ -153617,7 +153448,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
.unused,
.unused,
.unused,
@@ -153648,7 +153479,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
.unused,
.unused,
.unused,
@@ -153679,7 +153510,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fminq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fminq" } },
.unused,
.unused,
.unused,
@@ -154161,7 +153992,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
.unused,
.unused,
.unused,
@@ -154194,7 +154025,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
.unused,
.unused,
.unused,
@@ -154229,7 +154060,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmaxh" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmaxh" } },
.unused,
.unused,
.unused,
@@ -155309,7 +155140,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
.unused,
.unused,
.unused,
@@ -155340,7 +155171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
.unused,
.unused,
.unused,
@@ -155371,7 +155202,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaxq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } },
.unused,
.unused,
.unused,
@@ -156102,7 +155933,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -156135,7 +155966,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -156170,7 +156001,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addhf3" } },
.unused,
.unused,
.unused,
@@ -157568,7 +157399,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -157599,7 +157430,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -157630,7 +157461,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__addtf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } },
.unused,
.unused,
.unused,
@@ -158112,7 +157943,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -158145,7 +157976,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -158180,7 +158011,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .ax } },
.{ .type = .f32, .kind = .mem },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__mulhf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__mulhf3" } },
.unused,
.unused,
.unused,
@@ -159111,7 +158942,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -159142,7 +158973,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -159173,7 +159004,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .u32, .kind = .{ .rc = .general_purpose } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__multf3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__multf3" } },
.unused,
.unused,
.unused,
@@ -161054,7 +160885,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = @tagName(symbol) } } },
+ .{ .type = .usize, .kind = .{ .extern_func = @tagName(symbol) } },
.unused,
.unused,
.unused,
@@ -161103,7 +160934,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"32" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src0 } } },
+ .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src0 } } },
.unused,
.unused,
.unused,
@@ -161129,7 +160960,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src0 } } },
+ .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src0 } } },
.unused,
.unused,
.unused,
@@ -161154,7 +160985,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"8" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src0 } } },
+ .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src0 } } },
.unused,
.unused,
.unused,
@@ -161194,7 +161025,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"32" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src0 } } },
+ .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src0 } } },
.unused,
.unused,
.unused,
@@ -161219,7 +161050,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src0 } } },
+ .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src0 } } },
.unused,
.unused,
.unused,
@@ -161243,7 +161074,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"8" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src0 } } },
+ .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src0 } } },
.unused,
.unused,
.unused,
@@ -161282,7 +161113,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_gpr, .none, .none } },
},
.extra_temps = .{
- .{ .type = .anyerror, .kind = .{ .lazy_symbol = .{ .kind = .const_data } } },
+ .{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
.{ .type = .u32, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } } },
.unused,
.unused,
@@ -161311,7 +161142,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_gpr, .none, .none } },
},
.extra_temps = .{
- .{ .type = .anyerror, .kind = .{ .lazy_symbol = .{ .kind = .const_data } } },
+ .{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
.{ .type = .u32, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } } },
.unused,
.unused,
@@ -161340,7 +161171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_gpr, .none, .none } },
},
.extra_temps = .{
- .{ .type = .anyerror, .kind = .{ .lazy_symbol = .{ .kind = .const_data } } },
+ .{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
.{ .type = .u32, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } } },
.unused,
.unused,
@@ -161391,7 +161222,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"32" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src1 } } },
+ .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src1 } } },
.unused,
.unused,
.unused,
@@ -161417,7 +161248,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src1 } } },
+ .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src1 } } },
.unused,
.unused,
.unused,
@@ -161442,7 +161273,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"8" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .lazy_symbol = .{ .kind = .code, .ref = .src1 } } },
+ .{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .code, .ref = .src1 } } },
.unused,
.unused,
.unused,
@@ -161638,7 +161469,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmah" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmah" } },
.unused,
.unused,
.unused,
@@ -161781,7 +161612,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
.{ .type = .f16, .kind = .{ .reg = .xmm2 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmah" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmah" } },
.unused,
.unused,
.unused,
@@ -161818,7 +161649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
.{ .type = .f16, .kind = .{ .reg = .xmm2 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmah" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmah" } },
.unused,
.unused,
.unused,
@@ -161857,7 +161688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
.{ .type = .f16, .kind = .{ .reg = .xmm2 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmah" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmah" } },
.{ .type = .f16, .kind = .{ .reg = .ax } },
.unused,
.unused,
@@ -161899,7 +161730,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f16, .kind = .{ .reg = .xmm0 } },
.{ .type = .f16, .kind = .{ .reg = .xmm1 } },
.{ .type = .f16, .kind = .{ .reg = .xmm2 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmah" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmah" } },
.unused,
.unused,
.unused,
@@ -161987,7 +161818,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaf" } },
.unused,
.unused,
.unused,
@@ -162153,7 +161984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .{ .reg = .xmm1 } },
.{ .type = .f32, .kind = .{ .reg = .xmm2 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaf" } },
.unused,
.unused,
.unused,
@@ -162189,7 +162020,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f32, .kind = .{ .reg = .xmm0 } },
.{ .type = .f32, .kind = .{ .reg = .xmm1 } },
.{ .type = .f32, .kind = .{ .reg = .xmm2 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaf" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaf" } },
.unused,
.unused,
.unused,
@@ -162271,7 +162102,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fma" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fma" } },
.unused,
.unused,
.unused,
@@ -162437,7 +162268,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
.{ .type = .f64, .kind = .{ .reg = .xmm2 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fma" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fma" } },
.unused,
.unused,
.unused,
@@ -162473,7 +162304,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
.{ .type = .f64, .kind = .{ .reg = .xmm2 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fma" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fma" } },
.unused,
.unused,
.unused,
@@ -162509,7 +162340,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f64, .kind = .{ .reg = .xmm0 } },
.{ .type = .f64, .kind = .{ .reg = .xmm1 } },
.{ .type = .f64, .kind = .{ .reg = .xmm2 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fma" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fma" } },
.unused,
.unused,
.unused,
@@ -162546,7 +162377,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmax" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmax" } },
.unused,
.unused,
.unused,
@@ -162582,7 +162413,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
.{ .type = .f80, .kind = .{ .reg = .xmm0 } },
.{ .type = .f80, .kind = .{ .frame = .call_frame } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__fmax" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__fmax" } },
.unused,
.unused,
.unused,
@@ -162619,7 +162450,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
.unused,
.unused,
.unused,
@@ -162652,7 +162483,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
.{ .type = .f128, .kind = .{ .reg = .xmm2 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
.unused,
.unused,
.unused,
@@ -162688,7 +162519,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
.{ .type = .f128, .kind = .{ .reg = .xmm2 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
.unused,
.unused,
.unused,
@@ -162724,7 +162555,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .type = .f128, .kind = .{ .reg = .xmm0 } },
.{ .type = .f128, .kind = .{ .reg = .xmm1 } },
.{ .type = .f128, .kind = .{ .reg = .xmm2 } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "fmaq" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } },
.unused,
.unused,
.unused,
@@ -162778,7 +162609,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_gpr, .none, .none } },
},
.extra_temps = .{
- .{ .type = .anyerror, .kind = .{ .lazy_symbol = .{ .kind = .const_data } } },
+ .{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -162802,7 +162633,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_gpr, .none, .none } },
},
.extra_temps = .{
- .{ .type = .anyerror, .kind = .{ .lazy_symbol = .{ .kind = .const_data } } },
+ .{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -162826,7 +162657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_gpr, .none, .none } },
},
.extra_temps = .{
- .{ .type = .anyerror, .kind = .{ .lazy_symbol = .{ .kind = .const_data } } },
+ .{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -163517,65 +163348,18 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
};
for (ops) |op| try op.die(cg);
},
- .runtime_nav_ptr => switch (cg.bin_file.tag) {
- .elf, .macho => {
- const ty_nav = air_datas[@intFromEnum(inst)].ty_nav;
-
- const nav = ip.getNav(ty_nav.nav);
- const sym_index, const relocation = sym: {
- if (cg.bin_file.cast(.elf)) |elf_file| {
- const zo = elf_file.zigObjectPtr().?;
- if (nav.getExtern(ip)) |e| {
- const sym = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip));
- linkage: switch (e.linkage) {
- .internal => {},
- .strong => switch (e.visibility) {
- .default => zo.symbol(sym).flags.is_extern_ptr = true,
- .hidden, .protected => {},
- },
- .weak => {
- zo.symbol(sym).flags.weak = true;
- continue :linkage .strong;
- },
- .link_once => unreachable,
- }
- break :sym .{ sym, e.relocation };
- } else break :sym .{ try zo.getOrCreateMetadataForNav(zcu, ty_nav.nav), .any };
- } else if (cg.bin_file.cast(.macho)) |macho_file| {
- const zo = macho_file.getZigObject().?;
- if (nav.getExtern(ip)) |e| {
- const sym = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip));
- linkage: switch (e.linkage) {
- .internal => {},
- .strong => switch (e.visibility) {
- .default => zo.symbols.items[sym].flags.is_extern_ptr = true,
- .hidden, .protected => {},
- },
- .weak => {
- zo.symbols.items[sym].flags.weak = true;
- continue :linkage .strong;
- },
- .link_once => unreachable,
- }
- break :sym .{ sym, e.relocation };
- } else break :sym .{ try zo.getOrCreateMetadataForNav(macho_file, ty_nav.nav), .any };
- } else unreachable;
- };
-
- if (cg.mod.pic) {
- try cg.spillRegisters(&.{ .rdi, .rax });
- } else {
- try cg.spillRegisters(&.{.rax});
- }
-
- var slot = try cg.tempInit(.usize, switch (relocation) {
- .any => .{ .lea_symbol = .{ .sym_index = sym_index } },
- .pcrel => .{ .lea_pcrel = .{ .sym_index = sym_index } },
- });
- while (try slot.toRegClass(true, .general_purpose, cg)) {}
- try slot.finish(inst, &.{}, &.{}, cg);
- },
- else => return cg.fail("TODO implement runtime_nav_ptr on {}", .{cg.bin_file.tag}),
+ .runtime_nav_ptr => {
+ const ty_nav = air_datas[@intFromEnum(inst)].ty_nav;
+ const nav = ip.getNav(ty_nav.nav);
+ const is_threadlocal = zcu.comp.config.any_non_single_threaded and nav.isThreadlocal(ip);
+ if (is_threadlocal) if (cg.mod.pic) {
+ try cg.spillRegisters(&.{ .rdi, .rax });
+ } else {
+ try cg.spillRegisters(&.{.rax});
+ };
+ var res = try cg.tempInit(.fromInterned(ty_nav.ty), .{ .lea_nav = ty_nav.nav });
+ if (is_threadlocal) while (try res.toRegClass(true, .general_purpose, cg)) {};
+ try res.finish(inst, &.{}, &.{}, cg);
},
.c_va_arg => try cg.airVaArg(inst),
.c_va_copy => try cg.airVaCopy(inst),
@@ -164231,11 +164015,11 @@ fn airFptrunc(self: *CodeGen, inst: Air.Inst.Index) !void {
},
else => unreachable,
}) {
- var callee_buf: ["__trunc?f?f2".len]u8 = undefined;
- break :result try self.genCall(.{ .lib = .{
+ var sym_buf: ["__trunc?f?f2".len]u8 = undefined;
+ break :result try self.genCall(.{ .extern_func = .{
.return_type = self.floatCompilerRtAbiType(dst_ty, src_ty).toIntern(),
.param_types = &.{self.floatCompilerRtAbiType(src_ty, dst_ty).toIntern()},
- .callee = std.fmt.bufPrint(&callee_buf, "__trunc{c}f{c}f2", .{
+ .sym = std.fmt.bufPrint(&sym_buf, "__trunc{c}f{c}f2", .{
floatCompilerRtAbiName(src_bits),
floatCompilerRtAbiName(dst_bits),
}) catch unreachable,
@@ -164335,11 +164119,11 @@ fn airFpext(self: *CodeGen, inst: Air.Inst.Index) !void {
else => unreachable,
}) {
if (dst_ty.isVector(zcu)) break :result null;
- var callee_buf: ["__extend?f?f2".len]u8 = undefined;
- break :result try self.genCall(.{ .lib = .{
+ var sym_buf: ["__extend?f?f2".len]u8 = undefined;
+ break :result try self.genCall(.{ .extern_func = .{
.return_type = self.floatCompilerRtAbiType(dst_scalar_ty, src_scalar_ty).toIntern(),
.param_types = &.{self.floatCompilerRtAbiType(src_scalar_ty, dst_scalar_ty).toIntern()},
- .callee = std.fmt.bufPrint(&callee_buf, "__extend{c}f{c}f2", .{
+ .sym = std.fmt.bufPrint(&sym_buf, "__extend{c}f{c}f2", .{
floatCompilerRtAbiName(src_bits),
floatCompilerRtAbiName(dst_bits),
}) catch unreachable,
@@ -164776,7 +164560,7 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void {
.storage = .{ .repeated_elem = mask_val.ip_index },
} });
- const splat_mcv = try self.genTypedValue(.fromInterned(splat_val));
+ const splat_mcv = try self.lowerValue(.fromInterned(splat_val));
const splat_addr_mcv: MCValue = switch (splat_mcv) {
.memory, .indirect, .load_frame => splat_mcv.address(),
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
.mul, .mul_wrap => {},
.div_trunc, .div_floor, .div_exact, .rem, .mod => {
const signed = dst_ty.isSignedInt(zcu);
- var callee_buf: ["__udiv?i3".len]u8 = undefined;
+ var sym_buf: ["__udiv?i3".len]u8 = undefined;
const signed_div_floor_state: struct {
frame_index: FrameIndex,
state: State,
@@ -164994,7 +164778,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
const lhs_mcv = try self.resolveInst(bin_op.lhs);
const mat_lhs_mcv = switch (lhs_mcv) {
- .load_symbol => mat_lhs_mcv: {
+ .load_nav, .load_uav, .load_lazy_sym => mat_lhs_mcv: {
// TODO clean this up!
const addr_reg = try self.copyToTmpRegister(.usize, lhs_mcv.address());
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
const rhs_mcv = try self.resolveInst(bin_op.rhs);
const mat_rhs_mcv = switch (rhs_mcv) {
- .load_symbol => mat_rhs_mcv: {
+ .load_nav, .load_uav, .load_lazy_sym => mat_rhs_mcv: {
// TODO clean this up!
const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
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
break :state .{ .frame_index = frame_index, .state = state, .reloc = reloc };
} else undefined;
const call_mcv = try self.genCall(
- .{ .lib = .{
+ .{ .extern_func = .{
.return_type = dst_ty.toIntern(),
.param_types = &.{ src_ty.toIntern(), src_ty.toIntern() },
- .callee = std.fmt.bufPrint(&callee_buf, "__{s}{s}{c}i3", .{
+ .sym = std.fmt.bufPrint(&sym_buf, "__{s}{s}{c}i3", .{
if (signed) "" else "u",
switch (tag) {
.div_trunc, .div_exact => "div",
@@ -165082,10 +164866,10 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
});
self.performReloc(signed_div_floor_state.reloc);
const dst_mcv = try self.genCall(
- .{ .lib = .{
+ .{ .extern_func = .{
.return_type = dst_ty.toIntern(),
.param_types = &.{ src_ty.toIntern(), src_ty.toIntern() },
- .callee = std.fmt.bufPrint(&callee_buf, "__div{c}i3", .{
+ .sym = std.fmt.bufPrint(&sym_buf, "__div{c}i3", .{
intCompilerRtAbiName(@intCast(dst_ty.bitSize(zcu))),
}) catch unreachable,
} },
@@ -165119,7 +164903,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
const rhs_mcv = try self.resolveInst(bin_op.rhs);
const mat_rhs_mcv = switch (rhs_mcv) {
- .load_symbol => mat_rhs_mcv: {
+ .load_nav, .load_uav, .load_lazy_sym => mat_rhs_mcv: {
// TODO clean this up!
const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
@@ -165333,10 +165117,10 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {
const ptr_c_int = try pt.singleMutPtrType(.c_int);
const overflow = try self.allocTempRegOrMem(.c_int, false);
- const dst_mcv = try self.genCall(.{ .lib = .{
+ const dst_mcv = try self.genCall(.{ .extern_func = .{
.return_type = .i128_type,
.param_types = &.{ .i128_type, .i128_type, ptr_c_int.toIntern() },
- .callee = "__muloti4",
+ .sym = "__muloti4",
} }, &.{ .i128, .i128, ptr_c_int }, &.{
.{ .air_ref = bin_op.lhs },
.{ .air_ref = bin_op.rhs },
@@ -165351,7 +165135,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {
const lhs_mcv = try self.resolveInst(bin_op.lhs);
const mat_lhs_mcv = switch (lhs_mcv) {
- .load_symbol => mat_lhs_mcv: {
+ .load_nav, .load_uav, .load_lazy_sym => mat_lhs_mcv: {
// TODO clean this up!
const addr_reg = try self.copyToTmpRegister(.usize, lhs_mcv.address());
break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
@@ -165375,7 +165159,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {
const rhs_mcv = try self.resolveInst(bin_op.rhs);
const mat_rhs_mcv = switch (rhs_mcv) {
- .load_symbol => mat_rhs_mcv: {
+ .load_nav, .load_uav, .load_lazy_sym => mat_rhs_mcv: {
// TODO clean this up!
const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
@@ -165849,10 +165633,10 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
.signed => {
const ptr_c_int = try pt.singleMutPtrType(.c_int);
const overflow = try self.allocTempRegOrMem(.c_int, false);
- const result = try self.genCall(.{ .lib = .{
+ const result = try self.genCall(.{ .extern_func = .{
.return_type = .i128_type,
.param_types = &.{ .i128_type, .i128_type, ptr_c_int.toIntern() },
- .callee = "__muloti4",
+ .sym = "__muloti4",
} }, &.{ .i128, .i128, ptr_c_int }, &.{
.{ .air_ref = bin_op.lhs },
.{ .air_ref = bin_op.rhs },
@@ -165906,7 +165690,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
break :mat_lhs_mcv mat_lhs_mcv;
},
},
- .load_symbol => {
+ .load_nav, .load_uav, .load_lazy_sym => {
// TODO clean this up!
const addr_reg = try self.copyToTmpRegister(.usize, lhs_mcv.address());
break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
@@ -165930,7 +165714,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
break :mat_rhs_mcv mat_rhs_mcv;
},
},
- .load_symbol => {
+ .load_nav, .load_uav, .load_lazy_sym => {
// TODO clean this up!
const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
@@ -166406,7 +166190,7 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {
defer self.register_manager.unlockReg(shift_lock);
const mask_ty = try pt.vectorType(.{ .len = 16, .child = .u8_type });
- const mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
+ const mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
.ty = mask_ty.toIntern(),
.storage = .{ .elems = &([1]InternPool.Index{
(try rhs_ty.childType(zcu).maxIntScalar(pt, .u8)).toIntern(),
@@ -166547,7 +166331,7 @@ fn airShlSat(self: *CodeGen, inst: Air.Inst.Index) !void {
// if lhs is negative, it is min
switch (lhs_ty.intInfo(zcu).signedness) {
.unsigned => {
- const bound_mcv = try self.genTypedValue(try lhs_ty.maxIntScalar(self.pt, lhs_ty));
+ const bound_mcv = try self.lowerValue(try lhs_ty.maxIntScalar(self.pt, lhs_ty));
try self.genCopy(lhs_ty, dst_mcv, bound_mcv, .{});
},
.signed => {
@@ -166556,7 +166340,7 @@ fn airShlSat(self: *CodeGen, inst: Air.Inst.Index) !void {
// we only need the highest bit so shifting the highest part of lhs_mcv
// is enough to check the signedness. other parts can be skipped here.
var lhs_temp2 = try self.tempInit(lhs_ty, lhs_mcv);
- var zero_temp = try self.tempInit(lhs_ty, try self.genTypedValue(try self.pt.intValue(lhs_ty, 0)));
+ var zero_temp = try self.tempInit(lhs_ty, try self.lowerValue(try self.pt.intValue(lhs_ty, 0)));
const sign_cc_temp = lhs_temp2.cmpInts(.lt, &zero_temp, self) catch |err| switch (err) {
error.SelectFailed => unreachable,
else => |e| return e,
@@ -166567,13 +166351,13 @@ fn airShlSat(self: *CodeGen, inst: Air.Inst.Index) !void {
try sign_cc_temp.die(self);
// if it is negative
- const min_mcv = try self.genTypedValue(try lhs_ty.minIntScalar(self.pt, lhs_ty));
+ const min_mcv = try self.lowerValue(try lhs_ty.minIntScalar(self.pt, lhs_ty));
try self.genCopy(lhs_ty, dst_mcv, min_mcv, .{});
const sign_reloc_br = try self.asmJmpReloc(undefined);
self.performReloc(sign_reloc_condbr);
// if it is positive
- const max_mcv = try self.genTypedValue(try lhs_ty.maxIntScalar(self.pt, lhs_ty));
+ const max_mcv = try self.lowerValue(try lhs_ty.maxIntScalar(self.pt, lhs_ty));
try self.genCopy(lhs_ty, dst_mcv, max_mcv, .{});
self.performReloc(sign_reloc_br);
},
@@ -167294,7 +167078,12 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
}.to64(),
),
},
- .memory, .load_symbol, .load_direct, .load_got => switch (index_mcv) {
+ .memory,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
+ => switch (index_mcv) {
.immediate => |index_imm| try self.asmMemoryImmediate(
.{ ._, .bt },
.{
@@ -167356,11 +167145,15 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
},
),
.memory,
- .load_symbol,
- .load_direct,
- .load_got,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .load_extern_func,
+ .lea_extern_func,
=> try self.genSetReg(addr_reg, .usize, array_mcv.address(), .{}),
- .lea_symbol, .lea_direct => unreachable,
else => return self.fail("TODO airArrayElemVal_val for {s} of {}", .{
@tagName(array_mcv), array_ty.fmt(pt),
}),
@@ -168461,7 +168254,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A
.child = (try pt.intType(.signed, scalar_bits)).ip_index,
});
- const sign_mcv = try self.genTypedValue(switch (tag) {
+ const sign_mcv = try self.lowerValue(switch (tag) {
.neg => try vec_ty.minInt(pt, vec_ty),
.abs => try vec_ty.maxInt(pt, vec_ty),
else => unreachable,
@@ -168603,11 +168396,11 @@ fn genRoundLibcall(self: *CodeGen, ty: Type, src_mcv: MCValue, mode: bits.RoundM
if (ty.zigTypeTag(zcu) != .float)
return self.fail("TODO implement genRound for {}", .{ty.fmt(pt)});
- var callee_buf: ["__trunc?".len]u8 = undefined;
- return try self.genCall(.{ .lib = .{
+ var sym_buf: ["__trunc?".len]u8 = undefined;
+ return try self.genCall(.{ .extern_func = .{
.return_type = ty.toIntern(),
.param_types = &.{ty.toIntern()},
- .callee = std.fmt.bufPrint(&callee_buf, "{s}{s}{s}", .{
+ .sym = std.fmt.bufPrint(&sym_buf, "{s}{s}{s}", .{
floatLibcAbiPrefix(ty),
switch (mode.direction) {
.down => "floor",
@@ -168880,11 +168673,11 @@ fn airSqrt(self: *CodeGen, inst: Air.Inst.Index) !void {
80, 128 => true,
else => unreachable,
}) {
- var callee_buf: ["__sqrt?".len]u8 = undefined;
- break :result try self.genCall(.{ .lib = .{
+ var sym_buf: ["__sqrt?".len]u8 = undefined;
+ break :result try self.genCall(.{ .extern_func = .{
.return_type = ty.toIntern(),
.param_types = &.{ty.toIntern()},
- .callee = std.fmt.bufPrint(&callee_buf, "{s}sqrt{s}", .{
+ .sym = std.fmt.bufPrint(&sym_buf, "{s}sqrt{s}", .{
floatLibcAbiPrefix(ty),
floatLibcAbiSuffix(ty),
}) catch unreachable,
@@ -169033,11 +168826,11 @@ fn airSqrt(self: *CodeGen, inst: Air.Inst.Index) !void {
fn airUnaryMath(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
const ty = self.typeOf(un_op);
- var callee_buf: ["__round?".len]u8 = undefined;
- const result = try self.genCall(.{ .lib = .{
+ var sym_buf: ["__round?".len]u8 = undefined;
+ const result = try self.genCall(.{ .extern_func = .{
.return_type = ty.toIntern(),
.param_types = &.{ty.toIntern()},
- .callee = std.fmt.bufPrint(&callee_buf, "{s}{s}{s}", .{
+ .sym = std.fmt.bufPrint(&sym_buf, "{s}{s}{s}", .{
floatLibcAbiPrefix(ty),
switch (tag) {
.sin,
@@ -169237,19 +169030,19 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE
.immediate,
.register,
.register_offset,
- .lea_symbol,
- .lea_pcrel,
- .lea_direct,
- .lea_got,
.lea_frame,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
=> try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref(), .{}),
.memory,
.indirect,
- .load_symbol,
- .load_pcrel,
- .load_direct,
- .load_got,
.load_frame,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
=> {
const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv);
const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
@@ -169457,19 +169250,19 @@ fn store(
.immediate,
.register,
.register_offset,
- .lea_symbol,
- .lea_pcrel,
- .lea_direct,
- .lea_got,
.lea_frame,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
=> try self.genCopy(src_ty, ptr_mcv.deref(), src_mcv, opts),
.memory,
.indirect,
- .load_symbol,
- .load_pcrel,
- .load_direct,
- .load_got,
.load_frame,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
=> {
const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv);
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:
.eflags,
.register_overflow,
.register_mask,
- .lea_symbol,
- .lea_pcrel,
- .lea_direct,
- .lea_got,
.lea_frame,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
.elementwise_args,
.reserved_frame,
.air_ref,
=> unreachable, // unmodifiable destination
.register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)),
.register_pair, .register_triple, .register_quadruple => unreachable, // unimplemented
- .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => {
+ .memory, .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {
const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
defer self.register_manager.unlockReg(addr_reg_lock);
@@ -170706,7 +170499,7 @@ fn genMulDivBinOp(
defer for (reg_locks) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);
const mat_lhs_mcv = switch (lhs_mcv) {
- .load_symbol => mat_lhs_mcv: {
+ .load_nav, .load_uav, .load_lazy_sym => mat_lhs_mcv: {
// TODO clean this up!
const addr_reg = try self.copyToTmpRegister(.usize, lhs_mcv.address());
break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
@@ -170719,7 +170512,7 @@ fn genMulDivBinOp(
};
defer if (mat_lhs_lock) |lock| self.register_manager.unlockReg(lock);
const mat_rhs_mcv = switch (rhs_mcv) {
- .load_symbol => mat_rhs_mcv: {
+ .load_nav, .load_uav, .load_lazy_sym => mat_rhs_mcv: {
// TODO clean this up!
const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
@@ -170887,7 +170680,7 @@ fn genMulDivBinOp(
.is_const = true,
},
});
- _ = try self.genCall(.{ .lib = .{
+ _ = try self.genCall(.{ .extern_func = .{
.return_type = .void_type,
.param_types = &.{
manyptr_u32_ty.toIntern(),
@@ -170895,7 +170688,7 @@ fn genMulDivBinOp(
manyptr_const_u32_ty.toIntern(),
.usize_type,
},
- .callee = switch (tag) {
+ .sym = switch (tag) {
.div_trunc,
.div_floor,
.div_exact,
@@ -171118,8 +170911,8 @@ fn genBinOp(
.rem, .mod => {},
else => if (!type_needs_libcall) break :libcall,
}
- var callee_buf: ["__mod?f3".len]u8 = undefined;
- const callee = switch (air_tag) {
+ var sym_buf: ["__mod?f3".len]u8 = undefined;
+ const sym = switch (air_tag) {
.add,
.sub,
.mul,
@@ -171127,11 +170920,11 @@ fn genBinOp(
.div_trunc,
.div_floor,
.div_exact,
- => std.fmt.bufPrint(&callee_buf, "__{s}{c}f3", .{
+ => std.fmt.bufPrint(&sym_buf, "__{s}{c}f3", .{
@tagName(air_tag)[0..3],
floatCompilerRtAbiName(float_bits),
}),
- .rem, .mod, .min, .max => std.fmt.bufPrint(&callee_buf, "{s}f{s}{s}", .{
+ .rem, .mod, .min, .max => std.fmt.bufPrint(&sym_buf, "{s}f{s}{s}", .{
floatLibcAbiPrefix(lhs_ty),
switch (air_tag) {
.rem, .mod => "mod",
@@ -171145,22 +170938,22 @@ fn genBinOp(
@tagName(air_tag), lhs_ty.fmt(pt),
}),
} catch unreachable;
- const result = try self.genCall(.{ .lib = .{
+ const result = try self.genCall(.{ .extern_func = .{
.return_type = lhs_ty.toIntern(),
.param_types = &.{ lhs_ty.toIntern(), rhs_ty.toIntern() },
- .callee = callee,
+ .sym = sym,
} }, &.{ lhs_ty, rhs_ty }, &.{ .{ .air_ref = lhs_air }, .{ .air_ref = rhs_air } }, .{});
return switch (air_tag) {
.mod => result: {
const adjusted: MCValue = if (type_needs_libcall) adjusted: {
- var add_callee_buf: ["__add?f3".len]u8 = undefined;
- break :adjusted try self.genCall(.{ .lib = .{
+ var add_sym_buf: ["__add?f3".len]u8 = undefined;
+ break :adjusted try self.genCall(.{ .extern_func = .{
.return_type = lhs_ty.toIntern(),
.param_types = &.{
lhs_ty.toIntern(),
rhs_ty.toIntern(),
},
- .callee = std.fmt.bufPrint(&add_callee_buf, "__add{c}f3", .{
+ .sym = std.fmt.bufPrint(&add_sym_buf, "__add{c}f3", .{
floatCompilerRtAbiName(float_bits),
}) catch unreachable,
} }, &.{ lhs_ty, rhs_ty }, &.{ result, .{ .air_ref = rhs_air } }, .{});
@@ -171259,10 +171052,10 @@ fn genBinOp(
}),
else => unreachable,
};
- break :result try self.genCall(.{ .lib = .{
+ break :result try self.genCall(.{ .extern_func = .{
.return_type = lhs_ty.toIntern(),
.param_types = &.{ lhs_ty.toIntern(), rhs_ty.toIntern() },
- .callee = callee,
+ .sym = sym,
} }, &.{ lhs_ty, rhs_ty }, &.{ adjusted, .{ .air_ref = rhs_air } }, .{});
},
.div_trunc, .div_floor => try self.genRoundLibcall(lhs_ty, result, .{
@@ -171545,13 +171338,15 @@ fn genBinOp(
.immediate,
.eflags,
.register_offset,
- .load_symbol,
- .lea_symbol,
- .load_direct,
- .lea_direct,
- .load_got,
- .lea_got,
.lea_frame,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .load_extern_func,
+ .lea_extern_func,
=> true,
.memory => |addr| std.math.cast(i32, @as(i64, @bitCast(addr))) == null,
else => false,
@@ -171604,15 +171399,15 @@ fn genBinOp(
.register_offset,
.register_overflow,
.register_mask,
- .load_symbol,
- .lea_symbol,
- .load_pcrel,
- .lea_pcrel,
- .load_direct,
- .lea_direct,
- .load_got,
- .lea_got,
.lea_frame,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .load_extern_func,
+ .lea_extern_func,
.elementwise_args,
.reserved_frame,
.air_ref,
@@ -172710,7 +172505,7 @@ fn genBinOp(
.cmp_neq,
=> {
const unsigned_ty = try lhs_ty.toUnsigned(pt);
- const not_mcv = try self.genTypedValue(try unsigned_ty.maxInt(pt, unsigned_ty));
+ const not_mcv = try self.lowerValue(try unsigned_ty.maxInt(pt, unsigned_ty));
const not_mem: Memory = if (not_mcv.isBase())
try not_mcv.mem(self, .{ .size = .fromSize(abi_size) })
else
@@ -172792,11 +172587,11 @@ fn genBinOpMir(
.eflags,
.register_overflow,
.register_mask,
- .lea_direct,
- .lea_got,
.lea_frame,
- .lea_symbol,
- .lea_pcrel,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
.elementwise_args,
.reserved_frame,
.air_ref,
@@ -172886,16 +172681,16 @@ fn genBinOpMir(
.register_offset,
.memory,
.indirect,
- .load_symbol,
- .lea_symbol,
- .load_pcrel,
- .lea_pcrel,
- .load_direct,
- .lea_direct,
- .load_got,
- .lea_got,
.load_frame,
.lea_frame,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .load_extern_func,
+ .lea_extern_func,
=> {
direct: {
try self.asmRegisterMemory(mir_limb_tag, dst_alias, switch (src_mcv) {
@@ -172928,10 +172723,11 @@ fn genBinOpMir(
switch (src_mcv) {
.eflags,
.register_offset,
- .lea_symbol,
- .lea_direct,
- .lea_got,
.lea_frame,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
=> {
assert(off == 0);
const reg = try self.copyToTmpRegister(ty, src_mcv);
@@ -172943,9 +172739,10 @@ fn genBinOpMir(
);
},
.memory,
- .load_symbol,
- .load_direct,
- .load_got,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
=> {
const ptr_ty = try pt.singleConstPtrType(ty);
const addr_reg = try self.copyToTmpRegister(ptr_ty, src_mcv.address());
@@ -172965,13 +172762,20 @@ fn genBinOpMir(
}
}
},
- .memory, .indirect, .load_symbol, .load_pcrel, .load_got, .load_direct, .load_frame => {
+ .memory,
+ .indirect,
+ .load_frame,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
+ => {
const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock };
const limb_abi_size: u32 = @min(abi_size, 8);
const dst_info: OpInfo = switch (dst_mcv) {
else => unreachable,
- .memory, .load_symbol, .load_got, .load_direct => dst: {
+ .memory, .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => dst: {
const dst_addr_reg =
(try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
@@ -173007,19 +172811,24 @@ fn genBinOpMir(
.register_quadruple,
.register_offset,
.indirect,
- .lea_direct,
- .lea_got,
.load_frame,
.lea_frame,
- .lea_symbol,
- .lea_pcrel,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
=> null,
- .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => src: {
+ .memory,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
+ => src: {
switch (resolved_src_mcv) {
.memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr))) != null and
std.math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null)
break :src null,
- .load_symbol, .load_got, .load_direct => {},
+ .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {},
else => unreachable,
}
@@ -173059,9 +172868,10 @@ fn genBinOpMir(
};
const dst_limb_mem: Memory = switch (dst_mcv) {
.memory,
- .load_symbol,
- .load_got,
- .load_direct,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
=> .{
.base = .{ .reg = dst_info.?.addr_reg },
.mod = .{ .rm = .{
@@ -173151,16 +172961,16 @@ fn genBinOpMir(
.eflags,
.memory,
.indirect,
- .load_symbol,
- .lea_symbol,
- .load_pcrel,
- .lea_pcrel,
- .load_direct,
- .lea_direct,
- .load_got,
- .lea_got,
.load_frame,
.lea_frame,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .load_extern_func,
+ .lea_extern_func,
=> {
const src_limb_mcv: MCValue = if (src_info) |info| .{
.indirect = .{ .reg = info.addr_reg, .off = off },
@@ -173170,10 +172980,11 @@ fn genBinOpMir(
},
.eflags,
.register_offset,
- .lea_symbol,
- .lea_direct,
- .lea_got,
.lea_frame,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
=> switch (limb_i) {
0 => resolved_src_mcv,
else => .{ .immediate = 0 },
@@ -173221,11 +173032,11 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv
.register_offset,
.register_overflow,
.register_mask,
- .lea_symbol,
- .lea_pcrel,
- .lea_direct,
- .lea_got,
.lea_frame,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
.elementwise_args,
.reserved_frame,
.air_ref,
@@ -173283,15 +173094,15 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv
},
.register_offset,
.eflags,
- .load_symbol,
- .lea_symbol,
- .load_pcrel,
- .lea_pcrel,
- .load_direct,
- .lea_direct,
- .load_got,
- .lea_got,
.lea_frame,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .load_extern_func,
+ .lea_extern_func,
=> {
const src_reg = try self.copyToTmpRegister(dst_ty, resolved_src_mcv);
switch (abi_size) {
@@ -173346,7 +173157,14 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv
}
},
.register_pair, .register_triple, .register_quadruple => unreachable, // unimplemented
- .memory, .indirect, .load_symbol, .load_pcrel, .load_direct, .load_got, .load_frame => {
+ .memory,
+ .indirect,
+ .load_frame,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
+ => {
const tmp_reg = try self.copyToTmpRegister(dst_ty, dst_mcv);
const tmp_mcv = MCValue{ .register = tmp_reg };
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
}
fn airArg(self: *CodeGen, inst: Air.Inst.Index) !void {
- const pt = self.pt;
- const zcu = pt.zcu;
- // skip zero-bit arguments as they don't have a corresponding arg instruction
- var arg_index = self.arg_index;
- while (self.args[arg_index] == .none) arg_index += 1;
- self.arg_index = arg_index + 1;
-
- const result: MCValue = if (self.debug_output == .none and self.liveness.isUnused(inst)) .unreach else result: {
+ const zcu = self.pt.zcu;
+ const arg_index = for (self.args, 0..) |arg, arg_index| {
+ if (arg != .none) break arg_index;
+ } else unreachable;
+ const src_mcv = self.args[arg_index];
+ self.args = self.args[arg_index + 1 ..];
+ const result: MCValue = if (self.mod.strip and self.liveness.isUnused(inst)) .unreach else result: {
const arg_ty = self.typeOfIndex(inst);
- const src_mcv = self.args[arg_index];
switch (src_mcv) {
.register, .register_pair, .load_frame => {
for (src_mcv.getRegs()) |reg| self.register_manager.getRegAssumeFree(reg, inst);
@@ -173467,68 +173283,115 @@ fn airArg(self: *CodeGen, inst: Air.Inst.Index) !void {
return self.finishAir(inst, result, .{ .none, .none, .none });
}
-fn airDbgVarArgs(self: *CodeGen) !void {
- if (self.debug_output == .none) return;
- if (!self.pt.zcu.typeToFunc(self.fn_type).?.is_var_args) return;
- try self.asmPseudo(.pseudo_dbg_var_args_none);
-}
-
-fn genLocalDebugInfo(
- self: *CodeGen,
- inst: Air.Inst.Index,
- mcv: MCValue,
-) !void {
- if (self.debug_output == .none) return;
- switch (self.air.instructions.items(.tag)[@intFromEnum(inst)]) {
+fn genLocalDebugInfo(cg: *CodeGen, air_tag: Air.Inst.Tag, ty: Type, mcv: MCValue) !void {
+ assert(!cg.mod.strip);
+ _ = switch (air_tag) {
else => unreachable,
- .arg, .dbg_arg_inline, .dbg_var_val => |tag| {
- switch (mcv) {
- .none => try self.asmAir(.dbg_local, inst),
- .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
- .immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, .u(imm)),
- .lea_frame => |frame_addr| try self.asmAirFrameAddress(.dbg_local, inst, frame_addr),
- .lea_symbol => |sym_off| try self.asmAirImmediate(.dbg_local, inst, .rel(sym_off)),
- else => {
- const ty = switch (tag) {
- else => unreachable,
- .arg => self.typeOfIndex(inst),
- .dbg_arg_inline, .dbg_var_val => self.typeOf(
- self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op.operand,
- ),
- };
- const frame_index = try self.allocFrameIndex(.initSpill(ty, self.pt.zcu));
- try self.genSetMem(.{ .frame = frame_index }, 0, ty, mcv, .{});
- try self.asmAirMemory(.dbg_local, inst, .{
- .base = .{ .frame = frame_index },
- .mod = .{ .rm = .{ .size = .qword } },
- });
+ .arg, .dbg_var_val, .dbg_arg_inline => switch (mcv) {
+ .none, .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
+ .immediate => |imm| if (std.math.cast(u32, imm)) |small| try cg.addInst(.{
+ .tag = .pseudo,
+ .ops = switch (air_tag) {
+ else => unreachable,
+ .arg, .dbg_arg_inline => .pseudo_dbg_arg_i_u,
+ .dbg_var_val => .pseudo_dbg_var_i_u,
},
- }
+ .data = .{ .i = .{ .i = small } },
+ }) else try cg.addInst(.{
+ .tag = .pseudo,
+ .ops = switch (air_tag) {
+ else => unreachable,
+ .arg, .dbg_arg_inline => .pseudo_dbg_arg_i_64,
+ .dbg_var_val => .pseudo_dbg_var_i_64,
+ },
+ .data = .{ .i64 = imm },
+ }),
+ .lea_frame => |frame_addr| try cg.addInst(.{
+ .tag = .pseudo,
+ .ops = switch (air_tag) {
+ else => unreachable,
+ .arg, .dbg_arg_inline => .pseudo_dbg_arg_fa,
+ .dbg_var_val => .pseudo_dbg_var_fa,
+ },
+ .data = .{ .fa = frame_addr },
+ }),
+ else => {
+ const frame_index = try cg.allocFrameIndex(.initSpill(ty, cg.pt.zcu));
+ try cg.genSetMem(.{ .frame = frame_index }, 0, ty, mcv, .{});
+ _ = try cg.addInst(.{
+ .tag = .pseudo,
+ .ops = switch (air_tag) {
+ else => unreachable,
+ .arg, .dbg_arg_inline => .pseudo_dbg_arg_m,
+ .dbg_var_val => .pseudo_dbg_var_m,
+ },
+ .data = .{ .x = .{
+ .payload = try cg.addExtra(Mir.Memory.encode(.{
+ .base = .{ .frame = frame_index },
+ .mod = .{ .rm = .{ .size = .qword } },
+ })),
+ } },
+ });
+ },
},
.dbg_var_ptr => switch (mcv) {
else => unreachable,
- .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
- .lea_frame => |frame_addr| try self.asmAirMemory(.dbg_local, inst, .{
- .base = .{ .frame = frame_addr.index },
- .mod = .{ .rm = .{
- .size = .qword,
- .disp = frame_addr.off,
+ .none, .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
+ .lea_frame => |frame_addr| try cg.addInst(.{
+ .tag = .pseudo,
+ .ops = .pseudo_dbg_var_m,
+ .data = .{ .x = .{
+ .payload = try cg.addExtra(Mir.Memory.encode(.{
+ .base = .{ .frame = frame_addr.index },
+ .mod = .{ .rm = .{
+ .size = .qword,
+ .disp = frame_addr.off,
+ } },
+ })),
} },
}),
- // debug info should explicitly ignore pcrel requirements
- .lea_symbol, .lea_pcrel => |sym_off| try self.asmAirMemory(.dbg_local, inst, .{
- .base = .{ .reloc = sym_off.sym_index },
- .mod = .{ .rm = .{
- .size = .qword,
- .disp = sym_off.off,
+ .lea_nav => |nav| try cg.addInst(.{
+ .tag = .pseudo,
+ .ops = .pseudo_dbg_var_m,
+ .data = .{ .x = .{
+ .payload = try cg.addExtra(Mir.Memory.encode(.{
+ .base = .{ .nav = nav },
+ .mod = .{ .rm = .{ .size = .qword } },
+ })),
+ } },
+ }),
+ .lea_uav => |uav| try cg.addInst(.{
+ .tag = .pseudo,
+ .ops = .pseudo_dbg_var_m,
+ .data = .{ .x = .{
+ .payload = try cg.addExtra(Mir.Memory.encode(.{
+ .base = .{ .uav = uav },
+ .mod = .{ .rm = .{ .size = .qword } },
+ })),
} },
}),
- .lea_direct, .lea_got => |sym_index| try self.asmAirMemory(.dbg_local, inst, .{
- .base = .{ .reloc = sym_index },
- .mod = .{ .rm = .{ .size = .qword } },
+ .lea_lazy_sym => |lazy_sym| try cg.addInst(.{
+ .tag = .pseudo,
+ .ops = .pseudo_dbg_var_m,
+ .data = .{ .x = .{
+ .payload = try cg.addExtra(Mir.Memory.encode(.{
+ .base = .{ .lazy_sym = lazy_sym },
+ .mod = .{ .rm = .{ .size = .qword } },
+ })),
+ } },
+ }),
+ .lea_extern_func => |extern_func| try cg.addInst(.{
+ .tag = .pseudo,
+ .ops = .pseudo_dbg_var_m,
+ .data = .{ .x = .{
+ .payload = try cg.addExtra(Mir.Memory.encode(.{
+ .base = .{ .extern_func = extern_func },
+ .mod = .{ .rm = .{ .size = .qword } },
+ })),
+ } },
}),
},
- }
+ };
}
fn airRetAddr(self: *CodeGen, inst: Air.Inst.Index) !void {
@@ -173552,8 +173415,8 @@ fn airCall(self: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
@ptrCast(self.air.extra.items[extra.end..][0..extra.data.args_len]);
const ExpectedContents = extern struct {
- tys: [16][@sizeOf(Type)]u8 align(@alignOf(Type)),
- vals: [16][@sizeOf(MCValue)]u8 align(@alignOf(MCValue)),
+ tys: [32][@sizeOf(Type)]u8 align(@alignOf(Type)),
+ vals: [32][@sizeOf(MCValue)]u8 align(@alignOf(MCValue)),
};
var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
@@ -173579,11 +173442,10 @@ fn airCall(self: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
fn genCall(self: *CodeGen, info: union(enum) {
air: Air.Inst.Ref,
- lib: struct {
+ extern_func: struct {
return_type: InternPool.Index,
param_types: []const InternPool.Index,
- lib: ?[]const u8 = null,
- callee: []const u8,
+ sym: []const u8,
},
}, arg_types: []const Type, args: []const MCValue, opts: CopyOptions) !MCValue {
const pt = self.pt;
@@ -173599,18 +173461,18 @@ fn genCall(self: *CodeGen, info: union(enum) {
else => unreachable,
};
},
- .lib => |lib| try pt.funcType(.{
- .param_types = lib.param_types,
- .return_type = lib.return_type,
+ .extern_func => |extern_func| try pt.funcType(.{
+ .param_types = extern_func.param_types,
+ .return_type = extern_func.return_type,
.cc = self.target.cCallingConvention().?,
}),
};
const fn_info = zcu.typeToFunc(fn_ty).?;
const ExpectedContents = extern struct {
- var_args: [16][@sizeOf(Type)]u8 align(@alignOf(Type)),
- frame_indices: [16]FrameIndex,
- reg_locks: [16][@sizeOf(?RegisterLock)]u8 align(@alignOf(?RegisterLock)),
+ var_args: [32][@sizeOf(Type)]u8 align(@alignOf(Type)),
+ frame_indices: [32]FrameIndex,
+ reg_locks: [32][@sizeOf(?RegisterLock)]u8 align(@alignOf(?RegisterLock)),
};
var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
@@ -173830,52 +173692,9 @@ fn genCall(self: *CodeGen, info: union(enum) {
else => func_key,
} else func_key,
}) {
- .func => |func| {
- if (self.bin_file.cast(.elf)) |elf_file| {
- const zo = elf_file.zigObjectPtr().?;
- const sym_index = try zo.getOrCreateMetadataForNav(zcu, func.owner_nav);
- try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = sym_index }));
- } else if (self.bin_file.cast(.coff)) |coff_file| {
- const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
- const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
- const scratch_reg = abi.getCAbiLinkerScratchReg(fn_info.cc);
- try self.genSetReg(scratch_reg, .usize, .{ .lea_got = sym_index }, .{});
- try self.asmRegister(.{ ._, .call }, scratch_reg);
- } else if (self.bin_file.cast(.macho)) |macho_file| {
- const zo = macho_file.getZigObject().?;
- const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);
- const sym = zo.symbols.items[sym_index];
- try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = sym.nlist_idx }));
- } else if (self.bin_file.cast(.plan9)) |p9| {
- const atom_index = try p9.seeNav(pt, func.owner_nav);
- const atom = p9.getAtom(atom_index);
- try self.asmMemory(.{ ._, .call }, .{
- .base = .{ .reg = .ds },
- .mod = .{ .rm = .{
- .size = .qword,
- .disp = @intCast(atom.getOffsetTableAddress(p9)),
- } },
- });
- } else unreachable;
- },
- .@"extern" => |@"extern"| if (self.bin_file.cast(.elf)) |elf_file| {
- const target_sym_index = try elf_file.getGlobalSymbol(
- @"extern".name.toSlice(ip),
- @"extern".lib_name.toSlice(ip),
- );
- try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
- } else if (self.bin_file.cast(.macho)) |macho_file| {
- const target_sym_index = try macho_file.getGlobalSymbol(
- @"extern".name.toSlice(ip),
- @"extern".lib_name.toSlice(ip),
- );
- try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
- } else try self.genExternSymbolRef(
- .call,
- @"extern".lib_name.toSlice(ip),
- @"extern".name.toSlice(ip),
- ),
- else => return self.fail("TODO implement calling bitcasted functions", .{}),
+ else => unreachable,
+ .func => |func| try self.asmImmediate(.{ ._, .call }, .{ .nav = .{ .index = func.owner_nav } }),
+ .@"extern" => |@"extern"| try self.asmImmediate(.{ ._, .call }, .{ .nav = .{ .index = @"extern".owner_nav } }),
}
} else {
assert(self.typeOf(callee).zigTypeTag(zcu) == .pointer);
@@ -173883,13 +173702,7 @@ fn genCall(self: *CodeGen, info: union(enum) {
try self.genSetReg(scratch_reg, .usize, .{ .air_ref = callee }, .{});
try self.asmRegister(.{ ._, .call }, scratch_reg);
},
- .lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {
- const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);
- try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
- } else if (self.bin_file.cast(.macho)) |macho_file| {
- const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);
- try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
- } else try self.genExternSymbolRef(.call, lib.lib, lib.callee),
+ .extern_func => |extern_func| try self.asmImmediate(.{ ._, .call }, .{ .extern_func = try self.addString(extern_func.sym) }),
}
return call_info.return_value.short;
}
@@ -174023,11 +173836,11 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
80, 128 => false,
else => unreachable,
}) {
- var callee_buf: ["__???f2".len]u8 = undefined;
- const ret = try self.genCall(.{ .lib = .{
+ var sym_buf: ["__???f2".len]u8 = undefined;
+ const ret = try self.genCall(.{ .extern_func = .{
.return_type = .i32_type,
.param_types = &.{ ty.toIntern(), ty.toIntern() },
- .callee = std.fmt.bufPrint(&callee_buf, "__{s}{c}f2", .{
+ .sym = std.fmt.bufPrint(&sym_buf, "__{s}{c}f2", .{
switch (op) {
.eq => "eq",
.neq => "ne",
@@ -174170,17 +173983,27 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
.register_overflow,
.register_mask,
.indirect,
- .lea_direct,
- .lea_got,
.lea_frame,
- .lea_symbol,
- .lea_pcrel,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
.elementwise_args,
.reserved_frame,
.air_ref,
=> unreachable,
- .register, .register_pair, .register_triple, .register_quadruple, .load_frame => null,
- .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => dst: {
+ .register,
+ .register_pair,
+ .register_triple,
+ .register_quadruple,
+ .load_frame,
+ => null,
+ .memory,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
+ => dst: {
switch (resolved_dst_mcv) {
.memory => |addr| if (std.math.cast(
i32,
@@ -174189,7 +174012,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
i32,
@as(i64, @bitCast(addr)) + abi_size - 8,
) != null) break :dst null,
- .load_symbol, .load_pcrel, .load_got, .load_direct => {},
+ .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {},
else => unreachable,
}
@@ -174226,17 +174049,26 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
.register_overflow,
.register_mask,
.indirect,
- .lea_symbol,
- .lea_pcrel,
- .lea_direct,
- .lea_got,
.lea_frame,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
.elementwise_args,
.reserved_frame,
.air_ref,
=> unreachable,
- .register_pair, .register_triple, .register_quadruple, .load_frame => null,
- .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => src: {
+ .register_pair,
+ .register_triple,
+ .register_quadruple,
+ .load_frame,
+ => null,
+ .memory,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
+ => src: {
switch (resolved_src_mcv) {
.memory => |addr| if (std.math.cast(
i32,
@@ -174245,7 +174077,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
i32,
@as(i64, @bitCast(addr)) + abi_size - 8,
) != null) break :src null,
- .load_symbol, .load_pcrel, .load_got, .load_direct => {},
+ .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {},
else => unreachable,
}
@@ -174526,10 +174358,31 @@ fn genTry(
return result;
}
-fn airDbgVar(self: *CodeGen, inst: Air.Inst.Index) !void {
- const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
- try self.genLocalDebugInfo(inst, try self.resolveInst(pl_op.operand));
- return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none });
+fn airDbgVar(cg: *CodeGen, inst: Air.Inst.Index) !void {
+ if (cg.mod.strip) return;
+ const air_tag = cg.air.instructions.items(.tag)[@intFromEnum(inst)];
+ const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
+ const air_name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
+ const op_ty = cg.typeOf(pl_op.operand);
+ const local_ty = switch (air_tag) {
+ else => unreachable,
+ .dbg_var_ptr => op_ty.childType(cg.pt.zcu),
+ .dbg_var_val, .dbg_arg_inline => op_ty,
+ };
+
+ try cg.mir_locals.append(cg.gpa, .{
+ .name = switch (air_name) {
+ .none => switch (air_tag) {
+ else => unreachable,
+ .dbg_arg_inline => .none,
+ },
+ else => try cg.addString(air_name.toSlice(cg.air)),
+ },
+ .type = local_ty.toIntern(),
+ });
+
+ try cg.genLocalDebugInfo(air_tag, local_ty, try cg.resolveInst(pl_op.operand));
+ return cg.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none });
}
fn 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)
.register_offset,
.register_overflow,
.register_mask,
- .lea_direct,
- .lea_got,
- .lea_symbol,
- .lea_pcrel,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
.elementwise_args,
.reserved_frame,
.air_ref,
@@ -174684,10 +174537,10 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue)
},
.memory,
- .load_symbol,
- .load_pcrel,
- .load_got,
- .load_direct,
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
=> {
const addr_reg = (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
@@ -175721,7 +175574,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
.memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |_|
break :arg input_mcv,
.indirect, .load_frame => break :arg input_mcv,
- .load_symbol, .load_direct, .load_got => {},
+ .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {},
else => {
const temp_mcv = try self.allocTempRegOrMem(ty, false);
try self.genCopy(ty, temp_mcv, input_mcv, .{});
@@ -176000,12 +175853,20 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
} }
else
return self.fail("invalid modifier: '{s}'", .{modifier}),
- .lea_got => |sym_index| if (std.mem.eql(u8, modifier, "P"))
- .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_got = sym_index }) }
+ .lea_nav => |nav| if (std.mem.eql(u8, modifier, "P"))
+ .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_nav = nav }) }
+ else
+ return self.fail("invalid modifier: '{s}'", .{modifier}),
+ .lea_uav => |uav| if (std.mem.eql(u8, modifier, "P"))
+ .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_uav = uav }) }
+ else
+ return self.fail("invalid modifier: '{s}'", .{modifier}),
+ .lea_lazy_sym => |lazy_sym| if (std.mem.eql(u8, modifier, "P"))
+ .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_lazy_sym = lazy_sym }) }
else
return self.fail("invalid modifier: '{s}'", .{modifier}),
- .lea_symbol => |sym_off| if (std.mem.eql(u8, modifier, "P"))
- .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_symbol = sym_off }) }
+ .lea_extern_func => |extern_func| if (std.mem.eql(u8, modifier, "P"))
+ .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_extern_func = extern_func }) }
else
return self.fail("invalid modifier: '{s}'", .{modifier}),
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
.eflags,
.register_overflow,
.register_mask,
- .lea_direct,
- .lea_got,
.lea_frame,
- .lea_symbol,
- .lea_pcrel,
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
.elementwise_args,
.reserved_frame,
.air_ref,
@@ -176788,7 +176649,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
}
return;
},
- .load_symbol, .load_pcrel, .load_direct, .load_got => {
+ .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {
const src_addr_reg =
(try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
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
.undef => if (opts.safety and part_i > 0) .{ .register = dst_regs[0] } else .undef,
dst_tag => |src_regs| .{ .register = src_regs[part_i] },
.memory, .indirect, .load_frame => src_mcv.address().offset(part_disp).deref(),
- .load_symbol, .load_pcrel, .load_direct, .load_got => .{ .indirect = .{
+ .load_nav,
+ .load_uav,
+ .load_lazy_sym,
+ .load_extern_func,
+ => .{ .indirect = .{
.reg = src_info.?.addr_reg,
.off = part_disp,
} },
@@ -176842,11 +176707,11 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
src_mcv,
opts,
),
- .memory, .load_symbol, .load_pcrel, .load_direct, .load_got => {
+ .memory => {
switch (dst_mcv) {
.memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
return self.genSetMem(.{ .reg = .ds }, small_addr, ty, src_mcv, opts),
- .load_symbol, .load_pcrel, .load_direct, .load_got => {},
+ .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {},
else => unreachable,
}
@@ -176863,6 +176728,10 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
src_mcv,
opts,
),
+ .load_nav => |nav| try self.genSetMem(.{ .nav = nav }, 0, ty, src_mcv, opts),
+ .load_uav => |uav| try self.genSetMem(.{ .uav = uav }, 0, ty, src_mcv, opts),
+ .load_lazy_sym => |lazy_sym| try self.genSetMem(.{ .lazy_sym = lazy_sym }, 0, ty, src_mcv, opts),
+ .load_extern_func => |extern_func| try self.genSetMem(.{ .extern_func = extern_func }, 0, ty, src_mcv, opts),
}
}
@@ -176907,14 +176776,14 @@ fn genSetReg(
.len = self.vectorSize(.float),
.child = .u8_type,
});
- try self.genSetReg(dst_reg, full_ty, try self.genTypedValue(
+ try self.genSetReg(dst_reg, full_ty, try self.lowerValue(
.fromInterned(try pt.intern(.{ .aggregate = .{
.ty = full_ty.toIntern(),
.storage = .{ .repeated_elem = (try pt.intValue(.u8, 0xaa)).toIntern() },
} })),
), opts);
},
- .x87 => try self.genSetReg(dst_reg, .f80, try self.genTypedValue(
+ .x87 => try self.genSetReg(dst_reg, .f80, try self.lowerValue(
try pt.floatValue(.f80, @as(f80, @bitCast(@as(u80, 0xaaaaaaaaaaaaaaaaaaaa)))),
), opts),
.ip, .cr, .dr => unreachable,
@@ -176944,12 +176813,24 @@ fn genSetReg(
}
},
.register => |src_reg| if (dst_reg.id() != src_reg.id()) switch (dst_reg.class()) {
- .general_purpose, .gphi => switch (src_reg.class()) {
- .general_purpose, .gphi => try self.asmRegisterRegister(
+ .general_purpose => switch (src_reg.class()) {
+ .general_purpose => try self.asmRegisterRegister(
.{ ._, .mov },
dst_alias,
registerAlias(src_reg, abi_size),
),
+ .gphi => if (dst_reg.isClass(.gphi)) try self.asmRegisterRegister(
+ .{ ._, .mov },
+ dst_alias,
+ registerAlias(src_reg, abi_size),
+ ) else {
+ const src_lock = self.register_manager.lockReg(src_reg);
+ defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
+ const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gphi);
+
+ try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg.to8(), src_reg);
+ try self.asmRegisterRegister(.{ ._, .mov }, dst_alias, tmp_reg.to8());
+ },
.segment => try self.asmRegisterRegister(
.{ ._, .mov },
dst_alias,
@@ -176985,6 +176866,26 @@ fn genSetReg(
});
},
},
+ .gphi => switch (src_reg.class()) {
+ .general_purpose => if (src_reg.isClass(.gphi)) try self.asmRegisterRegister(
+ .{ ._, .mov },
+ dst_alias,
+ registerAlias(src_reg, abi_size),
+ ) else {
+ const dst_lock = self.register_manager.lockReg(dst_reg);
+ defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
+ const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gphi);
+
+ try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg.to8(), src_reg.to8());
+ try self.asmRegisterRegister(.{ ._, .mov }, dst_reg, tmp_reg.to8());
+ },
+ .gphi => try self.asmRegisterRegister(
+ .{ ._, .mov },
+ dst_alias,
+ registerAlias(src_reg, abi_size),
+ ),
+ .segment, .x87, .mmx, .ip, .cr, .dr, .sse => unreachable,
+ },
.segment => try self.asmRegisterRegister(
.{ ._, .mov },
dst_reg,
@@ -177303,7 +177204,7 @@ fn genSetReg(
if (src_reg_mask.info.inverted) try self.asmRegister(.{ ._, .not }, registerAlias(bits_reg, abi_size));
try self.genSetReg(dst_reg, ty, .{ .register = bits_reg }, .{});
},
- .memory, .load_symbol, .load_pcrel, .load_direct, .load_got => {
+ .memory, .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {
switch (src_mcv) {
.memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
return (try self.moveStrategy(
@@ -177317,52 +177218,50 @@ fn genSetReg(
.disp = small_addr,
} },
}),
- .load_symbol => |sym_off| switch (dst_reg.class()) {
+ .load_nav => |nav| switch (dst_reg.class()) {
.general_purpose, .gphi => {
- assert(sym_off.off == 0);
try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
- .base = .{ .reloc = sym_off.sym_index },
- .mod = .{ .rm = .{
- .size = self.memSize(ty),
- .disp = sym_off.off,
- } },
+ .base = .{ .nav = nav },
+ .mod = .{ .rm = .{ .size = self.memSize(ty) } },
});
return;
},
.segment, .mmx, .ip, .cr, .dr => unreachable,
.x87, .sse => {},
},
- .load_pcrel => |sym_off| switch (dst_reg.class()) {
+ .load_uav => |uav| switch (dst_reg.class()) {
.general_purpose, .gphi => {
- assert(sym_off.off == 0);
try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
- .base = .{ .pcrel = sym_off.sym_index },
- .mod = .{ .rm = .{
- .size = self.memSize(ty),
- .disp = sym_off.off,
- } },
+ .base = .{ .uav = uav },
+ .mod = .{ .rm = .{ .size = self.memSize(ty) } },
});
return;
},
.segment, .mmx, .ip, .cr, .dr => unreachable,
.x87, .sse => {},
},
- .load_direct => |sym_index| switch (dst_reg.class()) {
+ .load_lazy_sym => |lazy_sym| switch (dst_reg.class()) {
.general_purpose, .gphi => {
- _ = try self.addInst(.{
- .tag = .mov,
- .ops = .direct_reloc,
- .data = .{ .rx = .{
- .r1 = dst_alias,
- .payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
- } },
+ try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
+ .base = .{ .lazy_sym = lazy_sym },
+ .mod = .{ .rm = .{ .size = self.memSize(ty) } },
+ });
+ return;
+ },
+ .segment, .mmx, .ip, .cr, .dr => unreachable,
+ .x87, .sse => {},
+ },
+ .load_extern_func => |extern_func| switch (dst_reg.class()) {
+ .general_purpose, .gphi => {
+ try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
+ .base = .{ .extern_func = extern_func },
+ .mod = .{ .rm = .{ .size = self.memSize(ty) } },
});
return;
},
.segment, .mmx, .ip, .cr, .dr => unreachable,
.x87, .sse => {},
},
- .load_got => {},
else => unreachable,
}
@@ -177375,65 +177274,17 @@ fn genSetReg(
.mod = .{ .rm = .{ .size = self.memSize(ty) } },
});
},
- .lea_symbol => |sym_off| switch (self.bin_file.tag) {
- .elf, .macho => {
- try self.asmRegisterMemory(
- .{ ._, .lea },
- dst_reg.to64(),
- .{
- .base = .{ .reloc = sym_off.sym_index },
- },
- );
- if (sym_off.off != 0) try self.asmRegisterMemory(
- .{ ._, .lea },
- dst_reg.to64(),
- .{
- .base = .{ .reg = dst_reg.to64() },
- .mod = .{ .rm = .{ .disp = sym_off.off } },
- },
- );
- },
- else => return self.fail("TODO emit symbol sequence on {s}", .{
- @tagName(self.bin_file.tag),
- }),
- },
- .lea_pcrel => |sym_off| switch (self.bin_file.tag) {
- .elf, .macho => {
- try self.asmRegisterMemory(
- .{ ._, .lea },
- dst_reg.to64(),
- .{
- .base = .{ .pcrel = sym_off.sym_index },
- },
- );
- if (sym_off.off != 0) try self.asmRegisterMemory(
- .{ ._, .lea },
- dst_reg.to64(),
- .{
- .base = .{ .reg = dst_reg.to64() },
- .mod = .{ .rm = .{ .disp = sym_off.off } },
- },
- );
- },
- else => return self.fail("TODO emit symbol sequence on {s}", .{
- @tagName(self.bin_file.tag),
- }),
- },
- .lea_direct, .lea_got => |sym_index| _ = try self.addInst(.{
- .tag = switch (src_mcv) {
- .lea_direct => .lea,
- .lea_got => .mov,
- else => unreachable,
- },
- .ops = switch (src_mcv) {
- .lea_direct => .direct_reloc,
- .lea_got => .got_reloc,
- else => unreachable,
- },
- .data = .{ .rx = .{
- .r1 = dst_reg.to64(),
- .payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
- } },
+ .lea_nav => |nav| try self.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
+ .base = .{ .nav = nav },
+ }),
+ .lea_uav => |uav| try self.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
+ .base = .{ .uav = uav },
+ }),
+ .lea_lazy_sym => |lazy_sym| try self.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
+ .base = .{ .lazy_sym = lazy_sym },
+ }),
+ .lea_extern_func => |lazy_sym| try self.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
+ .base = .{ .extern_func = lazy_sym },
}),
.air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref), opts),
}
@@ -177454,9 +177305,10 @@ fn genSetMem(
.none => .{ .immediate = @bitCast(@as(i64, disp)) },
.reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
.frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },
- .table, .rip_inst => unreachable,
- .reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } },
- .pcrel => |sym_index| .{ .lea_pcrel = .{ .sym_index = sym_index, .off = disp } },
+ .table, .rip_inst, .lazy_sym => unreachable,
+ .nav => |nav| .{ .lea_nav = nav },
+ .uav => |uav| .{ .lea_uav = uav },
+ .extern_func => |extern_func| .{ .lea_extern_func = extern_func },
};
switch (src_mcv) {
.none,
@@ -177519,6 +177371,7 @@ fn genSetMem(
.rm = .{ .size = .byte, .disp = disp },
} }),
.register => |src_reg| {
+ const ip = &zcu.intern_pool;
const mem_size = switch (base) {
.frame => |base_fi| mem_size: {
assert(disp >= 0);
@@ -177572,8 +177425,9 @@ fn genSetMem(
.index = frame_index,
.off = disp,
}).compare(.gte, src_align),
- .table, .rip_inst => unreachable,
- .reloc, .pcrel => false,
+ .table, .rip_inst, .lazy_sym, .extern_func => unreachable,
+ .nav => |nav| ip.getNav(nav).getAlignment().compare(.gte, src_align),
+ .uav => |uav| Type.fromInterned(uav.orig_ty).ptrAlignment(zcu).compare(.gte, src_align),
})).write(
self,
.{ .base = base, .mod = .{ .rm = .{
@@ -177656,16 +177510,16 @@ fn genSetMem(
},
.memory,
.indirect,
- .load_direct,
- .lea_direct,
- .load_got,
- .lea_got,
.load_frame,
.lea_frame,
- .load_symbol,
- .lea_symbol,
- .load_pcrel,
- .lea_pcrel,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .load_extern_func,
+ .lea_extern_func,
=> switch (abi_size) {
0 => {},
1, 2, 4, 8 => {
@@ -177759,119 +177613,19 @@ fn genInlineMemset(
try self.asmOpOnly(.{ .@"rep _sb", .sto });
}
-fn genExternSymbolRef(
- self: *CodeGen,
- comptime tag: Mir.Inst.Tag,
- lib: ?[]const u8,
- callee: []const u8,
-) InnerError!void {
- if (self.bin_file.cast(.coff)) |coff_file| {
- const global_index = try coff_file.getGlobalSymbol(callee, lib);
- const scratch_reg = abi.getCAbiLinkerScratchReg(self.target.cCallingConvention().?);
- _ = try self.addInst(.{
- .tag = .mov,
- .ops = .import_reloc,
- .data = .{ .rx = .{
- .r1 = scratch_reg,
- .payload = try self.addExtra(bits.SymbolOffset{
- .sym_index = link.File.Coff.global_symbol_bit | global_index,
- }),
- } },
- });
- switch (tag) {
- .mov => {},
- .call => try self.asmRegister(.{ ._, .call }, scratch_reg),
- else => unreachable,
- }
- } else return self.fail("TODO implement calling extern functions", .{});
-}
-
fn genLazySymbolRef(
self: *CodeGen,
comptime tag: Mir.Inst.Tag,
reg: Register,
lazy_sym: link.File.LazySymbol,
) InnerError!void {
- const pt = self.pt;
- if (self.bin_file.cast(.elf)) |elf_file| {
- const zo = elf_file.zigObjectPtr().?;
- const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
- return self.fail("{s} creating lazy symbol", .{@errorName(err)});
- if (self.mod.pic) {
- switch (tag) {
- .lea, .call => try self.genSetReg(reg, .usize, .{
- .lea_symbol = .{ .sym_index = sym_index },
- }, .{}),
- .mov => try self.genSetReg(reg, .usize, .{
- .load_symbol = .{ .sym_index = sym_index },
- }, .{}),
- else => unreachable,
- }
- switch (tag) {
- .lea, .mov => {},
- .call => try self.asmRegister(.{ ._, .call }, reg),
- else => unreachable,
- }
- } else switch (tag) {
- .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
- .base = .{ .reloc = sym_index },
- .mod = .{ .rm = .{ .size = .qword } },
- }),
- .call => try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = sym_index })),
- else => unreachable,
- }
- } else if (self.bin_file.cast(.plan9)) |p9_file| {
- const atom_index = p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
- return self.fail("{s} creating lazy symbol", .{@errorName(err)});
- var atom = p9_file.getAtom(atom_index);
- _ = atom.getOrCreateOffsetTableEntry(p9_file);
- const got_addr = atom.getOffsetTableAddress(p9_file);
- const got_mem: Memory = .{
- .base = .{ .reg = .ds },
- .mod = .{ .rm = .{
- .size = .qword,
- .disp = @intCast(got_addr),
- } },
- };
- switch (tag) {
- .lea, .mov => try self.asmRegisterMemory(.{ ._, .mov }, reg.to64(), got_mem),
- .call => try self.asmMemory(.{ ._, .call }, got_mem),
- else => unreachable,
- }
- switch (tag) {
- .lea, .call => {},
- .mov => try self.asmRegisterMemory(
- .{ ._, tag },
- reg.to64(),
- .initSib(.qword, .{ .base = .{ .reg = reg.to64() } }),
- ),
- else => unreachable,
- }
- } else if (self.bin_file.cast(.coff)) |coff_file| {
- const atom_index = coff_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
- return self.fail("{s} creating lazy symbol", .{@errorName(err)});
- const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
- switch (tag) {
- .lea, .call => try self.genSetReg(reg, .usize, .{ .lea_got = sym_index }, .{}),
- .mov => try self.genSetReg(reg, .usize, .{ .load_got = sym_index }, .{}),
- else => unreachable,
- }
- switch (tag) {
- .lea, .mov => {},
- .call => try self.asmRegister(.{ ._, .call }, reg),
- else => unreachable,
- }
- } else if (self.bin_file.cast(.macho)) |macho_file| {
- const zo = macho_file.getZigObject().?;
- const sym_index = zo.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym) catch |err|
- return self.fail("{s} creating lazy symbol", .{@errorName(err)});
- const sym = zo.symbols.items[sym_index];
+ if (self.mod.pic) {
switch (tag) {
.lea, .call => try self.genSetReg(reg, .usize, .{
- .lea_symbol = .{ .sym_index = sym.nlist_idx },
+ .lea_lazy_sym = lazy_sym,
}, .{}),
.mov => try self.genSetReg(reg, .usize, .{
- .load_symbol = .{ .sym_index = sym.nlist_idx },
+ .lea_lazy_sym = lazy_sym,
}, .{}),
else => unreachable,
}
@@ -177880,8 +177634,13 @@ fn genLazySymbolRef(
.call => try self.asmRegister(.{ ._, .call }, reg),
else => unreachable,
}
- } else {
- return self.fail("TODO implement genLazySymbol for x86_64 {s}", .{@tagName(self.bin_file.tag)});
+ } else switch (tag) {
+ .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
+ .base = .{ .lazy_sym = lazy_sym },
+ .mod = .{ .rm = .{ .size = .qword } },
+ }),
+ .call => try self.asmImmediate(.{ ._, .call }, .{ .lazy_sym = lazy_sym }),
+ else => unreachable,
}
}
@@ -178034,11 +177793,11 @@ fn airFloatFromInt(self: *CodeGen, inst: Air.Inst.Index) !void {
src_ty.fmt(pt), dst_ty.fmt(pt),
});
- var callee_buf: ["__floatun?i?f".len]u8 = undefined;
- break :result try self.genCall(.{ .lib = .{
+ var sym_buf: ["__floatun?i?f".len]u8 = undefined;
+ break :result try self.genCall(.{ .extern_func = .{
.return_type = dst_ty.toIntern(),
.param_types = &.{src_ty.toIntern()},
- .callee = std.fmt.bufPrint(&callee_buf, "__float{s}{c}i{c}f", .{
+ .sym = std.fmt.bufPrint(&sym_buf, "__float{s}{c}i{c}f", .{
switch (src_signedness) {
.signed => "",
.unsigned => "un",
@@ -178114,11 +177873,11 @@ fn airIntFromFloat(self: *CodeGen, inst: Air.Inst.Index) !void {
src_ty.fmt(pt), dst_ty.fmt(pt),
});
- var callee_buf: ["__fixuns?f?i".len]u8 = undefined;
- break :result try self.genCall(.{ .lib = .{
+ var sym_buf: ["__fixuns?f?i".len]u8 = undefined;
+ break :result try self.genCall(.{ .extern_func = .{
.return_type = dst_ty.toIntern(),
.param_types = &.{src_ty.toIntern()},
- .callee = std.fmt.bufPrint(&callee_buf, "__fix{s}{c}f{c}i", .{
+ .sym = std.fmt.bufPrint(&sym_buf, "__fix{s}{c}f{c}i", .{
switch (dst_signedness) {
.signed => "",
.unsigned => "uns",
@@ -178219,9 +177978,9 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void {
.off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}),
}
const ptr_lock = switch (ptr_mem.base) {
- .none, .frame, .reloc, .pcrel => null,
+ .none, .frame, .nav, .uav => null,
.reg => |reg| self.register_manager.lockReg(reg),
- .table, .rip_inst => unreachable,
+ .table, .rip_inst, .lazy_sym, .extern_func => unreachable,
};
defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
@@ -178302,9 +178061,9 @@ fn atomicOp(
.off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}),
}
const mem_lock = switch (ptr_mem.base) {
- .none, .frame, .reloc, .pcrel => null,
+ .none, .frame, .nav, .uav => null,
.reg => |reg| self.register_manager.lockReg(reg),
- .table, .rip_inst => unreachable,
+ .table, .rip_inst, .lazy_sym, .extern_func => unreachable,
};
defer if (mem_lock) |lock| self.register_manager.unlockReg(lock);
@@ -179693,7 +179452,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
var mask_elems_buf: [32]u8 = undefined;
const mask_elems = mask_elems_buf[0..mask_len];
for (mask_elems, 0..) |*elem, bit| elem.* = @intCast(bit / elem_bits);
- const mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
+ const mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
.ty = mask_ty.toIntern(),
.storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, mask_elems, .maybe_embedded_nulls) },
} })));
@@ -179721,7 +179480,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
mask_elem_ty,
@as(u8, 1) << @truncate(bit),
)).toIntern();
- const mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
+ const mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
.ty = mask_ty.toIntern(),
.storage = .{ .elems = mask_elems },
} })));
@@ -180452,7 +180211,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {
else
try select_mask_elem_ty.minIntScalar(pt, select_mask_elem_ty)).toIntern();
}
- const select_mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
+ const select_mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
.ty = select_mask_ty.toIntern(),
.storage = .{ .elems = select_mask_elems[0..mask_elems.len] },
} })));
@@ -180597,7 +180356,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {
})).toIntern();
}
const lhs_mask_ty = try pt.vectorType(.{ .len = max_abi_size, .child = .u8_type });
- const lhs_mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
+ const lhs_mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
.ty = lhs_mask_ty.toIntern(),
.storage = .{ .elems = lhs_mask_elems[0..max_abi_size] },
} })));
@@ -180628,7 +180387,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {
})).toIntern();
}
const rhs_mask_ty = try pt.vectorType(.{ .len = max_abi_size, .child = .u8_type });
- const rhs_mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
+ const rhs_mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
.ty = rhs_mask_ty.toIntern(),
.storage = .{ .elems = rhs_mask_elems[0..max_abi_size] },
} })));
@@ -180962,7 +180721,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {
.{ .frame = frame_index },
@intCast(elem_size * elements.len),
elem_ty,
- try self.genTypedValue(sentinel),
+ try self.lowerValue(sentinel),
.{},
);
break :result .{ .load_frame = .{ .index = frame_index } };
@@ -181046,11 +180805,11 @@ fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void {
ty.fmt(pt),
});
- var callee_buf: ["__fma?".len]u8 = undefined;
- break :result try self.genCall(.{ .lib = .{
+ var sym_buf: ["__fma?".len]u8 = undefined;
+ break :result try self.genCall(.{ .extern_func = .{
.return_type = ty.toIntern(),
.param_types = &.{ ty.toIntern(), ty.toIntern(), ty.toIntern() },
- .callee = std.fmt.bufPrint(&callee_buf, "{s}fma{s}", .{
+ .sym = std.fmt.bufPrint(&sym_buf, "{s}fma{s}", .{
floatLibcAbiPrefix(ty),
floatLibcAbiSuffix(ty),
}) catch unreachable,
@@ -181450,7 +181209,7 @@ fn resolveInst(self: *CodeGen, ref: Air.Inst.Ref) InnerError!MCValue {
const mcv: MCValue = if (ref.toIndex()) |inst| mcv: {
break :mcv self.inst_tracking.getPtr(inst).?.short;
} else mcv: {
- break :mcv try self.genTypedValue(.fromInterned(ref.toInterned().?));
+ break :mcv try self.lowerValue(.fromInterned(ref.toInterned().?));
};
switch (mcv) {
@@ -181488,33 +181247,20 @@ fn limitImmediateType(self: *CodeGen, operand: Air.Inst.Ref, comptime T: type) !
return mcv;
}
-fn genResult(self: *CodeGen, res: codegen.GenResult) InnerError!MCValue {
- return switch (res) {
- .mcv => |mcv| switch (mcv) {
- .none => .none,
- .undef => .undef,
- .immediate => |imm| .{ .immediate = imm },
- .memory => |addr| .{ .memory = addr },
- .load_symbol => |sym_index| .{ .load_symbol = .{ .sym_index = sym_index } },
- .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index } },
- .load_direct => |sym_index| .{ .load_direct = sym_index },
- .lea_direct => |sym_index| .{ .lea_direct = sym_index },
- .load_got => |sym_index| .{ .lea_got = sym_index },
- },
- .fail => |msg| return self.failMsg(msg),
+fn lowerValue(cg: *CodeGen, val: Value) Allocator.Error!MCValue {
+ return switch (try codegen.lowerValue(cg.pt, val, cg.target)) {
+ .none => .none,
+ .undef => .undef,
+ .immediate => |imm| .{ .immediate = imm },
+ .lea_nav => |nav| .{ .lea_nav = nav },
+ .lea_uav => |uav| .{ .lea_uav = uav },
+ .load_uav => |uav| .{ .load_uav = uav },
};
}
-fn genTypedValue(self: *CodeGen, val: Value) InnerError!MCValue {
- return self.genResult(try codegen.genTypedValue(self.bin_file, self.pt, self.src_loc, val, self.target.*));
-}
-
-fn lowerUav(self: *CodeGen, val: Value, alignment: InternPool.Alignment) InnerError!MCValue {
- return self.genResult(try self.bin_file.lowerUav(self.pt, val.toIntern(), alignment, self.src_loc));
-}
-
const CallMCValues = struct {
args: []MCValue,
+ air_arg_count: u32,
return_value: InstTracking,
stack_byte_count: u31,
stack_align: InternPool.Alignment,
@@ -181550,13 +181296,14 @@ fn resolveCallingConventionValues(
const param_types = try allocator.alloc(Type, fn_info.param_types.len + var_args.len);
defer allocator.free(param_types);
- for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src|
- dest.* = .fromInterned(src);
+ for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*param_ty, arg_ty|
+ param_ty.* = .fromInterned(arg_ty);
for (param_types[fn_info.param_types.len..], var_args) |*param_ty, arg_ty|
param_ty.* = self.promoteVarArg(arg_ty);
var result: CallMCValues = .{
.args = try self.gpa.alloc(MCValue, param_types.len),
+ .air_arg_count = 0,
// These undefined values must be populated before returning from this function.
.return_value = undefined,
.stack_byte_count = 0,
@@ -181678,6 +181425,7 @@ fn resolveCallingConventionValues(
// Input params
for (param_types, result.args) |ty, *arg| {
assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
+ result.air_arg_count += 1;
switch (cc) {
.x86_64_sysv => {},
.x86_64_win => {
@@ -181850,6 +181598,7 @@ fn resolveCallingConventionValues(
arg.* = .none;
continue;
}
+ result.air_arg_count += 1;
const param_size: u31 = @intCast(param_ty.abiSize(zcu));
if (abi.zigcc.params_in_regs) switch (self.regClassForType(param_ty)) {
.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 {
.register_offset,
.register_mask,
.memory,
- .load_symbol,
- .lea_symbol,
- .load_pcrel,
- .lea_pcrel,
.indirect,
- .load_direct,
- .lea_direct,
- .load_got,
- .lea_got,
.lea_frame,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .lea_extern_func,
+ .load_extern_func,
.elementwise_args,
.reserved_frame,
.air_ref,
@@ -182425,15 +182174,11 @@ const Temp = struct {
.mod = .{ .rm = .{ .disp = reg_off.off + off } },
});
},
- .load_symbol, .load_frame => {
+ .load_frame, .load_nav, .lea_nav, .load_uav, .lea_uav, .load_lazy_sym, .lea_lazy_sym => {
const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{ .reg = new_reg, .off = off } });
try cg.genSetReg(new_reg, .usize, mcv, .{});
},
- .lea_symbol => |sym_off| new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = .{
- .sym_index = sym_off.sym_index,
- .off = sym_off.off + off,
- } }),
.lea_frame => |frame_addr| new_temp_index.tracking(cg).* = .init(.{ .lea_frame = .{
.index = frame_addr.index,
.off = frame_addr.off + off,
@@ -182466,14 +182211,6 @@ const Temp = struct {
} });
return;
},
- .lea_symbol => |sym_off| {
- assert(std.meta.eql(temp_tracking.long.lea_symbol, sym_off));
- temp_tracking.* = .init(.{ .lea_symbol = .{
- .sym_index = sym_off.sym_index,
- .off = sym_off.off + off,
- } });
- return;
- },
.lea_frame => |frame_addr| {
assert(std.meta.eql(temp_tracking.long.lea_frame, frame_addr));
temp_tracking.* = .init(.{ .lea_frame = .{
@@ -182522,53 +182259,85 @@ const Temp = struct {
.mod = .{ .rm = .{ .disp = reg_off.off + @as(u31, limb_index) * 8 } },
});
},
- .load_symbol => |sym_off| {
+ .load_frame => |frame_addr| {
+ const new_reg =
+ try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
+ try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
+ .base = .{ .frame = frame_addr.index },
+ .mod = .{ .rm = .{
+ .size = .qword,
+ .disp = frame_addr.off + @as(u31, limb_index) * 8,
+ } },
+ });
+ },
+ .lea_frame => |frame_addr| {
+ assert(limb_index == 0);
+ new_temp_index.tracking(cg).* = .init(.{ .lea_frame = frame_addr });
+ },
+ .load_nav => |nav| {
const new_reg =
try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
- .base = .{ .reloc = sym_off.sym_index },
+ .base = .{ .nav = nav },
.mod = .{ .rm = .{
.size = .qword,
- .disp = sym_off.off + @as(u31, limb_index) * 8,
+ .disp = @as(u31, limb_index) * 8,
} },
});
},
- .lea_symbol => |sym_off| {
+ .lea_nav => |nav| {
assert(limb_index == 0);
- new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = sym_off });
+ new_temp_index.tracking(cg).* = .init(.{ .lea_nav = nav });
},
- .load_pcrel => |sym_off| {
+ .load_uav => |uav| {
const new_reg =
try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
- .base = .{ .pcrel = sym_off.sym_index },
+ .base = .{ .uav = uav },
.mod = .{ .rm = .{
.size = .qword,
- .disp = sym_off.off + @as(u31, limb_index) * 8,
+ .disp = @as(u31, limb_index) * 8,
} },
});
},
- .lea_pcrel => |sym_off| {
+ .lea_uav => |uav| {
assert(limb_index == 0);
- new_temp_index.tracking(cg).* = .init(.{ .lea_pcrel = sym_off });
+ new_temp_index.tracking(cg).* = .init(.{ .lea_uav = uav });
},
- .load_frame => |frame_addr| {
+ .load_lazy_sym => |lazy_sym| {
const new_reg =
try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
- .base = .{ .frame = frame_addr.index },
+ .base = .{ .lazy_sym = lazy_sym },
.mod = .{ .rm = .{
.size = .qword,
- .disp = frame_addr.off + @as(u31, limb_index) * 8,
+ .disp = @as(u31, limb_index) * 8,
} },
});
},
- .lea_frame => |frame_addr| {
+ .lea_lazy_sym => |lazy_sym| {
assert(limb_index == 0);
- new_temp_index.tracking(cg).* = .init(.{ .lea_frame = frame_addr });
+ new_temp_index.tracking(cg).* = .init(.{ .lea_lazy_sym = lazy_sym });
+ },
+ .load_extern_func => |extern_func| {
+ const new_reg =
+ try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
+ try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
+ .base = .{ .extern_func = extern_func },
+ .mod = .{ .rm = .{
+ .size = .qword,
+ .disp = @as(u31, limb_index) * 8,
+ } },
+ });
+ },
+ .lea_extern_func => |extern_func| {
+ assert(limb_index == 0);
+ new_temp_index.tracking(cg).* = .init(.{ .lea_extern_func = extern_func });
},
}
cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
@@ -182625,7 +182394,7 @@ const Temp = struct {
const temp_tracking = temp_index.tracking(cg);
switch (temp_tracking.short) {
else => {},
- .register, .lea_symbol, .lea_frame => {
+ .register, .lea_frame, .lea_nav, .lea_uav, .lea_lazy_sym => {
assert(limb_index == 0);
cg.temp_type[@intFromEnum(temp_index)] = limb_ty;
return;
@@ -182642,15 +182411,6 @@ const Temp = struct {
cg.temp_type[@intFromEnum(temp_index)] = limb_ty;
return;
},
- .load_symbol => |sym_off| {
- assert(std.meta.eql(temp_tracking.long.load_symbol, sym_off));
- temp_tracking.* = .init(.{ .load_symbol = .{
- .sym_index = sym_off.sym_index,
- .off = sym_off.off + @as(u31, limb_index) * 8,
- } });
- cg.temp_type[@intFromEnum(temp_index)] = limb_ty;
- return;
- },
.load_frame => |frame_addr| if (!frame_addr.index.isNamed()) {
assert(std.meta.eql(temp_tracking.long.load_frame, frame_addr));
temp_tracking.* = .init(.{ .load_frame = .{
@@ -182841,27 +182601,20 @@ const Temp = struct {
.immediate,
.register,
.register_offset,
- .lea_direct,
- .lea_got,
.lea_frame,
=> return false,
.memory,
.indirect,
- .load_symbol,
- .load_pcrel,
- .load_direct,
- .load_got,
.load_frame,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .load_extern_func,
+ .lea_extern_func,
=> return temp.toRegClass(true, .general_purpose, cg),
- .lea_symbol, .lea_pcrel => |sym_off| {
- const off = sym_off.off;
- // hack around linker relocation bugs
- if (false and off == 0) return false;
- try temp.toOffset(-off, cg);
- while (try temp.toRegClass(true, .general_purpose, cg)) {}
- try temp.toOffset(off, cg);
- return true;
- },
}
}
@@ -182928,7 +182681,7 @@ const Temp = struct {
), cg),
else => unreachable,
},
- .memory, .indirect, .load_frame, .load_symbol => {
+ .memory, .indirect, .load_frame, .load_nav, .load_uav, .load_lazy_sym => {
var val_ptr = try cg.tempInit(.usize, val_mcv.address());
var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });
try val_ptr.memcpy(ptr, &len, cg);
@@ -182966,7 +182719,11 @@ const Temp = struct {
// hack around linker relocation bugs
switch (ptr.tracking(cg).short) {
else => {},
- .lea_symbol => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
+ => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
}
try cg.asmMemoryImmediate(
.{ ._, .mov },
@@ -182980,7 +182737,11 @@ const Temp = struct {
// hack around linker relocation bugs
switch (ptr.tracking(cg).short) {
else => {},
- .lea_symbol => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
+ .lea_nav,
+ .lea_uav,
+ .lea_lazy_sym,
+ .lea_extern_func,
+ => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
}
try cg.asmSetccMemory(
cc,
@@ -183024,8 +182785,8 @@ const Temp = struct {
try ptr.tracking(cg).short.deref().mem(cg, .{ .size = .byte }),
);
},
- .lea_frame, .lea_symbol => continue :val_to_gpr,
- .memory, .indirect, .load_frame, .load_symbol => {
+ .lea_frame, .lea_nav, .lea_uav, .lea_lazy_sym => continue :val_to_gpr,
+ .memory, .indirect, .load_frame, .load_nav, .load_uav, .load_lazy_sym => {
var val_ptr = try cg.tempInit(.usize, val_mcv.address());
var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });
try ptr.memcpy(&val_ptr, &len, cg);
@@ -183065,7 +182826,7 @@ const Temp = struct {
), cg),
else => unreachable,
},
- .memory, .indirect, .load_frame, .load_symbol => {
+ .memory, .indirect, .load_frame, .load_nav, .load_uav, .load_lazy_sym => {
var val_ptr = try cg.tempInit(.usize, val_mcv.address());
var src_ptr =
try cg.tempInit(.usize, src.tracking(cg).short.address().offset(opts.disp));
@@ -183159,8 +182920,8 @@ const Temp = struct {
}),
);
},
- .lea_frame, .lea_symbol => continue :val_to_gpr,
- .memory, .indirect, .load_frame, .load_symbol => {
+ .lea_frame, .lea_nav, .lea_uav, .lea_lazy_sym => continue :val_to_gpr,
+ .memory, .indirect, .load_frame, .load_nav, .load_uav, .load_lazy_sym => {
var dst_ptr =
try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(opts.disp));
var val_ptr = try cg.tempInit(.usize, val_mcv.address());
@@ -183181,7 +182942,7 @@ const Temp = struct {
// hack around linker relocation bugs
switch (ptr.tracking(cg).short) {
else => {},
- .lea_symbol => |sym_off| if (dst_rc != .general_purpose or sym_off.off != 0)
+ .lea_nav, .lea_uav, .lea_lazy_sym => if (dst_rc != .general_purpose)
while (try ptr.toRegClass(false, .general_purpose, cg)) {},
}
try strat.read(cg, dst_reg, try ptr.tracking(cg).short.deref().mem(cg, .{
@@ -183201,7 +182962,7 @@ const Temp = struct {
// hack around linker relocation bugs
switch (ptr.tracking(cg).short) {
else => {},
- .lea_symbol => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
+ .lea_nav, .lea_uav, .lea_lazy_sym => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
}
const strat = try cg.moveStrategy(src_ty, src_rc, false);
try strat.write(cg, try ptr.tracking(cg).short.deref().mem(cg, .{
@@ -186964,7 +186725,7 @@ const Temp = struct {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divti3" } },
.unused,
.unused,
.unused,
@@ -186993,7 +186754,7 @@ const Temp = struct {
},
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__udivti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__udivti3" } },
.unused,
.unused,
.unused,
@@ -187026,7 +186787,7 @@ const Temp = struct {
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divei4" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divei4" } },
.unused,
.unused,
.unused,
@@ -187059,7 +186820,7 @@ const Temp = struct {
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__udivei4" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__udivei4" } },
.unused,
.unused,
.unused,
@@ -187423,7 +187184,7 @@ const Temp = struct {
.{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .i64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divti3" } },
.{ .type = .u64, .kind = .{ .ret_gpr = .{ .cc = .ccc, .at = 0 } } },
.unused,
.unused,
@@ -187461,7 +187222,7 @@ const Temp = struct {
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .u64, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__udivti3" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__udivti3" } },
.{ .type = .u64, .kind = .{ .ret_gpr = .{ .cc = .ccc, .at = 0 } } },
.unused,
.unused,
@@ -187499,7 +187260,7 @@ const Temp = struct {
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__divei4" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__divei4" } },
.unused,
.unused,
.unused,
@@ -187535,7 +187296,7 @@ const Temp = struct {
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 1 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 2 } } },
.{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .at = 3 } } },
- .{ .type = .usize, .kind = .{ .symbol = &.{ .name = "__udivei4" } } },
+ .{ .type = .usize, .kind = .{ .extern_func = "__udivei4" } },
.unused,
.unused,
.unused,
@@ -187590,16 +187351,16 @@ const Temp = struct {
.register_overflow,
.register_mask,
.memory,
- .load_symbol,
- .lea_symbol,
- .load_pcrel,
- .lea_pcrel,
.indirect,
- .load_direct,
- .lea_direct,
- .load_got,
- .lea_got,
.load_frame,
+ .load_nav,
+ .lea_nav,
+ .load_uav,
+ .lea_uav,
+ .load_lazy_sym,
+ .lea_lazy_sym,
+ .load_extern_func,
+ .lea_extern_func,
=> {
const result = try cg.allocRegOrMem(inst, true);
try cg.genCopy(cg.typeOfIndex(inst), result, temp_mcv, .{});
@@ -187776,7 +187537,7 @@ fn tempInit(cg: *CodeGen, ty: Type, value: MCValue) InnerError!Temp {
}
fn tempFromValue(cg: *CodeGen, value: Value) InnerError!Temp {
- return cg.tempInit(value.typeOf(cg.pt.zcu), try cg.genTypedValue(value));
+ return cg.tempInit(value.typeOf(cg.pt.zcu), try cg.lowerValue(value));
}
fn tempMemFromValue(cg: *CodeGen, value: Value) InnerError!Temp {
@@ -187784,13 +187545,20 @@ fn tempMemFromValue(cg: *CodeGen, value: Value) InnerError!Temp {
}
fn tempMemFromAlignedValue(cg: *CodeGen, alignment: InternPool.Alignment, value: Value) InnerError!Temp {
- return cg.tempInit(value.typeOf(cg.pt.zcu), try cg.lowerUav(value, alignment));
+ const ty = value.typeOf(cg.pt.zcu);
+ return cg.tempInit(ty, .{ .load_uav = .{
+ .val = value.toIntern(),
+ .orig_ty = (try cg.pt.ptrType(.{
+ .child = ty.toIntern(),
+ .flags = .{
+ .is_const = true,
+ .alignment = alignment,
+ },
+ })).toIntern(),
+ } });
}
fn tempFromOperand(cg: *CodeGen, op_ref: Air.Inst.Ref, op_dies: bool) InnerError!Temp {
- const zcu = cg.pt.zcu;
- const ip = &zcu.intern_pool;
-
if (op_dies) {
const temp_index = cg.next_temp_index;
const temp: Temp = .{ .index = temp_index.toIndex() };
@@ -187804,8 +187572,7 @@ fn tempFromOperand(cg: *CodeGen, op_ref: Air.Inst.Ref, op_dies: bool) InnerError
}
if (op_ref.toIndex()) |op_inst| return .{ .index = op_inst };
- const val = op_ref.toInterned().?;
- return cg.tempInit(.fromInterned(ip.typeOf(val)), try cg.genTypedValue(.fromInterned(val)));
+ return cg.tempFromValue(.fromInterned(op_ref.toInterned().?));
}
fn tempsFromOperandsInner(
@@ -188640,8 +188407,8 @@ const Select = struct {
splat_int_mem: struct { ref: Select.Operand.Ref, inside: enum { umin, smin, smax } = .umin, outside: enum { smin, smax } },
splat_float_mem: struct { ref: Select.Operand.Ref, inside: enum { zero } = .zero, outside: f16 },
frame: FrameIndex,
- lazy_symbol: struct { kind: link.File.LazySymbol.Kind, ref: Select.Operand.Ref = .none },
- symbol: *const struct { lib: ?[]const u8 = null, name: []const u8 },
+ lazy_sym: struct { kind: link.File.LazySymbol.Kind, ref: Select.Operand.Ref = .none },
+ extern_func: [*:0]const u8,
const ConstSpec = struct {
ref: Select.Operand.Ref = .none,
@@ -189072,43 +188839,21 @@ const Select = struct {
} }))), true };
},
.frame => |frame_index| .{ try cg.tempInit(spec.type, .{ .load_frame = .{ .index = frame_index } }), true },
- .lazy_symbol => |lazy_symbol_spec| {
+ .lazy_sym => |lazy_symbol_spec| {
const ip = &pt.zcu.intern_pool;
const ty = if (lazy_symbol_spec.ref == .none) spec.type else lazy_symbol_spec.ref.typeOf(s);
- const lazy_symbol: link.File.LazySymbol = .{
+ return .{ try cg.tempInit(.usize, .{ .lea_lazy_sym = .{
.kind = lazy_symbol_spec.kind,
.ty = switch (ip.indexToKey(ty.toIntern())) {
.inferred_error_set_type => |func_index| switch (ip.funcIesResolvedUnordered(func_index)) {
- .none => unreachable, // unresolved inferred error set
+ .none => unreachable,
else => |ty_index| ty_index,
},
else => ty.toIntern(),
},
- };
- return .{ try cg.tempInit(.usize, .{ .lea_symbol = .{
- .sym_index = if (cg.bin_file.cast(.elf)) |elf_file|
- elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_symbol) catch |err|
- return cg.fail("{s} creating lazy symbol", .{@errorName(err)})
- else if (cg.bin_file.cast(.macho)) |macho_file|
- macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_symbol) catch |err|
- return cg.fail("{s} creating lazy symbol", .{@errorName(err)})
- else if (cg.bin_file.cast(.coff)) |coff_file|
- coff_file.getAtom(coff_file.getOrCreateAtomForLazySymbol(pt, lazy_symbol) catch |err|
- return cg.fail("{s} creating lazy symbol", .{@errorName(err)})).getSymbolIndex().?
- else
- return cg.fail("external symbols unimplemented for {s}", .{@tagName(cg.bin_file.tag)}),
} }), true };
},
- .symbol => |symbol_spec| .{ try cg.tempInit(spec.type, .{ .lea_symbol = .{
- .sym_index = if (cg.bin_file.cast(.elf)) |elf_file|
- try elf_file.getGlobalSymbol(symbol_spec.name, symbol_spec.lib)
- else if (cg.bin_file.cast(.macho)) |macho_file|
- try macho_file.getGlobalSymbol(symbol_spec.name, symbol_spec.lib)
- else if (cg.bin_file.cast(.coff)) |coff_file|
- link.File.Coff.global_symbol_bit | try coff_file.getGlobalSymbol(symbol_spec.name, symbol_spec.lib)
- else
- return cg.fail("external symbols unimplemented for {s}", .{@tagName(cg.bin_file.tag)}),
- } }), true },
+ .extern_func => |extern_func_spec| .{ try cg.tempInit(spec.type, .{ .lea_extern_func = try cg.addString(std.mem.span(extern_func_spec)) }), true },
};
}
@@ -190151,9 +189896,12 @@ const Select = struct {
.register => |reg| .{ .reg = s.lowerReg(reg.toSize(op.flags.base.size, s.cg.target)) },
.register_pair, .register_triple, .register_quadruple, .register_offset, .register_overflow => unreachable,
.register_mask => |reg_mask| .{ .reg = s.lowerReg(reg_mask.reg.toSize(op.flags.base.size, s.cg.target)) },
+ .lea_nav => |nav| .{ .imm = .{ .nav = .{ .index = nav } } },
+ .lea_uav => |uav| .{ .imm = .{ .uav = uav } },
+ .lea_lazy_sym => |lazy_sym| .{ .imm = .{ .lazy_sym = lazy_sym } },
+ .lea_extern_func => |extern_func| .{ .imm = .{ .extern_func = extern_func } },
else => |mcv| .{ .mem = try mcv.mem(s.cg, .{ .size = op.flags.base.size }) },
- .lea_symbol => |sym_off| .{ .imm = .rel(sym_off) },
- .load_direct, .lea_direct, .load_got, .lea_got, .lea_frame, .elementwise_args, .reserved_frame, .air_ref => unreachable,
+ .lea_frame, .elementwise_args, .reserved_frame, .air_ref => unreachable,
},
1...2 => |imm| switch (op.flags.base.ref.valueOf(s)) {
inline .register_pair, .register_triple, .register_quadruple => |regs| .{
@@ -190167,37 +189915,20 @@ const Select = struct {
},
.simm => .{ .imm = .s(op.adjustedImm(i32, s)) },
.uimm => .{ .imm = .u(@bitCast(op.adjustedImm(i64, s))) },
- .lea => .{ .mem = .{
- .base = switch (op.flags.base.ref.valueOf(s)) {
+ .lea => .{ .mem = try op.flags.base.ref.valueOf(s).deref().mem(s.cg, .{
+ .size = op.flags.base.size,
+ .index = switch (op.flags.index.ref.valueOf(s)) {
else => unreachable,
.none => .none,
- .register => |base_reg| .{ .reg = base_reg.toSize(.ptr, s.cg.target) },
- .register_offset => |base_reg_off| .{ .reg = base_reg_off.reg.toSize(.ptr, s.cg.target) },
- .lea_symbol => |base_sym_off| .{ .reloc = base_sym_off.sym_index },
- .lea_pcrel => |base_sym_off| .{ .pcrel = base_sym_off.sym_index },
+ .register => |index_reg| index_reg.toSize(.ptr, s.cg.target),
},
- .mod = .{ .rm = .{
- .size = op.flags.base.size,
- .index = switch (op.flags.index.ref.valueOf(s)) {
- else => unreachable,
- .none => .none,
- .register => |index_reg| index_reg.toSize(.ptr, s.cg.target),
- .register_offset => |index_reg_off| index_reg_off.reg.toSize(.ptr, s.cg.target),
- },
- .scale = op.flags.index.scale,
- .disp = op.adjustedImm(i32, s) + switch (op.flags.base.ref.valueOf(s)) {
- else => unreachable,
- .none, .register => 0,
- .register_offset => |base_reg_off| base_reg_off.off,
- .lea_symbol => |base_sym_off| base_sym_off.off,
- } + switch (op.flags.index.ref.valueOf(s)) {
- else => unreachable,
- .none, .register => 0,
- .register_offset => |base_reg_off| base_reg_off.off,
- .lea_symbol => |base_sym_off| base_sym_off.off,
- },
- } },
- } },
+ .scale = op.flags.index.scale,
+ .disp = op.adjustedImm(i32, s) + switch (op.flags.index.ref.valueOf(s)) {
+ else => unreachable,
+ .none, .register, .lea_nav, .lea_uav, .lea_lazy_sym, .lea_extern_func => 0,
+ .register_offset => |base_reg_off| base_reg_off.off,
+ },
+ }) },
.mem => .{ .mem = try op.flags.base.ref.valueOf(s).mem(s.cg, .{
.size = op.flags.base.size,
.index = switch (op.flags.index.ref.valueOf(s)) {
diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig
index d4116974cf..e6b4ac26bb 100644
--- a/src/arch/x86_64/Emit.zig
+++ b/src/arch/x86_64/Emit.zig
@@ -1,7 +1,9 @@
//! This file contains the functionality for emitting x86_64 MIR as machine code
-air: Air,
lower: Lower,
+bin_file: *link.File,
+pt: Zcu.PerThread,
+pic: bool,
atom_index: u32,
debug_output: link.File.DebugInfoOutput,
code: *std.ArrayListUnmanaged(u8),
@@ -10,26 +12,29 @@ prev_di_loc: Loc,
/// Relative to the beginning of `code`.
prev_di_pc: usize,
+code_offset_mapping: std.ArrayListUnmanaged(u32),
+relocs: std.ArrayListUnmanaged(Reloc),
+table_relocs: std.ArrayListUnmanaged(TableReloc),
+
pub const Error = Lower.Error || error{
EmitFail,
} || link.File.UpdateDebugInfoError;
pub fn emitMir(emit: *Emit) Error!void {
- const gpa = emit.lower.bin_file.comp.gpa;
- const code_offset_mapping = try emit.lower.allocator.alloc(u32, emit.lower.mir.instructions.len);
- defer emit.lower.allocator.free(code_offset_mapping);
- var relocs: std.ArrayListUnmanaged(Reloc) = .empty;
- defer relocs.deinit(emit.lower.allocator);
- var table_relocs: std.ArrayListUnmanaged(TableReloc) = .empty;
- defer table_relocs.deinit(emit.lower.allocator);
+ const comp = emit.bin_file.comp;
+ const gpa = comp.gpa;
+ try emit.code_offset_mapping.resize(gpa, emit.lower.mir.instructions.len);
+ emit.relocs.clearRetainingCapacity();
+ emit.table_relocs.clearRetainingCapacity();
+ var local_index: usize = 0;
for (0..emit.lower.mir.instructions.len) |mir_i| {
const mir_index: Mir.Inst.Index = @intCast(mir_i);
- code_offset_mapping[mir_index] = @intCast(emit.code.items.len);
+ emit.code_offset_mapping.items[mir_index] = @intCast(emit.code.items.len);
const lowered = try emit.lower.lowerMir(mir_index);
var lowered_relocs = lowered.relocs;
- for (lowered.insts, 0..) |lowered_inst, lowered_index| {
- const start_offset: u32 = @intCast(emit.code.items.len);
+ lowered_inst: for (lowered.insts, 0..) |lowered_inst, lowered_index| {
if (lowered_inst.prefix == .directive) {
+ const start_offset: u32 = @intCast(emit.code.items.len);
switch (emit.debug_output) {
.dwarf => |dwarf| switch (lowered_inst.encoding.mnemonic) {
.@".cfi_def_cfa" => try dwarf.genDebugFrame(start_offset, .{ .def_cfa = .{
@@ -82,204 +87,327 @@ pub fn emitMir(emit: *Emit) Error!void {
}
continue;
}
- try lowered_inst.encode(emit.code.writer(gpa), .{});
- const end_offset: u32 = @intCast(emit.code.items.len);
+ var reloc_info_buf: [2]RelocInfo = undefined;
+ var reloc_info_index: usize = 0;
while (lowered_relocs.len > 0 and
lowered_relocs[0].lowered_inst_index == lowered_index) : ({
lowered_relocs = lowered_relocs[1..];
- }) switch (lowered_relocs[0].target) {
- .inst => |target| {
- const inst_length: u4 = @intCast(end_offset - start_offset);
- const reloc_offset, const reloc_length = reloc_offset_length: {
- var reloc_offset = inst_length;
- var op_index: usize = lowered_inst.ops.len;
- while (true) {
- op_index -= 1;
- const op = lowered_inst.encoding.data.ops[op_index];
- if (op == .none) continue;
- const is_mem = op.isMemory();
- const enc_length: u4 = if (is_mem) switch (lowered_inst.ops[op_index].mem.sib.base) {
- .rip_inst => 4,
- else => unreachable,
- } else @intCast(std.math.divCeil(u7, @intCast(op.immBitSize()), 8) catch unreachable);
- reloc_offset -= enc_length;
- if (op_index == lowered_relocs[0].op_index) break :reloc_offset_length .{ reloc_offset, enc_length };
- std.debug.assert(!is_mem);
- }
- };
- try relocs.append(emit.lower.allocator, .{
- .inst_offset = start_offset,
- .inst_length = inst_length,
- .source_offset = reloc_offset,
- .source_length = reloc_length,
- .target = target,
- .target_offset = lowered_relocs[0].off,
- });
- },
- .table => try table_relocs.append(emit.lower.allocator, .{
- .source_offset = end_offset - 4,
- .target_offset = lowered_relocs[0].off,
- }),
- .linker_extern_fn => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
- // Add relocation to the decl.
- const zo = elf_file.zigObjectPtr().?;
- const atom_ptr = zo.symbol(emit.atom_index).atom(elf_file).?;
- const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);
- try atom_ptr.addReloc(gpa, .{
- .r_offset = end_offset - 4,
- .r_info = @as(u64, sym_index) << 32 | r_type,
- .r_addend = lowered_relocs[0].off - 4,
- }, zo);
- } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
- // Add relocation to the decl.
- const zo = macho_file.getZigObject().?;
- const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
- try atom.addReloc(macho_file, .{
- .tag = .@"extern",
- .offset = end_offset - 4,
- .target = sym_index,
- .addend = lowered_relocs[0].off,
- .type = .branch,
- .meta = .{
- .pcrel = true,
- .has_subtractor = false,
- .length = 2,
- .symbolnum = @intCast(sym_index),
+ reloc_info_index += 1;
+ }) reloc_info_buf[reloc_info_index] = .{
+ .op_index = lowered_relocs[0].op_index,
+ .off = lowered_relocs[0].off,
+ .target = target: switch (lowered_relocs[0].target) {
+ .inst => |inst| .{ .index = inst, .is_extern = false, .type = .inst },
+ .table => .{ .index = undefined, .is_extern = false, .type = .table },
+ .nav => |nav| {
+ const sym_index = switch (try codegen.genNavRef(
+ emit.bin_file,
+ emit.pt,
+ emit.lower.src_loc,
+ nav,
+ emit.lower.target.*,
+ )) {
+ .mcv => |mcv| mcv.lea_symbol,
+ .fail => |em| {
+ assert(emit.lower.err_msg == null);
+ emit.lower.err_msg = em;
+ return error.EmitFail;
+ },
+ };
+ const ip = &emit.pt.zcu.intern_pool;
+ break :target switch (ip.getNav(nav).status) {
+ .unresolved => unreachable,
+ .type_resolved => |type_resolved| .{
+ .index = sym_index,
+ .is_extern = false,
+ .type = if (type_resolved.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
+ },
+ .fully_resolved => |fully_resolved| switch (ip.indexToKey(fully_resolved.val)) {
+ .@"extern" => |@"extern"| .{
+ .index = sym_index,
+ .is_extern = switch (@"extern".visibility) {
+ .default => true,
+ .hidden, .protected => false,
+ },
+ .type = if (@"extern".is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
+ .force_pcrel_direct = switch (@"extern".relocation) {
+ .any => false,
+ .pcrel => true,
+ },
+ },
+ .variable => |variable| .{
+ .index = sym_index,
+ .is_extern = false,
+ .type = if (variable.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
+ },
+ else => .{ .index = sym_index, .is_extern = false, .type = .symbol },
+ },
+ };
+ },
+ .uav => |uav| .{
+ .index = switch (try emit.bin_file.lowerUav(
+ emit.pt,
+ uav.val,
+ Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),
+ emit.lower.src_loc,
+ )) {
+ .mcv => |mcv| mcv.load_symbol,
+ .fail => |em| {
+ assert(emit.lower.err_msg == null);
+ emit.lower.err_msg = em;
+ return error.EmitFail;
+ },
},
- });
- } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
- // Add relocation to the decl.
- const atom_index = coff_file.getAtomIndexForSymbol(
- .{ .sym_index = emit.atom_index, .file = null },
- ).?;
- const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
- coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
- else
- link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
- try coff_file.addRelocation(atom_index, .{
- .type = .direct,
- .target = target,
- .offset = end_offset - 4,
- .addend = @intCast(lowered_relocs[0].off),
- .pcrel = true,
- .length = 2,
- });
- } else return emit.fail("TODO implement extern reloc for {s}", .{
- @tagName(emit.lower.bin_file.tag),
- }),
- .linker_tlsld => |sym_index| {
- const elf_file = emit.lower.bin_file.cast(.elf).?;
- const zo = elf_file.zigObjectPtr().?;
- const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
- const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);
- try atom.addReloc(gpa, .{
- .r_offset = end_offset - 4,
- .r_info = @as(u64, sym_index) << 32 | r_type,
- .r_addend = lowered_relocs[0].off - 4,
- }, zo);
- },
- .linker_dtpoff => |sym_index| {
- const elf_file = emit.lower.bin_file.cast(.elf).?;
- const zo = elf_file.zigObjectPtr().?;
- const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
- const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);
- try atom.addReloc(gpa, .{
- .r_offset = end_offset - 4,
- .r_info = @as(u64, sym_index) << 32 | r_type,
- .r_addend = lowered_relocs[0].off,
- }, zo);
- },
- .linker_reloc, .linker_pcrel => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
- const zo = elf_file.zigObjectPtr().?;
- const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
- const sym = zo.symbol(sym_index);
- if (emit.lower.pic) {
- const r_type: u32 = if (sym.flags.is_extern_ptr and lowered_relocs[0].target != .linker_pcrel)
- @intFromEnum(std.elf.R_X86_64.GOTPCREL)
+ .is_extern = false,
+ .type = .symbol,
+ },
+ .lazy_sym => |lazy_sym| .{
+ .index = if (emit.bin_file.cast(.elf)) |elf_file|
+ elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, emit.pt, lazy_sym) catch |err|
+ return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
+ else if (emit.bin_file.cast(.macho)) |macho_file|
+ macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err|
+ return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
+ else if (emit.bin_file.cast(.coff)) |coff_file| sym_index: {
+ const atom = coff_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err|
+ return emit.fail("{s} creating lazy symbol", .{@errorName(err)});
+ break :sym_index coff_file.getAtom(atom).getSymbolIndex().?;
+ } else if (emit.bin_file.cast(.plan9)) |p9_file|
+ p9_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err|
+ return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
else
- @intFromEnum(std.elf.R_X86_64.PC32);
- try atom.addReloc(gpa, .{
- .r_offset = end_offset - 4,
- .r_info = @as(u64, sym_index) << 32 | r_type,
- .r_addend = lowered_relocs[0].off - 4,
- }, zo);
- } else {
- const r_type: u32 = if (sym.flags.is_tls)
- @intFromEnum(std.elf.R_X86_64.TPOFF32)
+ return emit.fail("lazy symbols unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
+ .is_extern = false,
+ .type = .symbol,
+ },
+ .extern_func => |extern_func| .{
+ .index = if (emit.bin_file.cast(.elf)) |elf_file|
+ try elf_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null)
+ else if (emit.bin_file.cast(.macho)) |macho_file|
+ try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null)
+ else if (emit.bin_file.cast(.coff)) |coff_file|
+ link.File.Coff.global_symbol_bit | try coff_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null)
else
- @intFromEnum(std.elf.R_X86_64.@"32");
- try atom.addReloc(gpa, .{
- .r_offset = end_offset - 4,
- .r_info = @as(u64, sym_index) << 32 | r_type,
- .r_addend = lowered_relocs[0].off,
- }, zo);
- }
- } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
- const zo = macho_file.getZigObject().?;
- const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
- const sym = &zo.symbols.items[sym_index];
- const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr and lowered_relocs[0].target != .linker_pcrel)
- .got_load
- else if (sym.flags.tlv)
- .tlv
- else
- .signed;
- try atom.addReloc(macho_file, .{
- .tag = .@"extern",
- .offset = @intCast(end_offset - 4),
- .target = sym_index,
- .addend = lowered_relocs[0].off,
- .type = @"type",
- .meta = .{
- .pcrel = true,
- .has_subtractor = false,
- .length = 2,
- .symbolnum = @intCast(sym_index),
+ return emit.fail("external symbols unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
+ .is_extern = true,
+ .type = .symbol,
+ },
+ },
+ };
+ const reloc_info = reloc_info_buf[0..reloc_info_index];
+ for (reloc_info) |*reloc| switch (reloc.target.type) {
+ .inst, .table => {},
+ .symbol => {
+ switch (lowered_inst.encoding.mnemonic) {
+ .call => {
+ reloc.target.type = .branch;
+ if (emit.bin_file.cast(.coff)) |_| try emit.encodeInst(try .new(.none, .call, &.{
+ .{ .mem = .initRip(.ptr, 0) },
+ }, emit.lower.target), reloc_info) else try emit.encodeInst(lowered_inst, reloc_info);
+ continue :lowered_inst;
},
+ else => {},
+ }
+ if (emit.bin_file.cast(.elf)) |_| {
+ if (!emit.pic) switch (lowered_inst.encoding.mnemonic) {
+ .lea => try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .imm = .s(0) },
+ }, emit.lower.target), reloc_info),
+ .mov => try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{
+ .base = .{ .reg = .ds },
+ }) },
+ }, emit.lower.target), reloc_info),
+ else => unreachable,
+ } else if (reloc.target.is_extern) switch (lowered_inst.encoding.mnemonic) {
+ .lea => try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(.ptr, 0) },
+ }, emit.lower.target), reloc_info),
+ .mov => {
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(.ptr, 0) },
+ }, emit.lower.target), reloc_info);
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{ .base = .{
+ .reg = lowered_inst.ops[0].reg.to64(),
+ } }) },
+ }, emit.lower.target), &.{});
+ },
+ else => unreachable,
+ } else switch (lowered_inst.encoding.mnemonic) {
+ .lea => try emit.encodeInst(try .new(.none, .lea, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(.none, 0) },
+ }, emit.lower.target), reloc_info),
+ .mov => try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, 0) },
+ }, emit.lower.target), reloc_info),
+ else => unreachable,
+ }
+ } else if (emit.bin_file.cast(.macho)) |_| {
+ if (reloc.target.is_extern) switch (lowered_inst.encoding.mnemonic) {
+ .lea => try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(.ptr, 0) },
+ }, emit.lower.target), reloc_info),
+ .mov => {
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(.ptr, 0) },
+ }, emit.lower.target), reloc_info);
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{ .base = .{
+ .reg = lowered_inst.ops[0].reg.to64(),
+ } }) },
+ }, emit.lower.target), &.{});
+ },
+ else => unreachable,
+ } else switch (lowered_inst.encoding.mnemonic) {
+ .lea => try emit.encodeInst(try .new(.none, .lea, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(.none, 0) },
+ }, emit.lower.target), reloc_info),
+ .mov => try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, 0) },
+ }, emit.lower.target), reloc_info),
+ else => unreachable,
+ }
+ } else if (emit.bin_file.cast(.coff)) |_| {
+ if (reloc.target.is_extern) switch (lowered_inst.encoding.mnemonic) {
+ .lea => try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(.ptr, 0) },
+ }, emit.lower.target), reloc_info),
+ .mov => {
+ const dst_reg = lowered_inst.ops[0].reg.to64();
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ .{ .reg = dst_reg },
+ .{ .mem = .initRip(.ptr, 0) },
+ }, emit.lower.target), reloc_info);
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{ .base = .{
+ .reg = dst_reg,
+ } }) },
+ }, emit.lower.target), &.{});
+ },
+ else => unreachable,
+ } else switch (lowered_inst.encoding.mnemonic) {
+ .lea => try emit.encodeInst(try .new(.none, .lea, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(.none, 0) },
+ }, emit.lower.target), reloc_info),
+ .mov => try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, 0) },
+ }, emit.lower.target), reloc_info),
+ else => unreachable,
+ }
+ } else return emit.fail("TODO implement relocs for {s}", .{
+ @tagName(emit.bin_file.tag),
});
- } else unreachable,
- .linker_got,
- .linker_direct,
- .linker_import,
- => |sym_index| if (emit.lower.bin_file.cast(.elf)) |_| {
- unreachable;
- } else if (emit.lower.bin_file.cast(.macho)) |_| {
- unreachable;
- } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
- const atom_index = coff_file.getAtomIndexForSymbol(.{
- .sym_index = emit.atom_index,
- .file = null,
- }).?;
- const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
- coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
- else
- link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
- try coff_file.addRelocation(atom_index, .{
- .type = switch (lowered_relocs[0].target) {
- .linker_got => .got,
- .linker_direct => .direct,
- .linker_import => .import,
+ continue :lowered_inst;
+ },
+ .branch, .tls => unreachable,
+ .tlv => {
+ if (emit.bin_file.cast(.elf)) |elf_file| {
+ // TODO handle extern TLS vars, i.e., emit GD model
+ if (emit.pic) switch (lowered_inst.encoding.mnemonic) {
+ .lea, .mov => {
+ // Here, we currently assume local dynamic TLS vars, and so
+ // we emit LD model.
+ try emit.encodeInst(try .new(.none, .lea, &.{
+ .{ .reg = .rdi },
+ .{ .mem = .initRip(.none, 0) },
+ }, emit.lower.target), &.{.{
+ .op_index = 1,
+ .target = .{
+ .index = reloc.target.index,
+ .is_extern = false,
+ .type = .tls,
+ },
+ }});
+ try emit.encodeInst(try .new(.none, .call, &.{
+ .{ .imm = .s(0) },
+ }, emit.lower.target), &.{.{
+ .op_index = 0,
+ .target = .{
+ .index = try elf_file.getGlobalSymbol("__tls_get_addr", null),
+ .is_extern = true,
+ .type = .branch,
+ },
+ }});
+ try emit.encodeInst(try .new(.none, lowered_inst.encoding.mnemonic, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initSib(.none, .{
+ .base = .{ .reg = .rax },
+ .disp = std.math.minInt(i32),
+ }) },
+ }, emit.lower.target), reloc_info);
+ },
+ else => unreachable,
+ } else switch (lowered_inst.encoding.mnemonic) {
+ .lea, .mov => {
+ // Since we are linking statically, we emit LE model directly.
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ .{ .reg = .rax },
+ .{ .mem = .initSib(.qword, .{ .base = .{ .reg = .fs } }) },
+ }, emit.lower.target), &.{});
+ try emit.encodeInst(try .new(.none, lowered_inst.encoding.mnemonic, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initSib(.none, .{
+ .base = .{ .reg = .rax },
+ .disp = std.math.minInt(i32),
+ }) },
+ }, emit.lower.target), reloc_info);
+ },
else => unreachable,
+ }
+ } else if (emit.bin_file.cast(.macho)) |_| switch (lowered_inst.encoding.mnemonic) {
+ .lea => {
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ .{ .reg = .rdi },
+ .{ .mem = .initRip(.ptr, 0) },
+ }, emit.lower.target), reloc_info);
+ try emit.encodeInst(try .new(.none, .call, &.{
+ .{ .mem = .initSib(.qword, .{ .base = .{ .reg = .rdi } }) },
+ }, emit.lower.target), &.{});
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .reg = .rax },
+ }, emit.lower.target), &.{});
},
- .target = target,
- .offset = @intCast(end_offset - 4),
- .addend = @intCast(lowered_relocs[0].off),
- .pcrel = true,
- .length = 2,
- });
- } else if (emit.lower.bin_file.cast(.plan9)) |p9_file| {
- 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
- .target = sym_index, // we set sym_index to just be the atom index
- .offset = @intCast(end_offset - 4),
- .addend = @intCast(lowered_relocs[0].off),
- .type = .pcrel,
+ .mov => {
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ .{ .reg = .rdi },
+ .{ .mem = .initRip(.ptr, 0) },
+ }, emit.lower.target), reloc_info);
+ try emit.encodeInst(try .new(.none, .call, &.{
+ .{ .mem = .initSib(.qword, .{ .base = .{ .reg = .rdi } }) },
+ }, emit.lower.target), &.{});
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initSib(.qword, .{ .base = .{ .reg = .rax } }) },
+ }, emit.lower.target), &.{});
+ },
+ else => unreachable,
+ } else return emit.fail("TODO implement relocs for {s}", .{
+ @tagName(emit.bin_file.tag),
});
- } else return emit.fail("TODO implement linker reloc for {s}", .{
- @tagName(emit.lower.bin_file.tag),
- }),
+ continue :lowered_inst;
+ },
};
+ try emit.encodeInst(lowered_inst, reloc_info);
}
- std.debug.assert(lowered_relocs.len == 0);
+ assert(lowered_relocs.len == 0);
if (lowered.insts.len == 0) {
const mir_inst = emit.lower.mir.instructions.get(mir_index);
@@ -338,7 +466,7 @@ pub fn emitMir(emit: *Emit) Error!void {
log.debug("mirDbgEnterInline (line={d}, col={d})", .{
emit.prev_di_loc.line, emit.prev_di_loc.column,
});
- try dwarf.enterInlineFunc(mir_inst.data.func, emit.code.items.len, emit.prev_di_loc.line, emit.prev_di_loc.column);
+ try dwarf.enterInlineFunc(mir_inst.data.ip_index, emit.code.items.len, emit.prev_di_loc.line, emit.prev_di_loc.column);
},
.plan9 => {},
.none => {},
@@ -348,77 +476,49 @@ pub fn emitMir(emit: *Emit) Error!void {
log.debug("mirDbgLeaveInline (line={d}, col={d})", .{
emit.prev_di_loc.line, emit.prev_di_loc.column,
});
- try dwarf.leaveInlineFunc(mir_inst.data.func, emit.code.items.len);
+ try dwarf.leaveInlineFunc(mir_inst.data.ip_index, emit.code.items.len);
},
.plan9 => {},
.none => {},
},
- .pseudo_dbg_local_a,
- .pseudo_dbg_local_ai_s,
- .pseudo_dbg_local_ai_u,
- .pseudo_dbg_local_ai_64,
- .pseudo_dbg_local_as,
- .pseudo_dbg_local_aso,
- .pseudo_dbg_local_aro,
- .pseudo_dbg_local_af,
- .pseudo_dbg_local_am,
+ .pseudo_dbg_arg_none,
+ .pseudo_dbg_arg_i_s,
+ .pseudo_dbg_arg_i_u,
+ .pseudo_dbg_arg_i_64,
+ .pseudo_dbg_arg_ro,
+ .pseudo_dbg_arg_fa,
+ .pseudo_dbg_arg_m,
+ .pseudo_dbg_var_none,
+ .pseudo_dbg_var_i_s,
+ .pseudo_dbg_var_i_u,
+ .pseudo_dbg_var_i_64,
+ .pseudo_dbg_var_ro,
+ .pseudo_dbg_var_fa,
+ .pseudo_dbg_var_m,
=> switch (emit.debug_output) {
.dwarf => |dwarf| {
var loc_buf: [2]link.File.Dwarf.Loc = undefined;
- const air_inst_index, const loc: link.File.Dwarf.Loc = switch (mir_inst.ops) {
+ const loc: link.File.Dwarf.Loc = loc: switch (mir_inst.ops) {
else => unreachable,
- .pseudo_dbg_local_a => .{ mir_inst.data.a.air_inst, .empty },
- .pseudo_dbg_local_ai_s,
- .pseudo_dbg_local_ai_u,
- .pseudo_dbg_local_ai_64,
- => .{ mir_inst.data.ai.air_inst, .{ .stack_value = stack_value: {
- loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.ai.i)) {
+ .pseudo_dbg_arg_none, .pseudo_dbg_var_none => .empty,
+ .pseudo_dbg_arg_i_s,
+ .pseudo_dbg_arg_i_u,
+ .pseudo_dbg_var_i_s,
+ .pseudo_dbg_var_i_u,
+ => .{ .stack_value = stack_value: {
+ loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.i.i)) {
.signed => |s| .{ .consts = s },
.unsigned => |u| .{ .constu = u },
};
break :stack_value &loc_buf[0];
- } } },
- .pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{
- .addr_reloc = mir_inst.data.as.sym_index,
} },
- .pseudo_dbg_local_aso => loc: {
- const sym_off = emit.lower.mir.extraData(
- bits.SymbolOffset,
- mir_inst.data.ax.payload,
- ).data;
- break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
- sym: {
- loc_buf[0] = .{ .addr_reloc = sym_off.sym_index };
- break :sym &loc_buf[0];
- },
- off: {
- loc_buf[1] = .{ .consts = sym_off.off };
- break :off &loc_buf[1];
- },
- } } };
- },
- .pseudo_dbg_local_aro => loc: {
- const air_off = emit.lower.mir.extraData(
- Mir.AirOffset,
- mir_inst.data.rx.payload,
- ).data;
- break :loc .{ air_off.air_inst, .{ .plus = .{
- reg: {
- loc_buf[0] = .{ .breg = mir_inst.data.rx.r1.dwarfNum() };
- break :reg &loc_buf[0];
- },
- off: {
- loc_buf[1] = .{ .consts = air_off.off };
- break :off &loc_buf[1];
- },
- } } };
- },
- .pseudo_dbg_local_af => loc: {
- const reg_off = emit.lower.mir.resolveFrameAddr(emit.lower.mir.extraData(
- bits.FrameAddr,
- mir_inst.data.ax.payload,
- ).data);
- break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
+ .pseudo_dbg_arg_i_64, .pseudo_dbg_var_i_64 => .{ .stack_value = stack_value: {
+ loc_buf[0] = .{ .constu = mir_inst.data.i64 };
+ break :stack_value &loc_buf[0];
+ } },
+ .pseudo_dbg_arg_fa, .pseudo_dbg_var_fa => {
+ const reg_off = emit.lower.mir.resolveFrameAddr(mir_inst.data.fa);
+ break :loc .{ .plus = .{
reg: {
loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() };
break :reg &loc_buf[0];
@@ -427,18 +527,54 @@ pub fn emitMir(emit: *Emit) Error!void {
loc_buf[1] = .{ .consts = reg_off.off };
break :off &loc_buf[1];
},
- } } };
+ } };
},
- .pseudo_dbg_local_am => loc: {
- const mem = emit.lower.mem(undefined, mir_inst.data.ax.payload);
- break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
+ .pseudo_dbg_arg_m, .pseudo_dbg_var_m => {
+ const mem = emit.lower.mir.resolveMemoryExtra(mir_inst.data.x.payload).decode();
+ break :loc .{ .plus = .{
base: {
loc_buf[0] = switch (mem.base()) {
.none => .{ .constu = 0 },
.reg => |reg| .{ .breg = reg.dwarfNum() },
.frame, .table, .rip_inst => unreachable,
- .reloc => |sym_index| .{ .addr_reloc = sym_index },
- .pcrel => unreachable,
+ .nav => |nav| .{ .addr_reloc = switch (codegen.genNavRef(
+ emit.bin_file,
+ emit.pt,
+ emit.lower.src_loc,
+ nav,
+ emit.lower.target.*,
+ ) catch |err| switch (err) {
+ error.CodegenFail,
+ => return emit.fail("unable to codegen: {s}", .{@errorName(err)}),
+ else => |e| return e,
+ }) {
+ .mcv => |mcv| switch (mcv) {
+ else => unreachable,
+ .load_direct, .load_symbol => |sym_index| sym_index,
+ },
+ .fail => |em| {
+ assert(emit.lower.err_msg == null);
+ emit.lower.err_msg = em;
+ return error.EmitFail;
+ },
+ } },
+ .uav => |uav| .{ .addr_reloc = switch (try emit.bin_file.lowerUav(
+ emit.pt,
+ uav.val,
+ Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),
+ emit.lower.src_loc,
+ )) {
+ .mcv => |mcv| switch (mcv) {
+ else => unreachable,
+ .load_direct, .load_symbol => |sym_index| sym_index,
+ },
+ .fail => |em| {
+ assert(emit.lower.err_msg == null);
+ emit.lower.err_msg = em;
+ return error.EmitFail;
+ },
+ } },
+ .lazy_sym, .extern_func => unreachable,
};
break :base &loc_buf[0];
},
@@ -449,34 +585,57 @@ pub fn emitMir(emit: *Emit) Error!void {
};
break :disp &loc_buf[1];
},
- } } };
+ } };
},
};
- const ip = &emit.lower.bin_file.comp.zcu.?.intern_pool;
- const air_inst = emit.air.instructions.get(@intFromEnum(air_inst_index));
- const name: Air.NullTerminatedString = switch (air_inst.tag) {
- else => unreachable,
- .arg => air_inst.data.arg.name,
- .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => @enumFromInt(air_inst.data.pl_op.payload),
- };
- try dwarf.genLocalDebugInfo(
- switch (air_inst.tag) {
+
+ const local = &emit.lower.mir.locals[local_index];
+ local_index += 1;
+ try dwarf.genLocalVarDebugInfo(
+ switch (mir_inst.ops) {
else => unreachable,
- .arg, .dbg_arg_inline => .local_arg,
- .dbg_var_ptr, .dbg_var_val => .local_var,
+ .pseudo_dbg_arg_none,
+ .pseudo_dbg_arg_i_s,
+ .pseudo_dbg_arg_i_u,
+ .pseudo_dbg_arg_i_64,
+ .pseudo_dbg_arg_ro,
+ .pseudo_dbg_arg_fa,
+ .pseudo_dbg_arg_m,
+ .pseudo_dbg_arg_val,
+ => .arg,
+ .pseudo_dbg_var_none,
+ .pseudo_dbg_var_i_s,
+ .pseudo_dbg_var_i_u,
+ .pseudo_dbg_var_i_64,
+ .pseudo_dbg_var_ro,
+ .pseudo_dbg_var_fa,
+ .pseudo_dbg_var_m,
+ .pseudo_dbg_var_val,
+ => .local_var,
},
- name.toSlice(emit.air),
- switch (air_inst.tag) {
+ local.name.toSlice(&emit.lower.mir),
+ .fromInterned(local.type),
+ loc,
+ );
+ },
+ .plan9, .none => local_index += 1,
+ },
+ .pseudo_dbg_arg_val, .pseudo_dbg_var_val => switch (emit.debug_output) {
+ .dwarf => |dwarf| {
+ const local = &emit.lower.mir.locals[local_index];
+ local_index += 1;
+ try dwarf.genLocalConstDebugInfo(
+ emit.lower.src_loc,
+ switch (mir_inst.ops) {
else => unreachable,
- .arg => emit.air.typeOfIndex(air_inst_index, ip),
- .dbg_var_ptr => emit.air.typeOf(air_inst.data.pl_op.operand, ip).childTypeIp(ip),
- .dbg_var_val, .dbg_arg_inline => emit.air.typeOf(air_inst.data.pl_op.operand, ip),
+ .pseudo_dbg_arg_val => .comptime_arg,
+ .pseudo_dbg_var_val => .local_const,
},
- loc,
+ local.name.toSlice(&emit.lower.mir),
+ .fromInterned(mir_inst.data.ip_index),
);
},
- .plan9 => {},
- .none => {},
+ .plan9, .none => local_index += 1,
},
.pseudo_dbg_var_args_none => switch (emit.debug_output) {
.dwarf => |dwarf| try dwarf.genVarArgsDebugInfo(),
@@ -488,8 +647,8 @@ pub fn emitMir(emit: *Emit) Error!void {
}
}
}
- for (relocs.items) |reloc| {
- const target = code_offset_mapping[reloc.target];
+ for (emit.relocs.items) |reloc| {
+ const target = emit.code_offset_mapping.items[reloc.target];
const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.inst_offset + reloc.inst_length)) + reloc.target_offset;
const inst_bytes = emit.code.items[reloc.inst_offset..][0..reloc.inst_length];
switch (reloc.source_length) {
@@ -503,13 +662,13 @@ pub fn emitMir(emit: *Emit) Error!void {
}
}
if (emit.lower.mir.table.len > 0) {
- if (emit.lower.bin_file.cast(.elf)) |elf_file| {
+ if (emit.bin_file.cast(.elf)) |elf_file| {
const zo = elf_file.zigObjectPtr().?;
const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
const ptr_size = @divExact(emit.lower.target.ptrBitWidth(), 8);
var table_offset = std.mem.alignForward(u32, @intCast(emit.code.items.len), ptr_size);
- for (table_relocs.items) |table_reloc| try atom.addReloc(gpa, .{
+ for (emit.table_relocs.items) |table_reloc| try atom.addReloc(gpa, .{
.r_offset = table_reloc.source_offset,
.r_info = @as(u64, emit.atom_index) << 32 | @intFromEnum(std.elf.R_X86_64.@"32"),
.r_addend = @as(i64, table_offset) + table_reloc.target_offset,
@@ -518,7 +677,7 @@ pub fn emitMir(emit: *Emit) Error!void {
try atom.addReloc(gpa, .{
.r_offset = table_offset,
.r_info = @as(u64, emit.atom_index) << 32 | @intFromEnum(std.elf.R_X86_64.@"64"),
- .r_addend = code_offset_mapping[entry],
+ .r_addend = emit.code_offset_mapping.items[entry],
}, zo);
table_offset += ptr_size;
}
@@ -527,6 +686,200 @@ pub fn emitMir(emit: *Emit) Error!void {
}
}
+pub fn deinit(emit: *Emit) void {
+ const gpa = emit.bin_file.comp.gpa;
+ emit.code_offset_mapping.deinit(gpa);
+ emit.relocs.deinit(gpa);
+ emit.table_relocs.deinit(gpa);
+ emit.* = undefined;
+}
+
+const RelocInfo = struct {
+ op_index: Lower.InstOpIndex,
+ off: i32 = 0,
+ target: Target,
+
+ const Target = struct {
+ index: u32,
+ is_extern: bool,
+ type: Target.Type,
+ force_pcrel_direct: bool = false,
+
+ const Type = enum { inst, table, symbol, branch, tls, tlv };
+ };
+};
+
+fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocInfo) Error!void {
+ const comp = emit.bin_file.comp;
+ const gpa = comp.gpa;
+ const start_offset: u32 = @intCast(emit.code.items.len);
+ try lowered_inst.encode(emit.code.writer(gpa), .{});
+ const end_offset: u32 = @intCast(emit.code.items.len);
+ for (reloc_info) |reloc| switch (reloc.target.type) {
+ .inst => {
+ const inst_length: u4 = @intCast(end_offset - start_offset);
+ const reloc_offset, const reloc_length = reloc_offset_length: {
+ var reloc_offset = inst_length;
+ var op_index: usize = lowered_inst.ops.len;
+ while (true) {
+ op_index -= 1;
+ const op = lowered_inst.encoding.data.ops[op_index];
+ if (op == .none) continue;
+ const is_mem = op.isMemory();
+ const enc_length: u4 = if (is_mem) switch (lowered_inst.ops[op_index].mem.sib.base) {
+ .rip_inst => 4,
+ else => unreachable,
+ } else @intCast(std.math.divCeil(u7, @intCast(op.immBitSize()), 8) catch unreachable);
+ reloc_offset -= enc_length;
+ if (op_index == reloc.op_index) break :reloc_offset_length .{ reloc_offset, enc_length };
+ assert(!is_mem);
+ }
+ };
+ try emit.relocs.append(emit.lower.allocator, .{
+ .inst_offset = start_offset,
+ .inst_length = inst_length,
+ .source_offset = reloc_offset,
+ .source_length = reloc_length,
+ .target = reloc.target.index,
+ .target_offset = reloc.off,
+ });
+ },
+ .table => try emit.table_relocs.append(emit.lower.allocator, .{
+ .source_offset = end_offset - 4,
+ .target_offset = reloc.off,
+ }),
+ .symbol => if (emit.bin_file.cast(.elf)) |elf_file| {
+ const zo = elf_file.zigObjectPtr().?;
+ const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
+ const r_type: std.elf.R_X86_64 = if (!emit.pic)
+ .@"32"
+ else if (reloc.target.is_extern and !reloc.target.force_pcrel_direct)
+ .GOTPCREL
+ else
+ .PC32;
+ try atom.addReloc(gpa, .{
+ .r_offset = end_offset - 4,
+ .r_info = @as(u64, reloc.target.index) << 32 | @intFromEnum(r_type),
+ .r_addend = if (emit.pic) reloc.off - 4 else reloc.off,
+ }, zo);
+ } else if (emit.bin_file.cast(.macho)) |macho_file| {
+ const zo = macho_file.getZigObject().?;
+ const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
+ try atom.addReloc(macho_file, .{
+ .tag = .@"extern",
+ .offset = end_offset - 4,
+ .target = reloc.target.index,
+ .addend = reloc.off,
+ .type = if (reloc.target.is_extern and !reloc.target.force_pcrel_direct) .got_load else .signed,
+ .meta = .{
+ .pcrel = true,
+ .has_subtractor = false,
+ .length = 2,
+ .symbolnum = @intCast(reloc.target.index),
+ },
+ });
+ } else if (emit.bin_file.cast(.coff)) |coff_file| {
+ const atom_index = coff_file.getAtomIndexForSymbol(
+ .{ .sym_index = emit.atom_index, .file = null },
+ ).?;
+ try coff_file.addRelocation(atom_index, .{
+ .type = if (reloc.target.is_extern) .got else .direct,
+ .target = if (reloc.target.is_extern)
+ coff_file.getGlobalByIndex(reloc.target.index)
+ else
+ .{ .sym_index = reloc.target.index, .file = null },
+ .offset = end_offset - 4,
+ .addend = @intCast(reloc.off),
+ .pcrel = true,
+ .length = 2,
+ });
+ } else unreachable,
+ .branch => if (emit.bin_file.cast(.elf)) |elf_file| {
+ const zo = elf_file.zigObjectPtr().?;
+ const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
+ const r_type: std.elf.R_X86_64 = .PLT32;
+ try atom.addReloc(gpa, .{
+ .r_offset = end_offset - 4,
+ .r_info = @as(u64, reloc.target.index) << 32 | @intFromEnum(r_type),
+ .r_addend = reloc.off - 4,
+ }, zo);
+ } else if (emit.bin_file.cast(.macho)) |macho_file| {
+ const zo = macho_file.getZigObject().?;
+ const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
+ try atom.addReloc(macho_file, .{
+ .tag = .@"extern",
+ .offset = end_offset - 4,
+ .target = reloc.target.index,
+ .addend = reloc.off,
+ .type = .branch,
+ .meta = .{
+ .pcrel = true,
+ .has_subtractor = false,
+ .length = 2,
+ .symbolnum = @intCast(reloc.target.index),
+ },
+ });
+ } else if (emit.bin_file.cast(.coff)) |coff_file| {
+ const atom_index = coff_file.getAtomIndexForSymbol(
+ .{ .sym_index = emit.atom_index, .file = null },
+ ).?;
+ try coff_file.addRelocation(atom_index, .{
+ .type = if (reloc.target.is_extern) .import else .got,
+ .target = if (reloc.target.is_extern)
+ coff_file.getGlobalByIndex(reloc.target.index)
+ else
+ .{ .sym_index = reloc.target.index, .file = null },
+ .offset = end_offset - 4,
+ .addend = @intCast(reloc.off),
+ .pcrel = true,
+ .length = 2,
+ });
+ } else return emit.fail("TODO implement {s} reloc for {s}", .{
+ @tagName(reloc.target.type), @tagName(emit.bin_file.tag),
+ }),
+ .tls => if (emit.bin_file.cast(.elf)) |elf_file| {
+ const zo = elf_file.zigObjectPtr().?;
+ const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
+ const r_type: std.elf.R_X86_64 = if (emit.pic) .TLSLD else unreachable;
+ try atom.addReloc(gpa, .{
+ .r_offset = end_offset - 4,
+ .r_info = @as(u64, reloc.target.index) << 32 | @intFromEnum(r_type),
+ .r_addend = reloc.off - 4,
+ }, zo);
+ } else return emit.fail("TODO implement {s} reloc for {s}", .{
+ @tagName(reloc.target.type), @tagName(emit.bin_file.tag),
+ }),
+ .tlv => if (emit.bin_file.cast(.elf)) |elf_file| {
+ const zo = elf_file.zigObjectPtr().?;
+ const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
+ const r_type: std.elf.R_X86_64 = if (emit.pic) .DTPOFF32 else .TPOFF32;
+ try atom.addReloc(gpa, .{
+ .r_offset = end_offset - 4,
+ .r_info = @as(u64, reloc.target.index) << 32 | @intFromEnum(r_type),
+ .r_addend = reloc.off,
+ }, zo);
+ } else if (emit.bin_file.cast(.macho)) |macho_file| {
+ const zo = macho_file.getZigObject().?;
+ const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
+ try atom.addReloc(macho_file, .{
+ .tag = .@"extern",
+ .offset = end_offset - 4,
+ .target = reloc.target.index,
+ .addend = reloc.off,
+ .type = .tlv,
+ .meta = .{
+ .pcrel = true,
+ .has_subtractor = false,
+ .length = 2,
+ .symbolnum = @intCast(reloc.target.index),
+ },
+ });
+ } else return emit.fail("TODO implement {s} reloc for {s}", .{
+ @tagName(reloc.target.type), @tagName(emit.bin_file.tag),
+ }),
+ };
+}
+
fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {
return switch (emit.lower.fail(format, args)) {
error.LowerFail => error.EmitFail,
@@ -610,12 +963,17 @@ fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void {
}
}
+const assert = std.debug.assert;
const bits = @import("bits.zig");
+const codegen = @import("../../codegen.zig");
+const Emit = @This();
+const encoder = @import("encoder.zig");
+const Instruction = encoder.Instruction;
+const InternPool = @import("../../InternPool.zig");
const link = @import("../../link.zig");
const log = std.log.scoped(.emit);
-const std = @import("std");
-
-const Air = @import("../../Air.zig");
-const Emit = @This();
const Lower = @import("Lower.zig");
const Mir = @import("Mir.zig");
+const std = @import("std");
+const Type = @import("../../Type.zig");
+const Zcu = @import("../../Zcu.zig");
diff --git a/src/arch/x86_64/Lower.zig b/src/arch/x86_64/Lower.zig
index 838f155d10..ca1fb1e428 100644
--- a/src/arch/x86_64/Lower.zig
+++ b/src/arch/x86_64/Lower.zig
@@ -1,10 +1,6 @@
//! This file contains the functionality for lowering x86_64 MIR to Instructions
-bin_file: *link.File,
target: *const std.Target,
-output_mode: std.builtin.OutputMode,
-link_mode: std.builtin.LinkMode,
-pic: bool,
allocator: std.mem.Allocator,
mir: Mir,
cc: std.builtin.CallingConvention,
@@ -17,7 +13,6 @@ result_relocs: [max_result_relocs]Reloc = undefined,
const max_result_insts = @max(
1, // non-pseudo instructions
- 3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode
2, // cmovcc: cmovcc \ cmovcc
3, // setcc: setcc \ setcc \ logicop
2, // jcc: jcc \ jcc
@@ -25,6 +20,7 @@ const max_result_insts = @max(
pseudo_probe_adjust_unrolled_max_insts,
pseudo_probe_adjust_setup_insts,
pseudo_probe_adjust_loop_insts,
+ abi.zigcc.callee_preserved_regs.len * 2, // push_regs/pop_regs
abi.Win64.callee_preserved_regs.len * 2, // push_regs/pop_regs
abi.SysV.callee_preserved_regs.len * 2, // push_regs/pop_regs
);
@@ -33,14 +29,13 @@ const max_result_relocs = @max(
2, // jcc: jcc \ jcc
2, // test \ jcc \ probe \ sub \ jmp
1, // probe \ sub \ jcc
- 3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode
);
-const ResultInstIndex = std.math.IntFittingRange(0, max_result_insts - 1);
-const ResultRelocIndex = std.math.IntFittingRange(0, max_result_relocs - 1);
-const InstOpIndex = std.math.IntFittingRange(
+const ResultInstIndex = std.math.IntFittingRange(0, max_result_insts);
+const ResultRelocIndex = std.math.IntFittingRange(0, max_result_relocs);
+pub const InstOpIndex = std.math.IntFittingRange(
0,
- @typeInfo(@FieldType(Instruction, "ops")).array.len - 1,
+ @typeInfo(@FieldType(Instruction, "ops")).array.len,
);
pub const pseudo_probe_align_insts = 5; // test \ jcc \ probe \ sub \ jmp
@@ -54,7 +49,8 @@ pub const Error = error{
LowerFail,
InvalidInstruction,
CannotEncode,
-};
+ CodegenFail,
+} || codegen.GenerateSymbolError;
pub const Reloc = struct {
lowered_inst_index: ResultInstIndex,
@@ -65,14 +61,10 @@ pub const Reloc = struct {
const Target = union(enum) {
inst: Mir.Inst.Index,
table,
- linker_reloc: u32,
- linker_pcrel: u32,
- linker_tlsld: u32,
- linker_dtpoff: u32,
- linker_extern_fn: u32,
- linker_got: u32,
- linker_direct: u32,
- linker_import: u32,
+ nav: InternPool.Nav.Index,
+ uav: InternPool.Key.Ptr.BaseAddr.Uav,
+ lazy_sym: link.File.LazySymbol,
+ extern_func: Mir.NullTerminatedString,
};
};
@@ -80,7 +72,7 @@ const Options = struct { allow_frame_locs: bool };
/// The returned slice is overwritten by the next call to lowerMir.
pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
- insts: []const Instruction,
+ insts: []Instruction,
relocs: []const Reloc,
} {
lower.result_insts = undefined;
@@ -98,130 +90,130 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.pseudo => switch (inst.ops) {
.pseudo_cmov_z_and_np_rr => {
assert(inst.data.rr.fixes == ._);
- try lower.emit(.none, .cmovnz, &.{
+ try lower.encode(.none, .cmovnz, &.{
.{ .reg = inst.data.rr.r2 },
.{ .reg = inst.data.rr.r1 },
});
- try lower.emit(.none, .cmovnp, &.{
+ try lower.encode(.none, .cmovnp, &.{
.{ .reg = inst.data.rr.r1 },
.{ .reg = inst.data.rr.r2 },
});
},
.pseudo_cmov_nz_or_p_rr => {
assert(inst.data.rr.fixes == ._);
- try lower.emit(.none, .cmovnz, &.{
+ try lower.encode(.none, .cmovnz, &.{
.{ .reg = inst.data.rr.r1 },
.{ .reg = inst.data.rr.r2 },
});
- try lower.emit(.none, .cmovp, &.{
+ try lower.encode(.none, .cmovp, &.{
.{ .reg = inst.data.rr.r1 },
.{ .reg = inst.data.rr.r2 },
});
},
.pseudo_cmov_nz_or_p_rm => {
assert(inst.data.rx.fixes == ._);
- try lower.emit(.none, .cmovnz, &.{
+ try lower.encode(.none, .cmovnz, &.{
.{ .reg = inst.data.rx.r1 },
.{ .mem = lower.mem(1, inst.data.rx.payload) },
});
- try lower.emit(.none, .cmovp, &.{
+ try lower.encode(.none, .cmovp, &.{
.{ .reg = inst.data.rx.r1 },
.{ .mem = lower.mem(1, inst.data.rx.payload) },
});
},
.pseudo_set_z_and_np_r => {
assert(inst.data.rr.fixes == ._);
- try lower.emit(.none, .setz, &.{
+ try lower.encode(.none, .setz, &.{
.{ .reg = inst.data.rr.r1 },
});
- try lower.emit(.none, .setnp, &.{
+ try lower.encode(.none, .setnp, &.{
.{ .reg = inst.data.rr.r2 },
});
- try lower.emit(.none, .@"and", &.{
+ try lower.encode(.none, .@"and", &.{
.{ .reg = inst.data.rr.r1 },
.{ .reg = inst.data.rr.r2 },
});
},
.pseudo_set_z_and_np_m => {
assert(inst.data.rx.fixes == ._);
- try lower.emit(.none, .setz, &.{
+ try lower.encode(.none, .setz, &.{
.{ .mem = lower.mem(0, inst.data.rx.payload) },
});
- try lower.emit(.none, .setnp, &.{
+ try lower.encode(.none, .setnp, &.{
.{ .reg = inst.data.rx.r1 },
});
- try lower.emit(.none, .@"and", &.{
+ try lower.encode(.none, .@"and", &.{
.{ .mem = lower.mem(0, inst.data.rx.payload) },
.{ .reg = inst.data.rx.r1 },
});
},
.pseudo_set_nz_or_p_r => {
assert(inst.data.rr.fixes == ._);
- try lower.emit(.none, .setnz, &.{
+ try lower.encode(.none, .setnz, &.{
.{ .reg = inst.data.rr.r1 },
});
- try lower.emit(.none, .setp, &.{
+ try lower.encode(.none, .setp, &.{
.{ .reg = inst.data.rr.r2 },
});
- try lower.emit(.none, .@"or", &.{
+ try lower.encode(.none, .@"or", &.{
.{ .reg = inst.data.rr.r1 },
.{ .reg = inst.data.rr.r2 },
});
},
.pseudo_set_nz_or_p_m => {
assert(inst.data.rx.fixes == ._);
- try lower.emit(.none, .setnz, &.{
+ try lower.encode(.none, .setnz, &.{
.{ .mem = lower.mem(0, inst.data.rx.payload) },
});
- try lower.emit(.none, .setp, &.{
+ try lower.encode(.none, .setp, &.{
.{ .reg = inst.data.rx.r1 },
});
- try lower.emit(.none, .@"or", &.{
+ try lower.encode(.none, .@"or", &.{
.{ .mem = lower.mem(0, inst.data.rx.payload) },
.{ .reg = inst.data.rx.r1 },
});
},
.pseudo_j_z_and_np_inst => {
assert(inst.data.inst.fixes == ._);
- try lower.emit(.none, .jnz, &.{
+ try lower.encode(.none, .jnz, &.{
.{ .imm = lower.reloc(0, .{ .inst = index + 1 }, 0) },
});
- try lower.emit(.none, .jnp, &.{
+ try lower.encode(.none, .jnp, &.{
.{ .imm = lower.reloc(0, .{ .inst = inst.data.inst.inst }, 0) },
});
},
.pseudo_j_nz_or_p_inst => {
assert(inst.data.inst.fixes == ._);
- try lower.emit(.none, .jnz, &.{
+ try lower.encode(.none, .jnz, &.{
.{ .imm = lower.reloc(0, .{ .inst = inst.data.inst.inst }, 0) },
});
- try lower.emit(.none, .jp, &.{
+ try lower.encode(.none, .jp, &.{
.{ .imm = lower.reloc(0, .{ .inst = inst.data.inst.inst }, 0) },
});
},
.pseudo_probe_align_ri_s => {
- try lower.emit(.none, .@"test", &.{
+ try lower.encode(.none, .@"test", &.{
.{ .reg = inst.data.ri.r1 },
.{ .imm = .s(@bitCast(inst.data.ri.i)) },
});
- try lower.emit(.none, .jz, &.{
+ try lower.encode(.none, .jz, &.{
.{ .imm = lower.reloc(0, .{ .inst = index + 1 }, 0) },
});
- try lower.emit(.none, .lea, &.{
+ try lower.encode(.none, .lea, &.{
.{ .reg = inst.data.ri.r1 },
.{ .mem = Memory.initSib(.qword, .{
.base = .{ .reg = inst.data.ri.r1 },
.disp = -page_size,
}) },
});
- try lower.emit(.none, .@"test", &.{
+ try lower.encode(.none, .@"test", &.{
.{ .mem = Memory.initSib(.dword, .{
.base = .{ .reg = inst.data.ri.r1 },
}) },
.{ .reg = inst.data.ri.r1.to32() },
});
- try lower.emit(.none, .jmp, &.{
+ try lower.encode(.none, .jmp, &.{
.{ .imm = lower.reloc(0, .{ .inst = index }, 0) },
});
assert(lower.result_insts_len == pseudo_probe_align_insts);
@@ -229,7 +221,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.pseudo_probe_adjust_unrolled_ri_s => {
var offset = page_size;
while (offset < @as(i32, @bitCast(inst.data.ri.i))) : (offset += page_size) {
- try lower.emit(.none, .@"test", &.{
+ try lower.encode(.none, .@"test", &.{
.{ .mem = Memory.initSib(.dword, .{
.base = .{ .reg = inst.data.ri.r1 },
.disp = -offset,
@@ -237,25 +229,25 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.{ .reg = inst.data.ri.r1.to32() },
});
}
- try lower.emit(.none, .sub, &.{
+ try lower.encode(.none, .sub, &.{
.{ .reg = inst.data.ri.r1 },
.{ .imm = .s(@bitCast(inst.data.ri.i)) },
});
assert(lower.result_insts_len <= pseudo_probe_adjust_unrolled_max_insts);
},
.pseudo_probe_adjust_setup_rri_s => {
- try lower.emit(.none, .mov, &.{
+ try lower.encode(.none, .mov, &.{
.{ .reg = inst.data.rri.r2.to32() },
.{ .imm = .s(@bitCast(inst.data.rri.i)) },
});
- try lower.emit(.none, .sub, &.{
+ try lower.encode(.none, .sub, &.{
.{ .reg = inst.data.rri.r1 },
.{ .reg = inst.data.rri.r2 },
});
assert(lower.result_insts_len == pseudo_probe_adjust_setup_insts);
},
.pseudo_probe_adjust_loop_rr => {
- try lower.emit(.none, .@"test", &.{
+ try lower.encode(.none, .@"test", &.{
.{ .mem = Memory.initSib(.dword, .{
.base = .{ .reg = inst.data.rr.r1 },
.scale_index = .{ .scale = 1, .index = inst.data.rr.r2 },
@@ -263,11 +255,11 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
}) },
.{ .reg = inst.data.rr.r1.to32() },
});
- try lower.emit(.none, .sub, &.{
+ try lower.encode(.none, .sub, &.{
.{ .reg = inst.data.rr.r2 },
.{ .imm = .s(page_size) },
});
- try lower.emit(.none, .jae, &.{
+ try lower.encode(.none, .jae, &.{
.{ .imm = lower.reloc(0, .{ .inst = index }, 0) },
});
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 {
.pseudo_push_reg_list => try lower.pushPopRegList(.push, inst),
.pseudo_pop_reg_list => try lower.pushPopRegList(.pop, inst),
- .pseudo_cfi_def_cfa_ri_s => try lower.emit(.directive, .@".cfi_def_cfa", &.{
+ .pseudo_cfi_def_cfa_ri_s => try lower.encode(.directive, .@".cfi_def_cfa", &.{
.{ .reg = inst.data.ri.r1 },
.{ .imm = lower.imm(.ri_s, inst.data.ri.i) },
}),
- .pseudo_cfi_def_cfa_register_r => try lower.emit(.directive, .@".cfi_def_cfa_register", &.{
+ .pseudo_cfi_def_cfa_register_r => try lower.encode(.directive, .@".cfi_def_cfa_register", &.{
.{ .reg = inst.data.r.r1 },
}),
- .pseudo_cfi_def_cfa_offset_i_s => try lower.emit(.directive, .@".cfi_def_cfa_offset", &.{
+ .pseudo_cfi_def_cfa_offset_i_s => try lower.encode(.directive, .@".cfi_def_cfa_offset", &.{
.{ .imm = lower.imm(.i_s, inst.data.i.i) },
}),
- .pseudo_cfi_adjust_cfa_offset_i_s => try lower.emit(.directive, .@".cfi_adjust_cfa_offset", &.{
+ .pseudo_cfi_adjust_cfa_offset_i_s => try lower.encode(.directive, .@".cfi_adjust_cfa_offset", &.{
.{ .imm = lower.imm(.i_s, inst.data.i.i) },
}),
- .pseudo_cfi_offset_ri_s => try lower.emit(.directive, .@".cfi_offset", &.{
+ .pseudo_cfi_offset_ri_s => try lower.encode(.directive, .@".cfi_offset", &.{
.{ .reg = inst.data.ri.r1 },
.{ .imm = lower.imm(.ri_s, inst.data.ri.i) },
}),
- .pseudo_cfi_val_offset_ri_s => try lower.emit(.directive, .@".cfi_val_offset", &.{
+ .pseudo_cfi_val_offset_ri_s => try lower.encode(.directive, .@".cfi_val_offset", &.{
.{ .reg = inst.data.ri.r1 },
.{ .imm = lower.imm(.ri_s, inst.data.ri.i) },
}),
- .pseudo_cfi_rel_offset_ri_s => try lower.emit(.directive, .@".cfi_rel_offset", &.{
+ .pseudo_cfi_rel_offset_ri_s => try lower.encode(.directive, .@".cfi_rel_offset", &.{
.{ .reg = inst.data.ri.r1 },
.{ .imm = lower.imm(.ri_s, inst.data.ri.i) },
}),
- .pseudo_cfi_register_rr => try lower.emit(.directive, .@".cfi_register", &.{
+ .pseudo_cfi_register_rr => try lower.encode(.directive, .@".cfi_register", &.{
.{ .reg = inst.data.rr.r1 },
.{ .reg = inst.data.rr.r2 },
}),
- .pseudo_cfi_restore_r => try lower.emit(.directive, .@".cfi_restore", &.{
+ .pseudo_cfi_restore_r => try lower.encode(.directive, .@".cfi_restore", &.{
.{ .reg = inst.data.r.r1 },
}),
- .pseudo_cfi_undefined_r => try lower.emit(.directive, .@".cfi_undefined", &.{
+ .pseudo_cfi_undefined_r => try lower.encode(.directive, .@".cfi_undefined", &.{
.{ .reg = inst.data.r.r1 },
}),
- .pseudo_cfi_same_value_r => try lower.emit(.directive, .@".cfi_same_value", &.{
+ .pseudo_cfi_same_value_r => try lower.encode(.directive, .@".cfi_same_value", &.{
.{ .reg = inst.data.r.r1 },
}),
- .pseudo_cfi_remember_state_none => try lower.emit(.directive, .@".cfi_remember_state", &.{}),
- .pseudo_cfi_restore_state_none => try lower.emit(.directive, .@".cfi_restore_state", &.{}),
- .pseudo_cfi_escape_bytes => try lower.emit(.directive, .@".cfi_escape", &.{
+ .pseudo_cfi_remember_state_none => try lower.encode(.directive, .@".cfi_remember_state", &.{}),
+ .pseudo_cfi_restore_state_none => try lower.encode(.directive, .@".cfi_restore_state", &.{}),
+ .pseudo_cfi_escape_bytes => try lower.encode(.directive, .@".cfi_escape", &.{
.{ .bytes = inst.data.bytes.get(lower.mir) },
}),
@@ -327,16 +319,23 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.pseudo_dbg_leave_block_none,
.pseudo_dbg_enter_inline_func,
.pseudo_dbg_leave_inline_func,
- .pseudo_dbg_local_a,
- .pseudo_dbg_local_ai_s,
- .pseudo_dbg_local_ai_u,
- .pseudo_dbg_local_ai_64,
- .pseudo_dbg_local_as,
- .pseudo_dbg_local_aso,
- .pseudo_dbg_local_aro,
- .pseudo_dbg_local_af,
- .pseudo_dbg_local_am,
+ .pseudo_dbg_arg_none,
+ .pseudo_dbg_arg_i_s,
+ .pseudo_dbg_arg_i_u,
+ .pseudo_dbg_arg_i_64,
+ .pseudo_dbg_arg_ro,
+ .pseudo_dbg_arg_fa,
+ .pseudo_dbg_arg_m,
+ .pseudo_dbg_arg_val,
.pseudo_dbg_var_args_none,
+ .pseudo_dbg_var_none,
+ .pseudo_dbg_var_i_s,
+ .pseudo_dbg_var_i_u,
+ .pseudo_dbg_var_i_64,
+ .pseudo_dbg_var_ro,
+ .pseudo_dbg_var_fa,
+ .pseudo_dbg_var_m,
+ .pseudo_dbg_var_val,
.pseudo_dead_none,
=> {},
@@ -353,7 +352,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error {
@branchHint(.cold);
assert(lower.err_msg == null);
- lower.err_msg = try Zcu.ErrorMsg.create(lower.allocator, lower.src_loc, format, args);
+ lower.err_msg = try .create(lower.allocator, lower.src_loc, format, args);
return error.LowerFail;
}
@@ -364,7 +363,8 @@ pub fn imm(lower: *const Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
.i_s,
.mi_s,
.rmi_s,
- .pseudo_dbg_local_ai_s,
+ .pseudo_dbg_arg_i_s,
+ .pseudo_dbg_var_i_s,
=> .s(@bitCast(i)),
.ii,
@@ -379,24 +379,32 @@ pub fn imm(lower: *const Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
.mri,
.rrm,
.rrmi,
- .pseudo_dbg_local_ai_u,
+ .pseudo_dbg_arg_i_u,
+ .pseudo_dbg_var_i_u,
=> .u(i),
.ri_64,
- .pseudo_dbg_local_ai_64,
=> .u(lower.mir.extraData(Mir.Imm64, i).data.decode()),
+ .pseudo_dbg_arg_i_64,
+ .pseudo_dbg_var_i_64,
+ => unreachable,
+
else => unreachable,
};
}
-pub fn mem(lower: *Lower, op_index: InstOpIndex, payload: u32) Memory {
- var m = lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();
+fn mem(lower: *Lower, op_index: InstOpIndex, payload: u32) Memory {
+ var m = lower.mir.resolveMemoryExtra(payload).decode();
switch (m) {
.sib => |*sib| switch (sib.base) {
- else => {},
+ .none, .reg, .frame => {},
.table => sib.disp = lower.reloc(op_index, .table, sib.disp).signed,
.rip_inst => |inst_index| sib.disp = lower.reloc(op_index, .{ .inst = inst_index }, sib.disp).signed,
+ .nav => |nav| sib.disp = lower.reloc(op_index, .{ .nav = nav }, sib.disp).signed,
+ .uav => |uav| sib.disp = lower.reloc(op_index, .{ .uav = uav }, sib.disp).signed,
+ .lazy_sym => |lazy_sym| sib.disp = lower.reloc(op_index, .{ .lazy_sym = lazy_sym }, sib.disp).signed,
+ .extern_func => |extern_func| sib.disp = lower.reloc(op_index, .{ .extern_func = extern_func }, sib.disp).signed,
},
else => {},
}
@@ -414,177 +422,40 @@ fn reloc(lower: *Lower, op_index: InstOpIndex, target: Reloc.Target, off: i32) I
return .s(0);
}
-fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
- const emit_prefix = prefix;
- var emit_mnemonic = mnemonic;
- var emit_ops_storage: [4]Operand = undefined;
- const emit_ops = emit_ops_storage[0..ops.len];
- for (emit_ops, ops, 0..) |*emit_op, op, op_index| {
- emit_op.* = switch (op) {
- else => op,
- .mem => |mem_op| op: switch (mem_op.base()) {
- else => op,
- .reloc => |sym_index| {
- assert(prefix == .none);
- assert(mem_op.sib.disp == 0);
- assert(mem_op.sib.scale_index.scale == 0);
-
- if (lower.bin_file.cast(.elf)) |elf_file| {
- const zo = elf_file.zigObjectPtr().?;
- const elf_sym = zo.symbol(sym_index);
-
- if (elf_sym.flags.is_tls) {
- // TODO handle extern TLS vars, i.e., emit GD model
- if (lower.pic) {
- // Here, we currently assume local dynamic TLS vars, and so
- // we emit LD model.
- _ = lower.reloc(1, .{ .linker_tlsld = sym_index }, 0);
- lower.result_insts[lower.result_insts_len] = try .new(.none, .lea, &.{
- .{ .reg = .rdi },
- .{ .mem = Memory.initRip(.none, 0) },
- }, lower.target);
- lower.result_insts_len += 1;
- _ = lower.reloc(0, .{
- .linker_extern_fn = try elf_file.getGlobalSymbol("__tls_get_addr", null),
- }, 0);
- lower.result_insts[lower.result_insts_len] = try .new(.none, .call, &.{
- .{ .imm = .s(0) },
- }, lower.target);
- lower.result_insts_len += 1;
- _ = lower.reloc(@intCast(op_index), .{ .linker_dtpoff = sym_index }, 0);
- emit_mnemonic = .lea;
- break :op .{ .mem = Memory.initSib(.none, .{
- .base = .{ .reg = .rax },
- .disp = std.math.minInt(i32),
- }) };
- } else {
- // Since we are linking statically, we emit LE model directly.
- lower.result_insts[lower.result_insts_len] = try .new(.none, .mov, &.{
- .{ .reg = .rax },
- .{ .mem = Memory.initSib(.qword, .{ .base = .{ .reg = .fs } }) },
- }, lower.target);
- lower.result_insts_len += 1;
- _ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
- emit_mnemonic = .lea;
- break :op .{ .mem = Memory.initSib(.none, .{
- .base = .{ .reg = .rax },
- .disp = std.math.minInt(i32),
- }) };
- }
- }
-
- if (lower.pic) switch (mnemonic) {
- .lea => {
- _ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
- if (!elf_sym.flags.is_extern_ptr) break :op .{ .mem = Memory.initRip(.none, 0) };
- emit_mnemonic = .mov;
- break :op .{ .mem = Memory.initRip(.ptr, 0) };
- },
- .mov => {
- if (elf_sym.flags.is_extern_ptr) {
- const reg = ops[0].reg;
- _ = lower.reloc(1, .{ .linker_reloc = sym_index }, 0);
- lower.result_insts[lower.result_insts_len] = try .new(.none, .mov, &.{
- .{ .reg = reg.to64() },
- .{ .mem = Memory.initRip(.qword, 0) },
- }, lower.target);
- lower.result_insts_len += 1;
- break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{ .base = .{
- .reg = reg.to64(),
- } }) };
- }
- _ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
- break :op .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) };
- },
- else => unreachable,
- };
- _ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
- switch (mnemonic) {
- .call => break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{
- .base = .{ .reg = .ds },
- }) },
- .lea => {
- emit_mnemonic = .mov;
- break :op .{ .imm = .s(0) };
- },
- .mov => break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{
- .base = .{ .reg = .ds },
- }) },
- else => unreachable,
- }
- } else if (lower.bin_file.cast(.macho)) |macho_file| {
- const zo = macho_file.getZigObject().?;
- const macho_sym = zo.symbols.items[sym_index];
-
- if (macho_sym.flags.tlv) {
- _ = lower.reloc(1, .{ .linker_reloc = sym_index }, 0);
- lower.result_insts[lower.result_insts_len] = try .new(.none, .mov, &.{
- .{ .reg = .rdi },
- .{ .mem = Memory.initRip(.ptr, 0) },
- }, lower.target);
- lower.result_insts_len += 1;
- lower.result_insts[lower.result_insts_len] = try .new(.none, .call, &.{
- .{ .mem = Memory.initSib(.qword, .{ .base = .{ .reg = .rdi } }) },
- }, lower.target);
- lower.result_insts_len += 1;
- emit_mnemonic = .mov;
- break :op .{ .reg = .rax };
- }
-
- break :op switch (mnemonic) {
- .lea => {
- _ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
- if (!macho_sym.flags.is_extern_ptr) break :op .{ .mem = Memory.initRip(.none, 0) };
- emit_mnemonic = .mov;
- break :op .{ .mem = Memory.initRip(.ptr, 0) };
- },
- .mov => {
- if (macho_sym.flags.is_extern_ptr) {
- const reg = ops[0].reg;
- _ = lower.reloc(1, .{ .linker_reloc = sym_index }, 0);
- lower.result_insts[lower.result_insts_len] = try .new(.none, .mov, &.{
- .{ .reg = reg.to64() },
- .{ .mem = Memory.initRip(.qword, 0) },
- }, lower.target);
- lower.result_insts_len += 1;
- break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{ .base = .{
- .reg = reg.to64(),
- } }) };
- }
- _ = lower.reloc(@intCast(op_index), .{ .linker_reloc = sym_index }, 0);
- break :op .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) };
- },
- else => unreachable,
- };
- } else {
- return lower.fail("TODO: bin format '{s}'", .{@tagName(lower.bin_file.tag)});
- }
- },
- .pcrel => |sym_index| {
- assert(prefix == .none);
- assert(mem_op.sib.disp == 0);
- assert(mem_op.sib.scale_index.scale == 0);
+fn encode(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
+ lower.result_insts[lower.result_insts_len] = try .new(prefix, mnemonic, ops, lower.target);
+ lower.result_insts_len += 1;
+}
- _ = lower.reloc(@intCast(op_index), .{ .linker_pcrel = sym_index }, 0);
- break :op switch (lower.bin_file.tag) {
- .elf => op,
- .macho => switch (mnemonic) {
- .lea => .{ .mem = Memory.initRip(.none, 0) },
- .mov => .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) },
- else => unreachable,
- },
- else => |tag| return lower.fail("TODO: bin format '{s}'", .{@tagName(tag)}),
- };
- },
- },
+const inst_tags_len = @typeInfo(Mir.Inst.Tag).@"enum".fields.len;
+const inst_fixes_len = @typeInfo(Mir.Inst.Fixes).@"enum".fields.len;
+/// Lookup table, indexed by `@intFromEnum(inst.tag) * inst_fixes_len + @intFromEnum(fixes)`.
+/// The value is the resulting `Mnemonic`, or `null` if the combination is not valid.
+const mnemonic_table: [inst_tags_len * inst_fixes_len]?Mnemonic = table: {
+ @setEvalBranchQuota(80_000);
+ var table: [inst_tags_len * inst_fixes_len]?Mnemonic = undefined;
+ for (0..inst_fixes_len) |fixes_i| {
+ const fixes: Mir.Inst.Fixes = @enumFromInt(fixes_i);
+ const prefix, const suffix = affix: {
+ const pattern = if (std.mem.indexOfScalar(u8, @tagName(fixes), ' ')) |i|
+ @tagName(fixes)[i + 1 ..]
+ else
+ @tagName(fixes);
+ const wildcard_idx = std.mem.indexOfScalar(u8, pattern, '_').?;
+ break :affix .{ pattern[0..wildcard_idx], pattern[wildcard_idx + 1 ..] };
};
+ for (0..inst_tags_len) |inst_tag_i| {
+ const inst_tag: Mir.Inst.Tag = @enumFromInt(inst_tag_i);
+ const name = prefix ++ @tagName(inst_tag) ++ suffix;
+ const idx = inst_tag_i * inst_fixes_len + fixes_i;
+ table[idx] = if (@hasField(Mnemonic, name)) @field(Mnemonic, name) else null;
+ }
}
- lower.result_insts[lower.result_insts_len] = try .new(emit_prefix, emit_mnemonic, emit_ops, lower.target);
- lower.result_insts_len += 1;
-}
+ break :table table;
+};
fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
- @setEvalBranchQuota(2_800);
+ @setEvalBranchQuota(2_000);
const fixes = switch (inst.ops) {
.none => inst.data.none.fixes,
.inst => inst.data.inst.fixes,
@@ -604,28 +475,27 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
.rrmi => inst.data.rrix.fixes,
.mi_u, .mi_s => inst.data.x.fixes,
.m => inst.data.x.fixes,
- .extern_fn_reloc, .got_reloc, .direct_reloc, .import_reloc, .tlv_reloc, .rel => ._,
+ .nav, .uav, .lazy_sym, .extern_func => ._,
else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),
};
- try lower.emit(switch (fixes) {
+ try lower.encode(switch (fixes) {
inline else => |tag| comptime if (std.mem.indexOfScalar(u8, @tagName(tag), ' ')) |space|
@field(Prefix, @tagName(tag)[0..space])
else
.none,
}, mnemonic: {
- comptime var max_len = 0;
- inline for (@typeInfo(Mnemonic).@"enum".fields) |field| max_len = @max(field.name.len, max_len);
- var buf: [max_len]u8 = undefined;
-
+ if (mnemonic_table[@intFromEnum(inst.tag) * inst_fixes_len + @intFromEnum(fixes)]) |mnemonic| {
+ break :mnemonic mnemonic;
+ }
+ // This combination is invalid; make the theoretical mnemonic name and emit an error with it.
const fixes_name = @tagName(fixes);
const pattern = fixes_name[if (std.mem.indexOfScalar(u8, fixes_name, ' ')) |i| i + " ".len else 0..];
const wildcard_index = std.mem.indexOfScalar(u8, pattern, '_').?;
- const parts = .{ pattern[0..wildcard_index], @tagName(inst.tag), pattern[wildcard_index + "_".len ..] };
- const err_msg = "unsupported mnemonic: ";
- const mnemonic = std.fmt.bufPrint(&buf, "{s}{s}{s}", parts) catch
- return lower.fail(err_msg ++ "'{s}{s}{s}'", parts);
- break :mnemonic std.meta.stringToEnum(Mnemonic, mnemonic) orelse
- return lower.fail(err_msg ++ "'{s}'", .{mnemonic});
+ return lower.fail("unsupported mnemonic: '{s}{s}{s}'", .{
+ pattern[0..wildcard_index],
+ @tagName(inst.tag),
+ pattern[wildcard_index + "_".len ..],
+ });
}, switch (inst.ops) {
.none => &.{},
.inst => &.{
@@ -738,22 +608,17 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
.{ .mem = lower.mem(2, inst.data.rrix.payload) },
.{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },
},
- .extern_fn_reloc, .rel => &.{
- .{ .imm = lower.reloc(0, .{ .linker_extern_fn = inst.data.reloc.sym_index }, inst.data.reloc.off) },
+ .nav => &.{
+ .{ .imm = lower.reloc(0, .{ .nav = inst.data.nav.index }, inst.data.nav.off) },
},
- .got_reloc, .direct_reloc, .import_reloc => ops: {
- const reg = inst.data.rx.r1;
- const extra = lower.mir.extraData(bits.SymbolOffset, inst.data.rx.payload).data;
- _ = lower.reloc(1, switch (inst.ops) {
- .got_reloc => .{ .linker_got = extra.sym_index },
- .direct_reloc => .{ .linker_direct = extra.sym_index },
- .import_reloc => .{ .linker_import = extra.sym_index },
- else => unreachable,
- }, extra.off);
- break :ops &.{
- .{ .reg = reg },
- .{ .mem = Memory.initRip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
- };
+ .uav => &.{
+ .{ .imm = lower.reloc(0, .{ .uav = inst.data.uav }, 0) },
+ },
+ .lazy_sym => &.{
+ .{ .imm = lower.reloc(0, .{ .lazy_sym = inst.data.lazy_sym }, 0) },
+ },
+ .extern_func => &.{
+ .{ .imm = lower.reloc(0, .{ .extern_func = inst.data.extern_func }, 0) },
},
else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
});
@@ -773,7 +638,7 @@ fn pushPopRegList(lower: *Lower, comptime mnemonic: Mnemonic, inst: Mir.Inst) Er
else => unreachable,
} });
while (it.next()) |i| {
- try lower.emit(.none, mnemonic, &.{.{
+ try lower.encode(.none, mnemonic, &.{.{
.reg = callee_preserved_regs[i],
}});
switch (mnemonic) {
@@ -787,7 +652,7 @@ fn pushPopRegList(lower: *Lower, comptime mnemonic: Mnemonic, inst: Mir.Inst) Er
.push => {
var it = inst.data.reg_list.iterator(.{});
while (it.next()) |i| {
- try lower.emit(.directive, .@".cfi_rel_offset", &.{
+ try lower.encode(.directive, .@".cfi_rel_offset", &.{
.{ .reg = callee_preserved_regs[i] },
.{ .imm = .s(off) },
});
@@ -805,12 +670,14 @@ const page_size: i32 = 1 << 12;
const abi = @import("abi.zig");
const assert = std.debug.assert;
const bits = @import("bits.zig");
+const codegen = @import("../../codegen.zig");
const encoder = @import("encoder.zig");
const link = @import("../../link.zig");
const std = @import("std");
const Immediate = Instruction.Immediate;
const Instruction = encoder.Instruction;
+const InternPool = @import("../../InternPool.zig");
const Lower = @This();
const Memory = Instruction.Memory;
const Mir = @import("Mir.zig");
@@ -819,3 +686,4 @@ const Zcu = @import("../../Zcu.zig");
const Operand = Instruction.Operand;
const Prefix = Instruction.Prefix;
const Register = bits.Register;
+const Type = @import("../../Type.zig");
diff --git a/src/arch/x86_64/Mir.zig b/src/arch/x86_64/Mir.zig
index 8d202e6bae..70f8090685 100644
--- a/src/arch/x86_64/Mir.zig
+++ b/src/arch/x86_64/Mir.zig
@@ -9,6 +9,8 @@
instructions: std.MultiArrayList(Inst).Slice,
/// The meaning of this data is determined by `Inst.Tag` value.
extra: []const u32,
+string_bytes: []const u8,
+locals: []const Local,
table: []const Inst.Index,
frame_locs: std.MultiArrayList(FrameLoc).Slice,
@@ -1361,9 +1363,6 @@ pub const Inst = struct {
/// Immediate (byte), register operands.
/// Uses `ri` payload.
ir,
- /// Relative displacement operand.
- /// Uses `reloc` payload.
- rel,
/// Register, memory operands.
/// Uses `rx` payload with extra data of type `Memory`.
rm,
@@ -1409,21 +1408,18 @@ pub const Inst = struct {
/// References another Mir instruction directly.
/// Uses `inst` payload.
inst,
- /// Linker relocation - external function.
- /// Uses `reloc` payload.
- extern_fn_reloc,
- /// Linker relocation - GOT indirection.
- /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
- got_reloc,
- /// Linker relocation - direct reference.
- /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
- direct_reloc,
- /// Linker relocation - imports table indirection (binding).
- /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
- import_reloc,
- /// Linker relocation - threadlocal variable via GOT indirection.
- /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
- tlv_reloc,
+ /// References a nav.
+ /// Uses `nav` payload.
+ nav,
+ /// References an uav.
+ /// Uses `uav` payload.
+ uav,
+ /// References a lazy symbol.
+ /// Uses `lazy_sym` payload.
+ lazy_sym,
+ /// References an external symbol.
+ /// Uses `extern_func` payload.
+ extern_func,
// Pseudo instructions:
@@ -1522,6 +1518,7 @@ pub const Inst = struct {
pseudo_cfi_escape_bytes,
/// End of prologue
+ /// Uses `none` payload.
pseudo_dbg_prologue_end_none,
/// Update debug line with is_stmt register set
/// Uses `line_column` payload.
@@ -1530,44 +1527,70 @@ pub const Inst = struct {
/// Uses `line_column` payload.
pseudo_dbg_line_line_column,
/// Start of epilogue
+ /// Uses `none` payload.
pseudo_dbg_epilogue_begin_none,
/// Start of lexical block
+ /// Uses `none` payload.
pseudo_dbg_enter_block_none,
/// End of lexical block
+ /// Uses `none` payload.
pseudo_dbg_leave_block_none,
/// Start of inline function
+ /// Uses `ip_index` payload.
pseudo_dbg_enter_inline_func,
/// End of inline function
+ /// Uses `ip_index` payload.
pseudo_dbg_leave_inline_func,
- /// Local argument or variable.
- /// Uses `a` payload.
- pseudo_dbg_local_a,
- /// Local argument or variable.
- /// Uses `ai` payload.
- pseudo_dbg_local_ai_s,
- /// Local argument or variable.
- /// Uses `ai` payload.
- pseudo_dbg_local_ai_u,
- /// Local argument or variable.
- /// Uses `ai` payload with extra data of type `Imm64`.
- pseudo_dbg_local_ai_64,
- /// Local argument or variable.
- /// Uses `as` payload.
- pseudo_dbg_local_as,
- /// Local argument or variable.
- /// Uses `ax` payload with extra data of type `bits.SymbolOffset`.
- pseudo_dbg_local_aso,
- /// Local argument or variable.
- /// Uses `rx` payload with extra data of type `AirOffset`.
- pseudo_dbg_local_aro,
- /// Local argument or variable.
- /// Uses `ax` payload with extra data of type `bits.FrameAddr`.
- pseudo_dbg_local_af,
- /// Local argument or variable.
- /// Uses `ax` payload with extra data of type `Memory`.
- pseudo_dbg_local_am,
+ /// Local argument.
+ /// Uses `none` payload.
+ pseudo_dbg_arg_none,
+ /// Local argument.
+ /// Uses `i` payload.
+ pseudo_dbg_arg_i_s,
+ /// Local argument.
+ /// Uses `i` payload.
+ pseudo_dbg_arg_i_u,
+ /// Local argument.
+ /// Uses `i64` payload.
+ pseudo_dbg_arg_i_64,
+ /// Local argument.
+ /// Uses `ro` payload.
+ pseudo_dbg_arg_ro,
+ /// Local argument.
+ /// Uses `fa` payload.
+ pseudo_dbg_arg_fa,
+ /// Local argument.
+ /// Uses `x` payload with extra data of type `Memory`.
+ pseudo_dbg_arg_m,
+ /// Local argument.
+ /// Uses `ip_index` payload.
+ pseudo_dbg_arg_val,
/// Remaining arguments are varargs.
pseudo_dbg_var_args_none,
+ /// Local variable.
+ /// Uses `none` payload.
+ pseudo_dbg_var_none,
+ /// Local variable.
+ /// Uses `i` payload.
+ pseudo_dbg_var_i_s,
+ /// Local variable.
+ /// Uses `i` payload.
+ pseudo_dbg_var_i_u,
+ /// Local variable.
+ /// Uses `i64` payload.
+ pseudo_dbg_var_i_64,
+ /// Local variable.
+ /// Uses `ro` payload.
+ pseudo_dbg_var_ro,
+ /// Local variable.
+ /// Uses `fa` payload.
+ pseudo_dbg_var_fa,
+ /// Local variable.
+ /// Uses `x` payload with extra data of type `Memory`.
+ pseudo_dbg_var_m,
+ /// Local variable.
+ /// Uses `ip_index` payload.
+ pseudo_dbg_var_val,
/// Tombstone
/// Emitter should skip this instruction.
@@ -1584,6 +1607,7 @@ pub const Inst = struct {
inst: Index,
},
/// A 32-bit immediate value.
+ i64: u64,
i: struct {
fixes: Fixes = ._,
i: u32,
@@ -1683,31 +1707,18 @@ pub const Inst = struct {
return std.mem.sliceAsBytes(mir.extra[bytes.payload..])[0..bytes.len];
}
},
- a: struct {
- air_inst: Air.Inst.Index,
- },
- ai: struct {
- air_inst: Air.Inst.Index,
- i: u32,
- },
- as: struct {
- air_inst: Air.Inst.Index,
- sym_index: u32,
- },
- ax: struct {
- air_inst: Air.Inst.Index,
- payload: u32,
- },
- /// Relocation for the linker where:
- /// * `sym_index` is the index of the target
- /// * `off` is the offset from the target
- reloc: bits.SymbolOffset,
+ fa: bits.FrameAddr,
+ ro: bits.RegisterOffset,
+ nav: bits.NavOffset,
+ uav: InternPool.Key.Ptr.BaseAddr.Uav,
+ lazy_sym: link.File.LazySymbol,
+ extern_func: Mir.NullTerminatedString,
/// Debug line and column position
line_column: struct {
line: u32,
column: u32,
},
- func: InternPool.Index,
+ ip_index: InternPool.Index,
/// Register list
reg_list: RegisterList,
};
@@ -1760,13 +1771,11 @@ pub const Inst = struct {
}
};
-pub const AirOffset = struct { air_inst: Air.Inst.Index, off: i32 };
-
/// Used in conjunction with payload to transfer a list of used registers in a compact manner.
pub const RegisterList = struct {
bitset: BitSet,
- const BitSet = IntegerBitSet(32);
+ const BitSet = std.bit_set.IntegerBitSet(32);
const Self = @This();
pub const empty: RegisterList = .{ .bitset = .initEmpty() };
@@ -1805,6 +1814,22 @@ pub const RegisterList = struct {
}
};
+pub const NullTerminatedString = enum(u32) {
+ none = std.math.maxInt(u32),
+ _,
+
+ pub fn toSlice(nts: NullTerminatedString, mir: *const Mir) ?[:0]const u8 {
+ if (nts == .none) return null;
+ const string_bytes = mir.string_bytes[@intFromEnum(nts)..];
+ return string_bytes[0..std.mem.indexOfScalar(u8, string_bytes, 0).? :0];
+ }
+};
+
+pub const Local = struct {
+ name: NullTerminatedString,
+ type: InternPool.Index,
+};
+
pub const Imm32 = struct {
imm: u32,
};
@@ -1840,11 +1865,10 @@ pub const Memory = struct {
size: bits.Memory.Size,
index: Register,
scale: bits.Memory.Scale,
- _: u14 = undefined,
+ _: u13 = undefined,
};
pub fn encode(mem: bits.Memory) Memory {
- assert(mem.base != .reloc or mem.mod != .off);
return .{
.info = .{
.base = mem.base,
@@ -1866,17 +1890,27 @@ pub const Memory = struct {
.none, .table => undefined,
.reg => |reg| @intFromEnum(reg),
.frame => |frame_index| @intFromEnum(frame_index),
- .reloc, .pcrel => |sym_index| sym_index,
.rip_inst => |inst_index| inst_index,
+ .nav => |nav| @intFromEnum(nav),
+ .uav => |uav| @intFromEnum(uav.val),
+ .lazy_sym => |lazy_sym| @intFromEnum(lazy_sym.ty),
+ .extern_func => |extern_func| @intFromEnum(extern_func),
},
.off = switch (mem.mod) {
.rm => |rm| @bitCast(rm.disp),
.off => |off| @truncate(off),
},
- .extra = if (mem.mod == .off)
- @intCast(mem.mod.off >> 32)
- else
- undefined,
+ .extra = switch (mem.mod) {
+ .rm => switch (mem.base) {
+ else => undefined,
+ .uav => |uav| @intFromEnum(uav.orig_ty),
+ .lazy_sym => |lazy_sym| @intFromEnum(lazy_sym.kind),
+ },
+ .off => switch (mem.base) {
+ .reg => @intCast(mem.mod.off >> 32),
+ else => unreachable,
+ },
+ },
};
}
@@ -1894,9 +1928,11 @@ pub const Memory = struct {
.reg => .{ .reg = @enumFromInt(mem.base) },
.frame => .{ .frame = @enumFromInt(mem.base) },
.table => .table,
- .reloc => .{ .reloc = mem.base },
- .pcrel => .{ .pcrel = mem.base },
.rip_inst => .{ .rip_inst = mem.base },
+ .nav => .{ .nav = @enumFromInt(mem.base) },
+ .uav => .{ .uav = .{ .val = @enumFromInt(mem.base), .orig_ty = @enumFromInt(mem.extra) } },
+ .lazy_sym => .{ .lazy_sym = .{ .kind = @enumFromInt(mem.extra), .ty = @enumFromInt(mem.base) } },
+ .extern_func => .{ .extern_func = @enumFromInt(mem.base) },
},
.scale_index = switch (mem.info.index) {
.none => null,
@@ -1924,11 +1960,132 @@ pub const Memory = struct {
pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
mir.instructions.deinit(gpa);
gpa.free(mir.extra);
+ gpa.free(mir.string_bytes);
+ gpa.free(mir.locals);
gpa.free(mir.table);
mir.frame_locs.deinit(gpa);
mir.* = undefined;
}
+pub fn emit(
+ mir: Mir,
+ lf: *link.File,
+ pt: Zcu.PerThread,
+ src_loc: Zcu.LazySrcLoc,
+ func_index: InternPool.Index,
+ code: *std.ArrayListUnmanaged(u8),
+ debug_output: link.File.DebugInfoOutput,
+) codegen.CodeGenError!void {
+ const zcu = pt.zcu;
+ const comp = zcu.comp;
+ const gpa = comp.gpa;
+ const func = zcu.funcInfo(func_index);
+ const fn_info = zcu.typeToFunc(.fromInterned(func.ty)).?;
+ const nav = func.owner_nav;
+ const mod = zcu.navFileScope(nav).mod.?;
+ var e: Emit = .{
+ .lower = .{
+ .target = &mod.resolved_target.result,
+ .allocator = gpa,
+ .mir = mir,
+ .cc = fn_info.cc,
+ .src_loc = src_loc,
+ },
+ .bin_file = lf,
+ .pt = pt,
+ .pic = mod.pic,
+ .atom_index = sym: {
+ if (lf.cast(.elf)) |ef| break :sym try ef.zigObjectPtr().?.getOrCreateMetadataForNav(zcu, nav);
+ if (lf.cast(.macho)) |mf| break :sym try mf.getZigObject().?.getOrCreateMetadataForNav(mf, nav);
+ if (lf.cast(.coff)) |cf| {
+ const atom = try cf.getOrCreateAtomForNav(nav);
+ break :sym cf.getAtom(atom).getSymbolIndex().?;
+ }
+ if (lf.cast(.plan9)) |p9f| break :sym try p9f.seeNav(pt, nav);
+ unreachable;
+ },
+ .debug_output = debug_output,
+ .code = code,
+
+ .prev_di_loc = .{
+ .line = func.lbrace_line,
+ .column = func.lbrace_column,
+ .is_stmt = switch (debug_output) {
+ .dwarf => |dwarf| dwarf.dwarf.debug_line.header.default_is_stmt,
+ .plan9 => undefined,
+ .none => undefined,
+ },
+ },
+ .prev_di_pc = 0,
+
+ .code_offset_mapping = .empty,
+ .relocs = .empty,
+ .table_relocs = .empty,
+ };
+ defer e.deinit();
+ e.emitMir() catch |err| switch (err) {
+ error.LowerFail, error.EmitFail => return zcu.codegenFailMsg(nav, e.lower.err_msg.?),
+ error.InvalidInstruction, error.CannotEncode => return zcu.codegenFail(nav, "emit MIR failed: {s} (Zig compiler bug)", .{@errorName(err)}),
+ else => return zcu.codegenFail(nav, "emit MIR failed: {s}", .{@errorName(err)}),
+ };
+}
+
+pub fn emitLazy(
+ mir: Mir,
+ lf: *link.File,
+ pt: Zcu.PerThread,
+ src_loc: Zcu.LazySrcLoc,
+ lazy_sym: link.File.LazySymbol,
+ code: *std.ArrayListUnmanaged(u8),
+ debug_output: link.File.DebugInfoOutput,
+) codegen.CodeGenError!void {
+ const zcu = pt.zcu;
+ const comp = zcu.comp;
+ const gpa = comp.gpa;
+ const mod = comp.root_mod;
+ var e: Emit = .{
+ .lower = .{
+ .target = &mod.resolved_target.result,
+ .allocator = gpa,
+ .mir = mir,
+ .cc = .auto,
+ .src_loc = src_loc,
+ },
+ .bin_file = lf,
+ .pt = pt,
+ .pic = mod.pic,
+ .atom_index = sym: {
+ if (lf.cast(.elf)) |ef| break :sym ef.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(ef, pt, lazy_sym) catch |err|
+ return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)});
+ if (lf.cast(.macho)) |mf| break :sym mf.getZigObject().?.getOrCreateMetadataForLazySymbol(mf, pt, lazy_sym) catch |err|
+ return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)});
+ if (lf.cast(.coff)) |cf| {
+ const atom = cf.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
+ return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)});
+ break :sym cf.getAtom(atom).getSymbolIndex().?;
+ }
+ if (lf.cast(.plan9)) |p9f| break :sym p9f.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
+ return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)});
+ unreachable;
+ },
+ .debug_output = debug_output,
+ .code = code,
+
+ .prev_di_loc = undefined,
+ .prev_di_pc = undefined,
+
+ .code_offset_mapping = .empty,
+ .relocs = .empty,
+ .table_relocs = .empty,
+ };
+ defer e.deinit();
+ e.emitMir() catch |err| switch (err) {
+ error.LowerFail, error.EmitFail => return zcu.codegenFailTypeMsg(lazy_sym.ty, e.lower.err_msg.?),
+ error.InvalidInstruction, error.CannotEncode => return zcu.codegenFailType(lazy_sym.ty, "emit MIR failed: {s} (Zig compiler bug)", .{@errorName(err)}),
+ else => return zcu.codegenFailType(lazy_sym.ty, "emit MIR failed: {s}", .{@errorName(err)}),
+ };
+}
+
pub fn extraData(mir: Mir, comptime T: type, index: u32) struct { data: T, end: u32 } {
const fields = std.meta.fields(T);
var i: u32 = index;
@@ -1937,7 +2094,7 @@ pub fn extraData(mir: Mir, comptime T: type, index: u32) struct { data: T, end:
@field(result, field.name) = switch (field.type) {
u32 => mir.extra[i],
i32, Memory.Info => @bitCast(mir.extra[i]),
- bits.FrameIndex, Air.Inst.Index => @enumFromInt(mir.extra[i]),
+ bits.FrameIndex => @enumFromInt(mir.extra[i]),
else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
};
i += 1;
@@ -1958,9 +2115,10 @@ pub fn resolveFrameAddr(mir: Mir, frame_addr: bits.FrameAddr) bits.RegisterOffse
return .{ .reg = frame_loc.base, .off = frame_loc.disp + frame_addr.off };
}
-pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {
+pub fn resolveMemoryExtra(mir: Mir, payload: u32) Memory {
+ const mem = mir.extraData(Mir.Memory, payload).data;
return switch (mem.info.base) {
- .none, .reg, .table, .reloc, .pcrel, .rip_inst => mem,
+ .none, .reg, .table, .rip_inst, .nav, .uav, .lazy_sym, .extern_func => mem,
.frame => if (mir.frame_locs.len > 0) .{
.info = .{
.base = .reg,
@@ -1982,8 +2140,10 @@ const builtin = @import("builtin");
const encoder = @import("encoder.zig");
const std = @import("std");
-const Air = @import("../../Air.zig");
-const IntegerBitSet = std.bit_set.IntegerBitSet;
const InternPool = @import("../../InternPool.zig");
const Mir = @This();
const Register = bits.Register;
+const Emit = @import("Emit.zig");
+const codegen = @import("../../codegen.zig");
+const link = @import("../../link.zig");
+const Zcu = @import("../../Zcu.zig");
diff --git a/src/arch/x86_64/bits.zig b/src/arch/x86_64/bits.zig
index 63b5d4b238..c854af91d2 100644
--- a/src/arch/x86_64/bits.zig
+++ b/src/arch/x86_64/bits.zig
@@ -4,6 +4,8 @@ const expect = std.testing.expect;
const Allocator = std.mem.Allocator;
const ArrayList = std.ArrayList;
+const InternPool = @import("../../InternPool.zig");
+const link = @import("../../link.zig");
const Mir = @import("Mir.zig");
/// EFLAGS condition codes
@@ -684,8 +686,6 @@ test "Register id - different classes" {
try expect(Register.xmm0.id() == Register.ymm0.id());
try expect(Register.xmm0.id() != Register.mm0.id());
try expect(Register.mm0.id() != Register.st0.id());
-
- try expect(Register.es.id() == 0b110000);
}
test "Register enc - different classes" {
@@ -750,20 +750,22 @@ pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
pub const RegisterOffset = struct { reg: Register, off: i32 = 0 };
-pub const SymbolOffset = struct { sym_index: u32, off: i32 = 0 };
+pub const NavOffset = struct { index: InternPool.Nav.Index, off: i32 = 0 };
pub const Memory = struct {
base: Base = .none,
mod: Mod = .{ .rm = .{} },
- pub const Base = union(enum(u3)) {
+ pub const Base = union(enum(u4)) {
none,
reg: Register,
frame: FrameIndex,
table,
- reloc: u32,
- pcrel: u32,
rip_inst: Mir.Inst.Index,
+ nav: InternPool.Nav.Index,
+ uav: InternPool.Key.Ptr.BaseAddr.Uav,
+ lazy_sym: link.File.LazySymbol,
+ extern_func: Mir.NullTerminatedString,
pub const Tag = @typeInfo(Base).@"union".tag_type.?;
};
@@ -899,7 +901,10 @@ pub const Memory = struct {
pub const Immediate = union(enum) {
signed: i32,
unsigned: u64,
- reloc: SymbolOffset,
+ nav: NavOffset,
+ uav: InternPool.Key.Ptr.BaseAddr.Uav,
+ lazy_sym: link.File.LazySymbol,
+ extern_func: Mir.NullTerminatedString,
pub fn u(x: u64) Immediate {
return .{ .unsigned = x };
@@ -909,10 +914,6 @@ pub const Immediate = union(enum) {
return .{ .signed = x };
}
- pub fn rel(sym_off: SymbolOffset) Immediate {
- return .{ .reloc = sym_off };
- }
-
pub fn format(
imm: Immediate,
comptime _: []const u8,
@@ -921,7 +922,10 @@ pub const Immediate = union(enum) {
) @TypeOf(writer).Error!void {
switch (imm) {
inline else => |int| try writer.print("{d}", .{int}),
- .reloc => |sym_off| try writer.print("Symbol({[sym_index]d}) + {[off]d}", sym_off),
+ .nav => |nav_off| try writer.print("Nav({d}) + {d}", .{ @intFromEnum(nav_off.nav), nav_off.off }),
+ .uav => |uav| try writer.print("Uav({d})", .{@intFromEnum(uav.val)}),
+ .lazy_sym => |lazy_sym| try writer.print("LazySym({s}, {d})", .{ @tagName(lazy_sym.kind), @intFromEnum(lazy_sym.ty) }),
+ .extern_func => |extern_func| try writer.print("ExternFunc({d})", .{@intFromEnum(extern_func)}),
}
}
};
diff --git a/src/arch/x86_64/encoder.zig b/src/arch/x86_64/encoder.zig
index cb1272fba0..8d07dce83a 100644
--- a/src/arch/x86_64/encoder.zig
+++ b/src/arch/x86_64/encoder.zig
@@ -138,7 +138,7 @@ pub const Instruction = struct {
.moffs => true,
.rip => false,
.sib => |s| switch (s.base) {
- .none, .frame, .table, .reloc, .pcrel, .rip_inst => false,
+ .none, .frame, .table, .rip_inst, .nav, .uav, .lazy_sym, .extern_func => false,
.reg => |reg| reg.isClass(.segment),
},
};
@@ -211,7 +211,7 @@ pub const Instruction = struct {
.none, .imm => 0b00,
.reg => |reg| @truncate(reg.enc() >> 3),
.mem => |mem| switch (mem.base()) {
- .none, .frame, .table, .reloc, .pcrel, .rip_inst => 0b00, // rsp, rbp, and rip are not extended
+ .none, .frame, .table, .rip_inst, .nav, .uav, .lazy_sym, .extern_func => 0b00, // rsp, rbp, and rip are not extended
.reg => |reg| @truncate(reg.enc() >> 3),
},
.bytes => unreachable,
@@ -281,9 +281,14 @@ pub const Instruction = struct {
.reg => |reg| try writer.print("{s}", .{@tagName(reg)}),
.frame => |frame_index| try writer.print("{}", .{frame_index}),
.table => try writer.print("Table", .{}),
- .reloc => |sym_index| try writer.print("Symbol({d})", .{sym_index}),
- .pcrel => |sym_index| try writer.print("PcRelSymbol({d})", .{sym_index}),
.rip_inst => |inst_index| try writer.print("RipInst({d})", .{inst_index}),
+ .nav => |nav| try writer.print("Nav({d})", .{@intFromEnum(nav)}),
+ .uav => |uav| try writer.print("Uav({d})", .{@intFromEnum(uav.val)}),
+ .lazy_sym => |lazy_sym| try writer.print("LazySym({s}, {d})", .{
+ @tagName(lazy_sym.kind),
+ @intFromEnum(lazy_sym.ty),
+ }),
+ .extern_func => |extern_func| try writer.print("ExternFunc({d})", .{@intFromEnum(extern_func)}),
}
if (mem.scaleIndex()) |si| {
if (any) try writer.writeAll(" + ");
@@ -718,11 +723,11 @@ pub const Instruction = struct {
try encoder.modRm_indirectDisp32(operand_enc, 0);
try encoder.disp32(undefined);
} else return error.CannotEncode,
- .reloc => if (@TypeOf(encoder).options.allow_symbols) {
+ .nav, .uav, .lazy_sym, .extern_func => if (@TypeOf(encoder).options.allow_symbols) {
try encoder.modRm_indirectDisp32(operand_enc, 0);
try encoder.disp32(undefined);
} else return error.CannotEncode,
- .pcrel, .rip_inst => {
+ .rip_inst => {
try encoder.modRm_RIPDisp32(operand_enc);
try encoder.disp32(sib.disp);
},
diff --git a/src/codegen.zig b/src/codegen.zig
index a2de3e2d01..9cc27b55ba 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -85,13 +85,99 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) ?*co
}
}
+/// Every code generation backend has a different MIR representation. However, we want to pass
+/// MIR from codegen to the linker *regardless* of which backend is in use. So, we use this: a
+/// union of all MIR types. The active tag is known from the backend in use; see `AnyMir.tag`.
+pub const AnyMir = union {
+ aarch64: @import("arch/aarch64/Mir.zig"),
+ arm: @import("arch/arm/Mir.zig"),
+ powerpc: noreturn, //@import("arch/powerpc/Mir.zig"),
+ riscv64: @import("arch/riscv64/Mir.zig"),
+ sparc64: @import("arch/sparc64/Mir.zig"),
+ x86_64: @import("arch/x86_64/Mir.zig"),
+ wasm: @import("arch/wasm/Mir.zig"),
+ c: @import("codegen/c.zig").Mir,
+
+ pub inline fn tag(comptime backend: std.builtin.CompilerBackend) []const u8 {
+ return switch (backend) {
+ .stage2_aarch64 => "aarch64",
+ .stage2_arm => "arm",
+ .stage2_powerpc => "powerpc",
+ .stage2_riscv64 => "riscv64",
+ .stage2_sparc64 => "sparc64",
+ .stage2_x86_64 => "x86_64",
+ .stage2_wasm => "wasm",
+ .stage2_c => "c",
+ else => unreachable,
+ };
+ }
+
+ pub fn deinit(mir: *AnyMir, zcu: *const Zcu) void {
+ const gpa = zcu.gpa;
+ const backend = target_util.zigBackend(zcu.root_mod.resolved_target.result, zcu.comp.config.use_llvm);
+ switch (backend) {
+ else => unreachable,
+ inline .stage2_aarch64,
+ .stage2_arm,
+ .stage2_powerpc,
+ .stage2_riscv64,
+ .stage2_sparc64,
+ .stage2_x86_64,
+ .stage2_wasm,
+ .stage2_c,
+ => |backend_ct| @field(mir, tag(backend_ct)).deinit(gpa),
+ }
+ }
+};
+
+/// Runs code generation for a function. This process converts the `Air` emitted by `Sema`,
+/// alongside annotated `Liveness` data, to machine code in the form of MIR (see `AnyMir`).
+///
+/// This is supposed to be a "pure" process, but some backends are currently buggy; see
+/// `Zcu.Feature.separate_thread` for details.
pub fn generateFunction(
lf: *link.File,
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ air: *const Air,
+ liveness: *const Air.Liveness,
+) CodeGenError!AnyMir {
+ const zcu = pt.zcu;
+ const func = zcu.funcInfo(func_index);
+ const target = zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;
+ switch (target_util.zigBackend(target, false)) {
+ else => unreachable,
+ inline .stage2_aarch64,
+ .stage2_arm,
+ .stage2_powerpc,
+ .stage2_riscv64,
+ .stage2_sparc64,
+ .stage2_x86_64,
+ .stage2_wasm,
+ .stage2_c,
+ => |backend| {
+ dev.check(devFeatureForBackend(backend));
+ const CodeGen = importBackend(backend);
+ const mir = try CodeGen.generate(lf, pt, src_loc, func_index, air, liveness);
+ return @unionInit(AnyMir, AnyMir.tag(backend), mir);
+ },
+ }
+}
+
+/// Converts the MIR returned by `generateFunction` to finalized machine code to be placed in
+/// the output binary. This is called from linker implementations, and may query linker state.
+///
+/// This function is not called for the C backend, as `link.C` directly understands its MIR.
+///
+/// The `air` parameter is not supposed to exist, but some backends are currently buggy; see
+/// `Zcu.Feature.separate_thread` for details.
+pub fn emitFunction(
+ lf: *link.File,
+ pt: Zcu.PerThread,
+ src_loc: Zcu.LazySrcLoc,
+ func_index: InternPool.Index,
+ any_mir: *const AnyMir,
code: *std.ArrayListUnmanaged(u8),
debug_output: link.File.DebugInfoOutput,
) CodeGenError!void {
@@ -108,7 +194,8 @@ pub fn generateFunction(
.stage2_x86_64,
=> |backend| {
dev.check(devFeatureForBackend(backend));
- return importBackend(backend).generate(lf, pt, src_loc, func_index, air, liveness, code, debug_output);
+ const mir = &@field(any_mir, AnyMir.tag(backend));
+ return mir.emit(lf, pt, src_loc, func_index, code, debug_output);
},
}
}
@@ -695,7 +782,6 @@ fn lowerUavRef(
const comp = lf.comp;
const target = &comp.root_mod.resolved_target.result;
const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
- const is_obj = comp.config.output_mode == .Obj;
const uav_val = uav.val;
const uav_ty = Type.fromInterned(ip.typeOf(uav_val));
const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn";
@@ -715,21 +801,7 @@ fn lowerUavRef(
dev.check(link.File.Tag.wasm.devFeature());
const wasm = lf.cast(.wasm).?;
assert(reloc_parent == .none);
- if (is_obj) {
- try wasm.out_relocs.append(gpa, .{
- .offset = @intCast(code.items.len),
- .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav.val) },
- .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64,
- .addend = @intCast(offset),
- });
- } else {
- try wasm.uav_fixups.ensureUnusedCapacity(gpa, 1);
- wasm.uav_fixups.appendAssumeCapacity(.{
- .uavs_exe_index = try wasm.refUavExe(uav.val, uav.orig_ty),
- .offset = @intCast(code.items.len),
- .addend = @intCast(offset),
- });
- }
+ try wasm.addUavReloc(code.items.len, uav.val, uav.orig_ty, @intCast(offset));
code.appendNTimesAssumeCapacity(0, ptr_width_bytes);
return;
},
@@ -879,73 +951,39 @@ pub const GenResult = union(enum) {
};
};
-fn genNavRef(
+pub fn genNavRef(
lf: *link.File,
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
- val: Value,
nav_index: InternPool.Nav.Index,
target: std.Target,
) CodeGenError!GenResult {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
- const ty = val.typeOf(zcu);
- log.debug("genNavRef: val = {}", .{val.fmtValue(pt)});
-
- if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) {
- const imm: u64 = switch (@divExact(target.ptrBitWidth(), 8)) {
- 1 => 0xaa,
- 2 => 0xaaaa,
- 4 => 0xaaaaaaaa,
- 8 => 0xaaaaaaaaaaaaaaaa,
- else => unreachable,
- };
- return .{ .mcv = .{ .immediate = imm } };
- }
-
- const comp = lf.comp;
- const gpa = comp.gpa;
-
- // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
- if (ty.castPtrToFn(zcu)) |fn_ty| {
- if (zcu.typeToFunc(fn_ty).?.is_generic) {
- return .{ .mcv = .{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? } };
- }
- } else if (ty.zigTypeTag(zcu) == .pointer) {
- const elem_ty = ty.elemType2(zcu);
- if (!elem_ty.hasRuntimeBits(zcu)) {
- return .{ .mcv = .{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? } };
- }
- }
-
const nav = ip.getNav(nav_index);
- assert(!nav.isThreadlocal(ip));
+ log.debug("genNavRef({})", .{nav.fqn.fmt(ip)});
- const lib_name, const linkage, const visibility = if (nav.getExtern(ip)) |e|
- .{ e.lib_name, e.linkage, e.visibility }
+ const lib_name, const linkage, const is_threadlocal = if (nav.getExtern(ip)) |e|
+ .{ e.lib_name, e.linkage, e.is_threadlocal and zcu.comp.config.any_non_single_threaded }
else
- .{ .none, .internal, .default };
-
- const name = nav.name;
+ .{ .none, .internal, false };
if (lf.cast(.elf)) |elf_file| {
const zo = elf_file.zigObjectPtr().?;
switch (linkage) {
.internal => {
const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index);
+ if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;
return .{ .mcv = .{ .lea_symbol = sym_index } };
},
.strong, .weak => {
- const sym_index = try elf_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
+ const sym_index = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
switch (linkage) {
.internal => unreachable,
.strong => {},
.weak => zo.symbol(sym_index).flags.weak = true,
.link_once => unreachable,
}
- switch (visibility) {
- .default => zo.symbol(sym_index).flags.is_extern_ptr = true,
- .hidden, .protected => {},
- }
+ if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;
return .{ .mcv = .{ .lea_symbol = sym_index } };
},
.link_once => unreachable,
@@ -955,21 +993,18 @@ fn genNavRef(
switch (linkage) {
.internal => {
const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index);
- const sym = zo.symbols.items[sym_index];
- return .{ .mcv = .{ .lea_symbol = sym.nlist_idx } };
+ if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;
+ return .{ .mcv = .{ .lea_symbol = sym_index } };
},
.strong, .weak => {
- const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
+ const sym_index = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
switch (linkage) {
.internal => unreachable,
.strong => {},
.weak => zo.symbols.items[sym_index].flags.weak = true,
.link_once => unreachable,
}
- switch (visibility) {
- .default => zo.symbols.items[sym_index].flags.is_extern_ptr = true,
- .hidden, .protected => {},
- }
+ if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;
return .{ .mcv = .{ .lea_symbol = sym_index } };
},
.link_once => unreachable,
@@ -980,12 +1015,12 @@ fn genNavRef(
.internal => {
const atom_index = try coff_file.getOrCreateAtomForNav(nav_index);
const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
- return .{ .mcv = .{ .load_got = sym_index } };
+ return .{ .mcv = .{ .lea_symbol = sym_index } };
},
.strong, .weak => {
- const global_index = try coff_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
- try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT
- return .{ .mcv = .{ .load_got = link.File.Coff.global_symbol_bit | global_index } };
+ const global_index = try coff_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
+ try coff_file.need_got_table.put(zcu.gpa, global_index, {}); // needs GOT
+ return .{ .mcv = .{ .lea_symbol = global_index } };
},
.link_once => unreachable,
}
@@ -994,11 +1029,12 @@ fn genNavRef(
const atom = p9.getAtom(atom_index);
return .{ .mcv = .{ .memory = atom.getOffsetTableAddress(p9) } };
} else {
- const msg = try ErrorMsg.create(gpa, src_loc, "TODO genNavRef for target {}", .{target});
+ const msg = try ErrorMsg.create(zcu.gpa, src_loc, "TODO genNavRef for target {}", .{target});
return .{ .fail = msg };
}
}
+/// deprecated legacy code path
pub fn genTypedValue(
lf: *link.File,
pt: Zcu.PerThread,
@@ -1006,45 +1042,96 @@ pub fn genTypedValue(
val: Value,
target: std.Target,
) CodeGenError!GenResult {
+ return switch (try lowerValue(pt, val, &target)) {
+ .none => .{ .mcv = .none },
+ .undef => .{ .mcv = .undef },
+ .immediate => |imm| .{ .mcv = .{ .immediate = imm } },
+ .lea_nav => |nav| genNavRef(lf, pt, src_loc, nav, target),
+ .lea_uav => |uav| switch (try lf.lowerUav(
+ pt,
+ uav.val,
+ Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),
+ src_loc,
+ )) {
+ .mcv => |mcv| .{ .mcv = switch (mcv) {
+ else => unreachable,
+ .load_direct => |sym_index| .{ .lea_direct = sym_index },
+ .load_symbol => |sym_index| .{ .lea_symbol = sym_index },
+ } },
+ .fail => |em| .{ .fail = em },
+ },
+ .load_uav => |uav| lf.lowerUav(
+ pt,
+ uav.val,
+ Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),
+ src_loc,
+ ),
+ };
+}
+
+const LowerResult = union(enum) {
+ none,
+ undef,
+ /// The bit-width of the immediate may be smaller than `u64`. For example, on 32-bit targets
+ /// such as ARM, the immediate will never exceed 32-bits.
+ immediate: u64,
+ lea_nav: InternPool.Nav.Index,
+ lea_uav: InternPool.Key.Ptr.BaseAddr.Uav,
+ load_uav: InternPool.Key.Ptr.BaseAddr.Uav,
+};
+
+pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allocator.Error!LowerResult {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const ty = val.typeOf(zcu);
- log.debug("genTypedValue: val = {}", .{val.fmtValue(pt)});
+ log.debug("lowerValue(@as({}, {}))", .{ ty.fmt(pt), val.fmtValue(pt) });
- if (val.isUndef(zcu)) return .{ .mcv = .undef };
+ if (val.isUndef(zcu)) return .undef;
switch (ty.zigTypeTag(zcu)) {
- .void => return .{ .mcv = .none },
+ .void => return .none,
.pointer => switch (ty.ptrSize(zcu)) {
.slice => {},
else => switch (val.toIntern()) {
.null_value => {
- return .{ .mcv = .{ .immediate = 0 } };
+ return .{ .immediate = 0 };
},
else => switch (ip.indexToKey(val.toIntern())) {
.int => {
- return .{ .mcv = .{ .immediate = val.toUnsignedInt(zcu) } };
+ return .{ .immediate = val.toUnsignedInt(zcu) };
},
.ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {
- .nav => |nav| return genNavRef(lf, pt, src_loc, val, nav, target),
- .uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).hasRuntimeBits(zcu))
- return switch (try lf.lowerUav(
- pt,
- uav.val,
- Type.fromInterned(uav.orig_ty).ptrAlignment(zcu),
- src_loc,
- )) {
- .mcv => |mcv| return .{ .mcv = switch (mcv) {
- .load_direct => |sym_index| .{ .lea_direct = sym_index },
- .load_symbol => |sym_index| .{ .lea_symbol = sym_index },
+ .nav => |nav| {
+ if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) {
+ const imm: u64 = switch (@divExact(target.ptrBitWidth(), 8)) {
+ 1 => 0xaa,
+ 2 => 0xaaaa,
+ 4 => 0xaaaaaaaa,
+ 8 => 0xaaaaaaaaaaaaaaaa,
else => unreachable,
- } },
- .fail => |em| return .{ .fail = em },
+ };
+ return .{ .immediate = imm };
}
+
+ if (ty.castPtrToFn(zcu)) |fn_ty| {
+ if (zcu.typeToFunc(fn_ty).?.is_generic) {
+ return .{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? };
+ }
+ } else if (ty.zigTypeTag(zcu) == .pointer) {
+ const elem_ty = ty.elemType2(zcu);
+ if (!elem_ty.hasRuntimeBits(zcu)) {
+ return .{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? };
+ }
+ }
+
+ return .{ .lea_nav = nav };
+ },
+ .uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).hasRuntimeBits(zcu))
+ return .{ .lea_uav = uav }
else
- return .{ .mcv = .{ .immediate = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu)
- .forward(@intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() | 1)) / 3)) } },
+ return .{ .immediate = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu)
+ .forward(@intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() | 1)) / 3)) },
else => {},
},
else => {},
@@ -1058,39 +1145,35 @@ pub fn genTypedValue(
.signed => @bitCast(val.toSignedInt(zcu)),
.unsigned => val.toUnsignedInt(zcu),
};
- return .{ .mcv = .{ .immediate = unsigned } };
+ return .{ .immediate = unsigned };
}
},
.bool => {
- return .{ .mcv = .{ .immediate = @intFromBool(val.toBool()) } };
+ return .{ .immediate = @intFromBool(val.toBool()) };
},
.optional => {
if (ty.isPtrLikeOptional(zcu)) {
- return genTypedValue(
- lf,
+ return lowerValue(
pt,
- src_loc,
- val.optionalValue(zcu) orelse return .{ .mcv = .{ .immediate = 0 } },
+ val.optionalValue(zcu) orelse return .{ .immediate = 0 },
target,
);
} else if (ty.abiSize(zcu) == 1) {
- return .{ .mcv = .{ .immediate = @intFromBool(!val.isNull(zcu)) } };
+ return .{ .immediate = @intFromBool(!val.isNull(zcu)) };
}
},
.@"enum" => {
const enum_tag = ip.indexToKey(val.toIntern()).enum_tag;
- return genTypedValue(
- lf,
+ return lowerValue(
pt,
- src_loc,
Value.fromInterned(enum_tag.int),
target,
);
},
.error_set => {
const err_name = ip.indexToKey(val.toIntern()).err.name;
- const error_index = try pt.getErrorValue(err_name);
- return .{ .mcv = .{ .immediate = error_index } };
+ const error_index = ip.getErrorValueIfExists(err_name).?;
+ return .{ .immediate = error_index };
},
.error_union => {
const err_type = ty.errorUnionSet(zcu);
@@ -1099,20 +1182,16 @@ pub fn genTypedValue(
// We use the error type directly as the type.
const err_int_ty = try pt.errorIntType();
switch (ip.indexToKey(val.toIntern()).error_union.val) {
- .err_name => |err_name| return genTypedValue(
- lf,
+ .err_name => |err_name| return lowerValue(
pt,
- src_loc,
Value.fromInterned(try pt.intern(.{ .err = .{
.ty = err_type.toIntern(),
.name = err_name,
} })),
target,
),
- .payload => return genTypedValue(
- lf,
+ .payload => return lowerValue(
pt,
- src_loc,
try pt.intValue(err_int_ty, 0),
target,
),
@@ -1132,7 +1211,10 @@ pub fn genTypedValue(
else => {},
}
- return lf.lowerUav(pt, val.toIntern(), .none, src_loc);
+ return .{ .load_uav = .{
+ .val = val.toIntern(),
+ .orig_ty = (try pt.singleConstPtrType(ty)).toIntern(),
+ } };
}
pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 {
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 3b8ab52982..f4952d4a58 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -3,6 +3,7 @@ const builtin = @import("builtin");
const assert = std.debug.assert;
const mem = std.mem;
const log = std.log.scoped(.c);
+const Allocator = mem.Allocator;
const dev = @import("../dev.zig");
const link = @import("../link.zig");
@@ -30,6 +31,35 @@ pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features {
}) else null; // we don't currently ask zig1 to use safe optimization modes
}
+/// For most backends, MIR is basically a sequence of machine code instructions, perhaps with some
+/// "pseudo instructions" thrown in. For the C backend, it is instead the generated C code for a
+/// single function. We also need to track some information to get merged into the global `link.C`
+/// state, including:
+/// * The UAVs used, so declarations can be emitted in `flush`
+/// * The types used, so declarations can be emitted in `flush`
+/// * The lazy functions used, so definitions can be emitted in `flush`
+pub const Mir = struct {
+ /// This map contains all the UAVs we saw generating this function.
+ /// `link.C` will merge them into its `uavs`/`aligned_uavs` fields.
+ /// Key is the value of the UAV; value is the UAV's alignment, or
+ /// `.none` for natural alignment. The specified alignment is never
+ /// less than the natural alignment.
+ uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
+ // These remaining fields are essentially just an owned version of `link.C.AvBlock`.
+ code: []u8,
+ fwd_decl: []u8,
+ ctype_pool: CType.Pool,
+ lazy_fns: LazyFnMap,
+
+ pub fn deinit(mir: *Mir, gpa: Allocator) void {
+ mir.uavs.deinit(gpa);
+ gpa.free(mir.code);
+ gpa.free(mir.fwd_decl);
+ mir.ctype_pool.deinit(gpa);
+ mir.lazy_fns.deinit(gpa);
+ }
+};
+
pub const CType = @import("c/Type.zig");
pub const CValue = union(enum) {
@@ -671,7 +701,7 @@ pub const Object = struct {
/// This data is available both when outputting .c code and when outputting an .h file.
pub const DeclGen = struct {
- gpa: mem.Allocator,
+ gpa: Allocator,
pt: Zcu.PerThread,
mod: *Module,
pass: Pass,
@@ -682,10 +712,12 @@ pub const DeclGen = struct {
error_msg: ?*Zcu.ErrorMsg,
ctype_pool: CType.Pool,
scratch: std.ArrayListUnmanaged(u32),
- /// Keeps track of anonymous decls that need to be rendered before this
- /// (named) Decl in the output C code.
- uav_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.AvBlock),
- aligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
+ /// This map contains all the UAVs we saw generating this function.
+ /// `link.C` will merge them into its `uavs`/`aligned_uavs` fields.
+ /// Key is the value of the UAV; value is the UAV's alignment, or
+ /// `.none` for natural alignment. The specified alignment is never
+ /// less than the natural alignment.
+ uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
pub const Pass = union(enum) {
nav: InternPool.Nav.Index,
@@ -753,21 +785,17 @@ pub const DeclGen = struct {
// Indicate that the anon decl should be rendered to the output so that
// our reference above is not undefined.
const ptr_type = ip.indexToKey(uav.orig_ty).ptr_type;
- const gop = try dg.uav_deps.getOrPut(dg.gpa, uav.val);
- if (!gop.found_existing) gop.value_ptr.* = .{};
-
- // Only insert an alignment entry if the alignment is greater than ABI
- // alignment. If there is already an entry, keep the greater alignment.
- const explicit_alignment = ptr_type.flags.alignment;
- if (explicit_alignment != .none) {
- const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(zcu);
- if (explicit_alignment.order(abi_alignment).compare(.gt)) {
- const aligned_gop = try dg.aligned_uavs.getOrPut(dg.gpa, uav.val);
- aligned_gop.value_ptr.* = if (aligned_gop.found_existing)
- aligned_gop.value_ptr.maxStrict(explicit_alignment)
- else
- explicit_alignment;
- }
+ const gop = try dg.uavs.getOrPut(dg.gpa, uav.val);
+ if (!gop.found_existing) gop.value_ptr.* = .none;
+ // If there is an explicit alignment, greater than the current one, use it.
+ // Note that we intentionally start at `.none`, so `gop.value_ptr.*` is never
+ // underaligned, so we don't need to worry about the `.none` case here.
+ if (ptr_type.flags.alignment != .none) {
+ // Resolve the current alignment so we can choose the bigger one.
+ const cur_alignment: Alignment = if (gop.value_ptr.* == .none) abi: {
+ break :abi Type.fromInterned(ptr_type.child).abiAlignment(zcu);
+ } else gop.value_ptr.*;
+ gop.value_ptr.* = cur_alignment.maxStrict(ptr_type.flags.alignment);
}
}
@@ -2895,7 +2923,79 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
}
}
-pub fn genFunc(f: *Function) !void {
+pub fn generate(
+ lf: *link.File,
+ pt: Zcu.PerThread,
+ src_loc: Zcu.LazySrcLoc,
+ func_index: InternPool.Index,
+ air: *const Air,
+ liveness: *const Air.Liveness,
+) @import("../codegen.zig").CodeGenError!Mir {
+ const zcu = pt.zcu;
+ const gpa = zcu.gpa;
+
+ _ = src_loc;
+ assert(lf.tag == .c);
+
+ const func = zcu.funcInfo(func_index);
+
+ var function: Function = .{
+ .value_map = .init(gpa),
+ .air = air.*,
+ .liveness = liveness.*,
+ .func_index = func_index,
+ .object = .{
+ .dg = .{
+ .gpa = gpa,
+ .pt = pt,
+ .mod = zcu.navFileScope(func.owner_nav).mod.?,
+ .error_msg = null,
+ .pass = .{ .nav = func.owner_nav },
+ .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,
+ .expected_block = null,
+ .fwd_decl = .init(gpa),
+ .ctype_pool = .empty,
+ .scratch = .empty,
+ .uavs = .empty,
+ },
+ .code = .init(gpa),
+ .indent_writer = undefined, // set later so we can get a pointer to object.code
+ },
+ .lazy_fns = .empty,
+ };
+ defer {
+ function.object.code.deinit();
+ function.object.dg.fwd_decl.deinit();
+ function.object.dg.ctype_pool.deinit(gpa);
+ function.object.dg.scratch.deinit(gpa);
+ function.object.dg.uavs.deinit(gpa);
+ function.deinit();
+ }
+ try function.object.dg.ctype_pool.init(gpa);
+ function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
+
+ genFunc(&function) catch |err| switch (err) {
+ error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.object.dg.error_msg.?),
+ error.OutOfMemory => |e| return e,
+ };
+
+ var mir: Mir = .{
+ .uavs = .empty,
+ .code = &.{},
+ .fwd_decl = &.{},
+ .ctype_pool = .empty,
+ .lazy_fns = .empty,
+ };
+ errdefer mir.deinit(gpa);
+ mir.uavs = function.object.dg.uavs.move();
+ mir.code = try function.object.code.toOwnedSlice();
+ mir.fwd_decl = try function.object.dg.fwd_decl.toOwnedSlice();
+ mir.ctype_pool = function.object.dg.ctype_pool.move();
+ mir.lazy_fns = function.lazy_fns.move();
+ return mir;
+}
+
+fn genFunc(f: *Function) !void {
const tracy = trace(@src());
defer tracy.end();
@@ -8482,7 +8582,7 @@ fn iterateBigTomb(f: *Function, inst: Air.Inst.Index) BigTomb {
/// A naive clone of this map would create copies of the ArrayList which is
/// stored in the values. This function additionally clones the values.
-fn cloneFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) !LocalsMap {
+fn cloneFreeLocalsMap(gpa: Allocator, map: *LocalsMap) !LocalsMap {
var cloned = try map.clone(gpa);
const values = cloned.values();
var i: usize = 0;
@@ -8499,7 +8599,7 @@ fn cloneFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) !LocalsMap {
return cloned;
}
-fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void {
+fn deinitFreeLocalsMap(gpa: Allocator, map: *LocalsMap) void {
for (map.values()) |*value| {
value.deinit(gpa);
}
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 3fc6250d3f..658764ba3c 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -1121,8 +1121,8 @@ pub const Object = struct {
o: *Object,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ air: *const Air,
+ liveness: *const Air.Liveness,
) !void {
assert(std.meta.eql(pt, o.pt));
const zcu = pt.zcu;
@@ -1479,8 +1479,8 @@ pub const Object = struct {
var fg: FuncGen = .{
.gpa = gpa,
- .air = air,
- .liveness = liveness,
+ .air = air.*,
+ .liveness = liveness.*,
.ng = &ng,
.wip = wip,
.is_naked = fn_info.cc == .naked,
@@ -1506,10 +1506,9 @@ pub const Object = struct {
deinit_wip = false;
fg.genBody(air.getMainBody(), .poi) catch |err| switch (err) {
- error.CodegenFail => {
- try zcu.failed_codegen.put(gpa, func.owner_nav, ng.err_msg.?);
- ng.err_msg = null;
- return;
+ error.CodegenFail => switch (zcu.codegenFailMsg(func.owner_nav, ng.err_msg.?)) {
+ error.CodegenFail => return,
+ error.OutOfMemory => |e| return e,
},
else => |e| return e,
};
@@ -1561,10 +1560,9 @@ pub const Object = struct {
.err_msg = null,
};
ng.genDecl() catch |err| switch (err) {
- error.CodegenFail => {
- try pt.zcu.failed_codegen.put(pt.zcu.gpa, nav_index, ng.err_msg.?);
- ng.err_msg = null;
- return;
+ error.CodegenFail => switch (pt.zcu.codegenFailMsg(nav_index, ng.err_msg.?)) {
+ error.CodegenFail => return,
+ error.OutOfMemory => |e| return e,
},
else => |e| return e,
};
@@ -1586,6 +1584,27 @@ pub const Object = struct {
const global_index = self.nav_map.get(nav_index).?;
const comp = zcu.comp;
+ // If we're on COFF and linking with LLD, the linker cares about our exports to determine the subsystem in use.
+ coff_export_flags: {
+ const lf = comp.bin_file orelse break :coff_export_flags;
+ const lld = lf.cast(.lld) orelse break :coff_export_flags;
+ const coff = switch (lld.ofmt) {
+ .elf, .wasm => break :coff_export_flags,
+ .coff => |*coff| coff,
+ };
+ if (!ip.isFunctionType(ip.getNav(nav_index).typeOf(ip))) break :coff_export_flags;
+ const flags = &coff.lld_export_flags;
+ for (export_indices) |export_index| {
+ const name = export_index.ptr(zcu).opts.name;
+ if (name.eqlSlice("main", ip)) flags.c_main = true;
+ if (name.eqlSlice("WinMain", ip)) flags.winmain = true;
+ if (name.eqlSlice("wWinMain", ip)) flags.wwinmain = true;
+ if (name.eqlSlice("WinMainCRTStartup", ip)) flags.winmain_crt_startup = true;
+ if (name.eqlSlice("wWinMainCRTStartup", ip)) flags.wwinmain_crt_startup = true;
+ if (name.eqlSlice("DllMainCRTStartup", ip)) flags.dllmain_crt_startup = true;
+ }
+ }
+
if (export_indices.len != 0) {
return updateExportedGlobal(self, zcu, global_index, export_indices);
} else {
@@ -9490,15 +9509,21 @@ pub const FuncGen = struct {
const inst_ty = self.typeOfIndex(inst);
- const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
- if (name == .none) return arg_val;
-
const func = zcu.funcInfo(zcu.navValue(self.ng.nav_index).toIntern());
+ const func_zir = func.zir_body_inst.resolveFull(&zcu.intern_pool).?;
+ const file = zcu.fileByIndex(func_zir.file);
+
+ const mod = file.mod.?;
+ if (mod.strip) return arg_val;
+ const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
+ const zir = &file.zir.?;
+ const name = zir.nullTerminatedString(zir.getParamName(zir.getParamBody(func_zir.inst)[arg.zir_param_index]).?);
+
const lbrace_line = zcu.navSrcLine(func.owner_nav) + func.lbrace_line + 1;
const lbrace_col = func.lbrace_column + 1;
const debug_parameter = try o.builder.debugParameter(
- try o.builder.metadataString(name.toSlice(self.air)),
+ try o.builder.metadataString(name),
self.file,
self.scope,
lbrace_line,
@@ -9516,7 +9541,6 @@ pub const FuncGen = struct {
},
};
- const mod = self.ng.ownerModule();
if (isByRef(inst_ty, zcu)) {
_ = try self.wip.callIntrinsic(
.normal,
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig
index f83c6979ff..b9eb56dd23 100644
--- a/src/codegen/spirv.zig
+++ b/src/codegen/spirv.zig
@@ -230,8 +230,9 @@ pub const Object = struct {
defer nav_gen.deinit();
nav_gen.genNav(do_codegen) catch |err| switch (err) {
- error.CodegenFail => {
- try zcu.failed_codegen.put(gpa, nav_index, nav_gen.error_msg.?);
+ error.CodegenFail => switch (zcu.codegenFailMsg(nav_index, nav_gen.error_msg.?)) {
+ error.CodegenFail => {},
+ error.OutOfMemory => |e| return e,
},
else => |other| {
// There might be an error that happened *after* self.error_msg
@@ -249,12 +250,12 @@ pub const Object = struct {
self: *Object,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ air: *const Air,
+ liveness: *const Air.Liveness,
) !void {
const nav = pt.zcu.funcInfo(func_index).owner_nav;
// TODO: Separate types for generating decls and functions?
- try self.genNav(pt, nav, air, liveness, true);
+ try self.genNav(pt, nav, air.*, liveness.*, true);
}
pub fn updateNav(
diff --git a/src/codegen/spirv/Section.zig b/src/codegen/spirv/Section.zig
index 4fe12f999f..5c2a5fde62 100644
--- a/src/codegen/spirv/Section.zig
+++ b/src/codegen/spirv/Section.zig
@@ -386,8 +386,6 @@ test "SPIR-V Section emit() - string" {
}
test "SPIR-V Section emit() - extended mask" {
- if (@import("builtin").zig_backend == .stage1) return error.SkipZigTest;
-
var section = Section{};
defer section.deinit(std.testing.allocator);
diff --git a/src/dev.zig b/src/dev.zig
index 1dc8264ebc..2438ae6df7 100644
--- a/src/dev.zig
+++ b/src/dev.zig
@@ -25,6 +25,9 @@ pub const Env = enum {
/// - `zig build-* -fno-emit-bin`
sema,
+ /// - `zig build-* -ofmt=c`
+ cbe,
+
/// - sema
/// - `zig build-* -fincremental -fno-llvm -fno-lld -target x86_64-linux --listen=-`
@"x86_64-linux",
@@ -144,6 +147,12 @@ pub const Env = enum {
=> true,
else => Env.ast_gen.supports(feature),
},
+ .cbe => switch (feature) {
+ .c_backend,
+ .c_linker,
+ => true,
+ else => Env.sema.supports(feature),
+ },
.@"x86_64-linux" => switch (feature) {
.build_command,
.stdio_listen,
diff --git a/src/libs/freebsd.zig b/src/libs/freebsd.zig
index 47fef32773..f6195ffa91 100644
--- a/src/libs/freebsd.zig
+++ b/src/libs/freebsd.zig
@@ -985,7 +985,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
assert(comp.freebsd_so_files == null);
comp.freebsd_so_files = so_files;
- var task_buffer: [libs.len]link.Task = undefined;
+ var task_buffer: [libs.len]link.PrelinkTask = undefined;
var task_buffer_i: usize = 0;
{
@@ -1004,7 +1004,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
}
}
- comp.queueLinkTasks(task_buffer[0..task_buffer_i]);
+ comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]);
}
fn buildSharedLib(
@@ -1019,10 +1019,6 @@ fn buildSharedLib(
defer tracy.end();
const basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover });
- const emit_bin = Compilation.EmitLoc{
- .directory = bin_directory,
- .basename = basename,
- };
const version: Version = .{ .major = lib.sover, .minor = 0, .patch = 0 };
const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?);
const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename;
@@ -1077,13 +1073,14 @@ fn buildSharedLib(
.dirs = comp.dirs.withoutLocalCache(),
.thread_pool = comp.thread_pool,
.self_exe_path = comp.self_exe_path,
- .cache_mode = .incremental,
+ // Because we manually cache the whole set of objects, we don't cache the individual objects
+ // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path.
+ .cache_mode = .none,
.config = config,
.root_mod = root_mod,
.root_name = lib.name,
.libc_installation = comp.libc_installation,
- .emit_bin = emit_bin,
- .emit_h = null,
+ .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) },
.verbose_cc = comp.verbose_cc,
.verbose_link = comp.verbose_link,
.verbose_air = comp.verbose_air,
diff --git a/src/libs/glibc.zig b/src/libs/glibc.zig
index cc781c5472..8031827a9d 100644
--- a/src/libs/glibc.zig
+++ b/src/libs/glibc.zig
@@ -1148,7 +1148,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
assert(comp.glibc_so_files == null);
comp.glibc_so_files = so_files;
- var task_buffer: [libs.len]link.Task = undefined;
+ var task_buffer: [libs.len]link.PrelinkTask = undefined;
var task_buffer_i: usize = 0;
{
@@ -1170,7 +1170,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
}
}
- comp.queueLinkTasks(task_buffer[0..task_buffer_i]);
+ comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]);
}
fn buildSharedLib(
@@ -1185,10 +1185,6 @@ fn buildSharedLib(
defer tracy.end();
const basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover });
- const emit_bin = Compilation.EmitLoc{
- .directory = bin_directory,
- .basename = basename,
- };
const version: Version = .{ .major = lib.sover, .minor = 0, .patch = 0 };
const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?);
const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename;
@@ -1243,13 +1239,14 @@ fn buildSharedLib(
.dirs = comp.dirs.withoutLocalCache(),
.thread_pool = comp.thread_pool,
.self_exe_path = comp.self_exe_path,
- .cache_mode = .incremental,
+ // Because we manually cache the whole set of objects, we don't cache the individual objects
+ // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path.
+ .cache_mode = .none,
.config = config,
.root_mod = root_mod,
.root_name = lib.name,
.libc_installation = comp.libc_installation,
- .emit_bin = emit_bin,
- .emit_h = null,
+ .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) },
.verbose_cc = comp.verbose_cc,
.verbose_link = comp.verbose_link,
.verbose_air = comp.verbose_air,
diff --git a/src/libs/libcxx.zig b/src/libs/libcxx.zig
index 17a7d3d29e..0009bfe120 100644
--- a/src/libs/libcxx.zig
+++ b/src/libs/libcxx.zig
@@ -122,17 +122,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
const output_mode = .Lib;
const link_mode = .static;
const target = comp.root_mod.resolved_target.result;
- const basename = try std.zig.binNameAlloc(arena, .{
- .root_name = root_name,
- .target = target,
- .output_mode = output_mode,
- .link_mode = link_mode,
- });
-
- const emit_bin = Compilation.EmitLoc{
- .directory = null, // Put it in the cache directory.
- .basename = basename,
- };
const cxxabi_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxxabi", "include" });
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!
.root_name = root_name,
.thread_pool = comp.thread_pool,
.libc_installation = comp.libc_installation,
- .emit_bin = emit_bin,
- .emit_h = null,
+ .emit_bin = .yes_cache,
.c_source_files = c_source_files.items,
.verbose_cc = comp.verbose_cc,
.verbose_link = comp.verbose_link,
@@ -308,7 +296,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
assert(comp.libcxx_static_lib == null);
const crt_file = try sub_compilation.toCrtFile();
comp.libcxx_static_lib = crt_file;
- comp.queueLinkTaskMode(crt_file.full_object_path, &config);
+ comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
}
pub 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
const output_mode = .Lib;
const link_mode = .static;
const target = comp.root_mod.resolved_target.result;
- const basename = try std.zig.binNameAlloc(arena, .{
- .root_name = root_name,
- .target = target,
- .output_mode = output_mode,
- .link_mode = link_mode,
- });
-
- const emit_bin = Compilation.EmitLoc{
- .directory = null, // Put it in the cache directory.
- .basename = basename,
- };
const cxxabi_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxxabi", "include" });
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
.root_name = root_name,
.thread_pool = comp.thread_pool,
.libc_installation = comp.libc_installation,
- .emit_bin = emit_bin,
- .emit_h = null,
+ .emit_bin = .yes_cache,
.c_source_files = c_source_files.items,
.verbose_cc = comp.verbose_cc,
.verbose_link = comp.verbose_link,
@@ -504,7 +480,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
assert(comp.libcxxabi_static_lib == null);
const crt_file = try sub_compilation.toCrtFile();
comp.libcxxabi_static_lib = crt_file;
- comp.queueLinkTaskMode(crt_file.full_object_path, &config);
+ comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
}
pub fn addCxxArgs(
diff --git a/src/libs/libtsan.zig b/src/libs/libtsan.zig
index 8a5ffd2eab..f2cd6831f7 100644
--- a/src/libs/libtsan.zig
+++ b/src/libs/libtsan.zig
@@ -45,11 +45,6 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
.link_mode = link_mode,
});
- const emit_bin = Compilation.EmitLoc{
- .directory = null, // Put it in the cache directory.
- .basename = basename,
- };
-
const optimize_mode = comp.compilerRtOptMode();
const strip = comp.compilerRtStrip();
const unwind_tables: std.builtin.UnwindTables =
@@ -287,8 +282,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
.root_mod = root_mod,
.root_name = root_name,
.libc_installation = comp.libc_installation,
- .emit_bin = emit_bin,
- .emit_h = null,
+ .emit_bin = .yes_cache,
.c_source_files = c_source_files.items,
.verbose_cc = comp.verbose_cc,
.verbose_link = comp.verbose_link,
@@ -325,7 +319,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
};
const crt_file = try sub_compilation.toCrtFile();
- comp.queueLinkTaskMode(crt_file.full_object_path, &config);
+ comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
assert(comp.tsan_lib == null);
comp.tsan_lib = crt_file;
}
diff --git a/src/libs/libunwind.zig b/src/libs/libunwind.zig
index 945689ebab..711d63ebbc 100644
--- a/src/libs/libunwind.zig
+++ b/src/libs/libunwind.zig
@@ -31,7 +31,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
const unwind_tables: std.builtin.UnwindTables =
if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .@"async";
const config = Compilation.Config.resolve(.{
- .output_mode = .Lib,
+ .output_mode = output_mode,
.resolved_target = comp.root_mod.resolved_target,
.is_test = false,
.have_zcu = false,
@@ -85,17 +85,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
};
const root_name = "unwind";
- const link_mode = .static;
- const basename = try std.zig.binNameAlloc(arena, .{
- .root_name = root_name,
- .target = target,
- .output_mode = output_mode,
- .link_mode = link_mode,
- });
- const emit_bin = Compilation.EmitLoc{
- .directory = null, // Put it in the cache directory.
- .basename = basename,
- };
var c_source_files: [unwind_src_list.len]Compilation.CSourceFile = undefined;
for (unwind_src_list, 0..) |unwind_src, i| {
var cflags = std.ArrayList([]const u8).init(arena);
@@ -160,7 +149,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
.main_mod = null,
.thread_pool = comp.thread_pool,
.libc_installation = comp.libc_installation,
- .emit_bin = emit_bin,
+ .emit_bin = .yes_cache,
.function_sections = comp.function_sections,
.c_source_files = &c_source_files,
.verbose_cc = comp.verbose_cc,
@@ -195,7 +184,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
};
const crt_file = try sub_compilation.toCrtFile();
- comp.queueLinkTaskMode(crt_file.full_object_path, &config);
+ comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
assert(comp.libunwind_static_lib == null);
comp.libunwind_static_lib = crt_file;
}
diff --git a/src/libs/musl.zig b/src/libs/musl.zig
index d208b09827..7c4e71c974 100644
--- a/src/libs/musl.zig
+++ b/src/libs/musl.zig
@@ -252,8 +252,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
.thread_pool = comp.thread_pool,
.root_name = "c",
.libc_installation = comp.libc_installation,
- .emit_bin = .{ .directory = null, .basename = "libc.so" },
- .emit_h = null,
+ .emit_bin = .yes_cache,
.verbose_cc = comp.verbose_cc,
.verbose_link = comp.verbose_link,
.verbose_air = comp.verbose_air,
@@ -278,7 +277,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
errdefer comp.gpa.free(basename);
const crt_file = try sub_compilation.toCrtFile();
- comp.queueLinkTaskMode(crt_file.full_object_path, &config);
+ comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
{
comp.mutex.lock();
defer comp.mutex.unlock();
diff --git a/src/libs/netbsd.zig b/src/libs/netbsd.zig
index 718861bf5c..fdab27f217 100644
--- a/src/libs/netbsd.zig
+++ b/src/libs/netbsd.zig
@@ -650,7 +650,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
assert(comp.netbsd_so_files == null);
comp.netbsd_so_files = so_files;
- var task_buffer: [libs.len]link.Task = undefined;
+ var task_buffer: [libs.len]link.PrelinkTask = undefined;
var task_buffer_i: usize = 0;
{
@@ -669,7 +669,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
}
}
- comp.queueLinkTasks(task_buffer[0..task_buffer_i]);
+ comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]);
}
fn buildSharedLib(
@@ -684,10 +684,6 @@ fn buildSharedLib(
defer tracy.end();
const basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover });
- const emit_bin = Compilation.EmitLoc{
- .directory = bin_directory,
- .basename = basename,
- };
const version: Version = .{ .major = lib.sover, .minor = 0, .patch = 0 };
const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?);
const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename;
@@ -741,13 +737,14 @@ fn buildSharedLib(
.dirs = comp.dirs.withoutLocalCache(),
.thread_pool = comp.thread_pool,
.self_exe_path = comp.self_exe_path,
- .cache_mode = .incremental,
+ // Because we manually cache the whole set of objects, we don't cache the individual objects
+ // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path.
+ .cache_mode = .none,
.config = config,
.root_mod = root_mod,
.root_name = lib.name,
.libc_installation = comp.libc_installation,
- .emit_bin = emit_bin,
- .emit_h = null,
+ .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) },
.verbose_cc = comp.verbose_cc,
.verbose_link = comp.verbose_link,
.verbose_air = comp.verbose_air,
diff --git a/src/link.zig b/src/link.zig
index 688210c355..9bed6b4131 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -8,7 +8,6 @@ const log = std.log.scoped(.link);
const trace = @import("tracy.zig").trace;
const wasi_libc = @import("libs/wasi_libc.zig");
-const Air = @import("Air.zig");
const Allocator = std.mem.Allocator;
const Cache = std.Build.Cache;
const Path = std.Build.Cache.Path;
@@ -19,15 +18,13 @@ const Zcu = @import("Zcu.zig");
const InternPool = @import("InternPool.zig");
const Type = @import("Type.zig");
const Value = @import("Value.zig");
-const LlvmObject = @import("codegen/llvm.zig").Object;
-const lldMain = @import("main.zig").lldMain;
const Package = @import("Package.zig");
const dev = @import("dev.zig");
-const ThreadSafeQueue = @import("ThreadSafeQueue.zig").ThreadSafeQueue;
const target_util = @import("target.zig");
const codegen = @import("codegen.zig");
pub const LdScript = @import("link/LdScript.zig");
+pub const Queue = @import("link/Queue.zig");
pub const Diags = struct {
/// Stored here so that function definitions can distinguish between
@@ -386,10 +383,11 @@ pub const File = struct {
emit: Path,
file: ?fs.File,
- /// When linking with LLD, this linker code will output an object file only at
- /// this location, and then this path can be placed on the LLD linker line.
- zcu_object_sub_path: ?[]const u8 = null,
- disable_lld_caching: bool,
+ /// When using the LLVM backend, the emitted object is written to a file with this name. This
+ /// object file then becomes a normal link input to LLD or a self-hosted linker.
+ ///
+ /// To convert this to an actual path, see `Compilation.resolveEmitPath` (with `kind == .temp`).
+ zcu_object_basename: ?[]const u8 = null,
gc_sections: bool,
print_gc_sections: bool,
build_id: std.zig.BuildId,
@@ -425,7 +423,7 @@ pub const File = struct {
tsaware: bool,
nxcompat: bool,
dynamicbase: bool,
- compress_debug_sections: Elf.CompressDebugSections,
+ compress_debug_sections: Lld.Elf.CompressDebugSections,
bind_global_refs_locally: bool,
import_symbols: bool,
import_table: bool,
@@ -436,9 +434,8 @@ pub const File = struct {
export_symbol_names: []const []const u8,
global_base: ?u64,
build_id: std.zig.BuildId,
- disable_lld_caching: bool,
- hash_style: Elf.HashStyle,
- sort_section: ?Elf.SortSection,
+ hash_style: Lld.Elf.HashStyle,
+ sort_section: ?Lld.Elf.SortSection,
major_subsystem_version: ?u16,
minor_subsystem_version: ?u16,
gc_sections: ?bool,
@@ -522,12 +519,20 @@ pub const File = struct {
emit: Path,
options: OpenOptions,
) !*File {
+ if (comp.config.use_lld) {
+ dev.check(.lld_linker);
+ assert(comp.zcu == null or comp.config.use_llvm);
+ // LLD does not support incremental linking.
+ const lld: *Lld = try .createEmpty(arena, comp, emit, options);
+ return &lld.base;
+ }
switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
inline else => |tag| {
dev.check(tag.devFeature());
const ptr = try tag.Type().open(arena, comp, emit, options);
return &ptr.base;
},
+ .lld => unreachable, // not known from ofmt
}
}
@@ -537,12 +542,19 @@ pub const File = struct {
emit: Path,
options: OpenOptions,
) !*File {
+ if (comp.config.use_lld) {
+ dev.check(.lld_linker);
+ assert(comp.zcu == null or comp.config.use_llvm);
+ const lld: *Lld = try .createEmpty(arena, comp, emit, options);
+ return &lld.base;
+ }
switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
inline else => |tag| {
dev.check(tag.devFeature());
const ptr = try tag.Type().createEmpty(arena, comp, emit, options);
return &ptr.base;
},
+ .lld => unreachable, // not known from ofmt
}
}
@@ -555,6 +567,7 @@ pub const File = struct {
const comp = base.comp;
const gpa = comp.gpa;
switch (base.tag) {
+ .lld => assert(base.file == null),
.coff, .elf, .macho, .plan9, .wasm, .goff, .xcoff => {
if (base.file != null) return;
dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
@@ -587,13 +600,12 @@ pub const File = struct {
}
}
}
- const use_lld = build_options.have_llvm and comp.config.use_lld;
const output_mode = comp.config.output_mode;
const link_mode = comp.config.link_mode;
base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
.truncate = false,
.read = true,
- .mode = determineMode(use_lld, output_mode, link_mode),
+ .mode = determineMode(output_mode, link_mode),
});
},
.c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }),
@@ -619,7 +631,6 @@ pub const File = struct {
const comp = base.comp;
const output_mode = comp.config.output_mode;
const link_mode = comp.config.link_mode;
- const use_lld = build_options.have_llvm and comp.config.use_lld;
switch (output_mode) {
.Obj => return,
@@ -630,13 +641,9 @@ pub const File = struct {
.Exe => {},
}
switch (base.tag) {
+ .lld => assert(base.file == null),
.elf => if (base.file) |f| {
dev.check(.elf_linker);
- if (base.zcu_object_sub_path != null and use_lld) {
- // The file we have open is not the final file that we want to
- // make executable, so we don't have to close it.
- return;
- }
f.close();
base.file = null;
@@ -651,11 +658,6 @@ pub const File = struct {
},
.coff, .macho, .plan9, .wasm, .goff, .xcoff => if (base.file) |f| {
dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
- if (base.zcu_object_sub_path != null) {
- // The file we have open is not the final file that we want to
- // make executable, so we don't have to close it.
- return;
- }
f.close();
base.file = null;
@@ -693,6 +695,7 @@ pub const File = struct {
pub fn getGlobalSymbol(base: *File, name: []const u8, lib_name: ?[]const u8) UpdateNavError!u32 {
log.debug("getGlobalSymbol '{s}' (expected in '{?s}')", .{ name, lib_name });
switch (base.tag) {
+ .lld => unreachable,
.plan9 => unreachable,
.spirv => unreachable,
.c => unreachable,
@@ -704,10 +707,13 @@ pub const File = struct {
}
/// May be called before or after updateExports for any given Nav.
- pub fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {
+ /// Asserts that the ZCU is not using the LLVM backend.
+ fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {
+ assert(base.comp.zcu.?.llvm_object == null);
const nav = pt.zcu.intern_pool.getNav(nav_index);
assert(nav.status == .fully_resolved);
switch (base.tag) {
+ .lld => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateNav(pt, nav_index);
@@ -721,8 +727,11 @@ pub const File = struct {
TypeFailureReported,
};
- pub fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {
+ /// Never called when LLVM is codegenning the ZCU.
+ fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
+ .lld => unreachable,
else => {},
inline .elf => |tag| {
dev.check(tag.devFeature());
@@ -732,17 +741,24 @@ pub const File = struct {
}
/// May be called before or after updateExports for any given Decl.
- pub fn updateFunc(
+ /// The active tag of `mir` is determined by the backend used for the module this function is in.
+ /// Never called when LLVM is codegenning the ZCU.
+ fn updateFunc(
base: *File,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ /// This is owned by the caller, but the callee is permitted to mutate it provided
+ /// that `mir.deinit` remains legal for the caller. For instance, the callee can
+ /// take ownership of an embedded slice and replace it with `&.{}` in `mir`.
+ mir: *codegen.AnyMir,
) UpdateNavError!void {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
+ .lld => unreachable,
+ .spirv => unreachable, // see corresponding special case in `Zcu.PerThread.runCodegenInner`
inline else => |tag| {
dev.check(tag.devFeature());
- return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(pt, func_index, air, liveness);
+ return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(pt, func_index, mir);
},
}
}
@@ -755,7 +771,9 @@ pub const File = struct {
/// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because
/// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`.
- pub fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateLineNumberError!void {
+ /// Never called when LLVM is codegenning the ZCU.
+ fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateLineNumberError!void {
+ assert(base.comp.zcu.?.llvm_object == null);
{
const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?;
const file = pt.zcu.fileByIndex(ti.file);
@@ -764,6 +782,7 @@ pub const File = struct {
}
switch (base.tag) {
+ .lld => unreachable,
.spirv => {},
.goff, .xcoff => {},
inline else => |tag| {
@@ -803,8 +822,7 @@ pub const File = struct {
OutOfMemory,
};
- /// Commit pending changes and write headers. Takes into account final output mode
- /// and `use_lld`, not only `effectiveOutputMode`.
+ /// Commit pending changes and write headers. Takes into account final output mode.
/// `arena` has the lifetime of the call to `Compilation.update`.
pub fn flush(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
const comp = base.comp;
@@ -826,15 +844,7 @@ pub const File = struct {
};
return;
}
-
assert(base.post_prelink);
-
- const use_lld = build_options.have_llvm and comp.config.use_lld;
- const output_mode = comp.config.output_mode;
- const link_mode = comp.config.link_mode;
- if (use_lld and output_mode == .Lib and link_mode == .static) {
- return base.linkAsArchive(arena, tid, prog_node);
- }
switch (base.tag) {
inline else => |tag| {
dev.check(tag.devFeature());
@@ -843,17 +853,6 @@ pub const File = struct {
}
}
- /// Commit pending changes and write headers. Works based on `effectiveOutputMode`
- /// rather than final output mode.
- pub fn flushModule(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
- switch (base.tag) {
- inline else => |tag| {
- dev.check(tag.devFeature());
- return @as(*tag.Type(), @fieldParentPtr("base", base)).flushModule(arena, tid, prog_node);
- },
- }
- }
-
pub const UpdateExportsError = error{
OutOfMemory,
AnalysisFail,
@@ -863,13 +862,16 @@ pub const File = struct {
/// a list of size 1, meaning that `exported` is exported once. However, it is possible
/// to export the same thing with multiple different symbol names (aliases).
/// May be called before or after updateDecl for any given Decl.
+ /// Never called when LLVM is codegenning the ZCU.
pub fn updateExports(
base: *File,
pt: Zcu.PerThread,
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
) UpdateExportsError!void {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
+ .lld => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateExports(pt, exported, export_indices);
@@ -895,8 +897,11 @@ pub const File = struct {
/// `Nav`'s address was not yet resolved, or the containing atom gets moved in virtual memory.
/// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate
/// the block/atom.
+ /// Never called when LLVM is codegenning the ZCU.
pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) !u64 {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
+ .lld => unreachable,
.c => unreachable,
.spirv => unreachable,
.wasm => unreachable,
@@ -908,6 +913,7 @@ pub const File = struct {
}
}
+ /// Never called when LLVM is codegenning the ZCU.
pub fn lowerUav(
base: *File,
pt: Zcu.PerThread,
@@ -915,7 +921,9 @@ pub const File = struct {
decl_align: InternPool.Alignment,
src_loc: Zcu.LazySrcLoc,
) !codegen.GenResult {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
+ .lld => unreachable,
.c => unreachable,
.spirv => unreachable,
.wasm => unreachable,
@@ -927,8 +935,11 @@ pub const File = struct {
}
}
+ /// Never called when LLVM is codegenning the ZCU.
pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
+ .lld => unreachable,
.c => unreachable,
.spirv => unreachable,
.wasm => unreachable,
@@ -940,12 +951,16 @@ pub const File = struct {
}
}
+ /// Never called when LLVM is codegenning the ZCU.
pub fn deleteExport(
base: *File,
exported: Zcu.Exported,
name: InternPool.NullTerminatedString,
) void {
+ assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
+ .lld => unreachable,
+
.plan9,
.spirv,
.goff,
@@ -961,6 +976,7 @@ pub const File = struct {
/// Opens a path as an object file and parses it into the linker.
fn openLoadObject(base: *File, path: Path) anyerror!void {
+ if (base.tag == .lld) return;
const diags = &base.comp.link_diags;
const input = try openObjectInput(diags, path);
errdefer input.object.file.close();
@@ -970,6 +986,7 @@ pub const File = struct {
/// Opens a path as a static library and parses it into the linker.
/// If `query` is non-null, allows GNU ld scripts.
fn openLoadArchive(base: *File, path: Path, opt_query: ?UnresolvedInput.Query) anyerror!void {
+ if (base.tag == .lld) return;
if (opt_query) |query| {
const archive = try openObject(path, query.must_link, query.hidden);
errdefer archive.file.close();
@@ -992,6 +1009,7 @@ pub const File = struct {
/// Opens a path as a shared library and parses it into the linker.
/// Handles GNU ld scripts.
fn openLoadDso(base: *File, path: Path, query: UnresolvedInput.Query) anyerror!void {
+ if (base.tag == .lld) return;
const dso = try openDso(path, query.needed, query.weak, query.reexport);
errdefer dso.file.close();
loadInput(base, .{ .dso = dso }) catch |err| switch (err) {
@@ -1044,8 +1062,7 @@ pub const File = struct {
}
pub fn loadInput(base: *File, input: Input) anyerror!void {
- const use_lld = build_options.have_llvm and base.comp.config.use_lld;
- if (use_lld) return;
+ if (base.tag == .lld) return;
switch (base.tag) {
inline .elf, .wasm => |tag| {
dev.check(tag.devFeature());
@@ -1057,186 +1074,23 @@ pub const File = struct {
/// Called when all linker inputs have been sent via `loadInput`. After
/// this, `loadInput` will not be called anymore.
- pub fn prelink(base: *File, prog_node: std.Progress.Node) FlushError!void {
+ pub fn prelink(base: *File) FlushError!void {
assert(!base.post_prelink);
- const use_lld = build_options.have_llvm and base.comp.config.use_lld;
- if (use_lld) return;
// In this case, an object file is created by the LLVM backend, so
// there is no prelink phase. The Zig code is linked as a standard
// object along with the others.
- if (base.zcu_object_sub_path != null) return;
+ if (base.zcu_object_basename != null) return;
switch (base.tag) {
inline .wasm => |tag| {
dev.check(tag.devFeature());
- return @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(prog_node);
+ return @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node);
},
else => {},
}
}
- pub fn linkAsArchive(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
- dev.check(.lld_linker);
-
- const tracy = trace(@src());
- defer tracy.end();
-
- const comp = base.comp;
- const diags = &comp.link_diags;
-
- return linkAsArchiveInner(base, arena, tid, prog_node) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.LinkFailure => return error.LinkFailure,
- else => |e| return diags.fail("failed to link as archive: {s}", .{@errorName(e)}),
- };
- }
-
- fn linkAsArchiveInner(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
- const comp = base.comp;
-
- const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
- const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
- const full_out_path_z = try arena.dupeZ(u8, full_out_path);
- const opt_zcu = comp.zcu;
-
- // If there is no Zig code to compile, then we should skip flushing the output file
- // because it will not be part of the linker line anyway.
- const zcu_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {
- try base.flushModule(arena, tid, prog_node);
-
- const dirname = fs.path.dirname(full_out_path_z) orelse ".";
- break :blk try fs.path.join(arena, &.{ dirname, base.zcu_object_sub_path.? });
- } else null;
-
- log.debug("zcu_obj_path={s}", .{if (zcu_obj_path) |s| s else "(null)"});
-
- const compiler_rt_path: ?Path = if (comp.compiler_rt_strat == .obj)
- comp.compiler_rt_obj.?.full_object_path
- else
- null;
-
- const ubsan_rt_path: ?Path = if (comp.ubsan_rt_strat == .obj)
- comp.ubsan_rt_obj.?.full_object_path
- else
- null;
-
- // This function follows the same pattern as link.Elf.linkWithLLD so if you want some
- // insight as to what's going on here you can read that function body which is more
- // well-commented.
-
- const id_symlink_basename = "llvm-ar.id";
-
- var man: Cache.Manifest = undefined;
- defer if (!base.disable_lld_caching) man.deinit();
-
- const link_inputs = comp.link_inputs;
-
- var digest: [Cache.hex_digest_len]u8 = undefined;
-
- if (!base.disable_lld_caching) {
- man = comp.cache_parent.obtain();
-
- // We are about to obtain this lock, so here we give other processes a chance first.
- base.releaseLock();
-
- try hashInputs(&man, link_inputs);
-
- for (comp.c_object_table.keys()) |key| {
- _ = try man.addFilePath(key.status.success.object_path, null);
- }
- for (comp.win32_resource_table.keys()) |key| {
- _ = try man.addFile(key.status.success.res_path, null);
- }
- try man.addOptionalFile(zcu_obj_path);
- try man.addOptionalFilePath(compiler_rt_path);
- try man.addOptionalFilePath(ubsan_rt_path);
-
- // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
- _ = try man.hit();
- digest = man.final();
-
- var prev_digest_buf: [digest.len]u8 = undefined;
- const prev_digest: []u8 = Cache.readSmallFile(
- directory.handle,
- id_symlink_basename,
- &prev_digest_buf,
- ) catch |err| b: {
- log.debug("archive new_digest={s} readFile error: {s}", .{ std.fmt.fmtSliceHexLower(&digest), @errorName(err) });
- break :b prev_digest_buf[0..0];
- };
- if (mem.eql(u8, prev_digest, &digest)) {
- log.debug("archive digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});
- base.lock = man.toOwnedLock();
- return;
- }
-
- // We are about to change the output file to be different, so we invalidate the build hash now.
- directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
- error.FileNotFound => {},
- else => |e| return e,
- };
- }
-
- var object_files: std.ArrayListUnmanaged([*:0]const u8) = .empty;
-
- try object_files.ensureUnusedCapacity(arena, link_inputs.len);
- for (link_inputs) |input| {
- object_files.appendAssumeCapacity(try input.path().?.toStringZ(arena));
- }
-
- try object_files.ensureUnusedCapacity(arena, comp.c_object_table.count() +
- comp.win32_resource_table.count() + 2);
-
- for (comp.c_object_table.keys()) |key| {
- object_files.appendAssumeCapacity(try key.status.success.object_path.toStringZ(arena));
- }
- for (comp.win32_resource_table.keys()) |key| {
- object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path));
- }
- if (zcu_obj_path) |p| object_files.appendAssumeCapacity(try arena.dupeZ(u8, p));
- if (compiler_rt_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
- if (ubsan_rt_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
-
- if (comp.verbose_link) {
- std.debug.print("ar rcs {s}", .{full_out_path_z});
- for (object_files.items) |arg| {
- std.debug.print(" {s}", .{arg});
- }
- std.debug.print("\n", .{});
- }
-
- const llvm_bindings = @import("codegen/llvm/bindings.zig");
- const llvm = @import("codegen/llvm.zig");
- const target = comp.root_mod.resolved_target.result;
- llvm.initializeLLVMTarget(target.cpu.arch);
- const bad = llvm_bindings.WriteArchive(
- full_out_path_z,
- object_files.items.ptr,
- object_files.items.len,
- switch (target.os.tag) {
- .aix => .AIXBIG,
- .windows => .COFF,
- else => if (target.os.tag.isDarwin()) .DARWIN else .GNU,
- },
- );
- if (bad) return error.UnableToWriteArchive;
-
- if (!base.disable_lld_caching) {
- Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
- log.warn("failed to save archive hash digest file: {s}", .{@errorName(err)});
- };
-
- if (man.have_exclusive_lock) {
- man.writeManifest() catch |err| {
- log.warn("failed to write cache manifest when archiving: {s}", .{@errorName(err)});
- };
- }
-
- base.lock = man.toOwnedLock();
- }
- }
-
pub const Tag = enum {
coff,
elf,
@@ -1247,6 +1101,7 @@ pub const File = struct {
plan9,
goff,
xcoff,
+ lld,
pub fn Type(comptime tag: Tag) type {
return switch (tag) {
@@ -1259,10 +1114,11 @@ pub const File = struct {
.plan9 => Plan9,
.goff => Goff,
.xcoff => Xcoff,
+ .lld => Lld,
};
}
- pub fn fromObjectFormat(ofmt: std.Target.ObjectFormat) Tag {
+ fn fromObjectFormat(ofmt: std.Target.ObjectFormat) Tag {
return switch (ofmt) {
.coff => .coff,
.elf => .elf,
@@ -1290,15 +1146,7 @@ pub const File = struct {
ty: InternPool.Index,
};
- pub fn effectiveOutputMode(
- use_lld: bool,
- output_mode: std.builtin.OutputMode,
- ) std.builtin.OutputMode {
- return if (use_lld) .Obj else output_mode;
- }
-
pub fn determineMode(
- use_lld: bool,
output_mode: std.builtin.OutputMode,
link_mode: std.builtin.LinkMode,
) fs.File.Mode {
@@ -1307,7 +1155,7 @@ pub const File = struct {
// more leniently. As another data point, C's fopen seems to open files with the
// 666 mode.
const executable_mode = if (builtin.target.os.tag == .windows) 0 else 0o777;
- switch (effectiveOutputMode(use_lld, output_mode)) {
+ switch (output_mode) {
.Lib => return switch (link_mode) {
.dynamic => executable_mode,
.static => fs.File.default_mode,
@@ -1345,21 +1193,6 @@ pub const File = struct {
return output_mode == .Lib and !self.isStatic();
}
- pub fn emitLlvmObject(
- base: File,
- arena: Allocator,
- llvm_object: LlvmObject.Ptr,
- prog_node: std.Progress.Node,
- ) !void {
- return base.comp.emitLlvmObject(arena, .{
- .root_dir = base.emit.root_dir,
- .sub_path = std.fs.path.dirname(base.emit.sub_path) orelse "",
- }, .{
- .directory = null,
- .basename = base.zcu_object_sub_path.?,
- }, llvm_object, prog_node);
- }
-
pub fn cgFail(
base: *File,
nav_index: InternPool.Nav.Index,
@@ -1370,6 +1203,7 @@ pub const File = struct {
return base.comp.zcu.?.codegenFail(nav_index, format, args);
}
+ pub const Lld = @import("link/Lld.zig");
pub const C = @import("link/C.zig");
pub const Coff = @import("link/Coff.zig");
pub const Plan9 = @import("link/Plan9.zig");
@@ -1382,40 +1216,7 @@ pub const File = struct {
pub const Dwarf = @import("link/Dwarf.zig");
};
-/// Does all the tasks in the queue. Runs in exactly one separate thread
-/// from the rest of compilation. All tasks performed here are
-/// single-threaded with respect to one another.
-pub fn flushTaskQueue(tid: usize, comp: *Compilation) void {
- const diags = &comp.link_diags;
- // As soon as check() is called, another `flushTaskQueue` call could occur,
- // so the safety lock must go after the check.
- while (comp.link_task_queue.check()) |tasks| {
- comp.link_task_queue_safety.lock();
- defer comp.link_task_queue_safety.unlock();
-
- if (comp.remaining_prelink_tasks > 0) {
- comp.link_task_queue_postponed.ensureUnusedCapacity(comp.gpa, tasks.len) catch |err| switch (err) {
- error.OutOfMemory => return diags.setAllocFailure(),
- };
- }
-
- for (tasks) |task| doTask(comp, tid, task);
-
- if (comp.remaining_prelink_tasks == 0) {
- if (comp.bin_file) |base| if (!base.post_prelink) {
- base.prelink(comp.work_queue_progress_node) catch |err| switch (err) {
- error.OutOfMemory => diags.setAllocFailure(),
- error.LinkFailure => continue,
- };
- base.post_prelink = true;
- for (comp.link_task_queue_postponed.items) |task| doTask(comp, tid, task);
- comp.link_task_queue_postponed.clearRetainingCapacity();
- };
- }
- }
-}
-
-pub const Task = union(enum) {
+pub const PrelinkTask = union(enum) {
/// Loads the objects, shared objects, and archives that are already
/// known from the command line.
load_explicitly_provided,
@@ -1433,32 +1234,74 @@ pub const Task = union(enum) {
/// Tells the linker to load an input which could be an object file,
/// archive, or shared library.
load_input: Input,
-
+};
+pub const ZcuTask = union(enum) {
/// Write the constant value for a Decl to the output file.
- codegen_nav: InternPool.Nav.Index,
+ link_nav: InternPool.Nav.Index,
/// Write the machine code for a function to the output file.
- codegen_func: CodegenFunc,
- codegen_type: InternPool.Index,
-
+ link_func: LinkFunc,
+ link_type: InternPool.Index,
update_line_number: InternPool.TrackedInst.Index,
-
- pub const CodegenFunc = struct {
+ pub fn deinit(task: ZcuTask, zcu: *const Zcu) void {
+ switch (task) {
+ .link_nav,
+ .link_type,
+ .update_line_number,
+ => {},
+ .link_func => |link_func| {
+ switch (link_func.mir.status.load(.monotonic)) {
+ .pending => unreachable, // cannot deinit until MIR done
+ .failed => {}, // MIR not populated so doesn't need freeing
+ .ready => link_func.mir.value.deinit(zcu),
+ }
+ zcu.gpa.destroy(link_func.mir);
+ },
+ }
+ }
+ pub const LinkFunc = struct {
/// This will either be a non-generic `func_decl` or a `func_instance`.
func: InternPool.Index,
- /// This `Air` is owned by the `Job` and allocated with `gpa`.
- /// It must be deinited when the job is processed.
- air: Air,
+ /// This pointer is allocated into `gpa` and must be freed when the `ZcuTask` is processed.
+ /// The pointer is shared with the codegen worker, which will populate the MIR inside once
+ /// it has been generated. It's important that the `link_func` is queued at the same time as
+ /// the codegen job to ensure that the linker receives functions in a deterministic order,
+ /// allowing reproducible builds.
+ mir: *SharedMir,
+ /// This is not actually used by `doZcuTask`. Instead, `Queue` uses this value as a heuristic
+ /// to avoid queueing too much AIR/MIR for codegen/link at a time. Essentially, we cap the
+ /// total number of AIR bytes which are being processed at once, preventing unbounded memory
+ /// usage when AIR is produced faster than it is processed.
+ air_bytes: u32,
+
+ pub const SharedMir = struct {
+ /// This is initially `.pending`. When `value` is populated, the codegen thread will set
+ /// this to `.ready`, and alert the queue if needed. It could also end up `.failed`.
+ /// The action of storing a value (other than `.pending`) to this atomic transfers
+ /// ownership of memory assoicated with `value` to this `ZcuTask`.
+ status: std.atomic.Value(enum(u8) {
+ /// We are waiting on codegen to generate MIR (or die trying).
+ pending,
+ /// `value` is not populated and will not be populated. Just drop the task from the queue and move on.
+ failed,
+ /// `value` is populated with the MIR from the backend in use, which is not LLVM.
+ ready,
+ }),
+ /// This is `undefined` until `ready` is set to `true`. Once populated, this MIR belongs
+ /// to the `ZcuTask`, and must be `deinit`ed when it is processed. Allocated into `gpa`.
+ value: codegen.AnyMir,
+ };
};
};
-pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
+pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
const diags = &comp.link_diags;
+ const base = comp.bin_file orelse {
+ comp.link_prog_node.completeOne();
+ return;
+ };
switch (task) {
.load_explicitly_provided => {
- comp.remaining_prelink_tasks -= 1;
- const base = comp.bin_file orelse return;
-
- const prog_node = comp.work_queue_progress_node.start("Parse Linker Inputs", comp.link_inputs.len);
+ const prog_node = comp.link_prog_node.start("Parse Inputs", comp.link_inputs.len);
defer prog_node.end();
for (comp.link_inputs) |input| {
base.loadInput(input) catch |err| switch (err) {
@@ -1475,10 +1318,7 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
}
},
.load_host_libc => {
- comp.remaining_prelink_tasks -= 1;
- const base = comp.bin_file orelse return;
-
- const prog_node = comp.work_queue_progress_node.start("Linker Parse Host libc", 0);
+ const prog_node = comp.link_prog_node.start("Parse Host libc", 0);
defer prog_node.end();
const target = comp.root_mod.resolved_target.result;
@@ -1537,9 +1377,7 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
}
},
.load_object => |path| {
- comp.remaining_prelink_tasks -= 1;
- const base = comp.bin_file orelse return;
- const prog_node = comp.work_queue_progress_node.start("Linker Parse Object", 0);
+ const prog_node = comp.link_prog_node.start("Parse Object", 0);
defer prog_node.end();
base.openLoadObject(path) catch |err| switch (err) {
error.LinkFailure => return, // error reported via diags
@@ -1547,9 +1385,7 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
};
},
.load_archive => |path| {
- comp.remaining_prelink_tasks -= 1;
- const base = comp.bin_file orelse return;
- const prog_node = comp.work_queue_progress_node.start("Linker Parse Archive", 0);
+ const prog_node = comp.link_prog_node.start("Parse Archive", 0);
defer prog_node.end();
base.openLoadArchive(path, null) catch |err| switch (err) {
error.LinkFailure => return, // error reported via link_diags
@@ -1557,9 +1393,7 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
};
},
.load_dso => |path| {
- comp.remaining_prelink_tasks -= 1;
- const base = comp.bin_file orelse return;
- const prog_node = comp.work_queue_progress_node.start("Linker Parse Shared Library", 0);
+ const prog_node = comp.link_prog_node.start("Parse Shared Library", 0);
defer prog_node.end();
base.openLoadDso(path, .{
.preferred_mode = .dynamic,
@@ -1570,9 +1404,7 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
};
},
.load_input => |input| {
- comp.remaining_prelink_tasks -= 1;
- const base = comp.bin_file orelse return;
- const prog_node = comp.work_queue_progress_node.start("Linker Parse Input", 0);
+ const prog_node = comp.link_prog_node.start("Parse Input", 0);
defer prog_node.end();
base.loadInput(input) catch |err| switch (err) {
error.LinkFailure => return, // error reported via link_diags
@@ -1585,159 +1417,113 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
},
};
},
- .codegen_nav => |nav_index| {
- if (comp.remaining_prelink_tasks == 0) {
- const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
- defer pt.deactivate();
- pt.linkerUpdateNav(nav_index) catch |err| switch (err) {
+ }
+}
+pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {
+ const diags = &comp.link_diags;
+ const zcu = comp.zcu.?;
+ const ip = &zcu.intern_pool;
+ const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid));
+ defer pt.deactivate();
+ switch (task) {
+ .link_nav => |nav_index| {
+ const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);
+ const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0);
+ defer nav_prog_node.end();
+ if (zcu.llvm_object) |llvm_object| {
+ llvm_object.updateNav(pt, nav_index) catch |err| switch (err) {
error.OutOfMemory => diags.setAllocFailure(),
};
- } else {
- comp.link_task_queue_postponed.appendAssumeCapacity(task);
- }
- },
- .codegen_func => |func| {
- if (comp.remaining_prelink_tasks == 0) {
- const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
- defer pt.deactivate();
- var air = func.air;
- defer air.deinit(comp.gpa);
- pt.linkerUpdateFunc(func.func, &air) catch |err| switch (err) {
+ } else if (comp.bin_file) |lf| {
+ lf.updateNav(pt, nav_index) catch |err| switch (err) {
error.OutOfMemory => diags.setAllocFailure(),
+ error.CodegenFail => zcu.assertCodegenFailed(nav_index),
+ error.Overflow, error.RelocationNotByteAligned => {
+ switch (zcu.codegenFail(nav_index, "unable to codegen: {s}", .{@errorName(err)})) {
+ error.CodegenFail => return,
+ error.OutOfMemory => return diags.setAllocFailure(),
+ }
+ // Not a retryable failure.
+ },
};
- } else {
- comp.link_task_queue_postponed.appendAssumeCapacity(task);
}
},
- .codegen_type => |ty| {
- if (comp.remaining_prelink_tasks == 0) {
- const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
- defer pt.deactivate();
- pt.linkerUpdateContainerType(ty) catch |err| switch (err) {
- error.OutOfMemory => diags.setAllocFailure(),
+ .link_func => |func| {
+ const nav = zcu.funcInfo(func.func).owner_nav;
+ const fqn_slice = ip.getNav(nav).fqn.toSlice(ip);
+ const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0);
+ defer nav_prog_node.end();
+ switch (func.mir.status.load(.monotonic)) {
+ .pending => unreachable,
+ .ready => {},
+ .failed => return,
+ }
+ assert(zcu.llvm_object == null); // LLVM codegen doesn't produce MIR
+ const mir = &func.mir.value;
+ if (comp.bin_file) |lf| {
+ lf.updateFunc(pt, func.func, mir) catch |err| switch (err) {
+ error.OutOfMemory => return diags.setAllocFailure(),
+ error.CodegenFail => return zcu.assertCodegenFailed(nav),
+ error.Overflow, error.RelocationNotByteAligned => {
+ switch (zcu.codegenFail(nav, "unable to codegen: {s}", .{@errorName(err)})) {
+ error.OutOfMemory => return diags.setAllocFailure(),
+ error.CodegenFail => return,
+ }
+ },
};
- } else {
- comp.link_task_queue_postponed.appendAssumeCapacity(task);
+ }
+ },
+ .link_type => |ty| {
+ const name = Type.fromInterned(ty).containerTypeName(ip).toSlice(ip);
+ const nav_prog_node = comp.link_prog_node.start(name, 0);
+ defer nav_prog_node.end();
+ if (zcu.llvm_object == null) {
+ if (comp.bin_file) |lf| {
+ lf.updateContainerType(pt, ty) catch |err| switch (err) {
+ error.OutOfMemory => diags.setAllocFailure(),
+ error.TypeFailureReported => assert(zcu.failed_types.contains(ty)),
+ };
+ }
}
},
.update_line_number => |ti| {
- const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
- defer pt.deactivate();
- pt.linkerUpdateLineNumber(ti) catch |err| switch (err) {
- error.OutOfMemory => diags.setAllocFailure(),
- };
+ const nav_prog_node = comp.link_prog_node.start("Update line number", 0);
+ defer nav_prog_node.end();
+ if (pt.zcu.llvm_object == null) {
+ if (comp.bin_file) |lf| {
+ lf.updateLineNumber(pt, ti) catch |err| switch (err) {
+ error.OutOfMemory => diags.setAllocFailure(),
+ else => |e| log.err("update line number failed: {s}", .{@errorName(e)}),
+ };
+ }
+ }
},
}
}
-
-pub fn spawnLld(
- comp: *Compilation,
- arena: Allocator,
- argv: []const []const u8,
-) !void {
- if (comp.verbose_link) {
- // Skip over our own name so that the LLD linker name is the first argv item.
- Compilation.dump_argv(argv[1..]);
- }
-
- // If possible, we run LLD as a child process because it does not always
- // behave properly as a library, unfortunately.
- // https://github.com/ziglang/zig/issues/3825
- if (!std.process.can_spawn) {
- const exit_code = try lldMain(arena, argv, false);
- if (exit_code == 0) return;
- if (comp.clang_passthrough_mode) std.process.exit(exit_code);
- return error.LinkFailure;
- }
-
- var stderr: []u8 = &.{};
- defer comp.gpa.free(stderr);
-
- var child = std.process.Child.init(argv, arena);
- const term = (if (comp.clang_passthrough_mode) term: {
- child.stdin_behavior = .Inherit;
- child.stdout_behavior = .Inherit;
- child.stderr_behavior = .Inherit;
-
- break :term child.spawnAndWait();
- } else term: {
- child.stdin_behavior = .Ignore;
- child.stdout_behavior = .Ignore;
- child.stderr_behavior = .Pipe;
-
- child.spawn() catch |err| break :term err;
- stderr = try child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize));
- break :term child.wait();
- }) catch |first_err| term: {
- const err = switch (first_err) {
- error.NameTooLong => err: {
- const s = fs.path.sep_str;
- const rand_int = std.crypto.random.int(u64);
- const rsp_path = "tmp" ++ s ++ std.fmt.hex(rand_int) ++ ".rsp";
-
- const rsp_file = try comp.dirs.local_cache.handle.createFileZ(rsp_path, .{});
- defer comp.dirs.local_cache.handle.deleteFileZ(rsp_path) catch |err|
- log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) });
- {
- defer rsp_file.close();
- var rsp_buf = std.io.bufferedWriter(rsp_file.writer());
- const rsp_writer = rsp_buf.writer();
- for (argv[2..]) |arg| {
- try rsp_writer.writeByte('"');
- for (arg) |c| {
- switch (c) {
- '\"', '\\' => try rsp_writer.writeByte('\\'),
- else => {},
- }
- try rsp_writer.writeByte(c);
- }
- try rsp_writer.writeByte('"');
- try rsp_writer.writeByte('\n');
- }
- try rsp_buf.flush();
- }
-
- var rsp_child = std.process.Child.init(&.{ argv[0], argv[1], try std.fmt.allocPrint(
- arena,
- "@{s}",
- .{try comp.dirs.local_cache.join(arena, &.{rsp_path})},
- ) }, arena);
- if (comp.clang_passthrough_mode) {
- rsp_child.stdin_behavior = .Inherit;
- rsp_child.stdout_behavior = .Inherit;
- rsp_child.stderr_behavior = .Inherit;
-
- break :term rsp_child.spawnAndWait() catch |err| break :err err;
- } else {
- rsp_child.stdin_behavior = .Ignore;
- rsp_child.stdout_behavior = .Ignore;
- rsp_child.stderr_behavior = .Pipe;
-
- rsp_child.spawn() catch |err| break :err err;
- stderr = try rsp_child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize));
- break :term rsp_child.wait() catch |err| break :err err;
+/// After the main pipeline is done, but before flush, the compilation may need to link one final
+/// `Nav` into the binary: the `builtin.test_functions` value. Since the link thread isn't running
+/// by then, we expose this function which can be called directly.
+pub fn linkTestFunctionsNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) void {
+ const zcu = pt.zcu;
+ const comp = zcu.comp;
+ const diags = &comp.link_diags;
+ if (zcu.llvm_object) |llvm_object| {
+ llvm_object.updateNav(pt, nav_index) catch |err| switch (err) {
+ error.OutOfMemory => diags.setAllocFailure(),
+ };
+ } else if (comp.bin_file) |lf| {
+ lf.updateNav(pt, nav_index) catch |err| switch (err) {
+ error.OutOfMemory => diags.setAllocFailure(),
+ error.CodegenFail => zcu.assertCodegenFailed(nav_index),
+ error.Overflow, error.RelocationNotByteAligned => {
+ switch (zcu.codegenFail(nav_index, "unable to codegen: {s}", .{@errorName(err)})) {
+ error.CodegenFail => return,
+ error.OutOfMemory => return diags.setAllocFailure(),
}
+ // Not a retryable failure.
},
- else => first_err,
};
- log.err("unable to spawn LLD {s}: {s}", .{ argv[0], @errorName(err) });
- return error.UnableToSpawnSelf;
- };
-
- const diags = &comp.link_diags;
- switch (term) {
- .Exited => |code| if (code != 0) {
- if (comp.clang_passthrough_mode) std.process.exit(code);
- diags.lockAndParseLldStderr(argv[1], stderr);
- return error.LinkFailure;
- },
- else => {
- if (comp.clang_passthrough_mode) std.process.abort();
- return diags.fail("{s} terminated with stderr:\n{s}", .{ argv[0], stderr });
- },
}
-
- if (stderr.len > 0) log.warn("unexpected LLD stderr:\n{s}", .{stderr});
}
/// Provided by the CLI, processed into `LinkInput` instances at the start of
diff --git a/src/link/C.zig b/src/link/C.zig
index c32d8ba80b..f3465055b8 100644
--- a/src/link/C.zig
+++ b/src/link/C.zig
@@ -17,7 +17,7 @@ const link = @import("../link.zig");
const trace = @import("../tracy.zig").trace;
const Type = @import("../Type.zig");
const Value = @import("../Value.zig");
-const Air = @import("../Air.zig");
+const AnyMir = @import("../codegen.zig").AnyMir;
pub const zig_h = "#include \"zig.h\"\n";
@@ -145,7 +145,6 @@ pub fn createEmpty(
.stack_size = options.stack_size orelse 16777216,
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
.file = file,
- .disable_lld_caching = options.disable_lld_caching,
.build_id = options.build_id,
},
};
@@ -167,6 +166,9 @@ pub fn deinit(self: *C) void {
self.uavs.deinit(gpa);
self.aligned_uavs.deinit(gpa);
+ self.exported_navs.deinit(gpa);
+ self.exported_uavs.deinit(gpa);
+
self.string_bytes.deinit(gpa);
self.fwd_decl_buf.deinit(gpa);
self.code_buf.deinit(gpa);
@@ -178,73 +180,23 @@ pub fn updateFunc(
self: *C,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ mir: *AnyMir,
) link.File.UpdateNavError!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const func = zcu.funcInfo(func_index);
- const gop = try self.navs.getOrPut(gpa, func.owner_nav);
- if (!gop.found_existing) gop.value_ptr.* = .{};
- const ctype_pool = &gop.value_ptr.ctype_pool;
- const lazy_fns = &gop.value_ptr.lazy_fns;
- const fwd_decl = &self.fwd_decl_buf;
- const code = &self.code_buf;
- try ctype_pool.init(gpa);
- ctype_pool.clearRetainingCapacity();
- lazy_fns.clearRetainingCapacity();
- fwd_decl.clearRetainingCapacity();
- code.clearRetainingCapacity();
-
- var function: codegen.Function = .{
- .value_map = codegen.CValueMap.init(gpa),
- .air = air,
- .liveness = liveness,
- .func_index = func_index,
- .object = .{
- .dg = .{
- .gpa = gpa,
- .pt = pt,
- .mod = zcu.navFileScope(func.owner_nav).mod.?,
- .error_msg = null,
- .pass = .{ .nav = func.owner_nav },
- .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,
- .expected_block = null,
- .fwd_decl = fwd_decl.toManaged(gpa),
- .ctype_pool = ctype_pool.*,
- .scratch = .{},
- .uav_deps = self.uavs,
- .aligned_uavs = self.aligned_uavs,
- },
- .code = code.toManaged(gpa),
- .indent_writer = undefined, // set later so we can get a pointer to object.code
- },
- .lazy_fns = lazy_fns.*,
- };
- function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
- defer {
- self.uavs = function.object.dg.uav_deps;
- self.aligned_uavs = function.object.dg.aligned_uavs;
- fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged();
- ctype_pool.* = function.object.dg.ctype_pool.move();
- ctype_pool.freeUnusedCapacity(gpa);
- function.object.dg.scratch.deinit(gpa);
- lazy_fns.* = function.lazy_fns.move();
- lazy_fns.shrinkAndFree(gpa, lazy_fns.count());
- code.* = function.object.code.moveToUnmanaged();
- function.deinit();
- }
- try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1);
- codegen.genFunc(&function) catch |err| switch (err) {
- error.AnalysisFail => {
- zcu.failed_codegen.putAssumeCapacityNoClobber(func.owner_nav, function.object.dg.error_msg.?);
- return;
- },
- else => |e| return e,
+ const gop = try self.navs.getOrPut(gpa, func.owner_nav);
+ if (gop.found_existing) gop.value_ptr.deinit(gpa);
+ gop.value_ptr.* = .{
+ .code = .empty,
+ .fwd_decl = .empty,
+ .ctype_pool = mir.c.ctype_pool.move(),
+ .lazy_fns = mir.c.lazy_fns.move(),
};
- gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items);
- gop.value_ptr.code = try self.addString(function.object.code.items);
+ gop.value_ptr.code = try self.addString(mir.c.code);
+ gop.value_ptr.fwd_decl = try self.addString(mir.c.fwd_decl);
+ try self.addUavsFromCodegen(&mir.c.uavs);
}
fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
@@ -268,16 +220,14 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
.fwd_decl = fwd_decl.toManaged(gpa),
.ctype_pool = codegen.CType.Pool.empty,
.scratch = .{},
- .uav_deps = self.uavs,
- .aligned_uavs = self.aligned_uavs,
+ .uavs = .empty,
},
.code = code.toManaged(gpa),
.indent_writer = undefined, // set later so we can get a pointer to object.code
};
object.indent_writer = .{ .underlying_writer = object.code.writer() };
defer {
- self.uavs = object.dg.uav_deps;
- self.aligned_uavs = object.dg.aligned_uavs;
+ object.dg.uavs.deinit(gpa);
fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
object.dg.ctype_pool.deinit(object.dg.gpa);
object.dg.scratch.deinit(gpa);
@@ -296,8 +246,10 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
else => |e| return e,
};
+ try self.addUavsFromCodegen(&object.dg.uavs);
+
object.dg.ctype_pool.freeUnusedCapacity(gpa);
- object.dg.uav_deps.values()[i] = .{
+ self.uavs.values()[i] = .{
.code = try self.addString(object.code.items),
.fwd_decl = try self.addString(object.dg.fwd_decl.items),
.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
.fwd_decl = fwd_decl.toManaged(gpa),
.ctype_pool = ctype_pool.*,
.scratch = .{},
- .uav_deps = self.uavs,
- .aligned_uavs = self.aligned_uavs,
+ .uavs = .empty,
},
.code = code.toManaged(gpa),
.indent_writer = undefined, // set later so we can get a pointer to object.code
};
object.indent_writer = .{ .underlying_writer = object.code.writer() };
defer {
- self.uavs = object.dg.uav_deps;
- self.aligned_uavs = object.dg.aligned_uavs;
+ object.dg.uavs.deinit(gpa);
fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
ctype_pool.* = object.dg.ctype_pool.move();
ctype_pool.freeUnusedCapacity(gpa);
@@ -361,16 +311,16 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
code.* = object.code.moveToUnmanaged();
}
- try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1);
codegen.genDecl(&object) catch |err| switch (err) {
- error.AnalysisFail => {
- zcu.failed_codegen.putAssumeCapacityNoClobber(nav_index, object.dg.error_msg.?);
- return;
+ error.AnalysisFail => switch (zcu.codegenFailMsg(nav_index, object.dg.error_msg.?)) {
+ error.CodegenFail => return,
+ error.OutOfMemory => |e| return e,
},
else => |e| return e,
};
gop.value_ptr.code = try self.addString(object.code.items);
gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items);
+ try self.addUavsFromCodegen(&object.dg.uavs);
}
pub 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
_ = ti_id;
}
-pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- return self.flushModule(arena, tid, prog_node);
-}
-
fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
const gpa = self.base.comp.gpa;
var defines = std.ArrayList(u8).init(gpa);
@@ -400,7 +346,7 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
return defines;
}
-pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
+pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
_ = arena; // Has the same lifetime as the call to Compilation.update.
const tracy = trace(@src());
@@ -676,16 +622,14 @@ fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) F
.fwd_decl = fwd_decl.toManaged(gpa),
.ctype_pool = ctype_pool.*,
.scratch = .{},
- .uav_deps = self.uavs,
- .aligned_uavs = self.aligned_uavs,
+ .uavs = .empty,
},
.code = code.toManaged(gpa),
.indent_writer = undefined, // set later so we can get a pointer to object.code
};
object.indent_writer = .{ .underlying_writer = object.code.writer() };
defer {
- self.uavs = object.dg.uav_deps;
- self.aligned_uavs = object.dg.aligned_uavs;
+ object.dg.uavs.deinit(gpa);
fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
ctype_pool.* = object.dg.ctype_pool.move();
ctype_pool.freeUnusedCapacity(gpa);
@@ -697,6 +641,8 @@ fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) F
error.AnalysisFail => unreachable,
else => |e| return e,
};
+
+ try self.addUavsFromCodegen(&object.dg.uavs);
}
fn flushLazyFn(
@@ -724,8 +670,7 @@ fn flushLazyFn(
.fwd_decl = fwd_decl.toManaged(gpa),
.ctype_pool = ctype_pool.*,
.scratch = .{},
- .uav_deps = .{},
- .aligned_uavs = .{},
+ .uavs = .empty,
},
.code = code.toManaged(gpa),
.indent_writer = undefined, // set later so we can get a pointer to object.code
@@ -734,8 +679,7 @@ fn flushLazyFn(
defer {
// If this assert trips just handle the anon_decl_deps the same as
// `updateFunc()` does.
- assert(object.dg.uav_deps.count() == 0);
- assert(object.dg.aligned_uavs.count() == 0);
+ assert(object.dg.uavs.count() == 0);
fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
ctype_pool.* = object.dg.ctype_pool.move();
ctype_pool.freeUnusedCapacity(gpa);
@@ -871,12 +815,10 @@ pub fn updateExports(
.fwd_decl = fwd_decl.toManaged(gpa),
.ctype_pool = decl_block.ctype_pool,
.scratch = .{},
- .uav_deps = .{},
- .aligned_uavs = .{},
+ .uavs = .empty,
};
defer {
- assert(dg.uav_deps.count() == 0);
- assert(dg.aligned_uavs.count() == 0);
+ assert(dg.uavs.count() == 0);
fwd_decl.* = dg.fwd_decl.moveToUnmanaged();
ctype_pool.* = dg.ctype_pool.move();
ctype_pool.freeUnusedCapacity(gpa);
@@ -896,3 +838,21 @@ pub fn deleteExport(
.uav => |uav| _ = self.exported_uavs.swapRemove(uav),
}
}
+
+fn addUavsFromCodegen(c: *C, uavs: *const std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment)) Allocator.Error!void {
+ const gpa = c.base.comp.gpa;
+ try c.uavs.ensureUnusedCapacity(gpa, uavs.count());
+ try c.aligned_uavs.ensureUnusedCapacity(gpa, uavs.count());
+ for (uavs.keys(), uavs.values()) |uav_val, uav_align| {
+ {
+ const gop = c.uavs.getOrPutAssumeCapacity(uav_val);
+ if (!gop.found_existing) gop.value_ptr.* = .{};
+ }
+ if (uav_align != .none) {
+ const gop = c.aligned_uavs.getOrPutAssumeCapacity(uav_val);
+ gop.value_ptr.* = if (gop.found_existing) max: {
+ break :max gop.value_ptr.*.maxStrict(uav_align);
+ } else uav_align;
+ }
+ }
+}
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
index 5100406030..0e00229b78 100644
--- a/src/link/Coff.zig
+++ b/src/link/Coff.zig
@@ -1,26 +1,14 @@
-//! The main driver of the COFF linker.
-//! Currently uses our own implementation for the incremental linker, and falls back to
-//! LLD for traditional linking (linking relocatable object files).
-//! LLD is also the default linker for LLVM.
-
-/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
-llvm_object: ?LlvmObject.Ptr = null,
+//! The main driver of the self-hosted COFF linker.
base: link.File,
image_base: u64,
-subsystem: ?std.Target.SubSystem,
-tsaware: bool,
-nxcompat: bool,
-dynamicbase: bool,
/// TODO this and minor_subsystem_version should be combined into one property and left as
/// default or populated together. They should not be separate fields.
major_subsystem_version: u16,
minor_subsystem_version: u16,
-lib_directories: []const Directory,
entry: link.File.OpenOptions.Entry,
entry_addr: ?u32,
module_definition_file: ?[]const u8,
-pdb_out_path: ?[]const u8,
repro: bool,
ptr_width: PtrWidth,
@@ -226,7 +214,6 @@ pub fn createEmpty(
const output_mode = comp.config.output_mode;
const link_mode = comp.config.link_mode;
const use_llvm = comp.config.use_llvm;
- const use_lld = build_options.have_llvm and comp.config.use_lld;
const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {
0...32 => .p32,
@@ -237,29 +224,21 @@ pub fn createEmpty(
else => 0x1000,
};
- // If using LLD to link, this code should produce an object file so that it
- // can be passed to LLD.
- // If using LLVM to generate the object file for the zig compilation unit,
- // we need a place to put the object file so that it can be subsequently
- // handled.
- const zcu_object_sub_path = if (!use_lld and !use_llvm)
- null
- else
- try allocPrint(arena, "{s}.obj", .{emit.sub_path});
-
const coff = try arena.create(Coff);
coff.* = .{
.base = .{
.tag = .coff,
.comp = comp,
.emit = emit,
- .zcu_object_sub_path = zcu_object_sub_path,
+ .zcu_object_basename = if (use_llvm)
+ try std.fmt.allocPrint(arena, "{s}_zcu.obj", .{fs.path.stem(emit.sub_path)})
+ else
+ null,
.stack_size = options.stack_size orelse 16777216,
.gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
.print_gc_sections = options.print_gc_sections,
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
.file = null,
- .disable_lld_caching = options.disable_lld_caching,
.build_id = options.build_id,
},
.ptr_width = ptr_width,
@@ -284,45 +263,23 @@ pub fn createEmpty(
.Obj => 0,
},
- // Subsystem depends on the set of public symbol names from linked objects.
- // See LinkerDriver::inferSubsystem from the LLD project for the flow chart.
- .subsystem = options.subsystem,
-
.entry = options.entry,
- .tsaware = options.tsaware,
- .nxcompat = options.nxcompat,
- .dynamicbase = options.dynamicbase,
.major_subsystem_version = options.major_subsystem_version orelse 6,
.minor_subsystem_version = options.minor_subsystem_version orelse 0,
- .lib_directories = options.lib_directories,
.entry_addr = math.cast(u32, options.entry_addr orelse 0) orelse
return error.EntryAddressTooBig,
.module_definition_file = options.module_definition_file,
- .pdb_out_path = options.pdb_out_path,
.repro = options.repro,
};
- if (use_llvm and comp.config.have_zcu) {
- coff.llvm_object = try LlvmObject.create(arena, comp);
- }
errdefer coff.base.destroy();
- if (use_lld and (use_llvm or !comp.config.have_zcu)) {
- // LLVM emits the object file (if any); LLD links it into the final product.
- return coff;
- }
-
- // What path should this COFF linker code output to?
- // If using LLD to link, this code should produce an object file so that it
- // can be passed to LLD.
- const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path;
- coff.base.file = try emit.root_dir.handle.createFile(sub_path, .{
+ coff.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
.truncate = true,
.read = true,
- .mode = link.File.determineMode(use_lld, output_mode, link_mode),
+ .mode = link.File.determineMode(output_mode, link_mode),
});
- assert(coff.llvm_object == null);
const gpa = comp.gpa;
try coff.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32));
@@ -428,8 +385,6 @@ pub fn open(
pub fn deinit(coff: *Coff) void {
const gpa = coff.base.comp.gpa;
- if (coff.llvm_object) |llvm_object| llvm_object.deinit();
-
for (coff.sections.items(.free_list)) |*free_list| {
free_list.deinit(gpa);
}
@@ -1097,15 +1052,11 @@ pub fn updateFunc(
coff: *Coff,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ mir: *const codegen.AnyMir,
) link.File.UpdateNavError!void {
if (build_options.skip_non_native and builtin.object_format != .coff) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (coff.llvm_object) |llvm_object| {
- return llvm_object.updateFunc(pt, func_index, air, liveness);
- }
const tracy = trace(@src());
defer tracy.end();
@@ -1122,29 +1073,15 @@ pub fn updateFunc(
var code_buffer: std.ArrayListUnmanaged(u8) = .empty;
defer code_buffer.deinit(gpa);
- codegen.generateFunction(
+ try codegen.emitFunction(
&coff.base,
pt,
zcu.navSrcLoc(nav_index),
func_index,
- air,
- liveness,
+ mir,
&code_buffer,
.none,
- ) catch |err| switch (err) {
- error.CodegenFail => return error.CodegenFail,
- error.OutOfMemory => return error.OutOfMemory,
- error.Overflow, error.RelocationNotByteAligned => |e| {
- try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
- gpa,
- zcu.navSrcLoc(nav_index),
- "unable to codegen: {s}",
- .{@errorName(e)},
- ));
- try zcu.retryable_failures.append(zcu.gpa, AnalUnit.wrap(.{ .func = func_index }));
- return error.CodegenFail;
- },
- };
+ );
try coff.updateNavCode(pt, nav_index, code_buffer.items, .FUNCTION);
@@ -1205,7 +1142,6 @@ pub fn updateNav(
if (build_options.skip_non_native and builtin.object_format != .coff) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (coff.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav_index);
const tracy = trace(@src());
defer tracy.end();
@@ -1330,7 +1266,7 @@ pub fn getOrCreateAtomForLazySymbol(
}
state_ptr.* = .pending_flush;
const atom = atom_ptr.*;
- // anyerror needs to be deferred until flushModule
+ // anyerror needs to be deferred until flush
if (lazy_sym.ty != .anyerror_type) try coff.updateLazySymbolAtom(pt, lazy_sym, atom, switch (lazy_sym.kind) {
.code => coff.text_section_index.?,
.const_data => coff.rdata_section_index.?,
@@ -1463,8 +1399,6 @@ fn updateNavCode(
}
pub fn freeNav(coff: *Coff, nav_index: InternPool.NavIndex) void {
- if (coff.llvm_object) |llvm_object| return llvm_object.freeNav(nav_index);
-
const gpa = coff.base.comp.gpa;
if (coff.decls.fetchOrderedRemove(nav_index)) |const_kv| {
@@ -1485,50 +1419,7 @@ pub fn updateExports(
}
const zcu = pt.zcu;
- const ip = &zcu.intern_pool;
- const comp = coff.base.comp;
- const target = comp.root_mod.resolved_target.result;
-
- if (comp.config.use_llvm) {
- // Even in the case of LLVM, we need to notice certain exported symbols in order to
- // detect the default subsystem.
- for (export_indices) |export_idx| {
- const exp = export_idx.ptr(zcu);
- const exported_nav_index = switch (exp.exported) {
- .nav => |nav| nav,
- .uav => continue,
- };
- const exported_nav = ip.getNav(exported_nav_index);
- const exported_ty = exported_nav.typeOf(ip);
- if (!ip.isFunctionType(exported_ty)) continue;
- const c_cc = target.cCallingConvention().?;
- const winapi_cc: std.builtin.CallingConvention = switch (target.cpu.arch) {
- .x86 => .{ .x86_stdcall = .{} },
- else => c_cc,
- };
- const exported_cc = Type.fromInterned(exported_ty).fnCallingConvention(zcu);
- const CcTag = std.builtin.CallingConvention.Tag;
- if (@as(CcTag, exported_cc) == @as(CcTag, c_cc) and exp.opts.name.eqlSlice("main", ip) and comp.config.link_libc) {
- zcu.stage1_flags.have_c_main = true;
- } else if (@as(CcTag, exported_cc) == @as(CcTag, winapi_cc) and target.os.tag == .windows) {
- if (exp.opts.name.eqlSlice("WinMain", ip)) {
- zcu.stage1_flags.have_winmain = true;
- } else if (exp.opts.name.eqlSlice("wWinMain", ip)) {
- zcu.stage1_flags.have_wwinmain = true;
- } else if (exp.opts.name.eqlSlice("WinMainCRTStartup", ip)) {
- zcu.stage1_flags.have_winmain_crt_startup = true;
- } else if (exp.opts.name.eqlSlice("wWinMainCRTStartup", ip)) {
- zcu.stage1_flags.have_wwinmain_crt_startup = true;
- } else if (exp.opts.name.eqlSlice("DllMainCRTStartup", ip)) {
- zcu.stage1_flags.have_dllmain_crt_startup = true;
- }
- }
- }
- }
-
- if (coff.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
-
- const gpa = comp.gpa;
+ const gpa = zcu.gpa;
const metadata = switch (exported) {
.nav => |nav| blk: {
@@ -1621,7 +1512,6 @@ pub fn deleteExport(
exported: Zcu.Exported,
name: InternPool.NullTerminatedString,
) void {
- if (coff.llvm_object) |_| return;
const metadata = switch (exported) {
.nav => |nav| coff.navs.getPtr(nav),
.uav => |uav| coff.uavs.getPtr(uav),
@@ -1680,571 +1570,7 @@ fn resolveGlobalSymbol(coff: *Coff, current: SymbolWithLoc) !void {
gop.value_ptr.* = current;
}
-pub fn flush(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- const comp = coff.base.comp;
- const use_lld = build_options.have_llvm and comp.config.use_lld;
- const diags = &comp.link_diags;
- if (use_lld) {
- return coff.linkWithLLD(arena, tid, prog_node) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.LinkFailure => return error.LinkFailure,
- else => |e| return diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),
- };
- }
- switch (comp.config.output_mode) {
- .Exe, .Obj => return coff.flushModule(arena, tid, prog_node),
- .Lib => return diags.fail("writing lib files not yet implemented for COFF", .{}),
- }
-}
-
-fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
- dev.check(.lld_linker);
-
- const tracy = trace(@src());
- defer tracy.end();
-
- const comp = coff.base.comp;
- const gpa = comp.gpa;
-
- const directory = coff.base.emit.root_dir; // Just an alias to make it shorter to type.
- const full_out_path = try directory.join(arena, &[_][]const u8{coff.base.emit.sub_path});
-
- // If there is no Zig code to compile, then we should skip flushing the output file because it
- // will not be part of the linker line anyway.
- const module_obj_path: ?[]const u8 = if (comp.zcu != null) blk: {
- try coff.flushModule(arena, tid, prog_node);
-
- if (fs.path.dirname(full_out_path)) |dirname| {
- break :blk try fs.path.join(arena, &.{ dirname, coff.base.zcu_object_sub_path.? });
- } else {
- break :blk coff.base.zcu_object_sub_path.?;
- }
- } else null;
-
- const sub_prog_node = prog_node.start("LLD Link", 0);
- defer sub_prog_node.end();
-
- const is_lib = comp.config.output_mode == .Lib;
- const is_dyn_lib = comp.config.link_mode == .dynamic and is_lib;
- const is_exe_or_dyn_lib = is_dyn_lib or comp.config.output_mode == .Exe;
- const link_in_crt = comp.config.link_libc and is_exe_or_dyn_lib;
- const target = comp.root_mod.resolved_target.result;
- const optimize_mode = comp.root_mod.optimize_mode;
- const entry_name: ?[]const u8 = switch (coff.entry) {
- // This logic isn't quite right for disabled or enabled. No point in fixing it
- // when the goal is to eliminate dependency on LLD anyway.
- // https://github.com/ziglang/zig/issues/17751
- .disabled, .default, .enabled => null,
- .named => |name| name,
- };
-
- // See link/Elf.zig for comments on how this mechanism works.
- const id_symlink_basename = "lld.id";
-
- var man: Cache.Manifest = undefined;
- defer if (!coff.base.disable_lld_caching) man.deinit();
-
- var digest: [Cache.hex_digest_len]u8 = undefined;
-
- if (!coff.base.disable_lld_caching) {
- man = comp.cache_parent.obtain();
- coff.base.releaseLock();
-
- comptime assert(Compilation.link_hash_implementation_version == 14);
-
- try link.hashInputs(&man, comp.link_inputs);
- for (comp.c_object_table.keys()) |key| {
- _ = try man.addFilePath(key.status.success.object_path, null);
- }
- for (comp.win32_resource_table.keys()) |key| {
- _ = try man.addFile(key.status.success.res_path, null);
- }
- try man.addOptionalFile(module_obj_path);
- man.hash.addOptionalBytes(entry_name);
- man.hash.add(coff.base.stack_size);
- man.hash.add(coff.image_base);
- man.hash.add(coff.base.build_id);
- {
- // TODO remove this, libraries must instead be resolved by the frontend.
- for (coff.lib_directories) |lib_directory| man.hash.addOptionalBytes(lib_directory.path);
- }
- man.hash.add(comp.skip_linker_dependencies);
- if (comp.config.link_libc) {
- man.hash.add(comp.libc_installation != null);
- if (comp.libc_installation) |libc_installation| {
- man.hash.addBytes(libc_installation.crt_dir.?);
- if (target.abi == .msvc or target.abi == .itanium) {
- man.hash.addBytes(libc_installation.msvc_lib_dir.?);
- man.hash.addBytes(libc_installation.kernel32_lib_dir.?);
- }
- }
- }
- man.hash.addListOfBytes(comp.windows_libs.keys());
- man.hash.addListOfBytes(comp.force_undefined_symbols.keys());
- man.hash.addOptional(coff.subsystem);
- man.hash.add(comp.config.is_test);
- man.hash.add(coff.tsaware);
- man.hash.add(coff.nxcompat);
- man.hash.add(coff.dynamicbase);
- man.hash.add(coff.base.allow_shlib_undefined);
- // strip does not need to go into the linker hash because it is part of the hash namespace
- man.hash.add(coff.major_subsystem_version);
- man.hash.add(coff.minor_subsystem_version);
- man.hash.add(coff.repro);
- man.hash.addOptional(comp.version);
- try man.addOptionalFile(coff.module_definition_file);
-
- // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
- _ = try man.hit();
- digest = man.final();
- var prev_digest_buf: [digest.len]u8 = undefined;
- const prev_digest: []u8 = Cache.readSmallFile(
- directory.handle,
- id_symlink_basename,
- &prev_digest_buf,
- ) catch |err| blk: {
- log.debug("COFF LLD new_digest={s} error: {s}", .{ std.fmt.fmtSliceHexLower(&digest), @errorName(err) });
- // Handle this as a cache miss.
- break :blk prev_digest_buf[0..0];
- };
- if (mem.eql(u8, prev_digest, &digest)) {
- log.debug("COFF LLD digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});
- // Hot diggity dog! The output binary is already there.
- coff.base.lock = man.toOwnedLock();
- return;
- }
- log.debug("COFF LLD prev_digest={s} new_digest={s}", .{ std.fmt.fmtSliceHexLower(prev_digest), std.fmt.fmtSliceHexLower(&digest) });
-
- // We are about to change the output file to be different, so we invalidate the build hash now.
- directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
- error.FileNotFound => {},
- else => |e| return e,
- };
- }
-
- if (comp.config.output_mode == .Obj) {
- // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy
- // here. TODO: think carefully about how we can avoid this redundant operation when doing
- // build-obj. See also the corresponding TODO in linkAsArchive.
- const the_object_path = blk: {
- if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
-
- if (comp.c_object_table.count() != 0)
- break :blk comp.c_object_table.keys()[0].status.success.object_path;
-
- if (module_obj_path) |p|
- break :blk Path.initCwd(p);
-
- // TODO I think this is unreachable. Audit this situation when solving the above TODO
- // regarding eliding redundant object -> object transformations.
- return error.NoObjectsToLink;
- };
- try std.fs.Dir.copyFile(
- the_object_path.root_dir.handle,
- the_object_path.sub_path,
- directory.handle,
- coff.base.emit.sub_path,
- .{},
- );
- } else {
- // Create an LLD command line and invoke it.
- var argv = std.ArrayList([]const u8).init(gpa);
- defer argv.deinit();
- // We will invoke ourselves as a child process to gain access to LLD.
- // This is necessary because LLD does not behave properly as a library -
- // it calls exit() and does not reset all global data between invocations.
- const linker_command = "lld-link";
- try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
-
- if (target.isMinGW()) {
- try argv.append("-lldmingw");
- }
-
- try argv.append("-ERRORLIMIT:0");
- try argv.append("-NOLOGO");
- if (comp.config.debug_format != .strip) {
- try argv.append("-DEBUG");
-
- const out_ext = std.fs.path.extension(full_out_path);
- const out_pdb = coff.pdb_out_path orelse try allocPrint(arena, "{s}.pdb", .{
- full_out_path[0 .. full_out_path.len - out_ext.len],
- });
- const out_pdb_basename = std.fs.path.basename(out_pdb);
-
- try argv.append(try allocPrint(arena, "-PDB:{s}", .{out_pdb}));
- try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb_basename}));
- }
- if (comp.version) |version| {
- try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));
- }
-
- if (target_util.llvmMachineAbi(target)) |mabi| {
- try argv.append(try allocPrint(arena, "-MLLVM:-target-abi={s}", .{mabi}));
- }
-
- try argv.append(try allocPrint(arena, "-MLLVM:-float-abi={s}", .{if (target.abi.float() == .hard) "hard" else "soft"}));
-
- if (comp.config.lto != .none) {
- switch (optimize_mode) {
- .Debug => {},
- .ReleaseSmall => try argv.append("-OPT:lldlto=2"),
- .ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"),
- }
- }
- if (comp.config.output_mode == .Exe) {
- try argv.append(try allocPrint(arena, "-STACK:{d}", .{coff.base.stack_size}));
- }
- try argv.append(try allocPrint(arena, "-BASE:{d}", .{coff.image_base}));
-
- switch (coff.base.build_id) {
- .none => try argv.append("-BUILD-ID:NO"),
- .fast => try argv.append("-BUILD-ID"),
- .uuid, .sha1, .md5, .hexstring => {},
- }
-
- if (target.cpu.arch == .x86) {
- try argv.append("-MACHINE:X86");
- } else if (target.cpu.arch == .x86_64) {
- try argv.append("-MACHINE:X64");
- } else if (target.cpu.arch == .thumb) {
- try argv.append("-MACHINE:ARM");
- } else if (target.cpu.arch == .aarch64) {
- try argv.append("-MACHINE:ARM64");
- }
-
- for (comp.force_undefined_symbols.keys()) |symbol| {
- try argv.append(try allocPrint(arena, "-INCLUDE:{s}", .{symbol}));
- }
-
- if (is_dyn_lib) {
- try argv.append("-DLL");
- }
-
- if (entry_name) |name| {
- try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{name}));
- }
-
- if (coff.repro) {
- try argv.append("-BREPRO");
- }
-
- if (coff.tsaware) {
- try argv.append("-tsaware");
- }
- if (coff.nxcompat) {
- try argv.append("-nxcompat");
- }
- if (!coff.dynamicbase) {
- try argv.append("-dynamicbase:NO");
- }
- if (coff.base.allow_shlib_undefined) {
- try argv.append("-FORCE:UNRESOLVED");
- }
-
- try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
-
- if (comp.implib_emit) |emit| {
- const implib_out_path = try emit.root_dir.join(arena, &[_][]const u8{emit.sub_path});
- try argv.append(try allocPrint(arena, "-IMPLIB:{s}", .{implib_out_path}));
- }
-
- if (comp.config.link_libc) {
- if (comp.libc_installation) |libc_installation| {
- try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));
-
- if (target.abi == .msvc or target.abi == .itanium) {
- try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.msvc_lib_dir.?}));
- try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.kernel32_lib_dir.?}));
- }
- }
- }
-
- for (coff.lib_directories) |lib_directory| {
- try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_directory.path orelse "."}));
- }
-
- try argv.ensureUnusedCapacity(comp.link_inputs.len);
- for (comp.link_inputs) |link_input| switch (link_input) {
- .dso_exact => unreachable, // not applicable to PE/COFF
- inline .dso, .res => |x| {
- argv.appendAssumeCapacity(try x.path.toString(arena));
- },
- .object, .archive => |obj| {
- if (obj.must_link) {
- argv.appendAssumeCapacity(try allocPrint(arena, "-WHOLEARCHIVE:{}", .{@as(Path, obj.path)}));
- } else {
- argv.appendAssumeCapacity(try obj.path.toString(arena));
- }
- },
- };
-
- for (comp.c_object_table.keys()) |key| {
- try argv.append(try key.status.success.object_path.toString(arena));
- }
-
- for (comp.win32_resource_table.keys()) |key| {
- try argv.append(key.status.success.res_path);
- }
-
- if (module_obj_path) |p| {
- try argv.append(p);
- }
-
- if (coff.module_definition_file) |def| {
- try argv.append(try allocPrint(arena, "-DEF:{s}", .{def}));
- }
-
- const resolved_subsystem: ?std.Target.SubSystem = blk: {
- if (coff.subsystem) |explicit| break :blk explicit;
- switch (target.os.tag) {
- .windows => {
- if (comp.zcu) |module| {
- if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib)
- break :blk null;
- if (module.stage1_flags.have_c_main or comp.config.is_test or
- module.stage1_flags.have_winmain_crt_startup or
- module.stage1_flags.have_wwinmain_crt_startup)
- {
- break :blk .Console;
- }
- if (module.stage1_flags.have_winmain or module.stage1_flags.have_wwinmain)
- break :blk .Windows;
- }
- },
- .uefi => break :blk .EfiApplication,
- else => {},
- }
- break :blk null;
- };
-
- const Mode = enum { uefi, win32 };
- const mode: Mode = mode: {
- if (resolved_subsystem) |subsystem| {
- const subsystem_suffix = try allocPrint(arena, ",{d}.{d}", .{
- coff.major_subsystem_version, coff.minor_subsystem_version,
- });
-
- switch (subsystem) {
- .Console => {
- try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{
- subsystem_suffix,
- }));
- break :mode .win32;
- },
- .EfiApplication => {
- try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{
- subsystem_suffix,
- }));
- break :mode .uefi;
- },
- .EfiBootServiceDriver => {
- try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{
- subsystem_suffix,
- }));
- break :mode .uefi;
- },
- .EfiRom => {
- try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{
- subsystem_suffix,
- }));
- break :mode .uefi;
- },
- .EfiRuntimeDriver => {
- try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{
- subsystem_suffix,
- }));
- break :mode .uefi;
- },
- .Native => {
- try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{
- subsystem_suffix,
- }));
- break :mode .win32;
- },
- .Posix => {
- try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{
- subsystem_suffix,
- }));
- break :mode .win32;
- },
- .Windows => {
- try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{
- subsystem_suffix,
- }));
- break :mode .win32;
- },
- }
- } else if (target.os.tag == .uefi) {
- break :mode .uefi;
- } else {
- break :mode .win32;
- }
- };
-
- switch (mode) {
- .uefi => try argv.appendSlice(&[_][]const u8{
- "-BASE:0",
- "-ENTRY:EfiMain",
- "-OPT:REF",
- "-SAFESEH:NO",
- "-MERGE:.rdata=.data",
- "-NODEFAULTLIB",
- "-SECTION:.xdata,D",
- }),
- .win32 => {
- if (link_in_crt) {
- if (target.abi.isGnu()) {
- if (target.cpu.arch == .x86) {
- try argv.append("-ALTERNATENAME:__image_base__=___ImageBase");
- } else {
- try argv.append("-ALTERNATENAME:__image_base__=__ImageBase");
- }
-
- if (is_dyn_lib) {
- try argv.append(try comp.crtFileAsString(arena, "dllcrt2.obj"));
- if (target.cpu.arch == .x86) {
- try argv.append("-ALTERNATENAME:__DllMainCRTStartup@12=_DllMainCRTStartup@12");
- } else {
- try argv.append("-ALTERNATENAME:_DllMainCRTStartup=DllMainCRTStartup");
- }
- } else {
- try argv.append(try comp.crtFileAsString(arena, "crt2.obj"));
- }
-
- try argv.append(try comp.crtFileAsString(arena, "libmingw32.lib"));
- } else {
- try argv.append(switch (comp.config.link_mode) {
- .static => "libcmt.lib",
- .dynamic => "msvcrt.lib",
- });
-
- const lib_str = switch (comp.config.link_mode) {
- .static => "lib",
- .dynamic => "",
- };
- try argv.append(try allocPrint(arena, "{s}vcruntime.lib", .{lib_str}));
- try argv.append(try allocPrint(arena, "{s}ucrt.lib", .{lib_str}));
-
- //Visual C++ 2015 Conformance Changes
- //https://msdn.microsoft.com/en-us/library/bb531344.aspx
- try argv.append("legacy_stdio_definitions.lib");
-
- // msvcrt depends on kernel32 and ntdll
- try argv.append("kernel32.lib");
- try argv.append("ntdll.lib");
- }
- } else {
- try argv.append("-NODEFAULTLIB");
- if (!is_lib and entry_name == null) {
- if (comp.zcu) |module| {
- if (module.stage1_flags.have_winmain_crt_startup) {
- try argv.append("-ENTRY:WinMainCRTStartup");
- } else {
- try argv.append("-ENTRY:wWinMainCRTStartup");
- }
- } else {
- try argv.append("-ENTRY:wWinMainCRTStartup");
- }
- }
- }
- },
- }
-
- if (comp.config.link_libc and link_in_crt) {
- if (comp.zigc_static_lib) |zigc| {
- try argv.append(try zigc.full_object_path.toString(arena));
- }
- }
-
- // libc++ dep
- if (comp.config.link_libcpp) {
- try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena));
- try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena));
- }
-
- // libunwind dep
- if (comp.config.link_libunwind) {
- try argv.append(try comp.libunwind_static_lib.?.full_object_path.toString(arena));
- }
-
- if (comp.config.any_fuzz) {
- try argv.append(try comp.fuzzer_lib.?.full_object_path.toString(arena));
- }
-
- const ubsan_rt_path: ?Path = blk: {
- if (comp.ubsan_rt_lib) |x| break :blk x.full_object_path;
- if (comp.ubsan_rt_obj) |x| break :blk x.full_object_path;
- break :blk null;
- };
- if (ubsan_rt_path) |path| {
- try argv.append(try path.toString(arena));
- }
-
- if (is_exe_or_dyn_lib and !comp.skip_linker_dependencies) {
- // MSVC compiler_rt is missing some stuff, so we build it unconditionally but
- // and rely on weak linkage to allow MSVC compiler_rt functions to override ours.
- if (comp.compiler_rt_obj) |obj| try argv.append(try obj.full_object_path.toString(arena));
- if (comp.compiler_rt_lib) |lib| try argv.append(try lib.full_object_path.toString(arena));
- }
-
- try argv.ensureUnusedCapacity(comp.windows_libs.count());
- for (comp.windows_libs.keys()) |key| {
- const lib_basename = try allocPrint(arena, "{s}.lib", .{key});
- if (comp.crt_files.get(lib_basename)) |crt_file| {
- argv.appendAssumeCapacity(try crt_file.full_object_path.toString(arena));
- continue;
- }
- if (try findLib(arena, lib_basename, coff.lib_directories)) |full_path| {
- argv.appendAssumeCapacity(full_path);
- continue;
- }
- if (target.abi.isGnu()) {
- const fallback_name = try allocPrint(arena, "lib{s}.dll.a", .{key});
- if (try findLib(arena, fallback_name, coff.lib_directories)) |full_path| {
- argv.appendAssumeCapacity(full_path);
- continue;
- }
- }
- if (target.abi == .msvc or target.abi == .itanium) {
- argv.appendAssumeCapacity(lib_basename);
- continue;
- }
-
- log.err("DLL import library for -l{s} not found", .{key});
- return error.DllImportLibraryNotFound;
- }
-
- try link.spawnLld(comp, arena, argv.items);
- }
-
- if (!coff.base.disable_lld_caching) {
- // Update the file with the digest. If it fails we can continue; it only
- // means that the next invocation will have an unnecessary cache miss.
- Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
- log.warn("failed to save linking hash digest file: {s}", .{@errorName(err)});
- };
- // Again failure here only means an unnecessary cache miss.
- man.writeManifest() catch |err| {
- log.warn("failed to write cache manifest when linking: {s}", .{@errorName(err)});
- };
- // We hang on to this lock so that the output file path can be used without
- // other processes clobbering it.
- coff.base.lock = man.toOwnedLock();
- }
-}
-
-fn findLib(arena: Allocator, name: []const u8, lib_directories: []const Directory) !?[]const u8 {
- for (lib_directories) |lib_directory| {
- lib_directory.handle.access(name, .{}) catch |err| switch (err) {
- error.FileNotFound => continue,
- else => |e| return e,
- };
- return try lib_directory.join(arena, &.{name});
- }
- return null;
-}
-
-pub fn flushModule(
+pub fn flush(
coff: *Coff,
arena: Allocator,
tid: Zcu.PerThread.Id,
@@ -2256,22 +1582,22 @@ pub fn flushModule(
const comp = coff.base.comp;
const diags = &comp.link_diags;
- if (coff.llvm_object) |llvm_object| {
- try coff.base.emitLlvmObject(arena, llvm_object, prog_node);
- return;
+ switch (coff.base.comp.config.output_mode) {
+ .Exe, .Obj => {},
+ .Lib => return diags.fail("writing lib files not yet implemented for COFF", .{}),
}
const sub_prog_node = prog_node.start("COFF Flush", 0);
defer sub_prog_node.end();
- return flushModuleInner(coff, arena, tid) catch |err| switch (err) {
+ return flushInner(coff, arena, tid) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
error.LinkFailure => return error.LinkFailure,
else => |e| return diags.fail("COFF flush failed: {s}", .{@errorName(e)}),
};
}
-fn flushModuleInner(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id) !void {
+fn flushInner(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id) !void {
_ = arena;
const comp = coff.base.comp;
@@ -2397,7 +1723,6 @@ pub fn getNavVAddr(
nav_index: InternPool.Nav.Index,
reloc_info: link.File.RelocInfo,
) !u64 {
- assert(coff.llvm_object == null);
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
@@ -2442,7 +1767,7 @@ pub fn lowerUav(
const atom = coff.getAtom(metadata.atom);
const existing_addr = atom.getSymbol(coff).value;
if (uav_alignment.check(existing_addr))
- return .{ .mcv = .{ .load_direct = atom.getSymbolIndex().? } };
+ return .{ .mcv = .{ .load_symbol = atom.getSymbolIndex().? } };
}
var name_buf: [32]u8 = undefined;
@@ -2474,7 +1799,7 @@ pub fn lowerUav(
.section = coff.rdata_section_index.?,
});
return .{ .mcv = .{
- .load_direct = coff.getAtom(atom_index).getSymbolIndex().?,
+ .load_symbol = coff.getAtom(atom_index).getSymbolIndex().?,
} };
}
@@ -2483,8 +1808,6 @@ pub fn getUavVAddr(
uav: InternPool.Index,
reloc_info: link.File.RelocInfo,
) !u64 {
- assert(coff.llvm_object == null);
-
const this_atom_index = coff.uavs.get(uav).?.atom;
const sym_index = coff.getAtom(this_atom_index).getSymbolIndex().?;
const atom_index = coff.getAtomIndexForSymbol(.{
@@ -3796,9 +3119,7 @@ const link = @import("../link.zig");
const target_util = @import("../target.zig");
const trace = @import("../tracy.zig").trace;
-const Air = @import("../Air.zig");
const Compilation = @import("../Compilation.zig");
-const LlvmObject = @import("../codegen/llvm.zig").Object;
const Zcu = @import("../Zcu.zig");
const InternPool = @import("../InternPool.zig");
const TableSection = @import("table_section.zig").TableSection;
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig
index e2b8229736..0afe10ef03 100644
--- a/src/link/Dwarf.zig
+++ b/src/link/Dwarf.zig
@@ -1474,24 +1474,59 @@ pub const WipNav = struct {
try cfa.write(wip_nav);
}
- pub const LocalTag = enum { local_arg, local_var };
- pub fn genLocalDebugInfo(
+ pub const LocalVarTag = enum { arg, local_var };
+ pub fn genLocalVarDebugInfo(
wip_nav: *WipNav,
- tag: LocalTag,
- name: []const u8,
+ tag: LocalVarTag,
+ opt_name: ?[]const u8,
ty: Type,
loc: Loc,
) UpdateError!void {
assert(wip_nav.func != .none);
try wip_nav.abbrevCode(switch (tag) {
- inline else => |ct_tag| @field(AbbrevCode, @tagName(ct_tag)),
+ .arg => if (opt_name) |_| .arg else .unnamed_arg,
+ .local_var => if (opt_name) |_| .local_var else unreachable,
});
- try wip_nav.strp(name);
+ if (opt_name) |name| try wip_nav.strp(name);
try wip_nav.refType(ty);
try wip_nav.infoExprLoc(loc);
wip_nav.any_children = true;
}
+ pub const LocalConstTag = enum { comptime_arg, local_const };
+ pub fn genLocalConstDebugInfo(
+ wip_nav: *WipNav,
+ src_loc: Zcu.LazySrcLoc,
+ tag: LocalConstTag,
+ opt_name: ?[]const u8,
+ val: Value,
+ ) UpdateError!void {
+ assert(wip_nav.func != .none);
+ const pt = wip_nav.pt;
+ const zcu = pt.zcu;
+ const ty = val.typeOf(zcu);
+ const has_runtime_bits = ty.hasRuntimeBits(zcu);
+ const has_comptime_state = ty.comptimeOnly(zcu) and try ty.onePossibleValue(pt) == null;
+ try wip_nav.abbrevCode(if (has_runtime_bits and has_comptime_state) switch (tag) {
+ .comptime_arg => if (opt_name) |_| .comptime_arg_runtime_bits_comptime_state else .unnamed_comptime_arg_runtime_bits_comptime_state,
+ .local_const => if (opt_name) |_| .local_const_runtime_bits_comptime_state else unreachable,
+ } else if (has_comptime_state) switch (tag) {
+ .comptime_arg => if (opt_name) |_| .comptime_arg_comptime_state else .unnamed_comptime_arg_comptime_state,
+ .local_const => if (opt_name) |_| .local_const_comptime_state else unreachable,
+ } else if (has_runtime_bits) switch (tag) {
+ .comptime_arg => if (opt_name) |_| .comptime_arg_runtime_bits else .unnamed_comptime_arg_runtime_bits,
+ .local_const => if (opt_name) |_| .local_const_runtime_bits else unreachable,
+ } else switch (tag) {
+ .comptime_arg => if (opt_name) |_| .comptime_arg else .unnamed_comptime_arg,
+ .local_const => if (opt_name) |_| .local_const else unreachable,
+ });
+ if (opt_name) |name| try wip_nav.strp(name);
+ try wip_nav.refType(ty);
+ if (has_runtime_bits) try wip_nav.blockValue(src_loc, val);
+ if (has_comptime_state) try wip_nav.refValue(val);
+ wip_nav.any_children = true;
+ }
+
pub fn genVarArgsDebugInfo(wip_nav: *WipNav) UpdateError!void {
assert(wip_nav.func != .none);
try wip_nav.abbrevCode(.is_var_args);
@@ -1825,7 +1860,8 @@ pub const WipNav = struct {
fn getNavEntry(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!struct { Unit.Index, Entry.Index } {
const zcu = wip_nav.pt.zcu;
const ip = &zcu.intern_pool;
- const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav_index).srcInst(ip).resolveFile(ip)).mod.?);
+ const nav = ip.getNav(nav_index);
+ const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?);
const gop = try wip_nav.dwarf.navs.getOrPut(wip_nav.dwarf.gpa, nav_index);
if (gop.found_existing) return .{ unit, gop.value_ptr.* };
const entry = try wip_nav.dwarf.addCommonEntry(unit);
@@ -1842,10 +1878,16 @@ pub const WipNav = struct {
const zcu = wip_nav.pt.zcu;
const ip = &zcu.intern_pool;
const maybe_inst_index = ty.typeDeclInst(zcu);
- const unit = if (maybe_inst_index) |inst_index|
- try wip_nav.dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?)
- else
- .main;
+ const unit = if (maybe_inst_index) |inst_index| switch (switch (ip.indexToKey(ty.toIntern())) {
+ else => unreachable,
+ .struct_type => ip.loadStructType(ty.toIntern()).name_nav,
+ .union_type => ip.loadUnionType(ty.toIntern()).name_nav,
+ .enum_type => ip.loadEnumType(ty.toIntern()).name_nav,
+ .opaque_type => ip.loadOpaqueType(ty.toIntern()).name_nav,
+ }) {
+ .none => try wip_nav.dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?),
+ else => |name_nav| return wip_nav.getNavEntry(name_nav.unwrap().?),
+ } else .main;
const gop = try wip_nav.dwarf.types.getOrPut(wip_nav.dwarf.gpa, ty.toIntern());
if (gop.found_existing) return .{ unit, gop.value_ptr.* };
const entry = try wip_nav.dwarf.addCommonEntry(unit);
@@ -1864,10 +1906,8 @@ pub const WipNav = struct {
const ip = &zcu.intern_pool;
const ty = value.typeOf(zcu);
if (std.debug.runtime_safety) assert(ty.comptimeOnly(zcu) and try ty.onePossibleValue(wip_nav.pt) == null);
- if (!value.isUndef(zcu)) {
- if (ty.toIntern() == .type_type) return wip_nav.getTypeEntry(value.toType());
- if (ip.isFunctionType(ty.toIntern())) return wip_nav.getNavEntry(zcu.funcInfo(value.toIntern()).owner_nav);
- }
+ if (ty.toIntern() == .type_type) return wip_nav.getTypeEntry(value.toType());
+ if (ip.isFunctionType(ty.toIntern()) and !value.isUndef(zcu)) return wip_nav.getNavEntry(zcu.funcInfo(value.toIntern()).owner_nav);
const gop = try wip_nav.dwarf.values.getOrPut(wip_nav.dwarf.gpa, value.toIntern());
const unit: Unit.Index = .main;
if (gop.found_existing) return .{ unit, gop.value_ptr.* };
@@ -1916,7 +1956,10 @@ pub const WipNav = struct {
&wip_nav.debug_info,
.{ .debug_output = .{ .dwarf = wip_nav } },
);
- assert(old_len + bytes == wip_nav.debug_info.items.len);
+ if (old_len + bytes != wip_nav.debug_info.items.len) {
+ std.debug.print("{} [{}]: {} != {}\n", .{ ty.fmt(wip_nav.pt), ty.toIntern(), bytes, wip_nav.debug_info.items.len - old_len });
+ unreachable;
+ }
}
const AbbrevCodeForForm = struct {
@@ -2788,6 +2831,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
if (type_gop.found_existing) {
if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;
+ assert(!nav_gop.found_existing);
nav_gop.value_ptr.* = type_gop.value_ptr.*;
} else {
if (nav_gop.found_existing)
@@ -2890,6 +2934,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
if (type_gop.found_existing) {
if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;
+ assert(!nav_gop.found_existing);
nav_gop.value_ptr.* = type_gop.value_ptr.*;
} else {
if (nav_gop.found_existing)
@@ -2928,6 +2973,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
if (type_gop.found_existing) {
if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;
+ assert(!nav_gop.found_existing);
nav_gop.value_ptr.* = type_gop.value_ptr.*;
} else {
if (nav_gop.found_existing)
@@ -2998,6 +3044,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
if (type_gop.found_existing) {
if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;
+ assert(!nav_gop.found_existing);
nav_gop.value_ptr.* = type_gop.value_ptr.*;
} else {
if (nav_gop.found_existing)
@@ -3164,6 +3211,7 @@ fn updateLazyType(
) UpdateError!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
+ assert(ip.typeOf(type_index) == .type_type);
const ty: Type = .fromInterned(type_index);
switch (type_index) {
.generic_poison_type => log.debug("updateLazyType({s})", .{"anytype"}),
@@ -3200,6 +3248,10 @@ fn updateLazyType(
defer dwarf.gpa.free(name);
switch (ip.indexToKey(type_index)) {
+ .undef => {
+ try wip_nav.abbrevCode(.undefined_comptime_value);
+ try wip_nav.refType(.type);
+ },
.int_type => |int_type| {
try wip_nav.abbrevCode(.numeric_type);
try wip_nav.strp(name);
@@ -3633,7 +3685,6 @@ fn updateLazyType(
},
// values, not types
- .undef,
.simple_value,
.variable,
.@"extern",
@@ -3666,7 +3717,11 @@ fn updateLazyValue(
) UpdateError!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
- log.debug("updateLazyValue({})", .{Value.fromInterned(value_index).fmtValue(pt)});
+ assert(ip.typeOf(value_index) != .type_type);
+ log.debug("updateLazyValue(@as({}, {}))", .{
+ Value.fromInterned(value_index).typeOf(zcu).fmt(pt),
+ Value.fromInterned(value_index).fmtValue(pt),
+ });
var wip_nav: WipNav = .{
.dwarf = dwarf,
.pt = pt,
@@ -3710,9 +3765,8 @@ fn updateLazyValue(
.inferred_error_set_type,
=> unreachable, // already handled
.undef => |ty| {
- try wip_nav.abbrevCode(.aggregate_comptime_value);
+ try wip_nav.abbrevCode(.undefined_comptime_value);
try wip_nav.refType(.fromInterned(ty));
- try uleb128(diw, @intFromEnum(AbbrevCode.null));
},
.simple_value => unreachable, // opv state
.variable, .@"extern" => unreachable, // not a value
@@ -4391,7 +4445,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A
return @intFromEnum(abbrev_code);
}
-pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
+pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
@@ -4890,8 +4944,22 @@ const AbbrevCode = enum {
block,
empty_inlined_func,
inlined_func,
- local_arg,
+ arg,
+ unnamed_arg,
+ comptime_arg,
+ unnamed_comptime_arg,
+ comptime_arg_runtime_bits,
+ unnamed_comptime_arg_runtime_bits,
+ comptime_arg_comptime_state,
+ unnamed_comptime_arg_comptime_state,
+ comptime_arg_runtime_bits_comptime_state,
+ unnamed_comptime_arg_runtime_bits_comptime_state,
local_var,
+ local_const,
+ local_const_runtime_bits,
+ local_const_comptime_state,
+ local_const_runtime_bits_comptime_state,
+ undefined_comptime_value,
data2_comptime_value,
data4_comptime_value,
data8_comptime_value,
@@ -5663,7 +5731,7 @@ const AbbrevCode = enum {
.{ .high_pc, .data4 },
},
},
- .local_arg = .{
+ .arg = .{
.tag = .formal_parameter,
.attrs = &.{
.{ .name, .strp },
@@ -5671,6 +5739,81 @@ const AbbrevCode = enum {
.{ .location, .exprloc },
},
},
+ .unnamed_arg = .{
+ .tag = .formal_parameter,
+ .attrs = &.{
+ .{ .type, .ref_addr },
+ .{ .location, .exprloc },
+ },
+ },
+ .comptime_arg = .{
+ .tag = .formal_parameter,
+ .attrs = &.{
+ .{ .const_expr, .flag_present },
+ .{ .name, .strp },
+ .{ .type, .ref_addr },
+ },
+ },
+ .unnamed_comptime_arg = .{
+ .tag = .formal_parameter,
+ .attrs = &.{
+ .{ .const_expr, .flag_present },
+ .{ .type, .ref_addr },
+ },
+ },
+ .comptime_arg_runtime_bits = .{
+ .tag = .formal_parameter,
+ .attrs = &.{
+ .{ .const_expr, .flag_present },
+ .{ .name, .strp },
+ .{ .type, .ref_addr },
+ .{ .const_value, .block },
+ },
+ },
+ .unnamed_comptime_arg_runtime_bits = .{
+ .tag = .formal_parameter,
+ .attrs = &.{
+ .{ .const_expr, .flag_present },
+ .{ .type, .ref_addr },
+ .{ .const_value, .block },
+ },
+ },
+ .comptime_arg_comptime_state = .{
+ .tag = .formal_parameter,
+ .attrs = &.{
+ .{ .const_expr, .flag_present },
+ .{ .name, .strp },
+ .{ .type, .ref_addr },
+ .{ .ZIG_comptime_value, .ref_addr },
+ },
+ },
+ .unnamed_comptime_arg_comptime_state = .{
+ .tag = .formal_parameter,
+ .attrs = &.{
+ .{ .const_expr, .flag_present },
+ .{ .type, .ref_addr },
+ .{ .ZIG_comptime_value, .ref_addr },
+ },
+ },
+ .comptime_arg_runtime_bits_comptime_state = .{
+ .tag = .formal_parameter,
+ .attrs = &.{
+ .{ .const_expr, .flag_present },
+ .{ .name, .strp },
+ .{ .type, .ref_addr },
+ .{ .const_value, .block },
+ .{ .ZIG_comptime_value, .ref_addr },
+ },
+ },
+ .unnamed_comptime_arg_runtime_bits_comptime_state = .{
+ .tag = .formal_parameter,
+ .attrs = &.{
+ .{ .const_expr, .flag_present },
+ .{ .type, .ref_addr },
+ .{ .const_value, .block },
+ .{ .ZIG_comptime_value, .ref_addr },
+ },
+ },
.local_var = .{
.tag = .variable,
.attrs = &.{
@@ -5679,6 +5822,44 @@ const AbbrevCode = enum {
.{ .location, .exprloc },
},
},
+ .local_const = .{
+ .tag = .constant,
+ .attrs = &.{
+ .{ .name, .strp },
+ .{ .type, .ref_addr },
+ },
+ },
+ .local_const_runtime_bits = .{
+ .tag = .constant,
+ .attrs = &.{
+ .{ .name, .strp },
+ .{ .type, .ref_addr },
+ .{ .const_value, .block },
+ },
+ },
+ .local_const_comptime_state = .{
+ .tag = .constant,
+ .attrs = &.{
+ .{ .name, .strp },
+ .{ .type, .ref_addr },
+ .{ .ZIG_comptime_value, .ref_addr },
+ },
+ },
+ .local_const_runtime_bits_comptime_state = .{
+ .tag = .constant,
+ .attrs = &.{
+ .{ .name, .strp },
+ .{ .type, .ref_addr },
+ .{ .const_value, .block },
+ .{ .ZIG_comptime_value, .ref_addr },
+ },
+ },
+ .undefined_comptime_value = .{
+ .tag = .ZIG_comptime_value,
+ .attrs = &.{
+ .{ .type, .ref_addr },
+ },
+ },
.data2_comptime_value = .{
.tag = .ZIG_comptime_value,
.attrs = &.{
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 1516993c74..0beea0d9e7 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -4,7 +4,6 @@ base: link.File,
zig_object: ?*ZigObject,
rpath_table: std.StringArrayHashMapUnmanaged(void),
image_base: u64,
-emit_relocs: bool,
z_nodelete: bool,
z_notext: bool,
z_defs: bool,
@@ -16,25 +15,11 @@ z_relro: bool,
z_common_page_size: ?u64,
/// TODO make this non optional and resolve the default in open()
z_max_page_size: ?u64,
-hash_style: HashStyle,
-compress_debug_sections: CompressDebugSections,
-symbol_wrap_set: std.StringArrayHashMapUnmanaged(void),
-sort_section: ?SortSection,
soname: ?[]const u8,
-bind_global_refs_locally: bool,
-linker_script: ?[]const u8,
-version_script: ?[]const u8,
-allow_undefined_version: bool,
-enable_new_dtags: ?bool,
-print_icf_sections: bool,
-print_map: bool,
entry_name: ?[]const u8,
ptr_width: PtrWidth,
-/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
-llvm_object: ?LlvmObject.Ptr = null,
-
/// A list of all input files.
/// First index is a special "null file". Order is otherwise not observed.
files: std.MultiArrayList(File.Entry) = .{},
@@ -204,9 +189,6 @@ const minimum_atom_size = 64;
pub const min_text_capacity = padToIdeal(minimum_atom_size);
pub const PtrWidth = enum { p32, p64 };
-pub const HashStyle = enum { sysv, gnu, both };
-pub const CompressDebugSections = enum { none, zlib, zstd };
-pub const SortSection = enum { name, alignment };
pub fn createEmpty(
arena: Allocator,
@@ -217,7 +199,6 @@ pub fn createEmpty(
const target = comp.root_mod.resolved_target.result;
assert(target.ofmt == .elf);
- const use_lld = build_options.have_llvm and comp.config.use_lld;
const use_llvm = comp.config.use_llvm;
const opt_zcu = comp.zcu;
const output_mode = comp.config.output_mode;
@@ -268,16 +249,6 @@ pub fn createEmpty(
const is_dyn_lib = output_mode == .Lib and link_mode == .dynamic;
const default_sym_version: elf.Versym = if (is_dyn_lib or comp.config.rdynamic) .GLOBAL else .LOCAL;
- // If using LLD to link, this code should produce an object file so that it
- // can be passed to LLD.
- // If using LLVM to generate the object file for the zig compilation unit,
- // we need a place to put the object file so that it can be subsequently
- // handled.
- const zcu_object_sub_path = if (!use_lld and !use_llvm)
- null
- else
- try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path});
-
var rpath_table: std.StringArrayHashMapUnmanaged(void) = .empty;
try rpath_table.entries.resize(arena, options.rpath_list.len);
@memcpy(rpath_table.entries.items(.key), options.rpath_list);
@@ -289,13 +260,15 @@ pub fn createEmpty(
.tag = .elf,
.comp = comp,
.emit = emit,
- .zcu_object_sub_path = zcu_object_sub_path,
+ .zcu_object_basename = if (use_llvm)
+ try std.fmt.allocPrint(arena, "{s}_zcu.o", .{fs.path.stem(emit.sub_path)})
+ else
+ null,
.gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
.print_gc_sections = options.print_gc_sections,
.stack_size = options.stack_size orelse 16777216,
.allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os,
.file = null,
- .disable_lld_caching = options.disable_lld_caching,
.build_id = options.build_id,
},
.zig_object = null,
@@ -320,7 +293,6 @@ pub fn createEmpty(
};
},
- .emit_relocs = options.emit_relocs,
.z_nodelete = options.z_nodelete,
.z_notext = options.z_notext,
.z_defs = options.z_defs,
@@ -330,30 +302,11 @@ pub fn createEmpty(
.z_relro = options.z_relro,
.z_common_page_size = options.z_common_page_size,
.z_max_page_size = options.z_max_page_size,
- .hash_style = options.hash_style,
- .compress_debug_sections = options.compress_debug_sections,
- .symbol_wrap_set = options.symbol_wrap_set,
- .sort_section = options.sort_section,
.soname = options.soname,
- .bind_global_refs_locally = options.bind_global_refs_locally,
- .linker_script = options.linker_script,
- .version_script = options.version_script,
- .allow_undefined_version = options.allow_undefined_version,
- .enable_new_dtags = options.enable_new_dtags,
- .print_icf_sections = options.print_icf_sections,
- .print_map = options.print_map,
.dump_argv_list = .empty,
};
- if (use_llvm and comp.config.have_zcu) {
- self.llvm_object = try LlvmObject.create(arena, comp);
- }
errdefer self.base.destroy();
- if (use_lld and (use_llvm or !comp.config.have_zcu)) {
- // LLVM emits the object file (if any); LLD links it into the final product.
- return self;
- }
-
// --verbose-link
if (comp.verbose_link) try dumpArgvInit(self, arena);
@@ -361,13 +314,11 @@ pub fn createEmpty(
const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .static);
// What path should this ELF linker code output to?
- // If using LLD to link, this code should produce an object file so that it
- // can be passed to LLD.
- const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path;
+ const sub_path = emit.sub_path;
self.base.file = try emit.root_dir.handle.createFile(sub_path, .{
.truncate = true,
.read = true,
- .mode = link.File.determineMode(use_lld, output_mode, link_mode),
+ .mode = link.File.determineMode(output_mode, link_mode),
});
const gpa = comp.gpa;
@@ -457,8 +408,6 @@ pub fn open(
pub fn deinit(self: *Elf) void {
const gpa = self.base.comp.gpa;
- if (self.llvm_object) |llvm_object| llvm_object.deinit();
-
for (self.file_handles.items) |fh| {
fh.close();
}
@@ -515,7 +464,6 @@ pub fn deinit(self: *Elf) void {
}
pub fn getNavVAddr(self: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
- assert(self.llvm_object == null);
return self.zigObjectPtr().?.getNavVAddr(self, pt, nav_index, reloc_info);
}
@@ -530,7 +478,6 @@ pub fn lowerUav(
}
pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
- assert(self.llvm_object == null);
return self.zigObjectPtr().?.getUavVAddr(self, uav, reloc_info);
}
@@ -795,60 +742,36 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
}
pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- const comp = self.base.comp;
- const use_lld = build_options.have_llvm and comp.config.use_lld;
- const diags = &comp.link_diags;
- if (use_lld) {
- return self.linkWithLLD(arena, tid, prog_node) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.LinkFailure => return error.LinkFailure,
- else => |e| return diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),
- };
- }
- try self.flushModule(arena, tid, prog_node);
-}
-
-pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
const tracy = trace(@src());
defer tracy.end();
const comp = self.base.comp;
const diags = &comp.link_diags;
- if (self.llvm_object) |llvm_object| {
- try self.base.emitLlvmObject(arena, llvm_object, prog_node);
- const use_lld = build_options.have_llvm and comp.config.use_lld;
- if (use_lld) return;
- }
-
if (comp.verbose_link) Compilation.dump_argv(self.dump_argv_list.items);
const sub_prog_node = prog_node.start("ELF Flush", 0);
defer sub_prog_node.end();
- return flushModuleInner(self, arena, tid) catch |err| switch (err) {
+ return flushInner(self, arena, tid) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
error.LinkFailure => return error.LinkFailure,
else => |e| return diags.fail("ELF flush failed: {s}", .{@errorName(e)}),
};
}
-fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
+fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
const comp = self.base.comp;
const gpa = comp.gpa;
const diags = &comp.link_diags;
- const module_obj_path: ?Path = if (self.base.zcu_object_sub_path) |path| .{
- .root_dir = self.base.emit.root_dir,
- .sub_path = if (fs.path.dirname(self.base.emit.sub_path)) |dirname|
- try fs.path.join(arena, &.{ dirname, path })
- else
- path,
+ const zcu_obj_path: ?Path = if (self.base.zcu_object_basename) |raw| p: {
+ break :p try comp.resolveEmitPathFlush(arena, .temp, raw);
} else null;
if (self.zigObjectPtr()) |zig_object| try zig_object.flush(self, tid);
- if (module_obj_path) |path| openParseObjectReportingFailure(self, path);
+ if (zcu_obj_path) |path| openParseObjectReportingFailure(self, path);
switch (comp.config.output_mode) {
.Obj => return relocatable.flushObject(self, comp),
@@ -1508,639 +1431,6 @@ pub fn initOutputSection(self: *Elf, args: struct {
return out_shndx;
}
-fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
- dev.check(.lld_linker);
-
- const tracy = trace(@src());
- defer tracy.end();
-
- const comp = self.base.comp;
- const gpa = comp.gpa;
- const diags = &comp.link_diags;
-
- const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type.
- const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
-
- // If there is no Zig code to compile, then we should skip flushing the output file because it
- // will not be part of the linker line anyway.
- const module_obj_path: ?[]const u8 = if (comp.zcu != null) blk: {
- try self.flushModule(arena, tid, prog_node);
-
- if (fs.path.dirname(full_out_path)) |dirname| {
- break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? });
- } else {
- break :blk self.base.zcu_object_sub_path.?;
- }
- } else null;
-
- const sub_prog_node = prog_node.start("LLD Link", 0);
- defer sub_prog_node.end();
-
- const output_mode = comp.config.output_mode;
- const is_obj = output_mode == .Obj;
- const is_lib = output_mode == .Lib;
- const link_mode = comp.config.link_mode;
- const is_dyn_lib = link_mode == .dynamic and is_lib;
- const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe;
- const have_dynamic_linker = link_mode == .dynamic and is_exe_or_dyn_lib;
- const target = self.getTarget();
- const compiler_rt_path: ?Path = blk: {
- if (comp.compiler_rt_lib) |x| break :blk x.full_object_path;
- if (comp.compiler_rt_obj) |x| break :blk x.full_object_path;
- break :blk null;
- };
- const ubsan_rt_path: ?Path = blk: {
- if (comp.ubsan_rt_lib) |x| break :blk x.full_object_path;
- if (comp.ubsan_rt_obj) |x| break :blk x.full_object_path;
- break :blk null;
- };
-
- // Here we want to determine whether we can save time by not invoking LLD when the
- // output is unchanged. None of the linker options or the object files that are being
- // linked are in the hash that namespaces the directory we are outputting to. Therefore,
- // we must hash those now, and the resulting digest will form the "id" of the linking
- // job we are about to perform.
- // After a successful link, we store the id in the metadata of a symlink named "lld.id" in
- // the artifact directory. So, now, we check if this symlink exists, and if it matches
- // our digest. If so, we can skip linking. Otherwise, we proceed with invoking LLD.
- const id_symlink_basename = "lld.id";
-
- var man: std.Build.Cache.Manifest = undefined;
- defer if (!self.base.disable_lld_caching) man.deinit();
-
- var digest: [std.Build.Cache.hex_digest_len]u8 = undefined;
-
- if (!self.base.disable_lld_caching) {
- man = comp.cache_parent.obtain();
-
- // We are about to obtain this lock, so here we give other processes a chance first.
- self.base.releaseLock();
-
- comptime assert(Compilation.link_hash_implementation_version == 14);
-
- try man.addOptionalFile(self.linker_script);
- try man.addOptionalFile(self.version_script);
- man.hash.add(self.allow_undefined_version);
- man.hash.addOptional(self.enable_new_dtags);
- try link.hashInputs(&man, comp.link_inputs);
- for (comp.c_object_table.keys()) |key| {
- _ = try man.addFilePath(key.status.success.object_path, null);
- }
- try man.addOptionalFile(module_obj_path);
- try man.addOptionalFilePath(compiler_rt_path);
- try man.addOptionalFilePath(ubsan_rt_path);
- try man.addOptionalFilePath(if (comp.tsan_lib) |l| l.full_object_path else null);
- try man.addOptionalFilePath(if (comp.fuzzer_lib) |l| l.full_object_path else null);
-
- // We can skip hashing libc and libc++ components that we are in charge of building from Zig
- // installation sources because they are always a product of the compiler version + target information.
- man.hash.addOptionalBytes(self.entry_name);
- man.hash.add(self.image_base);
- man.hash.add(self.base.gc_sections);
- man.hash.addOptional(self.sort_section);
- man.hash.add(comp.link_eh_frame_hdr);
- man.hash.add(self.emit_relocs);
- man.hash.add(comp.config.rdynamic);
- man.hash.addListOfBytes(self.rpath_table.keys());
- if (output_mode == .Exe) {
- man.hash.add(self.base.stack_size);
- }
- man.hash.add(self.base.build_id);
- man.hash.addListOfBytes(self.symbol_wrap_set.keys());
- man.hash.add(comp.skip_linker_dependencies);
- man.hash.add(self.z_nodelete);
- man.hash.add(self.z_notext);
- man.hash.add(self.z_defs);
- man.hash.add(self.z_origin);
- man.hash.add(self.z_nocopyreloc);
- man.hash.add(self.z_now);
- man.hash.add(self.z_relro);
- man.hash.add(self.z_common_page_size orelse 0);
- man.hash.add(self.z_max_page_size orelse 0);
- man.hash.add(self.hash_style);
- // strip does not need to go into the linker hash because it is part of the hash namespace
- if (comp.config.link_libc) {
- man.hash.add(comp.libc_installation != null);
- if (comp.libc_installation) |libc_installation| {
- man.hash.addBytes(libc_installation.crt_dir.?);
- }
- }
- if (have_dynamic_linker) {
- man.hash.addOptionalBytes(target.dynamic_linker.get());
- }
- man.hash.addOptionalBytes(self.soname);
- man.hash.addOptional(comp.version);
- man.hash.addListOfBytes(comp.force_undefined_symbols.keys());
- man.hash.add(self.base.allow_shlib_undefined);
- man.hash.add(self.bind_global_refs_locally);
- man.hash.add(self.compress_debug_sections);
- man.hash.add(comp.config.any_sanitize_thread);
- man.hash.add(comp.config.any_fuzz);
- man.hash.addOptionalBytes(comp.sysroot);
-
- // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
- _ = try man.hit();
- digest = man.final();
-
- var prev_digest_buf: [digest.len]u8 = undefined;
- const prev_digest: []u8 = std.Build.Cache.readSmallFile(
- directory.handle,
- id_symlink_basename,
- &prev_digest_buf,
- ) catch |err| blk: {
- log.debug("ELF LLD new_digest={s} error: {s}", .{ std.fmt.fmtSliceHexLower(&digest), @errorName(err) });
- // Handle this as a cache miss.
- break :blk prev_digest_buf[0..0];
- };
- if (mem.eql(u8, prev_digest, &digest)) {
- log.debug("ELF LLD digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});
- // Hot diggity dog! The output binary is already there.
- self.base.lock = man.toOwnedLock();
- return;
- }
- log.debug("ELF LLD prev_digest={s} new_digest={s}", .{ std.fmt.fmtSliceHexLower(prev_digest), std.fmt.fmtSliceHexLower(&digest) });
-
- // We are about to change the output file to be different, so we invalidate the build hash now.
- directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
- error.FileNotFound => {},
- else => |e| return e,
- };
- }
-
- // Due to a deficiency in LLD, we need to special-case BPF to a simple file
- // copy when generating relocatables. Normally, we would expect `lld -r` to work.
- // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails
- // before even generating the relocatable.
- //
- // For m68k, we go through this path because LLD doesn't support it yet, but LLVM can
- // produce usable object files.
- if (output_mode == .Obj and
- (comp.config.lto != .none or
- target.cpu.arch.isBpf() or
- target.cpu.arch == .lanai or
- target.cpu.arch == .m68k or
- target.cpu.arch.isSPARC() or
- target.cpu.arch == .ve or
- target.cpu.arch == .xcore))
- {
- // In this case we must do a simple file copy
- // here. TODO: think carefully about how we can avoid this redundant operation when doing
- // build-obj. See also the corresponding TODO in linkAsArchive.
- const the_object_path = blk: {
- if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
-
- if (comp.c_object_table.count() != 0)
- break :blk comp.c_object_table.keys()[0].status.success.object_path;
-
- if (module_obj_path) |p|
- break :blk Path.initCwd(p);
-
- // TODO I think this is unreachable. Audit this situation when solving the above TODO
- // regarding eliding redundant object -> object transformations.
- return error.NoObjectsToLink;
- };
- try std.fs.Dir.copyFile(
- the_object_path.root_dir.handle,
- the_object_path.sub_path,
- directory.handle,
- self.base.emit.sub_path,
- .{},
- );
- } else {
- // Create an LLD command line and invoke it.
- var argv = std.ArrayList([]const u8).init(gpa);
- defer argv.deinit();
- // We will invoke ourselves as a child process to gain access to LLD.
- // This is necessary because LLD does not behave properly as a library -
- // it calls exit() and does not reset all global data between invocations.
- const linker_command = "ld.lld";
- try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
- if (is_obj) {
- try argv.append("-r");
- }
-
- try argv.append("--error-limit=0");
-
- if (comp.sysroot) |sysroot| {
- try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot}));
- }
-
- if (target_util.llvmMachineAbi(target)) |mabi| {
- try argv.appendSlice(&.{
- "-mllvm",
- try std.fmt.allocPrint(arena, "-target-abi={s}", .{mabi}),
- });
- }
-
- try argv.appendSlice(&.{
- "-mllvm",
- try std.fmt.allocPrint(arena, "-float-abi={s}", .{if (target.abi.float() == .hard) "hard" else "soft"}),
- });
-
- if (comp.config.lto != .none) {
- switch (comp.root_mod.optimize_mode) {
- .Debug => {},
- .ReleaseSmall => try argv.append("--lto-O2"),
- .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"),
- }
- }
- switch (comp.root_mod.optimize_mode) {
- .Debug => {},
- .ReleaseSmall => try argv.append("-O2"),
- .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
- }
-
- if (self.entry_name) |name| {
- try argv.appendSlice(&.{ "--entry", name });
- }
-
- for (comp.force_undefined_symbols.keys()) |sym| {
- try argv.append("-u");
- try argv.append(sym);
- }
-
- switch (self.hash_style) {
- .gnu => try argv.append("--hash-style=gnu"),
- .sysv => try argv.append("--hash-style=sysv"),
- .both => {}, // this is the default
- }
-
- if (output_mode == .Exe) {
- try argv.appendSlice(&.{
- "-z",
- try std.fmt.allocPrint(arena, "stack-size={d}", .{self.base.stack_size}),
- });
- }
-
- switch (self.base.build_id) {
- .none => try argv.append("--build-id=none"),
- .fast, .uuid, .sha1, .md5 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
- @tagName(self.base.build_id),
- })),
- .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{
- std.fmt.fmtSliceHexLower(hs.toSlice()),
- })),
- }
-
- try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base}));
-
- if (self.linker_script) |linker_script| {
- try argv.append("-T");
- try argv.append(linker_script);
- }
-
- if (self.sort_section) |how| {
- const arg = try std.fmt.allocPrint(arena, "--sort-section={s}", .{@tagName(how)});
- try argv.append(arg);
- }
-
- if (self.base.gc_sections) {
- try argv.append("--gc-sections");
- }
-
- if (self.base.print_gc_sections) {
- try argv.append("--print-gc-sections");
- }
-
- if (self.print_icf_sections) {
- try argv.append("--print-icf-sections");
- }
-
- if (self.print_map) {
- try argv.append("--print-map");
- }
-
- if (comp.link_eh_frame_hdr) {
- try argv.append("--eh-frame-hdr");
- }
-
- if (self.emit_relocs) {
- try argv.append("--emit-relocs");
- }
-
- if (comp.config.rdynamic) {
- try argv.append("--export-dynamic");
- }
-
- if (comp.config.debug_format == .strip) {
- try argv.append("-s");
- }
-
- if (self.z_nodelete) {
- try argv.append("-z");
- try argv.append("nodelete");
- }
- if (self.z_notext) {
- try argv.append("-z");
- try argv.append("notext");
- }
- if (self.z_defs) {
- try argv.append("-z");
- try argv.append("defs");
- }
- if (self.z_origin) {
- try argv.append("-z");
- try argv.append("origin");
- }
- if (self.z_nocopyreloc) {
- try argv.append("-z");
- try argv.append("nocopyreloc");
- }
- if (self.z_now) {
- // LLD defaults to -zlazy
- try argv.append("-znow");
- }
- if (!self.z_relro) {
- // LLD defaults to -zrelro
- try argv.append("-znorelro");
- }
- if (self.z_common_page_size) |size| {
- try argv.append("-z");
- try argv.append(try std.fmt.allocPrint(arena, "common-page-size={d}", .{size}));
- }
- if (self.z_max_page_size) |size| {
- try argv.append("-z");
- try argv.append(try std.fmt.allocPrint(arena, "max-page-size={d}", .{size}));
- }
-
- if (getLDMOption(target)) |ldm| {
- try argv.append("-m");
- try argv.append(ldm);
- }
-
- if (link_mode == .static) {
- if (target.cpu.arch.isArm()) {
- try argv.append("-Bstatic");
- } else {
- try argv.append("-static");
- }
- } else if (switch (target.os.tag) {
- else => is_dyn_lib,
- .haiku => is_exe_or_dyn_lib,
- }) {
- try argv.append("-shared");
- }
-
- if (comp.config.pie and output_mode == .Exe) {
- try argv.append("-pie");
- }
-
- if (is_exe_or_dyn_lib and target.os.tag == .netbsd) {
- // Add options to produce shared objects with only 2 PT_LOAD segments.
- // NetBSD expects 2 PT_LOAD segments in a shared object, otherwise
- // ld.elf_so fails loading dynamic libraries with "not found" error.
- // See https://github.com/ziglang/zig/issues/9109 .
- try argv.append("--no-rosegment");
- try argv.append("-znorelro");
- }
-
- try argv.append("-o");
- try argv.append(full_out_path);
-
- // csu prelude
- const csu = try comp.getCrtPaths(arena);
- if (csu.crt0) |p| try argv.append(try p.toString(arena));
- if (csu.crti) |p| try argv.append(try p.toString(arena));
- if (csu.crtbegin) |p| try argv.append(try p.toString(arena));
-
- for (self.rpath_table.keys()) |rpath| {
- try argv.appendSlice(&.{ "-rpath", rpath });
- }
-
- for (self.symbol_wrap_set.keys()) |symbol_name| {
- try argv.appendSlice(&.{ "-wrap", symbol_name });
- }
-
- if (comp.config.link_libc) {
- if (comp.libc_installation) |libc_installation| {
- try argv.append("-L");
- try argv.append(libc_installation.crt_dir.?);
- }
- }
-
- if (have_dynamic_linker and
- (comp.config.link_libc or comp.root_mod.resolved_target.is_explicit_dynamic_linker))
- {
- if (target.dynamic_linker.get()) |dynamic_linker| {
- try argv.append("-dynamic-linker");
- try argv.append(dynamic_linker);
- }
- }
-
- if (is_dyn_lib) {
- if (self.soname) |soname| {
- try argv.append("-soname");
- try argv.append(soname);
- }
- if (self.version_script) |version_script| {
- try argv.append("-version-script");
- try argv.append(version_script);
- }
- if (self.allow_undefined_version) {
- try argv.append("--undefined-version");
- } else {
- try argv.append("--no-undefined-version");
- }
- if (self.enable_new_dtags) |enable_new_dtags| {
- if (enable_new_dtags) {
- try argv.append("--enable-new-dtags");
- } else {
- try argv.append("--disable-new-dtags");
- }
- }
- }
-
- // Positional arguments to the linker such as object files.
- var whole_archive = false;
-
- for (self.base.comp.link_inputs) |link_input| switch (link_input) {
- .res => unreachable, // Windows-only
- .dso => continue,
- .object, .archive => |obj| {
- if (obj.must_link and !whole_archive) {
- try argv.append("-whole-archive");
- whole_archive = true;
- } else if (!obj.must_link and whole_archive) {
- try argv.append("-no-whole-archive");
- whole_archive = false;
- }
- try argv.append(try obj.path.toString(arena));
- },
- .dso_exact => |dso_exact| {
- assert(dso_exact.name[0] == ':');
- try argv.appendSlice(&.{ "-l", dso_exact.name });
- },
- };
-
- if (whole_archive) {
- try argv.append("-no-whole-archive");
- whole_archive = false;
- }
-
- for (comp.c_object_table.keys()) |key| {
- try argv.append(try key.status.success.object_path.toString(arena));
- }
-
- if (module_obj_path) |p| {
- try argv.append(p);
- }
-
- if (comp.tsan_lib) |lib| {
- assert(comp.config.any_sanitize_thread);
- try argv.append(try lib.full_object_path.toString(arena));
- }
-
- if (comp.fuzzer_lib) |lib| {
- assert(comp.config.any_fuzz);
- try argv.append(try lib.full_object_path.toString(arena));
- }
-
- if (ubsan_rt_path) |p| {
- try argv.append(try p.toString(arena));
- }
-
- // Shared libraries.
- if (is_exe_or_dyn_lib) {
- // Worst-case, we need an --as-needed argument for every lib, as well
- // as one before and one after.
- try argv.ensureUnusedCapacity(2 * self.base.comp.link_inputs.len + 2);
- argv.appendAssumeCapacity("--as-needed");
- var as_needed = true;
-
- for (self.base.comp.link_inputs) |link_input| switch (link_input) {
- .res => unreachable, // Windows-only
- .object, .archive, .dso_exact => continue,
- .dso => |dso| {
- const lib_as_needed = !dso.needed;
- switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) {
- 0b00, 0b11 => {},
- 0b01 => {
- argv.appendAssumeCapacity("--no-as-needed");
- as_needed = false;
- },
- 0b10 => {
- argv.appendAssumeCapacity("--as-needed");
- as_needed = true;
- },
- }
-
- // By this time, we depend on these libs being dynamically linked
- // libraries and not static libraries (the check for that needs to be earlier),
- // but they could be full paths to .so files, in which case we
- // want to avoid prepending "-l".
- argv.appendAssumeCapacity(try dso.path.toString(arena));
- },
- };
-
- if (!as_needed) {
- argv.appendAssumeCapacity("--as-needed");
- as_needed = true;
- }
-
- // libc++ dep
- if (comp.config.link_libcpp) {
- try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena));
- try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena));
- }
-
- // libunwind dep
- if (comp.config.link_libunwind) {
- try argv.append(try comp.libunwind_static_lib.?.full_object_path.toString(arena));
- }
-
- // libc dep
- diags.flags.missing_libc = false;
- if (comp.config.link_libc) {
- if (comp.libc_installation != null) {
- const needs_grouping = link_mode == .static;
- if (needs_grouping) try argv.append("--start-group");
- try argv.appendSlice(target_util.libcFullLinkFlags(target));
- if (needs_grouping) try argv.append("--end-group");
- } else if (target.isGnuLibC()) {
- for (glibc.libs) |lib| {
- if (lib.removed_in) |rem_in| {
- if (target.os.versionRange().gnuLibCVersion().?.order(rem_in) != .lt) continue;
- }
-
- const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
- comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
- });
- try argv.append(lib_path);
- }
- try argv.append(try comp.crtFileAsString(arena, "libc_nonshared.a"));
- } else if (target.isMuslLibC()) {
- try argv.append(try comp.crtFileAsString(arena, switch (link_mode) {
- .static => "libc.a",
- .dynamic => "libc.so",
- }));
- } else if (target.isFreeBSDLibC()) {
- for (freebsd.libs) |lib| {
- const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
- comp.freebsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
- });
- try argv.append(lib_path);
- }
- } else if (target.isNetBSDLibC()) {
- for (netbsd.libs) |lib| {
- const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
- comp.netbsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
- });
- try argv.append(lib_path);
- }
- } else {
- diags.flags.missing_libc = true;
- }
-
- if (comp.zigc_static_lib) |zigc| {
- try argv.append(try zigc.full_object_path.toString(arena));
- }
- }
- }
-
- // compiler-rt. Since compiler_rt exports symbols like `memset`, it needs
- // to be after the shared libraries, so they are picked up from the shared
- // libraries, not libcompiler_rt.
- if (compiler_rt_path) |p| {
- try argv.append(try p.toString(arena));
- }
-
- // crt postlude
- if (csu.crtend) |p| try argv.append(try p.toString(arena));
- if (csu.crtn) |p| try argv.append(try p.toString(arena));
-
- if (self.base.allow_shlib_undefined) {
- try argv.append("--allow-shlib-undefined");
- }
-
- switch (self.compress_debug_sections) {
- .none => {},
- .zlib => try argv.append("--compress-debug-sections=zlib"),
- .zstd => try argv.append("--compress-debug-sections=zstd"),
- }
-
- if (self.bind_global_refs_locally) {
- try argv.append("-Bsymbolic");
- }
-
- try link.spawnLld(comp, arena, argv.items);
- }
-
- if (!self.base.disable_lld_caching) {
- // Update the file with the digest. If it fails we can continue; it only
- // means that the next invocation will have an unnecessary cache miss.
- std.Build.Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
- log.warn("failed to save linking hash digest file: {s}", .{@errorName(err)});
- };
- // Again failure here only means an unnecessary cache miss.
- man.writeManifest() catch |err| {
- log.warn("failed to write cache manifest when linking: {s}", .{@errorName(err)});
- };
- // We hang on to this lock so that the output file path can be used without
- // other processes clobbering it.
- self.base.lock = man.toOwnedLock();
- }
-}
-
pub fn writeShdrTable(self: *Elf) !void {
const gpa = self.base.comp.gpa;
const target_endian = self.getTarget().cpu.arch.endian();
@@ -2385,7 +1675,6 @@ pub fn writeElfHeader(self: *Elf) !void {
}
pub fn freeNav(self: *Elf, nav: InternPool.Nav.Index) void {
- if (self.llvm_object) |llvm_object| return llvm_object.freeNav(nav);
return self.zigObjectPtr().?.freeNav(self, nav);
}
@@ -2393,14 +1682,12 @@ pub fn updateFunc(
self: *Elf,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ mir: *const codegen.AnyMir,
) link.File.UpdateNavError!void {
if (build_options.skip_non_native and builtin.object_format != .elf) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
- return self.zigObjectPtr().?.updateFunc(self, pt, func_index, air, liveness);
+ return self.zigObjectPtr().?.updateFunc(self, pt, func_index, mir);
}
pub fn updateNav(
@@ -2411,7 +1698,6 @@ pub fn updateNav(
if (build_options.skip_non_native and builtin.object_format != .elf) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav);
return self.zigObjectPtr().?.updateNav(self, pt, nav);
}
@@ -2423,7 +1709,6 @@ pub fn updateContainerType(
if (build_options.skip_non_native and builtin.object_format != .elf) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |_| return;
const zcu = pt.zcu;
const gpa = zcu.gpa;
return self.zigObjectPtr().?.updateContainerType(pt, ty) catch |err| switch (err) {
@@ -2449,12 +1734,10 @@ pub fn updateExports(
if (build_options.skip_non_native and builtin.object_format != .elf) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices);
}
pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
- if (self.llvm_object) |_| return;
return self.zigObjectPtr().?.updateLineNumber(pt, ti_id);
}
@@ -2463,7 +1746,6 @@ pub fn deleteExport(
exported: Zcu.Exported,
name: InternPool.NullTerminatedString,
) void {
- if (self.llvm_object) |_| return;
return self.zigObjectPtr().?.deleteExport(self, exported, name);
}
@@ -4140,85 +3422,6 @@ fn shdrTo32(shdr: elf.Elf64_Shdr) elf.Elf32_Shdr {
};
}
-fn getLDMOption(target: std.Target) ?[]const u8 {
- // This should only return emulations understood by LLD's parseEmulation().
- return switch (target.cpu.arch) {
- .aarch64 => switch (target.os.tag) {
- .linux => "aarch64linux",
- else => "aarch64elf",
- },
- .aarch64_be => switch (target.os.tag) {
- .linux => "aarch64linuxb",
- else => "aarch64elfb",
- },
- .amdgcn => "elf64_amdgpu",
- .arm, .thumb => switch (target.os.tag) {
- .linux => "armelf_linux_eabi",
- else => "armelf",
- },
- .armeb, .thumbeb => switch (target.os.tag) {
- .linux => "armelfb_linux_eabi",
- else => "armelfb",
- },
- .hexagon => "hexagonelf",
- .loongarch32 => "elf32loongarch",
- .loongarch64 => "elf64loongarch",
- .mips => switch (target.os.tag) {
- .freebsd => "elf32btsmip_fbsd",
- else => "elf32btsmip",
- },
- .mipsel => switch (target.os.tag) {
- .freebsd => "elf32ltsmip_fbsd",
- else => "elf32ltsmip",
- },
- .mips64 => switch (target.os.tag) {
- .freebsd => switch (target.abi) {
- .gnuabin32, .muslabin32 => "elf32btsmipn32_fbsd",
- else => "elf64btsmip_fbsd",
- },
- else => switch (target.abi) {
- .gnuabin32, .muslabin32 => "elf32btsmipn32",
- else => "elf64btsmip",
- },
- },
- .mips64el => switch (target.os.tag) {
- .freebsd => switch (target.abi) {
- .gnuabin32, .muslabin32 => "elf32ltsmipn32_fbsd",
- else => "elf64ltsmip_fbsd",
- },
- else => switch (target.abi) {
- .gnuabin32, .muslabin32 => "elf32ltsmipn32",
- else => "elf64ltsmip",
- },
- },
- .msp430 => "msp430elf",
- .powerpc => switch (target.os.tag) {
- .freebsd => "elf32ppc_fbsd",
- .linux => "elf32ppclinux",
- else => "elf32ppc",
- },
- .powerpcle => switch (target.os.tag) {
- .linux => "elf32lppclinux",
- else => "elf32lppc",
- },
- .powerpc64 => "elf64ppc",
- .powerpc64le => "elf64lppc",
- .riscv32 => "elf32lriscv",
- .riscv64 => "elf64lriscv",
- .s390x => "elf64_s390",
- .sparc64 => "elf64_sparc",
- .x86 => switch (target.os.tag) {
- .freebsd => "elf_i386_fbsd",
- else => "elf_i386",
- },
- .x86_64 => switch (target.abi) {
- .gnux32, .muslx32 => "elf32_x86_64",
- else => "elf_x86_64",
- },
- else => null,
- };
-}
-
pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
return actual_size +| (actual_size / ideal_factor);
}
@@ -5303,10 +4506,7 @@ const codegen = @import("../codegen.zig");
const dev = @import("../dev.zig");
const eh_frame = @import("Elf/eh_frame.zig");
const gc = @import("Elf/gc.zig");
-const glibc = @import("../libs/glibc.zig");
const musl = @import("../libs/musl.zig");
-const freebsd = @import("../libs/freebsd.zig");
-const netbsd = @import("../libs/netbsd.zig");
const link = @import("../link.zig");
const relocatable = @import("Elf/relocatable.zig");
const relocation = @import("Elf/relocation.zig");
@@ -5315,7 +4515,6 @@ const trace = @import("../tracy.zig").trace;
const synthetic_sections = @import("Elf/synthetic_sections.zig");
const Merge = @import("Elf/Merge.zig");
-const Air = @import("../Air.zig");
const Archive = @import("Elf/Archive.zig");
const AtomList = @import("Elf/AtomList.zig");
const Compilation = @import("../Compilation.zig");
@@ -5332,7 +4531,6 @@ const GotSection = synthetic_sections.GotSection;
const GotPltSection = synthetic_sections.GotPltSection;
const HashSection = synthetic_sections.HashSection;
const LinkerDefined = @import("Elf/LinkerDefined.zig");
-const LlvmObject = @import("../codegen/llvm.zig").Object;
const Zcu = @import("../Zcu.zig");
const Object = @import("Elf/Object.zig");
const InternPool = @import("../InternPool.zig");
diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig
index 31584ca406..843c23dca4 100644
--- a/src/link/Elf/Symbol.zig
+++ b/src/link/Elf/Symbol.zig
@@ -462,9 +462,6 @@ pub const Flags = packed struct {
/// Whether the symbol is a TLS variable.
is_tls: bool = false,
-
- /// Whether the symbol is an extern pointer (as opposed to function).
- is_extern_ptr: bool = false,
};
pub const Extra = struct {
diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig
index 13816940fe..71b42819e2 100644
--- a/src/link/Elf/ZigObject.zig
+++ b/src/link/Elf/ZigObject.zig
@@ -310,7 +310,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
if (self.dwarf) |*dwarf| {
const pt: Zcu.PerThread = .activate(elf_file.base.comp.zcu.?, tid);
defer pt.deactivate();
- try dwarf.flushModule(pt);
+ try dwarf.flush(pt);
const gpa = elf_file.base.comp.gpa;
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 {
self.debug_str_section_dirty = false;
}
- // The point of flushModule() is to commit changes, so in theory, nothing should
+ // The point of flush() is to commit changes, so in theory, nothing should
// be dirty after this. However, it is possible for some things to remain
// dirty because they fail to be written in the event of compile errors,
// 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 {
if (shdr.sh_type == elf.SHT_NOBITS) continue;
if (atom_ptr.scanRelocsRequiresCode(elf_file)) {
// TODO ideally we don't have to fetch the code here.
- // Perhaps it would make sense to save the code until flushModule where we
+ // Perhaps it would make sense to save the code until flush where we
// would free all of generated code?
const code = try self.codeAlloc(elf_file, atom_index);
defer gpa.free(code);
@@ -1075,7 +1075,7 @@ pub fn getOrCreateMetadataForLazySymbol(
}
state_ptr.* = .pending_flush;
const symbol_index = symbol_index_ptr.*;
- // anyerror needs to be deferred until flushModule
+ // anyerror needs to be deferred until flush
if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(elf_file, pt, lazy_sym, symbol_index);
return symbol_index;
}
@@ -1142,7 +1142,6 @@ fn getNavShdrIndex(
const gpa = elf_file.base.comp.gpa;
const ptr_size = elf_file.ptrWidthBytes();
const ip = &zcu.intern_pool;
- const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
const nav_val = zcu.navValue(nav_index);
if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) {
if (self.text_index) |symbol_index|
@@ -1162,7 +1161,7 @@ fn getNavShdrIndex(
else => .{ true, false, nav_val.toIntern() },
};
const has_relocs = self.symbol(sym_index).atom(elf_file).?.relocs(elf_file).len > 0;
- if (any_non_single_threaded and is_threadlocal) {
+ if (is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) {
const is_bss = !has_relocs and for (code) |byte| {
if (byte != 0) break false;
} else true;
@@ -1416,8 +1415,7 @@ pub fn updateFunc(
elf_file: *Elf,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ mir: *const codegen.AnyMir,
) link.File.UpdateNavError!void {
const tracy = trace(@src());
defer tracy.end();
@@ -1438,13 +1436,12 @@ pub fn updateFunc(
var debug_wip_nav = if (self.dwarf) |*dwarf| try dwarf.initWipNav(pt, func.owner_nav, sym_index) else null;
defer if (debug_wip_nav) |*wip_nav| wip_nav.deinit();
- try codegen.generateFunction(
+ try codegen.emitFunction(
&elf_file.base,
pt,
zcu.navSrcLoc(func.owner_nav),
func_index,
- air,
- liveness,
+ mir,
&code_buffer,
if (debug_wip_nav) |*dn| .{ .dwarf = dn } else .none,
);
@@ -1544,11 +1541,7 @@ pub fn updateNav(
nav.name.toSlice(ip),
@"extern".lib_name.toSlice(ip),
);
- if (!ip.isFunctionType(@"extern".ty)) {
- const sym = self.symbol(sym_index);
- sym.flags.is_extern_ptr = true;
- if (@"extern".is_threadlocal) sym.flags.is_tls = true;
- }
+ if (@"extern".is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) self.symbol(sym_index).flags.is_tls = true;
if (self.dwarf) |*dwarf| dwarf: {
var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf;
defer debug_wip_nav.deinit();
@@ -2361,7 +2354,6 @@ const trace = @import("../../tracy.zig").trace;
const std = @import("std");
const Allocator = std.mem.Allocator;
-const Air = @import("../../Air.zig");
const Archive = @import("Archive.zig");
const Atom = @import("Atom.zig");
const Dwarf = @import("../Dwarf.zig");
diff --git a/src/link/Goff.zig b/src/link/Goff.zig
index 6ed360be25..1f4a7a4d30 100644
--- a/src/link/Goff.zig
+++ b/src/link/Goff.zig
@@ -13,14 +13,12 @@ const Path = std.Build.Cache.Path;
const Zcu = @import("../Zcu.zig");
const InternPool = @import("../InternPool.zig");
const Compilation = @import("../Compilation.zig");
+const codegen = @import("../codegen.zig");
const link = @import("../link.zig");
const trace = @import("../tracy.zig").trace;
const build_options = @import("build_options");
-const Air = @import("../Air.zig");
-const LlvmObject = @import("../codegen/llvm.zig").Object;
base: link.File,
-llvm_object: LlvmObject.Ptr,
pub fn createEmpty(
arena: Allocator,
@@ -36,23 +34,20 @@ pub fn createEmpty(
assert(!use_lld); // Caught by Compilation.Config.resolve.
assert(target.os.tag == .zos); // Caught by Compilation.Config.resolve.
- const llvm_object = try LlvmObject.create(arena, comp);
const goff = try arena.create(Goff);
goff.* = .{
.base = .{
.tag = .goff,
.comp = comp,
.emit = emit,
- .zcu_object_sub_path = emit.sub_path,
+ .zcu_object_basename = emit.sub_path,
.gc_sections = options.gc_sections orelse false,
.print_gc_sections = options.print_gc_sections,
.stack_size = options.stack_size orelse 0,
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
.file = null,
- .disable_lld_caching = options.disable_lld_caching,
.build_id = options.build_id,
},
- .llvm_object = llvm_object,
};
return goff;
@@ -70,27 +65,27 @@ pub fn open(
}
pub fn deinit(self: *Goff) void {
- self.llvm_object.deinit();
+ _ = self;
}
pub fn updateFunc(
self: *Goff,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ mir: *const codegen.AnyMir,
) link.File.UpdateNavError!void {
- if (build_options.skip_non_native and builtin.object_format != .goff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
- try self.llvm_object.updateFunc(pt, func_index, air, liveness);
+ _ = self;
+ _ = pt;
+ _ = func_index;
+ _ = mir;
+ unreachable; // we always use llvm
}
pub fn updateNav(self: *Goff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
- if (build_options.skip_non_native and builtin.object_format != .goff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
- return self.llvm_object.updateNav(pt, nav);
+ _ = self;
+ _ = pt;
+ _ = nav;
+ unreachable; // we always use llvm
}
pub fn updateExports(
@@ -99,21 +94,19 @@ pub fn updateExports(
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
) !void {
- if (build_options.skip_non_native and builtin.object_format != .goff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
- return self.llvm_object.updateExports(pt, exported, export_indices);
+ _ = self;
+ _ = pt;
+ _ = exported;
+ _ = export_indices;
+ unreachable; // we always use llvm
}
pub fn flush(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- return self.flushModule(arena, tid, prog_node);
-}
-
-pub fn flushModule(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
if (build_options.skip_non_native and builtin.object_format != .goff)
@panic("Attempted to compile for object format that was disabled by build configuration");
+ _ = self;
+ _ = arena;
_ = tid;
-
- try self.base.emitLlvmObject(arena, self.llvm_object, prog_node);
+ _ = prog_node;
}
diff --git a/src/link/Lld.zig b/src/link/Lld.zig
new file mode 100644
index 0000000000..4ea809428e
--- /dev/null
+++ b/src/link/Lld.zig
@@ -0,0 +1,1757 @@
+base: link.File,
+ofmt: union(enum) {
+ elf: Elf,
+ coff: Coff,
+ wasm: Wasm,
+},
+
+const Coff = struct {
+ image_base: u64,
+ entry: link.File.OpenOptions.Entry,
+ pdb_out_path: ?[]const u8,
+ repro: bool,
+ tsaware: bool,
+ nxcompat: bool,
+ dynamicbase: bool,
+ /// TODO this and minor_subsystem_version should be combined into one property and left as
+ /// default or populated together. They should not be separate fields.
+ major_subsystem_version: u16,
+ minor_subsystem_version: u16,
+ lib_directories: []const Cache.Directory,
+ module_definition_file: ?[]const u8,
+ subsystem: ?std.Target.SubSystem,
+ /// These flags are populated by `codegen.llvm.updateExports` to allow us to guess the subsystem.
+ lld_export_flags: struct {
+ c_main: bool,
+ winmain: bool,
+ wwinmain: bool,
+ winmain_crt_startup: bool,
+ wwinmain_crt_startup: bool,
+ dllmain_crt_startup: bool,
+ },
+ fn init(comp: *Compilation, options: link.File.OpenOptions) !Coff {
+ const target = comp.root_mod.resolved_target.result;
+ const output_mode = comp.config.output_mode;
+ return .{
+ .image_base = options.image_base orelse switch (output_mode) {
+ .Exe => switch (target.cpu.arch) {
+ .aarch64, .x86_64 => 0x140000000,
+ .thumb, .x86 => 0x400000,
+ else => unreachable,
+ },
+ .Lib => switch (target.cpu.arch) {
+ .aarch64, .x86_64 => 0x180000000,
+ .thumb, .x86 => 0x10000000,
+ else => unreachable,
+ },
+ .Obj => 0,
+ },
+ .entry = options.entry,
+ .pdb_out_path = options.pdb_out_path,
+ .repro = options.repro,
+ .tsaware = options.tsaware,
+ .nxcompat = options.nxcompat,
+ .dynamicbase = options.dynamicbase,
+ .major_subsystem_version = options.major_subsystem_version orelse 6,
+ .minor_subsystem_version = options.minor_subsystem_version orelse 0,
+ .lib_directories = options.lib_directories,
+ .module_definition_file = options.module_definition_file,
+ // Subsystem depends on the set of public symbol names from linked objects.
+ // See LinkerDriver::inferSubsystem from the LLD project for the flow chart.
+ .subsystem = options.subsystem,
+ // These flags are initially all `false`; the LLVM backend populates them when it learns about exports.
+ .lld_export_flags = .{
+ .c_main = false,
+ .winmain = false,
+ .wwinmain = false,
+ .winmain_crt_startup = false,
+ .wwinmain_crt_startup = false,
+ .dllmain_crt_startup = false,
+ },
+ };
+ }
+};
+pub const Elf = struct {
+ entry_name: ?[]const u8,
+ hash_style: HashStyle,
+ image_base: u64,
+ linker_script: ?[]const u8,
+ version_script: ?[]const u8,
+ sort_section: ?SortSection,
+ print_icf_sections: bool,
+ print_map: bool,
+ emit_relocs: bool,
+ z_nodelete: bool,
+ z_notext: bool,
+ z_defs: bool,
+ z_origin: bool,
+ z_nocopyreloc: bool,
+ z_now: bool,
+ z_relro: bool,
+ z_common_page_size: ?u64,
+ z_max_page_size: ?u64,
+ rpath_list: []const []const u8,
+ symbol_wrap_set: []const []const u8,
+ soname: ?[]const u8,
+ allow_undefined_version: bool,
+ enable_new_dtags: ?bool,
+ compress_debug_sections: CompressDebugSections,
+ bind_global_refs_locally: bool,
+ pub const HashStyle = enum { sysv, gnu, both };
+ pub const SortSection = enum { name, alignment };
+ pub const CompressDebugSections = enum { none, zlib, zstd };
+
+ fn init(comp: *Compilation, options: link.File.OpenOptions) !Elf {
+ const PtrWidth = enum { p32, p64 };
+ const target = comp.root_mod.resolved_target.result;
+ const output_mode = comp.config.output_mode;
+ const is_dyn_lib = output_mode == .Lib and comp.config.link_mode == .dynamic;
+ const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {
+ 0...32 => .p32,
+ 33...64 => .p64,
+ else => return error.UnsupportedElfArchitecture,
+ };
+ const default_entry_name: []const u8 = switch (target.cpu.arch) {
+ .mips, .mipsel, .mips64, .mips64el => "__start",
+ else => "_start",
+ };
+ return .{
+ .entry_name = switch (options.entry) {
+ .disabled => null,
+ .default => if (output_mode != .Exe) null else default_entry_name,
+ .enabled => default_entry_name,
+ .named => |name| name,
+ },
+ .hash_style = options.hash_style,
+ .image_base = b: {
+ if (is_dyn_lib) break :b 0;
+ if (output_mode == .Exe and comp.config.pie) break :b 0;
+ break :b options.image_base orelse switch (ptr_width) {
+ .p32 => 0x10000,
+ .p64 => 0x1000000,
+ };
+ },
+ .linker_script = options.linker_script,
+ .version_script = options.version_script,
+ .sort_section = options.sort_section,
+ .print_icf_sections = options.print_icf_sections,
+ .print_map = options.print_map,
+ .emit_relocs = options.emit_relocs,
+ .z_nodelete = options.z_nodelete,
+ .z_notext = options.z_notext,
+ .z_defs = options.z_defs,
+ .z_origin = options.z_origin,
+ .z_nocopyreloc = options.z_nocopyreloc,
+ .z_now = options.z_now,
+ .z_relro = options.z_relro,
+ .z_common_page_size = options.z_common_page_size,
+ .z_max_page_size = options.z_max_page_size,
+ .rpath_list = options.rpath_list,
+ .symbol_wrap_set = options.symbol_wrap_set.keys(),
+ .soname = options.soname,
+ .allow_undefined_version = options.allow_undefined_version,
+ .enable_new_dtags = options.enable_new_dtags,
+ .compress_debug_sections = options.compress_debug_sections,
+ .bind_global_refs_locally = options.bind_global_refs_locally,
+ };
+ }
+};
+const Wasm = struct {
+ /// Symbol name of the entry function to export
+ entry_name: ?[]const u8,
+ /// When true, will import the function table from the host environment.
+ import_table: bool,
+ /// When true, will export the function table to the host environment.
+ export_table: bool,
+ /// When defined, sets the initial memory size of the memory.
+ initial_memory: ?u64,
+ /// When defined, sets the maximum memory size of the memory.
+ max_memory: ?u64,
+ /// When defined, sets the start of the data section.
+ global_base: ?u64,
+ /// Set of *global* symbol names to export to the host environment.
+ export_symbol_names: []const []const u8,
+ /// When true, will allow undefined symbols
+ import_symbols: bool,
+ fn init(comp: *Compilation, options: link.File.OpenOptions) !Wasm {
+ const default_entry_name: []const u8 = switch (comp.config.wasi_exec_model) {
+ .reactor => "_initialize",
+ .command => "_start",
+ };
+ return .{
+ .entry_name = switch (options.entry) {
+ .disabled => null,
+ .default => if (comp.config.output_mode != .Exe) null else default_entry_name,
+ .enabled => default_entry_name,
+ .named => |name| name,
+ },
+ .import_table = options.import_table,
+ .export_table = options.export_table,
+ .initial_memory = options.initial_memory,
+ .max_memory = options.max_memory,
+ .global_base = options.global_base,
+ .export_symbol_names = options.export_symbol_names,
+ .import_symbols = options.import_symbols,
+ };
+ }
+};
+
+pub fn createEmpty(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Cache.Path,
+ options: link.File.OpenOptions,
+) !*Lld {
+ const target = comp.root_mod.resolved_target.result;
+ const output_mode = comp.config.output_mode;
+ const optimize_mode = comp.root_mod.optimize_mode;
+ const is_native_os = comp.root_mod.resolved_target.is_native_os;
+
+ const obj_file_ext: []const u8 = switch (target.ofmt) {
+ .coff => "obj",
+ .elf, .wasm => "o",
+ else => unreachable,
+ };
+ const gc_sections: bool = options.gc_sections orelse switch (target.ofmt) {
+ .coff => optimize_mode != .Debug,
+ .elf => optimize_mode != .Debug and output_mode != .Obj,
+ .wasm => output_mode != .Obj,
+ else => unreachable,
+ };
+ const stack_size: u64 = options.stack_size orelse default: {
+ if (target.ofmt == .wasm and target.os.tag == .freestanding)
+ break :default 1 * 1024 * 1024; // 1 MiB
+ break :default 16 * 1024 * 1024; // 16 MiB
+ };
+
+ const lld = try arena.create(Lld);
+ lld.* = .{
+ .base = .{
+ .tag = .lld,
+ .comp = comp,
+ .emit = emit,
+ .zcu_object_basename = try allocPrint(arena, "{s}_zcu.{s}", .{ fs.path.stem(emit.sub_path), obj_file_ext }),
+ .gc_sections = gc_sections,
+ .print_gc_sections = options.print_gc_sections,
+ .stack_size = stack_size,
+ .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os,
+ .file = null,
+ .build_id = options.build_id,
+ },
+ .ofmt = switch (target.ofmt) {
+ .coff => .{ .coff = try .init(comp, options) },
+ .elf => .{ .elf = try .init(comp, options) },
+ .wasm => .{ .wasm = try .init(comp, options) },
+ else => unreachable,
+ },
+ };
+ return lld;
+}
+pub fn deinit(lld: *Lld) void {
+ _ = lld;
+}
+pub fn flush(
+ lld: *Lld,
+ arena: Allocator,
+ tid: Zcu.PerThread.Id,
+ prog_node: std.Progress.Node,
+) link.File.FlushError!void {
+ dev.check(.lld_linker);
+ _ = tid;
+
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ const sub_prog_node = prog_node.start("LLD Link", 0);
+ defer sub_prog_node.end();
+
+ const comp = lld.base.comp;
+ const result = if (comp.config.output_mode == .Lib and comp.config.link_mode == .static) r: {
+ if (!@import("build_options").have_llvm or !comp.config.use_lib_llvm) {
+ return lld.base.comp.link_diags.fail("using lld without libllvm not implemented", .{});
+ }
+ break :r linkAsArchive(lld, arena);
+ } else switch (lld.ofmt) {
+ .coff => coffLink(lld, arena),
+ .elf => elfLink(lld, arena),
+ .wasm => wasmLink(lld, arena),
+ };
+ result catch |err| switch (err) {
+ error.OutOfMemory, error.LinkFailure => |e| return e,
+ else => |e| return lld.base.comp.link_diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),
+ };
+}
+
+fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
+ const base = &lld.base;
+ const comp = base.comp;
+ const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
+ const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
+ const full_out_path_z = try arena.dupeZ(u8, full_out_path);
+ const opt_zcu = comp.zcu;
+
+ const zcu_obj_path: ?Cache.Path = if (opt_zcu != null) p: {
+ break :p try comp.resolveEmitPathFlush(arena, .temp, base.zcu_object_basename.?);
+ } else null;
+
+ log.debug("zcu_obj_path={?}", .{zcu_obj_path});
+
+ const compiler_rt_path: ?Cache.Path = if (comp.compiler_rt_strat == .obj)
+ comp.compiler_rt_obj.?.full_object_path
+ else
+ null;
+
+ const ubsan_rt_path: ?Cache.Path = if (comp.ubsan_rt_strat == .obj)
+ comp.ubsan_rt_obj.?.full_object_path
+ else
+ null;
+
+ // This function follows the same pattern as link.Elf.linkWithLLD so if you want some
+ // insight as to what's going on here you can read that function body which is more
+ // well-commented.
+
+ const link_inputs = comp.link_inputs;
+
+ var object_files: std.ArrayListUnmanaged([*:0]const u8) = .empty;
+
+ try object_files.ensureUnusedCapacity(arena, link_inputs.len);
+ for (link_inputs) |input| {
+ object_files.appendAssumeCapacity(try input.path().?.toStringZ(arena));
+ }
+
+ try object_files.ensureUnusedCapacity(arena, comp.c_object_table.count() +
+ comp.win32_resource_table.count() + 2);
+
+ for (comp.c_object_table.keys()) |key| {
+ object_files.appendAssumeCapacity(try key.status.success.object_path.toStringZ(arena));
+ }
+ for (comp.win32_resource_table.keys()) |key| {
+ object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path));
+ }
+ if (zcu_obj_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
+ if (compiler_rt_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
+ if (ubsan_rt_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
+
+ if (comp.verbose_link) {
+ std.debug.print("ar rcs {s}", .{full_out_path_z});
+ for (object_files.items) |arg| {
+ std.debug.print(" {s}", .{arg});
+ }
+ std.debug.print("\n", .{});
+ }
+
+ const llvm_bindings = @import("../codegen/llvm/bindings.zig");
+ const llvm = @import("../codegen/llvm.zig");
+ const target = comp.root_mod.resolved_target.result;
+ llvm.initializeLLVMTarget(target.cpu.arch);
+ const bad = llvm_bindings.WriteArchive(
+ full_out_path_z,
+ object_files.items.ptr,
+ object_files.items.len,
+ switch (target.os.tag) {
+ .aix => .AIXBIG,
+ .windows => .COFF,
+ else => if (target.os.tag.isDarwin()) .DARWIN else .GNU,
+ },
+ );
+ if (bad) return error.UnableToWriteArchive;
+}
+
+fn coffLink(lld: *Lld, arena: Allocator) !void {
+ const comp = lld.base.comp;
+ const gpa = comp.gpa;
+ const base = &lld.base;
+ const coff = &lld.ofmt.coff;
+
+ const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
+ const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
+
+ const zcu_obj_path: ?Cache.Path = if (comp.zcu != null) p: {
+ break :p try comp.resolveEmitPathFlush(arena, .temp, base.zcu_object_basename.?);
+ } else null;
+
+ const is_lib = comp.config.output_mode == .Lib;
+ const is_dyn_lib = comp.config.link_mode == .dynamic and is_lib;
+ const is_exe_or_dyn_lib = is_dyn_lib or comp.config.output_mode == .Exe;
+ const link_in_crt = comp.config.link_libc and is_exe_or_dyn_lib;
+ const target = comp.root_mod.resolved_target.result;
+ const optimize_mode = comp.root_mod.optimize_mode;
+ const entry_name: ?[]const u8 = switch (coff.entry) {
+ // This logic isn't quite right for disabled or enabled. No point in fixing it
+ // when the goal is to eliminate dependency on LLD anyway.
+ // https://github.com/ziglang/zig/issues/17751
+ .disabled, .default, .enabled => null,
+ .named => |name| name,
+ };
+
+ if (comp.config.output_mode == .Obj) {
+ // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy
+ // here. TODO: think carefully about how we can avoid this redundant operation when doing
+ // build-obj. See also the corresponding TODO in linkAsArchive.
+ const the_object_path = blk: {
+ if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
+
+ if (comp.c_object_table.count() != 0)
+ break :blk comp.c_object_table.keys()[0].status.success.object_path;
+
+ if (zcu_obj_path) |p|
+ break :blk p;
+
+ // TODO I think this is unreachable. Audit this situation when solving the above TODO
+ // regarding eliding redundant object -> object transformations.
+ return error.NoObjectsToLink;
+ };
+ try std.fs.Dir.copyFile(
+ the_object_path.root_dir.handle,
+ the_object_path.sub_path,
+ directory.handle,
+ base.emit.sub_path,
+ .{},
+ );
+ } else {
+ // Create an LLD command line and invoke it.
+ var argv = std.ArrayList([]const u8).init(gpa);
+ defer argv.deinit();
+ // We will invoke ourselves as a child process to gain access to LLD.
+ // This is necessary because LLD does not behave properly as a library -
+ // it calls exit() and does not reset all global data between invocations.
+ const linker_command = "lld-link";
+ try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
+
+ if (target.isMinGW()) {
+ try argv.append("-lldmingw");
+ }
+
+ try argv.append("-ERRORLIMIT:0");
+ try argv.append("-NOLOGO");
+ if (comp.config.debug_format != .strip) {
+ try argv.append("-DEBUG");
+
+ const out_ext = std.fs.path.extension(full_out_path);
+ const out_pdb = coff.pdb_out_path orelse try allocPrint(arena, "{s}.pdb", .{
+ full_out_path[0 .. full_out_path.len - out_ext.len],
+ });
+ const out_pdb_basename = std.fs.path.basename(out_pdb);
+
+ try argv.append(try allocPrint(arena, "-PDB:{s}", .{out_pdb}));
+ try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb_basename}));
+ }
+ if (comp.version) |version| {
+ try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));
+ }
+
+ if (target_util.llvmMachineAbi(target)) |mabi| {
+ try argv.append(try allocPrint(arena, "-MLLVM:-target-abi={s}", .{mabi}));
+ }
+
+ try argv.append(try allocPrint(arena, "-MLLVM:-float-abi={s}", .{if (target.abi.float() == .hard) "hard" else "soft"}));
+
+ if (comp.config.lto != .none) {
+ switch (optimize_mode) {
+ .Debug => {},
+ .ReleaseSmall => try argv.append("-OPT:lldlto=2"),
+ .ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"),
+ }
+ }
+ if (comp.config.output_mode == .Exe) {
+ try argv.append(try allocPrint(arena, "-STACK:{d}", .{base.stack_size}));
+ }
+ try argv.append(try allocPrint(arena, "-BASE:{d}", .{coff.image_base}));
+
+ switch (base.build_id) {
+ .none => try argv.append("-BUILD-ID:NO"),
+ .fast => try argv.append("-BUILD-ID"),
+ .uuid, .sha1, .md5, .hexstring => {},
+ }
+
+ if (target.cpu.arch == .x86) {
+ try argv.append("-MACHINE:X86");
+ } else if (target.cpu.arch == .x86_64) {
+ try argv.append("-MACHINE:X64");
+ } else if (target.cpu.arch == .thumb) {
+ try argv.append("-MACHINE:ARM");
+ } else if (target.cpu.arch == .aarch64) {
+ try argv.append("-MACHINE:ARM64");
+ }
+
+ for (comp.force_undefined_symbols.keys()) |symbol| {
+ try argv.append(try allocPrint(arena, "-INCLUDE:{s}", .{symbol}));
+ }
+
+ if (is_dyn_lib) {
+ try argv.append("-DLL");
+ }
+
+ if (entry_name) |name| {
+ try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{name}));
+ }
+
+ if (coff.repro) {
+ try argv.append("-BREPRO");
+ }
+
+ if (coff.tsaware) {
+ try argv.append("-tsaware");
+ }
+ if (coff.nxcompat) {
+ try argv.append("-nxcompat");
+ }
+ if (!coff.dynamicbase) {
+ try argv.append("-dynamicbase:NO");
+ }
+ if (base.allow_shlib_undefined) {
+ try argv.append("-FORCE:UNRESOLVED");
+ }
+
+ try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
+
+ if (comp.emit_implib) |raw_emit_path| {
+ const path = try comp.resolveEmitPathFlush(arena, .temp, raw_emit_path);
+ try argv.append(try allocPrint(arena, "-IMPLIB:{}", .{path}));
+ }
+
+ if (comp.config.link_libc) {
+ if (comp.libc_installation) |libc_installation| {
+ try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));
+
+ if (target.abi == .msvc or target.abi == .itanium) {
+ try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.msvc_lib_dir.?}));
+ try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.kernel32_lib_dir.?}));
+ }
+ }
+ }
+
+ for (coff.lib_directories) |lib_directory| {
+ try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_directory.path orelse "."}));
+ }
+
+ try argv.ensureUnusedCapacity(comp.link_inputs.len);
+ for (comp.link_inputs) |link_input| switch (link_input) {
+ .dso_exact => unreachable, // not applicable to PE/COFF
+ inline .dso, .res => |x| {
+ argv.appendAssumeCapacity(try x.path.toString(arena));
+ },
+ .object, .archive => |obj| {
+ if (obj.must_link) {
+ argv.appendAssumeCapacity(try allocPrint(arena, "-WHOLEARCHIVE:{}", .{@as(Cache.Path, obj.path)}));
+ } else {
+ argv.appendAssumeCapacity(try obj.path.toString(arena));
+ }
+ },
+ };
+
+ for (comp.c_object_table.keys()) |key| {
+ try argv.append(try key.status.success.object_path.toString(arena));
+ }
+
+ for (comp.win32_resource_table.keys()) |key| {
+ try argv.append(key.status.success.res_path);
+ }
+
+ if (zcu_obj_path) |p| {
+ try argv.append(try p.toString(arena));
+ }
+
+ if (coff.module_definition_file) |def| {
+ try argv.append(try allocPrint(arena, "-DEF:{s}", .{def}));
+ }
+
+ const resolved_subsystem: ?std.Target.SubSystem = blk: {
+ if (coff.subsystem) |explicit| break :blk explicit;
+ switch (target.os.tag) {
+ .windows => {
+ if (comp.zcu != null) {
+ if (coff.lld_export_flags.dllmain_crt_startup or is_dyn_lib)
+ break :blk null;
+ if (coff.lld_export_flags.c_main or comp.config.is_test or
+ coff.lld_export_flags.winmain_crt_startup or
+ coff.lld_export_flags.wwinmain_crt_startup)
+ {
+ break :blk .Console;
+ }
+ if (coff.lld_export_flags.winmain or coff.lld_export_flags.wwinmain)
+ break :blk .Windows;
+ }
+ },
+ .uefi => break :blk .EfiApplication,
+ else => {},
+ }
+ break :blk null;
+ };
+
+ const Mode = enum { uefi, win32 };
+ const mode: Mode = mode: {
+ if (resolved_subsystem) |subsystem| {
+ const subsystem_suffix = try allocPrint(arena, ",{d}.{d}", .{
+ coff.major_subsystem_version, coff.minor_subsystem_version,
+ });
+
+ switch (subsystem) {
+ .Console => {
+ try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{
+ subsystem_suffix,
+ }));
+ break :mode .win32;
+ },
+ .EfiApplication => {
+ try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{
+ subsystem_suffix,
+ }));
+ break :mode .uefi;
+ },
+ .EfiBootServiceDriver => {
+ try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{
+ subsystem_suffix,
+ }));
+ break :mode .uefi;
+ },
+ .EfiRom => {
+ try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{
+ subsystem_suffix,
+ }));
+ break :mode .uefi;
+ },
+ .EfiRuntimeDriver => {
+ try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{
+ subsystem_suffix,
+ }));
+ break :mode .uefi;
+ },
+ .Native => {
+ try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{
+ subsystem_suffix,
+ }));
+ break :mode .win32;
+ },
+ .Posix => {
+ try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{
+ subsystem_suffix,
+ }));
+ break :mode .win32;
+ },
+ .Windows => {
+ try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{
+ subsystem_suffix,
+ }));
+ break :mode .win32;
+ },
+ }
+ } else if (target.os.tag == .uefi) {
+ break :mode .uefi;
+ } else {
+ break :mode .win32;
+ }
+ };
+
+ switch (mode) {
+ .uefi => try argv.appendSlice(&[_][]const u8{
+ "-BASE:0",
+ "-ENTRY:EfiMain",
+ "-OPT:REF",
+ "-SAFESEH:NO",
+ "-MERGE:.rdata=.data",
+ "-NODEFAULTLIB",
+ "-SECTION:.xdata,D",
+ }),
+ .win32 => {
+ if (link_in_crt) {
+ if (target.abi.isGnu()) {
+ if (target.cpu.arch == .x86) {
+ try argv.append("-ALTERNATENAME:__image_base__=___ImageBase");
+ } else {
+ try argv.append("-ALTERNATENAME:__image_base__=__ImageBase");
+ }
+
+ if (is_dyn_lib) {
+ try argv.append(try comp.crtFileAsString(arena, "dllcrt2.obj"));
+ if (target.cpu.arch == .x86) {
+ try argv.append("-ALTERNATENAME:__DllMainCRTStartup@12=_DllMainCRTStartup@12");
+ } else {
+ try argv.append("-ALTERNATENAME:_DllMainCRTStartup=DllMainCRTStartup");
+ }
+ } else {
+ try argv.append(try comp.crtFileAsString(arena, "crt2.obj"));
+ }
+
+ try argv.append(try comp.crtFileAsString(arena, "libmingw32.lib"));
+ } else {
+ try argv.append(switch (comp.config.link_mode) {
+ .static => "libcmt.lib",
+ .dynamic => "msvcrt.lib",
+ });
+
+ const lib_str = switch (comp.config.link_mode) {
+ .static => "lib",
+ .dynamic => "",
+ };
+ try argv.append(try allocPrint(arena, "{s}vcruntime.lib", .{lib_str}));
+ try argv.append(try allocPrint(arena, "{s}ucrt.lib", .{lib_str}));
+
+ //Visual C++ 2015 Conformance Changes
+ //https://msdn.microsoft.com/en-us/library/bb531344.aspx
+ try argv.append("legacy_stdio_definitions.lib");
+
+ // msvcrt depends on kernel32 and ntdll
+ try argv.append("kernel32.lib");
+ try argv.append("ntdll.lib");
+ }
+ } else {
+ try argv.append("-NODEFAULTLIB");
+ if (!is_lib and entry_name == null) {
+ if (comp.zcu != null) {
+ if (coff.lld_export_flags.winmain_crt_startup) {
+ try argv.append("-ENTRY:WinMainCRTStartup");
+ } else {
+ try argv.append("-ENTRY:wWinMainCRTStartup");
+ }
+ } else {
+ try argv.append("-ENTRY:wWinMainCRTStartup");
+ }
+ }
+ }
+ },
+ }
+
+ if (comp.config.link_libc and link_in_crt) {
+ if (comp.zigc_static_lib) |zigc| {
+ try argv.append(try zigc.full_object_path.toString(arena));
+ }
+ }
+
+ // libc++ dep
+ if (comp.config.link_libcpp) {
+ try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena));
+ try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena));
+ }
+
+ // libunwind dep
+ if (comp.config.link_libunwind) {
+ try argv.append(try comp.libunwind_static_lib.?.full_object_path.toString(arena));
+ }
+
+ if (comp.config.any_fuzz) {
+ try argv.append(try comp.fuzzer_lib.?.full_object_path.toString(arena));
+ }
+
+ const ubsan_rt_path: ?Cache.Path = blk: {
+ if (comp.ubsan_rt_lib) |x| break :blk x.full_object_path;
+ if (comp.ubsan_rt_obj) |x| break :blk x.full_object_path;
+ break :blk null;
+ };
+ if (ubsan_rt_path) |path| {
+ try argv.append(try path.toString(arena));
+ }
+
+ if (is_exe_or_dyn_lib and !comp.skip_linker_dependencies) {
+ // MSVC compiler_rt is missing some stuff, so we build it unconditionally but
+ // and rely on weak linkage to allow MSVC compiler_rt functions to override ours.
+ if (comp.compiler_rt_obj) |obj| try argv.append(try obj.full_object_path.toString(arena));
+ if (comp.compiler_rt_lib) |lib| try argv.append(try lib.full_object_path.toString(arena));
+ }
+
+ try argv.ensureUnusedCapacity(comp.windows_libs.count());
+ for (comp.windows_libs.keys()) |key| {
+ const lib_basename = try allocPrint(arena, "{s}.lib", .{key});
+ if (comp.crt_files.get(lib_basename)) |crt_file| {
+ argv.appendAssumeCapacity(try crt_file.full_object_path.toString(arena));
+ continue;
+ }
+ if (try findLib(arena, lib_basename, coff.lib_directories)) |full_path| {
+ argv.appendAssumeCapacity(full_path);
+ continue;
+ }
+ if (target.abi.isGnu()) {
+ const fallback_name = try allocPrint(arena, "lib{s}.dll.a", .{key});
+ if (try findLib(arena, fallback_name, coff.lib_directories)) |full_path| {
+ argv.appendAssumeCapacity(full_path);
+ continue;
+ }
+ }
+ if (target.abi == .msvc or target.abi == .itanium) {
+ argv.appendAssumeCapacity(lib_basename);
+ continue;
+ }
+
+ log.err("DLL import library for -l{s} not found", .{key});
+ return error.DllImportLibraryNotFound;
+ }
+
+ try spawnLld(comp, arena, argv.items);
+ }
+}
+fn findLib(arena: Allocator, name: []const u8, lib_directories: []const Cache.Directory) !?[]const u8 {
+ for (lib_directories) |lib_directory| {
+ lib_directory.handle.access(name, .{}) catch |err| switch (err) {
+ error.FileNotFound => continue,
+ else => |e| return e,
+ };
+ return try lib_directory.join(arena, &.{name});
+ }
+ return null;
+}
+
+fn elfLink(lld: *Lld, arena: Allocator) !void {
+ const comp = lld.base.comp;
+ const gpa = comp.gpa;
+ const diags = &comp.link_diags;
+ const base = &lld.base;
+ const elf = &lld.ofmt.elf;
+
+ const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
+ const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
+
+ const zcu_obj_path: ?Cache.Path = if (comp.zcu != null) p: {
+ break :p try comp.resolveEmitPathFlush(arena, .temp, base.zcu_object_basename.?);
+ } else null;
+
+ const output_mode = comp.config.output_mode;
+ const is_obj = output_mode == .Obj;
+ const is_lib = output_mode == .Lib;
+ const link_mode = comp.config.link_mode;
+ const is_dyn_lib = link_mode == .dynamic and is_lib;
+ const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe;
+ const have_dynamic_linker = link_mode == .dynamic and is_exe_or_dyn_lib;
+ const target = comp.root_mod.resolved_target.result;
+ const compiler_rt_path: ?Cache.Path = blk: {
+ if (comp.compiler_rt_lib) |x| break :blk x.full_object_path;
+ if (comp.compiler_rt_obj) |x| break :blk x.full_object_path;
+ break :blk null;
+ };
+ const ubsan_rt_path: ?Cache.Path = blk: {
+ if (comp.ubsan_rt_lib) |x| break :blk x.full_object_path;
+ if (comp.ubsan_rt_obj) |x| break :blk x.full_object_path;
+ break :blk null;
+ };
+
+ // Due to a deficiency in LLD, we need to special-case BPF to a simple file
+ // copy when generating relocatables. Normally, we would expect `lld -r` to work.
+ // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails
+ // before even generating the relocatable.
+ //
+ // For m68k, we go through this path because LLD doesn't support it yet, but LLVM can
+ // produce usable object files.
+ if (output_mode == .Obj and
+ (comp.config.lto != .none or
+ target.cpu.arch.isBpf() or
+ target.cpu.arch == .lanai or
+ target.cpu.arch == .m68k or
+ target.cpu.arch.isSPARC() or
+ target.cpu.arch == .ve or
+ target.cpu.arch == .xcore))
+ {
+ // In this case we must do a simple file copy
+ // here. TODO: think carefully about how we can avoid this redundant operation when doing
+ // build-obj. See also the corresponding TODO in linkAsArchive.
+ const the_object_path = blk: {
+ if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
+
+ if (comp.c_object_table.count() != 0)
+ break :blk comp.c_object_table.keys()[0].status.success.object_path;
+
+ if (zcu_obj_path) |p|
+ break :blk p;
+
+ // TODO I think this is unreachable. Audit this situation when solving the above TODO
+ // regarding eliding redundant object -> object transformations.
+ return error.NoObjectsToLink;
+ };
+ try std.fs.Dir.copyFile(
+ the_object_path.root_dir.handle,
+ the_object_path.sub_path,
+ directory.handle,
+ base.emit.sub_path,
+ .{},
+ );
+ } else {
+ // Create an LLD command line and invoke it.
+ var argv = std.ArrayList([]const u8).init(gpa);
+ defer argv.deinit();
+ // We will invoke ourselves as a child process to gain access to LLD.
+ // This is necessary because LLD does not behave properly as a library -
+ // it calls exit() and does not reset all global data between invocations.
+ const linker_command = "ld.lld";
+ try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
+ if (is_obj) {
+ try argv.append("-r");
+ }
+
+ try argv.append("--error-limit=0");
+
+ if (comp.sysroot) |sysroot| {
+ try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot}));
+ }
+
+ if (target_util.llvmMachineAbi(target)) |mabi| {
+ try argv.appendSlice(&.{
+ "-mllvm",
+ try std.fmt.allocPrint(arena, "-target-abi={s}", .{mabi}),
+ });
+ }
+
+ try argv.appendSlice(&.{
+ "-mllvm",
+ try std.fmt.allocPrint(arena, "-float-abi={s}", .{if (target.abi.float() == .hard) "hard" else "soft"}),
+ });
+
+ if (comp.config.lto != .none) {
+ switch (comp.root_mod.optimize_mode) {
+ .Debug => {},
+ .ReleaseSmall => try argv.append("--lto-O2"),
+ .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"),
+ }
+ }
+ switch (comp.root_mod.optimize_mode) {
+ .Debug => {},
+ .ReleaseSmall => try argv.append("-O2"),
+ .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
+ }
+
+ if (elf.entry_name) |name| {
+ try argv.appendSlice(&.{ "--entry", name });
+ }
+
+ for (comp.force_undefined_symbols.keys()) |sym| {
+ try argv.append("-u");
+ try argv.append(sym);
+ }
+
+ switch (elf.hash_style) {
+ .gnu => try argv.append("--hash-style=gnu"),
+ .sysv => try argv.append("--hash-style=sysv"),
+ .both => {}, // this is the default
+ }
+
+ if (output_mode == .Exe) {
+ try argv.appendSlice(&.{
+ "-z",
+ try std.fmt.allocPrint(arena, "stack-size={d}", .{base.stack_size}),
+ });
+ }
+
+ switch (base.build_id) {
+ .none => try argv.append("--build-id=none"),
+ .fast, .uuid, .sha1, .md5 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
+ @tagName(base.build_id),
+ })),
+ .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{
+ std.fmt.fmtSliceHexLower(hs.toSlice()),
+ })),
+ }
+
+ try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{elf.image_base}));
+
+ if (elf.linker_script) |linker_script| {
+ try argv.append("-T");
+ try argv.append(linker_script);
+ }
+
+ if (elf.sort_section) |how| {
+ const arg = try std.fmt.allocPrint(arena, "--sort-section={s}", .{@tagName(how)});
+ try argv.append(arg);
+ }
+
+ if (base.gc_sections) {
+ try argv.append("--gc-sections");
+ }
+
+ if (base.print_gc_sections) {
+ try argv.append("--print-gc-sections");
+ }
+
+ if (elf.print_icf_sections) {
+ try argv.append("--print-icf-sections");
+ }
+
+ if (elf.print_map) {
+ try argv.append("--print-map");
+ }
+
+ if (comp.link_eh_frame_hdr) {
+ try argv.append("--eh-frame-hdr");
+ }
+
+ if (elf.emit_relocs) {
+ try argv.append("--emit-relocs");
+ }
+
+ if (comp.config.rdynamic) {
+ try argv.append("--export-dynamic");
+ }
+
+ if (comp.config.debug_format == .strip) {
+ try argv.append("-s");
+ }
+
+ if (elf.z_nodelete) {
+ try argv.append("-z");
+ try argv.append("nodelete");
+ }
+ if (elf.z_notext) {
+ try argv.append("-z");
+ try argv.append("notext");
+ }
+ if (elf.z_defs) {
+ try argv.append("-z");
+ try argv.append("defs");
+ }
+ if (elf.z_origin) {
+ try argv.append("-z");
+ try argv.append("origin");
+ }
+ if (elf.z_nocopyreloc) {
+ try argv.append("-z");
+ try argv.append("nocopyreloc");
+ }
+ if (elf.z_now) {
+ // LLD defaults to -zlazy
+ try argv.append("-znow");
+ }
+ if (!elf.z_relro) {
+ // LLD defaults to -zrelro
+ try argv.append("-znorelro");
+ }
+ if (elf.z_common_page_size) |size| {
+ try argv.append("-z");
+ try argv.append(try std.fmt.allocPrint(arena, "common-page-size={d}", .{size}));
+ }
+ if (elf.z_max_page_size) |size| {
+ try argv.append("-z");
+ try argv.append(try std.fmt.allocPrint(arena, "max-page-size={d}", .{size}));
+ }
+
+ if (getLDMOption(target)) |ldm| {
+ try argv.append("-m");
+ try argv.append(ldm);
+ }
+
+ if (link_mode == .static) {
+ if (target.cpu.arch.isArm()) {
+ try argv.append("-Bstatic");
+ } else {
+ try argv.append("-static");
+ }
+ } else if (switch (target.os.tag) {
+ else => is_dyn_lib,
+ .haiku => is_exe_or_dyn_lib,
+ }) {
+ try argv.append("-shared");
+ }
+
+ if (comp.config.pie and output_mode == .Exe) {
+ try argv.append("-pie");
+ }
+
+ if (is_exe_or_dyn_lib and target.os.tag == .netbsd) {
+ // Add options to produce shared objects with only 2 PT_LOAD segments.
+ // NetBSD expects 2 PT_LOAD segments in a shared object, otherwise
+ // ld.elf_so fails loading dynamic libraries with "not found" error.
+ // See https://github.com/ziglang/zig/issues/9109 .
+ try argv.append("--no-rosegment");
+ try argv.append("-znorelro");
+ }
+
+ try argv.append("-o");
+ try argv.append(full_out_path);
+
+ // csu prelude
+ const csu = try comp.getCrtPaths(arena);
+ if (csu.crt0) |p| try argv.append(try p.toString(arena));
+ if (csu.crti) |p| try argv.append(try p.toString(arena));
+ if (csu.crtbegin) |p| try argv.append(try p.toString(arena));
+
+ for (elf.rpath_list) |rpath| {
+ try argv.appendSlice(&.{ "-rpath", rpath });
+ }
+
+ for (elf.symbol_wrap_set) |symbol_name| {
+ try argv.appendSlice(&.{ "-wrap", symbol_name });
+ }
+
+ if (comp.config.link_libc) {
+ if (comp.libc_installation) |libc_installation| {
+ try argv.append("-L");
+ try argv.append(libc_installation.crt_dir.?);
+ }
+ }
+
+ if (have_dynamic_linker and
+ (comp.config.link_libc or comp.root_mod.resolved_target.is_explicit_dynamic_linker))
+ {
+ if (target.dynamic_linker.get()) |dynamic_linker| {
+ try argv.append("-dynamic-linker");
+ try argv.append(dynamic_linker);
+ }
+ }
+
+ if (is_dyn_lib) {
+ if (elf.soname) |soname| {
+ try argv.append("-soname");
+ try argv.append(soname);
+ }
+ if (elf.version_script) |version_script| {
+ try argv.append("-version-script");
+ try argv.append(version_script);
+ }
+ if (elf.allow_undefined_version) {
+ try argv.append("--undefined-version");
+ } else {
+ try argv.append("--no-undefined-version");
+ }
+ if (elf.enable_new_dtags) |enable_new_dtags| {
+ if (enable_new_dtags) {
+ try argv.append("--enable-new-dtags");
+ } else {
+ try argv.append("--disable-new-dtags");
+ }
+ }
+ }
+
+ // Positional arguments to the linker such as object files.
+ var whole_archive = false;
+
+ for (base.comp.link_inputs) |link_input| switch (link_input) {
+ .res => unreachable, // Windows-only
+ .dso => continue,
+ .object, .archive => |obj| {
+ if (obj.must_link and !whole_archive) {
+ try argv.append("-whole-archive");
+ whole_archive = true;
+ } else if (!obj.must_link and whole_archive) {
+ try argv.append("-no-whole-archive");
+ whole_archive = false;
+ }
+ try argv.append(try obj.path.toString(arena));
+ },
+ .dso_exact => |dso_exact| {
+ assert(dso_exact.name[0] == ':');
+ try argv.appendSlice(&.{ "-l", dso_exact.name });
+ },
+ };
+
+ if (whole_archive) {
+ try argv.append("-no-whole-archive");
+ whole_archive = false;
+ }
+
+ for (comp.c_object_table.keys()) |key| {
+ try argv.append(try key.status.success.object_path.toString(arena));
+ }
+
+ if (zcu_obj_path) |p| {
+ try argv.append(try p.toString(arena));
+ }
+
+ if (comp.tsan_lib) |lib| {
+ assert(comp.config.any_sanitize_thread);
+ try argv.append(try lib.full_object_path.toString(arena));
+ }
+
+ if (comp.fuzzer_lib) |lib| {
+ assert(comp.config.any_fuzz);
+ try argv.append(try lib.full_object_path.toString(arena));
+ }
+
+ if (ubsan_rt_path) |p| {
+ try argv.append(try p.toString(arena));
+ }
+
+ // Shared libraries.
+ if (is_exe_or_dyn_lib) {
+ // Worst-case, we need an --as-needed argument for every lib, as well
+ // as one before and one after.
+ try argv.ensureUnusedCapacity(2 * base.comp.link_inputs.len + 2);
+ argv.appendAssumeCapacity("--as-needed");
+ var as_needed = true;
+
+ for (base.comp.link_inputs) |link_input| switch (link_input) {
+ .res => unreachable, // Windows-only
+ .object, .archive, .dso_exact => continue,
+ .dso => |dso| {
+ const lib_as_needed = !dso.needed;
+ switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) {
+ 0b00, 0b11 => {},
+ 0b01 => {
+ argv.appendAssumeCapacity("--no-as-needed");
+ as_needed = false;
+ },
+ 0b10 => {
+ argv.appendAssumeCapacity("--as-needed");
+ as_needed = true;
+ },
+ }
+
+ // By this time, we depend on these libs being dynamically linked
+ // libraries and not static libraries (the check for that needs to be earlier),
+ // but they could be full paths to .so files, in which case we
+ // want to avoid prepending "-l".
+ argv.appendAssumeCapacity(try dso.path.toString(arena));
+ },
+ };
+
+ if (!as_needed) {
+ argv.appendAssumeCapacity("--as-needed");
+ as_needed = true;
+ }
+
+ // libc++ dep
+ if (comp.config.link_libcpp) {
+ try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena));
+ try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena));
+ }
+
+ // libunwind dep
+ if (comp.config.link_libunwind) {
+ try argv.append(try comp.libunwind_static_lib.?.full_object_path.toString(arena));
+ }
+
+ // libc dep
+ diags.flags.missing_libc = false;
+ if (comp.config.link_libc) {
+ if (comp.libc_installation != null) {
+ const needs_grouping = link_mode == .static;
+ if (needs_grouping) try argv.append("--start-group");
+ try argv.appendSlice(target_util.libcFullLinkFlags(target));
+ if (needs_grouping) try argv.append("--end-group");
+ } else if (target.isGnuLibC()) {
+ for (glibc.libs) |lib| {
+ if (lib.removed_in) |rem_in| {
+ if (target.os.versionRange().gnuLibCVersion().?.order(rem_in) != .lt) continue;
+ }
+
+ const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
+ comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
+ });
+ try argv.append(lib_path);
+ }
+ try argv.append(try comp.crtFileAsString(arena, "libc_nonshared.a"));
+ } else if (target.isMuslLibC()) {
+ try argv.append(try comp.crtFileAsString(arena, switch (link_mode) {
+ .static => "libc.a",
+ .dynamic => "libc.so",
+ }));
+ } else if (target.isFreeBSDLibC()) {
+ for (freebsd.libs) |lib| {
+ const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
+ comp.freebsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
+ });
+ try argv.append(lib_path);
+ }
+ } else if (target.isNetBSDLibC()) {
+ for (netbsd.libs) |lib| {
+ const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
+ comp.netbsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
+ });
+ try argv.append(lib_path);
+ }
+ } else {
+ diags.flags.missing_libc = true;
+ }
+
+ if (comp.zigc_static_lib) |zigc| {
+ try argv.append(try zigc.full_object_path.toString(arena));
+ }
+ }
+ }
+
+ // compiler-rt. Since compiler_rt exports symbols like `memset`, it needs
+ // to be after the shared libraries, so they are picked up from the shared
+ // libraries, not libcompiler_rt.
+ if (compiler_rt_path) |p| {
+ try argv.append(try p.toString(arena));
+ }
+
+ // crt postlude
+ if (csu.crtend) |p| try argv.append(try p.toString(arena));
+ if (csu.crtn) |p| try argv.append(try p.toString(arena));
+
+ if (base.allow_shlib_undefined) {
+ try argv.append("--allow-shlib-undefined");
+ }
+
+ switch (elf.compress_debug_sections) {
+ .none => {},
+ .zlib => try argv.append("--compress-debug-sections=zlib"),
+ .zstd => try argv.append("--compress-debug-sections=zstd"),
+ }
+
+ if (elf.bind_global_refs_locally) {
+ try argv.append("-Bsymbolic");
+ }
+
+ try spawnLld(comp, arena, argv.items);
+ }
+}
+fn getLDMOption(target: std.Target) ?[]const u8 {
+ // This should only return emulations understood by LLD's parseEmulation().
+ return switch (target.cpu.arch) {
+ .aarch64 => switch (target.os.tag) {
+ .linux => "aarch64linux",
+ else => "aarch64elf",
+ },
+ .aarch64_be => switch (target.os.tag) {
+ .linux => "aarch64linuxb",
+ else => "aarch64elfb",
+ },
+ .amdgcn => "elf64_amdgpu",
+ .arm, .thumb => switch (target.os.tag) {
+ .linux => "armelf_linux_eabi",
+ else => "armelf",
+ },
+ .armeb, .thumbeb => switch (target.os.tag) {
+ .linux => "armelfb_linux_eabi",
+ else => "armelfb",
+ },
+ .hexagon => "hexagonelf",
+ .loongarch32 => "elf32loongarch",
+ .loongarch64 => "elf64loongarch",
+ .mips => switch (target.os.tag) {
+ .freebsd => "elf32btsmip_fbsd",
+ else => "elf32btsmip",
+ },
+ .mipsel => switch (target.os.tag) {
+ .freebsd => "elf32ltsmip_fbsd",
+ else => "elf32ltsmip",
+ },
+ .mips64 => switch (target.os.tag) {
+ .freebsd => switch (target.abi) {
+ .gnuabin32, .muslabin32 => "elf32btsmipn32_fbsd",
+ else => "elf64btsmip_fbsd",
+ },
+ else => switch (target.abi) {
+ .gnuabin32, .muslabin32 => "elf32btsmipn32",
+ else => "elf64btsmip",
+ },
+ },
+ .mips64el => switch (target.os.tag) {
+ .freebsd => switch (target.abi) {
+ .gnuabin32, .muslabin32 => "elf32ltsmipn32_fbsd",
+ else => "elf64ltsmip_fbsd",
+ },
+ else => switch (target.abi) {
+ .gnuabin32, .muslabin32 => "elf32ltsmipn32",
+ else => "elf64ltsmip",
+ },
+ },
+ .msp430 => "msp430elf",
+ .powerpc => switch (target.os.tag) {
+ .freebsd => "elf32ppc_fbsd",
+ .linux => "elf32ppclinux",
+ else => "elf32ppc",
+ },
+ .powerpcle => switch (target.os.tag) {
+ .linux => "elf32lppclinux",
+ else => "elf32lppc",
+ },
+ .powerpc64 => "elf64ppc",
+ .powerpc64le => "elf64lppc",
+ .riscv32 => "elf32lriscv",
+ .riscv64 => "elf64lriscv",
+ .s390x => "elf64_s390",
+ .sparc64 => "elf64_sparc",
+ .x86 => switch (target.os.tag) {
+ .freebsd => "elf_i386_fbsd",
+ else => "elf_i386",
+ },
+ .x86_64 => switch (target.abi) {
+ .gnux32, .muslx32 => "elf32_x86_64",
+ else => "elf_x86_64",
+ },
+ else => null,
+ };
+}
+fn wasmLink(lld: *Lld, arena: Allocator) !void {
+ const comp = lld.base.comp;
+ const shared_memory = comp.config.shared_memory;
+ const export_memory = comp.config.export_memory;
+ const import_memory = comp.config.import_memory;
+ const target = comp.root_mod.resolved_target.result;
+ const base = &lld.base;
+ const wasm = &lld.ofmt.wasm;
+
+ const gpa = comp.gpa;
+
+ const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
+ const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
+
+ const zcu_obj_path: ?Cache.Path = if (comp.zcu != null) p: {
+ break :p try comp.resolveEmitPathFlush(arena, .temp, base.zcu_object_basename.?);
+ } else null;
+
+ const is_obj = comp.config.output_mode == .Obj;
+ const compiler_rt_path: ?Cache.Path = blk: {
+ if (comp.compiler_rt_lib) |lib| break :blk lib.full_object_path;
+ if (comp.compiler_rt_obj) |obj| break :blk obj.full_object_path;
+ break :blk null;
+ };
+ const ubsan_rt_path: ?Cache.Path = blk: {
+ if (comp.ubsan_rt_lib) |lib| break :blk lib.full_object_path;
+ if (comp.ubsan_rt_obj) |obj| break :blk obj.full_object_path;
+ break :blk null;
+ };
+
+ if (is_obj) {
+ // LLD's WASM driver does not support the equivalent of `-r` so we do a simple file copy
+ // here. TODO: think carefully about how we can avoid this redundant operation when doing
+ // build-obj. See also the corresponding TODO in linkAsArchive.
+ const the_object_path = blk: {
+ if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
+
+ if (comp.c_object_table.count() != 0)
+ break :blk comp.c_object_table.keys()[0].status.success.object_path;
+
+ if (zcu_obj_path) |p|
+ break :blk p;
+
+ // TODO I think this is unreachable. Audit this situation when solving the above TODO
+ // regarding eliding redundant object -> object transformations.
+ return error.NoObjectsToLink;
+ };
+ try fs.Dir.copyFile(
+ the_object_path.root_dir.handle,
+ the_object_path.sub_path,
+ directory.handle,
+ base.emit.sub_path,
+ .{},
+ );
+ } else {
+ // Create an LLD command line and invoke it.
+ var argv = std.ArrayList([]const u8).init(gpa);
+ defer argv.deinit();
+ // We will invoke ourselves as a child process to gain access to LLD.
+ // This is necessary because LLD does not behave properly as a library -
+ // it calls exit() and does not reset all global data between invocations.
+ const linker_command = "wasm-ld";
+ try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
+ try argv.append("--error-limit=0");
+
+ if (comp.config.lto != .none) {
+ switch (comp.root_mod.optimize_mode) {
+ .Debug => {},
+ .ReleaseSmall => try argv.append("-O2"),
+ .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
+ }
+ }
+
+ if (import_memory) {
+ try argv.append("--import-memory");
+ }
+
+ if (export_memory) {
+ try argv.append("--export-memory");
+ }
+
+ if (wasm.import_table) {
+ assert(!wasm.export_table);
+ try argv.append("--import-table");
+ }
+
+ if (wasm.export_table) {
+ assert(!wasm.import_table);
+ try argv.append("--export-table");
+ }
+
+ // For wasm-ld we only need to specify '--no-gc-sections' when the user explicitly
+ // specified it as garbage collection is enabled by default.
+ if (!base.gc_sections) {
+ try argv.append("--no-gc-sections");
+ }
+
+ if (comp.config.debug_format == .strip) {
+ try argv.append("-s");
+ }
+
+ if (wasm.initial_memory) |initial_memory| {
+ const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory});
+ try argv.append(arg);
+ }
+
+ if (wasm.max_memory) |max_memory| {
+ const arg = try std.fmt.allocPrint(arena, "--max-memory={d}", .{max_memory});
+ try argv.append(arg);
+ }
+
+ if (shared_memory) {
+ try argv.append("--shared-memory");
+ }
+
+ if (wasm.global_base) |global_base| {
+ const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base});
+ try argv.append(arg);
+ } else {
+ // We prepend it by default, so when a stack overflow happens the runtime will trap correctly,
+ // rather than silently overwrite all global declarations. See https://github.com/ziglang/zig/issues/4496
+ //
+ // The user can overwrite this behavior by setting the global-base
+ try argv.append("--stack-first");
+ }
+
+ // Users are allowed to specify which symbols they want to export to the wasm host.
+ for (wasm.export_symbol_names) |symbol_name| {
+ const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name});
+ try argv.append(arg);
+ }
+
+ if (comp.config.rdynamic) {
+ try argv.append("--export-dynamic");
+ }
+
+ if (wasm.entry_name) |entry_name| {
+ try argv.appendSlice(&.{ "--entry", entry_name });
+ } else {
+ try argv.append("--no-entry");
+ }
+
+ try argv.appendSlice(&.{
+ "-z",
+ try std.fmt.allocPrint(arena, "stack-size={d}", .{base.stack_size}),
+ });
+
+ switch (base.build_id) {
+ .none => try argv.append("--build-id=none"),
+ .fast, .uuid, .sha1 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
+ @tagName(base.build_id),
+ })),
+ .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{
+ std.fmt.fmtSliceHexLower(hs.toSlice()),
+ })),
+ .md5 => {},
+ }
+
+ if (wasm.import_symbols) {
+ try argv.append("--allow-undefined");
+ }
+
+ if (comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic) {
+ try argv.append("--shared");
+ }
+ if (comp.config.pie) {
+ try argv.append("--pie");
+ }
+
+ try argv.appendSlice(&.{ "-o", full_out_path });
+
+ if (target.cpu.arch == .wasm64) {
+ try argv.append("-mwasm64");
+ }
+
+ const is_exe_or_dyn_lib = comp.config.output_mode == .Exe or
+ (comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic);
+
+ if (comp.config.link_libc and is_exe_or_dyn_lib) {
+ if (target.os.tag == .wasi) {
+ for (comp.wasi_emulated_libs) |crt_file| {
+ try argv.append(try comp.crtFileAsString(
+ arena,
+ wasi_libc.emulatedLibCRFileLibName(crt_file),
+ ));
+ }
+
+ try argv.append(try comp.crtFileAsString(
+ arena,
+ wasi_libc.execModelCrtFileFullName(comp.config.wasi_exec_model),
+ ));
+ try argv.append(try comp.crtFileAsString(arena, "libc.a"));
+ }
+
+ if (comp.zigc_static_lib) |zigc| {
+ try argv.append(try zigc.full_object_path.toString(arena));
+ }
+
+ if (comp.config.link_libcpp) {
+ try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena));
+ try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena));
+ }
+ }
+
+ // Positional arguments to the linker such as object files.
+ var whole_archive = false;
+ for (comp.link_inputs) |link_input| switch (link_input) {
+ .object, .archive => |obj| {
+ if (obj.must_link and !whole_archive) {
+ try argv.append("-whole-archive");
+ whole_archive = true;
+ } else if (!obj.must_link and whole_archive) {
+ try argv.append("-no-whole-archive");
+ whole_archive = false;
+ }
+ try argv.append(try obj.path.toString(arena));
+ },
+ .dso => |dso| {
+ try argv.append(try dso.path.toString(arena));
+ },
+ .dso_exact => unreachable,
+ .res => unreachable,
+ };
+ if (whole_archive) {
+ try argv.append("-no-whole-archive");
+ whole_archive = false;
+ }
+
+ for (comp.c_object_table.keys()) |key| {
+ try argv.append(try key.status.success.object_path.toString(arena));
+ }
+ if (zcu_obj_path) |p| {
+ try argv.append(try p.toString(arena));
+ }
+
+ if (compiler_rt_path) |p| {
+ try argv.append(try p.toString(arena));
+ }
+
+ if (ubsan_rt_path) |p| {
+ try argv.append(try p.toStringZ(arena));
+ }
+
+ try spawnLld(comp, arena, argv.items);
+
+ // Give +x to the .wasm file if it is an executable and the OS is WASI.
+ // Some systems may be configured to execute such binaries directly. Even if that
+ // is not the case, it means we will get "exec format error" when trying to run
+ // it, and then can react to that in the same way as trying to run an ELF file
+ // from a foreign CPU architecture.
+ if (fs.has_executable_bit and target.os.tag == .wasi and
+ comp.config.output_mode == .Exe)
+ {
+ // TODO: what's our strategy for reporting linker errors from this function?
+ // report a nice error here with the file path if it fails instead of
+ // just returning the error code.
+ // chmod does not interact with umask, so we use a conservative -rwxr--r-- here.
+ std.posix.fchmodat(fs.cwd().fd, full_out_path, 0o744, 0) catch |err| switch (err) {
+ error.OperationNotSupported => unreachable, // Not a symlink.
+ else => |e| return e,
+ };
+ }
+ }
+}
+
+fn spawnLld(
+ comp: *Compilation,
+ arena: Allocator,
+ argv: []const []const u8,
+) !void {
+ if (comp.verbose_link) {
+ // Skip over our own name so that the LLD linker name is the first argv item.
+ Compilation.dump_argv(argv[1..]);
+ }
+
+ // If possible, we run LLD as a child process because it does not always
+ // behave properly as a library, unfortunately.
+ // https://github.com/ziglang/zig/issues/3825
+ if (!std.process.can_spawn) {
+ const exit_code = try lldMain(arena, argv, false);
+ if (exit_code == 0) return;
+ if (comp.clang_passthrough_mode) std.process.exit(exit_code);
+ return error.LinkFailure;
+ }
+
+ var stderr: []u8 = &.{};
+ defer comp.gpa.free(stderr);
+
+ var child = std.process.Child.init(argv, arena);
+ const term = (if (comp.clang_passthrough_mode) term: {
+ child.stdin_behavior = .Inherit;
+ child.stdout_behavior = .Inherit;
+ child.stderr_behavior = .Inherit;
+
+ break :term child.spawnAndWait();
+ } else term: {
+ child.stdin_behavior = .Ignore;
+ child.stdout_behavior = .Ignore;
+ child.stderr_behavior = .Pipe;
+
+ child.spawn() catch |err| break :term err;
+ stderr = try child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize));
+ break :term child.wait();
+ }) catch |first_err| term: {
+ const err = switch (first_err) {
+ error.NameTooLong => err: {
+ const s = fs.path.sep_str;
+ const rand_int = std.crypto.random.int(u64);
+ const rsp_path = "tmp" ++ s ++ std.fmt.hex(rand_int) ++ ".rsp";
+
+ const rsp_file = try comp.dirs.local_cache.handle.createFileZ(rsp_path, .{});
+ defer comp.dirs.local_cache.handle.deleteFileZ(rsp_path) catch |err|
+ log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) });
+ {
+ defer rsp_file.close();
+ var rsp_buf = std.io.bufferedWriter(rsp_file.writer());
+ const rsp_writer = rsp_buf.writer();
+ for (argv[2..]) |arg| {
+ try rsp_writer.writeByte('"');
+ for (arg) |c| {
+ switch (c) {
+ '\"', '\\' => try rsp_writer.writeByte('\\'),
+ else => {},
+ }
+ try rsp_writer.writeByte(c);
+ }
+ try rsp_writer.writeByte('"');
+ try rsp_writer.writeByte('\n');
+ }
+ try rsp_buf.flush();
+ }
+
+ var rsp_child = std.process.Child.init(&.{ argv[0], argv[1], try std.fmt.allocPrint(
+ arena,
+ "@{s}",
+ .{try comp.dirs.local_cache.join(arena, &.{rsp_path})},
+ ) }, arena);
+ if (comp.clang_passthrough_mode) {
+ rsp_child.stdin_behavior = .Inherit;
+ rsp_child.stdout_behavior = .Inherit;
+ rsp_child.stderr_behavior = .Inherit;
+
+ break :term rsp_child.spawnAndWait() catch |err| break :err err;
+ } else {
+ rsp_child.stdin_behavior = .Ignore;
+ rsp_child.stdout_behavior = .Ignore;
+ rsp_child.stderr_behavior = .Pipe;
+
+ rsp_child.spawn() catch |err| break :err err;
+ stderr = try rsp_child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize));
+ break :term rsp_child.wait() catch |err| break :err err;
+ }
+ },
+ else => first_err,
+ };
+ log.err("unable to spawn LLD {s}: {s}", .{ argv[0], @errorName(err) });
+ return error.UnableToSpawnSelf;
+ };
+
+ const diags = &comp.link_diags;
+ switch (term) {
+ .Exited => |code| if (code != 0) {
+ if (comp.clang_passthrough_mode) std.process.exit(code);
+ diags.lockAndParseLldStderr(argv[1], stderr);
+ return error.LinkFailure;
+ },
+ else => {
+ if (comp.clang_passthrough_mode) std.process.abort();
+ return diags.fail("{s} terminated with stderr:\n{s}", .{ argv[0], stderr });
+ },
+ }
+
+ if (stderr.len > 0) log.warn("unexpected LLD stderr:\n{s}", .{stderr});
+}
+
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const Cache = std.Build.Cache;
+const allocPrint = std.fmt.allocPrint;
+const assert = std.debug.assert;
+const fs = std.fs;
+const log = std.log.scoped(.link);
+const mem = std.mem;
+
+const Compilation = @import("../Compilation.zig");
+const Zcu = @import("../Zcu.zig");
+const dev = @import("../dev.zig");
+const freebsd = @import("../libs/freebsd.zig");
+const glibc = @import("../libs/glibc.zig");
+const netbsd = @import("../libs/netbsd.zig");
+const wasi_libc = @import("../libs/wasi_libc.zig");
+const link = @import("../link.zig");
+const lldMain = @import("../main.zig").lldMain;
+const target_util = @import("../target.zig");
+const trace = @import("../tracy.zig").trace;
+const Lld = @This();
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 3ddc12a5b0..3f3a94bee7 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -6,9 +6,6 @@ base: link.File,
rpath_list: []const []const u8,
-/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
-llvm_object: ?LlvmObject.Ptr = null,
-
/// Debug symbols bundle (or dSym).
d_sym: ?DebugSymbols = null,
@@ -176,13 +173,6 @@ pub fn createEmpty(
const output_mode = comp.config.output_mode;
const link_mode = comp.config.link_mode;
- // If using LLVM to generate the object file for the zig compilation unit,
- // we need a place to put the object file so that it can be subsequently
- // handled.
- const zcu_object_sub_path = if (!use_llvm)
- null
- else
- try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path});
const allow_shlib_undefined = options.allow_shlib_undefined orelse false;
const self = try arena.create(MachO);
@@ -191,13 +181,15 @@ pub fn createEmpty(
.tag = .macho,
.comp = comp,
.emit = emit,
- .zcu_object_sub_path = zcu_object_sub_path,
+ .zcu_object_basename = if (use_llvm)
+ try std.fmt.allocPrint(arena, "{s}_zcu.o", .{fs.path.stem(emit.sub_path)})
+ else
+ null,
.gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
.print_gc_sections = options.print_gc_sections,
.stack_size = options.stack_size orelse 16777216,
.allow_shlib_undefined = allow_shlib_undefined,
.file = null,
- .disable_lld_caching = options.disable_lld_caching,
.build_id = options.build_id,
},
.rpath_list = options.rpath_list,
@@ -225,15 +217,12 @@ pub fn createEmpty(
.force_load_objc = options.force_load_objc,
.discard_local_symbols = options.discard_local_symbols,
};
- if (use_llvm and comp.config.have_zcu) {
- self.llvm_object = try LlvmObject.create(arena, comp);
- }
errdefer self.base.destroy();
self.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
.truncate = true,
.read = true,
- .mode = link.File.determineMode(false, output_mode, link_mode),
+ .mode = link.File.determineMode(output_mode, link_mode),
});
// Append null file
@@ -280,8 +269,6 @@ pub fn open(
pub fn deinit(self: *MachO) void {
const gpa = self.base.comp.gpa;
- if (self.llvm_object) |llvm_object| llvm_object.deinit();
-
if (self.d_sym) |*d_sym| {
d_sym.deinit();
}
@@ -350,15 +337,6 @@ pub fn flush(
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
) link.File.FlushError!void {
- try self.flushModule(arena, tid, prog_node);
-}
-
-pub fn flushModule(
- self: *MachO,
- arena: Allocator,
- tid: Zcu.PerThread.Id,
- prog_node: std.Progress.Node,
-) link.File.FlushError!void {
const tracy = trace(@src());
defer tracy.end();
@@ -366,28 +344,19 @@ pub fn flushModule(
const gpa = comp.gpa;
const diags = &self.base.comp.link_diags;
- if (self.llvm_object) |llvm_object| {
- try self.base.emitLlvmObject(arena, llvm_object, prog_node);
- }
-
const sub_prog_node = prog_node.start("MachO Flush", 0);
defer sub_prog_node.end();
- const directory = self.base.emit.root_dir;
- const module_obj_path: ?Path = if (self.base.zcu_object_sub_path) |path| .{
- .root_dir = directory,
- .sub_path = if (fs.path.dirname(self.base.emit.sub_path)) |dirname|
- try fs.path.join(arena, &.{ dirname, path })
- else
- path,
+ const zcu_obj_path: ?Path = if (self.base.zcu_object_basename) |raw| p: {
+ break :p try comp.resolveEmitPathFlush(arena, .temp, raw);
} else null;
// --verbose-link
if (comp.verbose_link) try self.dumpArgv(comp);
- if (self.getZigObject()) |zo| try zo.flushModule(self, tid);
- if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path);
- if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path);
+ if (self.getZigObject()) |zo| try zo.flush(self, tid);
+ if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, zcu_obj_path);
+ if (self.base.isObject()) return relocatable.flushObject(self, comp, zcu_obj_path);
var positionals = std.ArrayList(link.Input).init(gpa);
defer positionals.deinit();
@@ -409,7 +378,7 @@ pub fn flushModule(
positionals.appendAssumeCapacity(try link.openObjectInput(diags, key.status.success.object_path));
}
- if (module_obj_path) |path| try positionals.append(try link.openObjectInput(diags, path));
+ if (zcu_obj_path) |path| try positionals.append(try link.openObjectInput(diags, path));
if (comp.config.any_sanitize_thread) {
try positionals.append(try link.openObjectInput(diags, comp.tsan_lib.?.full_object_path));
@@ -629,7 +598,7 @@ pub fn flushModule(
error.LinkFailure => return error.LinkFailure,
else => |e| return diags.fail("failed to calculate and write uuid: {s}", .{@errorName(e)}),
};
- if (self.getDebugSymbols()) |dsym| dsym.flushModule(self) catch |err| switch (err) {
+ if (self.getDebugSymbols()) |dsym| dsym.flush(self) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
else => |e| return diags.fail("failed to get debug symbols: {s}", .{@errorName(e)}),
};
@@ -658,12 +627,9 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
const directory = self.base.emit.root_dir;
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
- const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: {
- if (fs.path.dirname(full_out_path)) |dirname| {
- break :blk try fs.path.join(arena, &.{ dirname, path });
- } else {
- break :blk path;
- }
+ const zcu_obj_path: ?[]const u8 = if (self.base.zcu_object_basename) |raw| p: {
+ const p = try comp.resolveEmitPathFlush(arena, .temp, raw);
+ break :p try p.toString(arena);
} else null;
var argv = std.ArrayList([]const u8).init(arena);
@@ -692,7 +658,7 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
try argv.append(try key.status.success.object_path.toString(arena));
}
- if (module_obj_path) |p| {
+ if (zcu_obj_path) |p| {
try argv.append(p);
}
} else {
@@ -784,7 +750,7 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
try argv.append(try key.status.success.object_path.toString(arena));
}
- if (module_obj_path) |p| {
+ if (zcu_obj_path) |p| {
try argv.append(p);
}
@@ -3073,26 +3039,22 @@ pub fn updateFunc(
self: *MachO,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ mir: *const codegen.AnyMir,
) link.File.UpdateNavError!void {
if (build_options.skip_non_native and builtin.object_format != .macho) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
- return self.getZigObject().?.updateFunc(self, pt, func_index, air, liveness);
+ return self.getZigObject().?.updateFunc(self, pt, func_index, mir);
}
pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
if (build_options.skip_non_native and builtin.object_format != .macho) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav);
return self.getZigObject().?.updateNav(self, pt, nav);
}
pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
- if (self.llvm_object) |_| return;
return self.getZigObject().?.updateLineNumber(pt, ti_id);
}
@@ -3105,7 +3067,6 @@ pub fn updateExports(
if (build_options.skip_non_native and builtin.object_format != .macho) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (self.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
return self.getZigObject().?.updateExports(self, pt, exported, export_indices);
}
@@ -3114,17 +3075,14 @@ pub fn deleteExport(
exported: Zcu.Exported,
name: InternPool.NullTerminatedString,
) void {
- if (self.llvm_object) |_| return;
return self.getZigObject().?.deleteExport(self, exported, name);
}
pub fn freeNav(self: *MachO, nav: InternPool.Nav.Index) void {
- if (self.llvm_object) |llvm_object| return llvm_object.freeNav(nav);
return self.getZigObject().?.freeNav(nav);
}
pub fn getNavVAddr(self: *MachO, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
- assert(self.llvm_object == null);
return self.getZigObject().?.getNavVAddr(self, pt, nav_index, reloc_info);
}
@@ -3139,7 +3097,6 @@ pub fn lowerUav(
}
pub fn getUavVAddr(self: *MachO, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
- assert(self.llvm_object == null);
return self.getZigObject().?.getUavVAddr(self, uav, reloc_info);
}
@@ -5473,7 +5430,6 @@ const target_util = @import("../target.zig");
const trace = @import("../tracy.zig").trace;
const synthetic = @import("MachO/synthetic.zig");
-const Air = @import("../Air.zig");
const Alignment = Atom.Alignment;
const Allocator = mem.Allocator;
const Archive = @import("MachO/Archive.zig");
@@ -5496,7 +5452,6 @@ const ObjcStubsSection = synthetic.ObjcStubsSection;
const Object = @import("MachO/Object.zig");
const LazyBind = bind.LazyBind;
const LaSymbolPtrSection = synthetic.LaSymbolPtrSection;
-const LlvmObject = @import("../codegen/llvm.zig").Object;
const Md5 = std.crypto.hash.Md5;
const Zcu = @import("../Zcu.zig");
const InternPool = @import("../InternPool.zig");
diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig
index 04b2fe92b0..eef3492b48 100644
--- a/src/link/MachO/DebugSymbols.zig
+++ b/src/link/MachO/DebugSymbols.zig
@@ -178,7 +178,7 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) !u64
return offset;
}
-pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
+pub fn flush(self: *DebugSymbols, macho_file: *MachO) !void {
const zo = macho_file.getZigObject().?;
for (self.relocs.items) |*reloc| {
const sym = zo.symbols.items[reloc.target];
diff --git a/src/link/MachO/Symbol.zig b/src/link/MachO/Symbol.zig
index 7493d3ceab..be126b0963 100644
--- a/src/link/MachO/Symbol.zig
+++ b/src/link/MachO/Symbol.zig
@@ -389,9 +389,6 @@ pub const Flags = packed struct {
/// ZigObject specific flags
/// Whether the symbol has a trampoline
trampoline: bool = false,
-
- /// Whether the symbol is an extern pointer (as opposed to function).
- is_extern_ptr: bool = false,
};
pub const SectionFlags = packed struct(u8) {
diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig
index a0de866544..f9ecdc6fb5 100644
--- a/src/link/MachO/ZigObject.zig
+++ b/src/link/MachO/ZigObject.zig
@@ -550,7 +550,7 @@ pub fn getInputSection(self: ZigObject, atom: Atom, macho_file: *MachO) macho.se
return sect;
}
-pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.File.FlushError!void {
+pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.File.FlushError!void {
const diags = &macho_file.base.comp.link_diags;
// 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)
if (self.dwarf) |*dwarf| {
const pt: Zcu.PerThread = .activate(macho_file.base.comp.zcu.?, tid);
defer pt.deactivate();
- dwarf.flushModule(pt) catch |err| switch (err) {
+ dwarf.flush(pt) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
else => |e| return diags.fail("failed to flush dwarf module: {s}", .{@errorName(e)}),
};
@@ -599,7 +599,7 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id)
self.debug_strtab_dirty = false;
}
- // The point of flushModule() is to commit changes, so in theory, nothing should
+ // The point of flush() is to commit changes, so in theory, nothing should
// be dirty after this. However, it is possible for some things to remain
// dirty because they fail to be written in the event of compile errors,
// such as debug_line_header_dirty and debug_info_header_dirty.
@@ -777,8 +777,7 @@ pub fn updateFunc(
macho_file: *MachO,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ mir: *const codegen.AnyMir,
) link.File.UpdateNavError!void {
const tracy = trace(@src());
defer tracy.end();
@@ -796,13 +795,12 @@ pub fn updateFunc(
var debug_wip_nav = if (self.dwarf) |*dwarf| try dwarf.initWipNav(pt, func.owner_nav, sym_index) else null;
defer if (debug_wip_nav) |*wip_nav| wip_nav.deinit();
- try codegen.generateFunction(
+ try codegen.emitFunction(
&macho_file.base,
pt,
zcu.navSrcLoc(func.owner_nav),
func_index,
- air,
- liveness,
+ mir,
&code_buffer,
if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,
);
@@ -883,11 +881,7 @@ pub fn updateNav(
const name = @"extern".name.toSlice(ip);
const lib_name = @"extern".lib_name.toSlice(ip);
const sym_index = try self.getGlobalSymbol(macho_file, name, lib_name);
- if (!ip.isFunctionType(@"extern".ty)) {
- const sym = &self.symbols.items[sym_index];
- sym.flags.is_extern_ptr = true;
- if (@"extern".is_threadlocal) sym.flags.tlv = true;
- }
+ if (@"extern".is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) self.symbols.items[sym_index].flags.tlv = true;
if (self.dwarf) |*dwarf| dwarf: {
var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf;
defer debug_wip_nav.deinit();
@@ -1160,7 +1154,6 @@ fn getNavOutputSection(
) error{OutOfMemory}!u8 {
_ = self;
const ip = &zcu.intern_pool;
- const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
const nav_val = zcu.navValue(nav_index);
if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return macho_file.zig_text_sect_index.?;
const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
@@ -1168,7 +1161,7 @@ fn getNavOutputSection(
.@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none },
else => .{ true, false, nav_val.toIntern() },
};
- if (any_non_single_threaded and is_threadlocal) {
+ if (is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) {
for (code) |byte| {
if (byte != 0) break;
} else return macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(
@@ -1537,7 +1530,7 @@ pub fn getOrCreateMetadataForLazySymbol(
}
state_ptr.* = .pending_flush;
const symbol_index = symbol_index_ptr.*;
- // anyerror needs to be deferred until flushModule
+ // anyerror needs to be deferred until flush
if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(macho_file, pt, lazy_sym, symbol_index);
return symbol_index;
}
@@ -1813,7 +1806,6 @@ const target_util = @import("../../target.zig");
const trace = @import("../../tracy.zig").trace;
const std = @import("std");
-const Air = @import("../../Air.zig");
const Allocator = std.mem.Allocator;
const Archive = @import("Archive.zig");
const Atom = @import("Atom.zig");
diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig
index 5cbb9287d7..c99ebb81bb 100644
--- a/src/link/Plan9.zig
+++ b/src/link/Plan9.zig
@@ -301,7 +301,6 @@ pub fn createEmpty(
.stack_size = options.stack_size orelse 16777216,
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
.file = null,
- .disable_lld_caching = options.disable_lld_caching,
.build_id = options.build_id,
},
.sixtyfour_bit = sixtyfour_bit,
@@ -387,8 +386,7 @@ pub fn updateFunc(
self: *Plan9,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ mir: *const codegen.AnyMir,
) link.File.UpdateNavError!void {
if (build_options.skip_non_native and builtin.object_format != .plan9) {
@panic("Attempted to compile for object format that was disabled by build configuration");
@@ -413,13 +411,12 @@ pub fn updateFunc(
};
defer dbg_info_output.dbg_line.deinit();
- try codegen.generateFunction(
+ try codegen.emitFunction(
&self.base,
pt,
zcu.navSrcLoc(func.owner_nav),
func_index,
- air,
- liveness,
+ mir,
&code_buffer,
.{ .plan9 = &dbg_info_output },
);
@@ -494,7 +491,7 @@ fn updateFinish(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
// write the symbol
// we already have the got index
const sym: aout.Sym = .{
- .value = undefined, // the value of stuff gets filled in in flushModule
+ .value = undefined, // the value of stuff gets filled in in flush
.type = atom.type,
.name = try gpa.dupe(u8, nav.name.toSlice(ip)),
};
@@ -527,25 +524,6 @@ fn allocateGotIndex(self: *Plan9) usize {
}
}
-pub fn flush(
- self: *Plan9,
- arena: Allocator,
- tid: Zcu.PerThread.Id,
- prog_node: std.Progress.Node,
-) link.File.FlushError!void {
- const comp = self.base.comp;
- const diags = &comp.link_diags;
- const use_lld = build_options.have_llvm and comp.config.use_lld;
- assert(!use_lld);
-
- switch (link.File.effectiveOutputMode(use_lld, comp.config.output_mode)) {
- .Exe => {},
- .Obj => return diags.fail("writing plan9 object files unimplemented", .{}),
- .Lib => return diags.fail("writing plan9 lib files unimplemented", .{}),
- }
- return self.flushModule(arena, tid, prog_node);
-}
-
pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {
if (delta_line > 0 and delta_line < 65) {
const toappend = @as(u8, @intCast(delta_line));
@@ -586,7 +564,7 @@ fn atomCount(self: *Plan9) usize {
return data_nav_count + fn_nav_count + lazy_atom_count + extern_atom_count + uav_atom_count;
}
-pub fn flushModule(
+pub fn flush(
self: *Plan9,
arena: Allocator,
/// TODO: stop using this
@@ -607,10 +585,16 @@ pub fn flushModule(
const gpa = comp.gpa;
const target = comp.root_mod.resolved_target.result;
+ switch (comp.config.output_mode) {
+ .Exe => {},
+ .Obj => return diags.fail("writing plan9 object files unimplemented", .{}),
+ .Lib => return diags.fail("writing plan9 lib files unimplemented", .{}),
+ }
+
const sub_prog_node = prog_node.start("Flush Module", 0);
defer sub_prog_node.end();
- log.debug("flushModule", .{});
+ log.debug("flush", .{});
defer assert(self.hdr.entry != 0x0);
@@ -1039,7 +1023,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *Plan9, pt: Zcu.PerThread, lazy_sym: F
const atom = atom_ptr.*;
_ = try self.getAtomPtr(atom).getOrCreateSymbolTableEntry(self);
_ = self.getAtomPtr(atom).getOrCreateOffsetTableEntry(self);
- // anyerror needs to be deferred until flushModule
+ // anyerror needs to be deferred until flush
if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbolAtom(pt, lazy_sym, atom);
return atom;
}
@@ -1182,11 +1166,7 @@ pub fn open(
const file = try emit.root_dir.handle.createFile(emit.sub_path, .{
.read = true,
- .mode = link.File.determineMode(
- use_lld,
- comp.config.output_mode,
- comp.config.link_mode,
- ),
+ .mode = link.File.determineMode(comp.config.output_mode, comp.config.link_mode),
});
errdefer file.close();
self.base.file = file;
diff --git a/src/link/Queue.zig b/src/link/Queue.zig
new file mode 100644
index 0000000000..d197edab02
--- /dev/null
+++ b/src/link/Queue.zig
@@ -0,0 +1,279 @@
+//! Stores and manages the queue of link tasks. Each task is either a `PrelinkTask` or a `ZcuTask`.
+//!
+//! There must be at most one link thread (the thread processing these tasks) active at a time. If
+//! `!comp.separateCodegenThreadOk()`, then ZCU tasks will be run on the main thread, bypassing this
+//! queue entirely.
+//!
+//! All prelink tasks must be processed before any ZCU tasks are processed. After all prelink tasks
+//! are run, but before any ZCU tasks are run, `prelink` must be called on the `link.File`.
+//!
+//! There will sometimes be a `ZcuTask` in the queue which is not yet ready because it depends on
+//! MIR which has not yet been generated by any codegen thread. In this case, we must pause
+//! processing of linker tasks until the MIR is ready. It would be incorrect to run any other link
+//! tasks first, since this would make builds unreproducible.
+
+mutex: std.Thread.Mutex,
+/// Validates that only one `flushTaskQueue` thread is running at a time.
+flush_safety: std.debug.SafetyLock,
+
+/// This is the number of prelink tasks which are expected but have not yet been enqueued.
+/// Guarded by `mutex`.
+pending_prelink_tasks: u32,
+
+/// Prelink tasks which have been enqueued and are not yet owned by the worker thread.
+/// Allocated into `gpa`, guarded by `mutex`.
+queued_prelink: std.ArrayListUnmanaged(PrelinkTask),
+/// The worker thread moves items from `queued_prelink` into this array in order to process them.
+/// Allocated into `gpa`, accessed only by the worker thread.
+wip_prelink: std.ArrayListUnmanaged(PrelinkTask),
+
+/// Like `queued_prelink`, but for ZCU tasks.
+/// Allocated into `gpa`, guarded by `mutex`.
+queued_zcu: std.ArrayListUnmanaged(ZcuTask),
+/// Like `wip_prelink`, but for ZCU tasks.
+/// Allocated into `gpa`, accessed only by the worker thread.
+wip_zcu: std.ArrayListUnmanaged(ZcuTask),
+
+/// When processing ZCU link tasks, we might have to block due to unpopulated MIR. When this
+/// happens, some tasks in `wip_zcu` have been run, and some are still pending. This is the
+/// index into `wip_zcu` which we have reached.
+wip_zcu_idx: usize,
+
+/// The sum of all `air_bytes` for all currently-queued `ZcuTask.link_func` tasks. Because
+/// MIR bytes are approximately proportional to AIR bytes, this acts to limit the amount of
+/// AIR and MIR which is queued for codegen and link respectively, to prevent excessive
+/// memory usage if analysis produces AIR faster than it can be processed by codegen/link.
+/// The cap is `max_air_bytes_in_flight`.
+/// Guarded by `mutex`.
+air_bytes_in_flight: u32,
+/// If nonzero, then a call to `enqueueZcu` is blocked waiting to add a `link_func` task, but
+/// cannot until `air_bytes_in_flight` is no greater than this value.
+/// Guarded by `mutex`.
+air_bytes_waiting: u32,
+/// After setting `air_bytes_waiting`, `enqueueZcu` will wait on this condition (with `mutex`).
+/// When `air_bytes_waiting` many bytes can be queued, this condition should be signaled.
+air_bytes_cond: std.Thread.Condition,
+
+/// Guarded by `mutex`.
+state: union(enum) {
+ /// The link thread is currently running or queued to run.
+ running,
+ /// The link thread is not running or queued, because it has exhausted all immediately available
+ /// tasks. It should be spawned when more tasks are enqueued. If `pending_prelink_tasks` is not
+ /// zero, we are specifically waiting for prelink tasks.
+ finished,
+ /// The link thread is not running or queued, because it is waiting for this MIR to be populated.
+ /// Once codegen completes, it must call `mirReady` which will restart the link thread.
+ wait_for_mir: *ZcuTask.LinkFunc.SharedMir,
+},
+
+/// In the worst observed case, MIR is around 50 times as large as AIR. More typically, the ratio is
+/// around 20. Going by that 50x multiplier, and assuming we want to consume no more than 500 MiB of
+/// memory on AIR/MIR, we see a limit of around 10 MiB of AIR in-flight.
+const max_air_bytes_in_flight = 10 * 1024 * 1024;
+
+/// The initial `Queue` state, containing no tasks, expecting no prelink tasks, and with no running worker thread.
+/// The `pending_prelink_tasks` and `queued_prelink` fields may be modified as needed before calling `start`.
+pub const empty: Queue = .{
+ .mutex = .{},
+ .flush_safety = .{},
+ .pending_prelink_tasks = 0,
+ .queued_prelink = .empty,
+ .wip_prelink = .empty,
+ .queued_zcu = .empty,
+ .wip_zcu = .empty,
+ .wip_zcu_idx = 0,
+ .state = .finished,
+ .air_bytes_in_flight = 0,
+ .air_bytes_waiting = 0,
+ .air_bytes_cond = .{},
+};
+/// `lf` is needed to correctly deinit any pending `ZcuTask`s.
+pub fn deinit(q: *Queue, comp: *Compilation) void {
+ const gpa = comp.gpa;
+ for (q.queued_zcu.items) |t| t.deinit(comp.zcu.?);
+ for (q.wip_zcu.items[q.wip_zcu_idx..]) |t| t.deinit(comp.zcu.?);
+ q.queued_prelink.deinit(gpa);
+ q.wip_prelink.deinit(gpa);
+ q.queued_zcu.deinit(gpa);
+ q.wip_zcu.deinit(gpa);
+}
+
+/// This is expected to be called exactly once, after which the caller must not directly access
+/// `queued_prelink` or `pending_prelink_tasks` any longer. This will spawn the link thread if
+/// necessary.
+pub fn start(q: *Queue, comp: *Compilation) void {
+ assert(q.state == .finished);
+ assert(q.queued_zcu.items.len == 0);
+ if (q.queued_prelink.items.len != 0) {
+ q.state = .running;
+ comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
+ }
+}
+
+/// Called by codegen workers after they have populated a `ZcuTask.LinkFunc.SharedMir`. If the link
+/// thread was waiting for this MIR, it can resume.
+pub fn mirReady(q: *Queue, comp: *Compilation, mir: *ZcuTask.LinkFunc.SharedMir) void {
+ // We would like to assert that `mir` is not pending, but that would race with a worker thread
+ // potentially freeing it.
+ {
+ q.mutex.lock();
+ defer q.mutex.unlock();
+ switch (q.state) {
+ .finished, .running => return,
+ .wait_for_mir => |wait_for| if (wait_for != mir) return,
+ }
+ // We were waiting for `mir`, so we will restart the linker thread.
+ q.state = .running;
+ }
+ assert(mir.status.load(.monotonic) != .pending);
+ comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
+}
+
+/// Enqueues all prelink tasks in `tasks`. Asserts that they were expected, i.e. that `tasks.len` is
+/// less than or equal to `q.pending_prelink_tasks`. Also asserts that `tasks.len` is not 0.
+pub fn enqueuePrelink(q: *Queue, comp: *Compilation, tasks: []const PrelinkTask) Allocator.Error!void {
+ {
+ q.mutex.lock();
+ defer q.mutex.unlock();
+ try q.queued_prelink.appendSlice(comp.gpa, tasks);
+ q.pending_prelink_tasks -= @intCast(tasks.len);
+ switch (q.state) {
+ .wait_for_mir => unreachable, // we've not started zcu tasks yet
+ .running => return,
+ .finished => {},
+ }
+ // Restart the linker thread, because it was waiting for a task
+ q.state = .running;
+ }
+ comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
+}
+
+pub fn enqueueZcu(q: *Queue, comp: *Compilation, task: ZcuTask) Allocator.Error!void {
+ assert(comp.separateCodegenThreadOk());
+ {
+ q.mutex.lock();
+ defer q.mutex.unlock();
+ // If this is a `link_func` task, we might need to wait for `air_bytes_in_flight` to fall.
+ if (task == .link_func) {
+ const max_in_flight = max_air_bytes_in_flight -| task.link_func.air_bytes;
+ while (q.air_bytes_in_flight > max_in_flight) {
+ q.air_bytes_waiting = task.link_func.air_bytes;
+ q.air_bytes_cond.wait(&q.mutex);
+ q.air_bytes_waiting = 0;
+ }
+ q.air_bytes_in_flight += task.link_func.air_bytes;
+ }
+ try q.queued_zcu.append(comp.gpa, task);
+ switch (q.state) {
+ .running, .wait_for_mir => return,
+ .finished => if (q.pending_prelink_tasks != 0) return,
+ }
+ // Restart the linker thread, unless it would immediately be blocked
+ if (task == .link_func and task.link_func.mir.status.load(.monotonic) == .pending) {
+ q.state = .{ .wait_for_mir = task.link_func.mir };
+ return;
+ }
+ q.state = .running;
+ }
+ comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
+}
+
+fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void {
+ q.flush_safety.lock(); // every `return` site should unlock this before unlocking `q.mutex`
+
+ if (std.debug.runtime_safety) {
+ q.mutex.lock();
+ defer q.mutex.unlock();
+ assert(q.state == .running);
+ }
+ prelink: while (true) {
+ assert(q.wip_prelink.items.len == 0);
+ {
+ q.mutex.lock();
+ defer q.mutex.unlock();
+ std.mem.swap(std.ArrayListUnmanaged(PrelinkTask), &q.queued_prelink, &q.wip_prelink);
+ if (q.wip_prelink.items.len == 0) {
+ if (q.pending_prelink_tasks == 0) {
+ break :prelink; // prelink is done
+ } else {
+ // We're expecting more prelink tasks so can't move on to ZCU tasks.
+ q.state = .finished;
+ q.flush_safety.unlock();
+ return;
+ }
+ }
+ }
+ for (q.wip_prelink.items) |task| {
+ link.doPrelinkTask(comp, task);
+ }
+ q.wip_prelink.clearRetainingCapacity();
+ }
+
+ // We've finished the prelink tasks, so run prelink if necessary.
+ if (comp.bin_file) |lf| {
+ if (!lf.post_prelink) {
+ if (lf.prelink()) |_| {
+ lf.post_prelink = true;
+ } else |err| switch (err) {
+ error.OutOfMemory => comp.link_diags.setAllocFailure(),
+ error.LinkFailure => {},
+ }
+ }
+ }
+
+ // Now we can run ZCU tasks.
+ while (true) {
+ if (q.wip_zcu.items.len == q.wip_zcu_idx) {
+ q.wip_zcu.clearRetainingCapacity();
+ q.wip_zcu_idx = 0;
+ q.mutex.lock();
+ defer q.mutex.unlock();
+ std.mem.swap(std.ArrayListUnmanaged(ZcuTask), &q.queued_zcu, &q.wip_zcu);
+ if (q.wip_zcu.items.len == 0) {
+ // We've exhausted all available tasks.
+ q.state = .finished;
+ q.flush_safety.unlock();
+ return;
+ }
+ }
+ const task = q.wip_zcu.items[q.wip_zcu_idx];
+ // If the task is a `link_func`, we might have to stop until its MIR is populated.
+ pending: {
+ if (task != .link_func) break :pending;
+ const status_ptr = &task.link_func.mir.status;
+ // First check without the mutex to optimize for the common case where MIR is ready.
+ if (status_ptr.load(.monotonic) != .pending) break :pending;
+ q.mutex.lock();
+ defer q.mutex.unlock();
+ if (status_ptr.load(.monotonic) != .pending) break :pending;
+ // We will stop for now, and get restarted once this MIR is ready.
+ q.state = .{ .wait_for_mir = task.link_func.mir };
+ q.flush_safety.unlock();
+ return;
+ }
+ link.doZcuTask(comp, tid, task);
+ task.deinit(comp.zcu.?);
+ if (task == .link_func) {
+ // Decrease `air_bytes_in_flight`, since we've finished processing this MIR.
+ q.mutex.lock();
+ defer q.mutex.unlock();
+ q.air_bytes_in_flight -= task.link_func.air_bytes;
+ if (q.air_bytes_waiting != 0 and
+ q.air_bytes_in_flight <= max_air_bytes_in_flight -| q.air_bytes_waiting)
+ {
+ q.air_bytes_cond.signal();
+ }
+ }
+ q.wip_zcu_idx += 1;
+ }
+}
+
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const Compilation = @import("../Compilation.zig");
+const link = @import("../link.zig");
+const PrelinkTask = link.PrelinkTask;
+const ZcuTask = link.ZcuTask;
+const Queue = @This();
diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig
index a49771c3e2..bafefccfc0 100644
--- a/src/link/SpirV.zig
+++ b/src/link/SpirV.zig
@@ -17,7 +17,7 @@
//! All regular functions.
// Because SPIR-V requires re-compilation anyway, and so hot swapping will not work
-// anyway, we simply generate all the code in flushModule. This keeps
+// anyway, we simply generate all the code in flush. This keeps
// things considerably simpler.
const SpirV = @This();
@@ -83,7 +83,6 @@ pub fn createEmpty(
.stack_size = options.stack_size orelse 0,
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
.file = null,
- .disable_lld_caching = options.disable_lld_caching,
.build_id = options.build_id,
},
.object = codegen.Object.init(gpa, comp.getTarget()),
@@ -112,24 +111,6 @@ pub fn deinit(self: *SpirV) void {
self.object.deinit();
}
-pub fn updateFunc(
- self: *SpirV,
- pt: Zcu.PerThread,
- func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
-) link.File.UpdateNavError!void {
- if (build_options.skip_non_native) {
- @panic("Attempted to compile for architecture that was disabled by build configuration");
- }
-
- const ip = &pt.zcu.intern_pool;
- const func = pt.zcu.funcInfo(func_index);
- log.debug("lowering function {}", .{ip.getNav(func.owner_nav).name.fmt(ip)});
-
- try self.object.updateFunc(pt, func_index, air, liveness);
-}
-
pub fn updateNav(self: *SpirV, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
if (build_options.skip_non_native) {
@panic("Attempted to compile for architecture that was disabled by build configuration");
@@ -193,18 +174,14 @@ pub fn updateExports(
// TODO: Export regular functions, variables, etc using Linkage attributes.
}
-pub fn flush(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- return self.flushModule(arena, tid, prog_node);
-}
-
-pub fn flushModule(
+pub fn flush(
self: *SpirV,
arena: Allocator,
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
) link.File.FlushError!void {
// The goal is to never use this because it's only needed if we need to
- // write to InternPool, but flushModule is too late to be writing to the
+ // write to InternPool, but flush is too late to be writing to the
// InternPool.
_ = tid;
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index 69684724a5..eda7552986 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -29,19 +29,16 @@ const leb = std.leb;
const log = std.log.scoped(.link);
const mem = std.mem;
-const Air = @import("../Air.zig");
const Mir = @import("../arch/wasm/Mir.zig");
const CodeGen = @import("../arch/wasm/CodeGen.zig");
const abi = @import("../arch/wasm/abi.zig");
const Compilation = @import("../Compilation.zig");
const Dwarf = @import("Dwarf.zig");
const InternPool = @import("../InternPool.zig");
-const LlvmObject = @import("../codegen/llvm.zig").Object;
const Zcu = @import("../Zcu.zig");
const codegen = @import("../codegen.zig");
const dev = @import("../dev.zig");
const link = @import("../link.zig");
-const lldMain = @import("../main.zig").lldMain;
const trace = @import("../tracy.zig").trace;
const wasi_libc = @import("../libs/wasi_libc.zig");
const Value = @import("../Value.zig");
@@ -75,14 +72,10 @@ global_base: ?u64,
initial_memory: ?u64,
/// When defined, sets the maximum memory size of the memory.
max_memory: ?u64,
-/// When true, will import the function table from the host environment.
-import_table: bool,
/// When true, will export the function table to the host environment.
export_table: bool,
/// Output name of the file
name: []const u8,
-/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
-llvm_object: ?LlvmObject.Ptr = null,
/// List of relocatable files to be linked into the final binary.
objects: std.ArrayListUnmanaged(Object) = .{},
@@ -288,7 +281,7 @@ mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
/// Corresponds to `mir_instructions`.
mir_extra: std.ArrayListUnmanaged(u32) = .empty,
/// All local types for all Zcu functions.
-all_zcu_locals: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
+mir_locals: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
params_scratch: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
returns_scratch: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
@@ -872,9 +865,24 @@ const ZcuDataStarts = struct {
};
pub const ZcuFunc = union {
- function: CodeGen.Function,
+ function: Function,
tag_name: TagName,
+ pub const Function = extern struct {
+ /// Index into `Wasm.mir_instructions`.
+ instructions_off: u32,
+ /// This is unused except for as a safety slice bound and could be removed.
+ instructions_len: u32,
+ /// Index into `Wasm.mir_extra`.
+ extra_off: u32,
+ /// This is unused except for as a safety slice bound and could be removed.
+ extra_len: u32,
+ /// Index into `Wasm.mir_locals`.
+ locals_off: u32,
+ locals_len: u32,
+ prologue: Mir.Prologue,
+ };
+
pub const TagName = extern struct {
symbol_name: String,
type_index: FunctionType.Index,
@@ -2938,28 +2946,20 @@ pub fn createEmpty(
const target = comp.root_mod.resolved_target.result;
assert(target.ofmt == .wasm);
- const use_lld = build_options.have_llvm and comp.config.use_lld;
const use_llvm = comp.config.use_llvm;
const output_mode = comp.config.output_mode;
const wasi_exec_model = comp.config.wasi_exec_model;
- // If using LLD to link, this code should produce an object file so that it
- // can be passed to LLD.
- // If using LLVM to generate the object file for the zig compilation unit,
- // we need a place to put the object file so that it can be subsequently
- // handled.
- const zcu_object_sub_path = if (!use_lld and !use_llvm)
- null
- else
- try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path});
-
const wasm = try arena.create(Wasm);
wasm.* = .{
.base = .{
.tag = .wasm,
.comp = comp,
.emit = emit,
- .zcu_object_sub_path = zcu_object_sub_path,
+ .zcu_object_basename = if (use_llvm)
+ try std.fmt.allocPrint(arena, "{s}_zcu.o", .{fs.path.stem(emit.sub_path)})
+ else
+ null,
// Garbage collection is so crucial to WebAssembly that we design
// the linker around the assumption that it will be on in the vast
// majority of cases, and therefore express "no garbage collection"
@@ -2973,13 +2973,11 @@ pub fn createEmpty(
},
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
.file = null,
- .disable_lld_caching = options.disable_lld_caching,
.build_id = options.build_id,
},
.name = undefined,
.string_table = .empty,
.string_bytes = .empty,
- .import_table = options.import_table,
.export_table = options.export_table,
.import_symbols = options.import_symbols,
.export_symbol_names = options.export_symbol_names,
@@ -2992,9 +2990,6 @@ pub fn createEmpty(
.object_host_name = .none,
.preloaded_strings = undefined,
};
- if (use_llvm and comp.config.have_zcu) {
- wasm.llvm_object = try LlvmObject.create(arena, comp);
- }
errdefer wasm.base.destroy();
if (options.object_host_name) |name| wasm.object_host_name = (try wasm.internString(name)).toOptional();
@@ -3010,17 +3005,7 @@ pub fn createEmpty(
.named => |name| (try wasm.internString(name)).toOptional(),
};
- if (use_lld and (use_llvm or !comp.config.have_zcu)) {
- // LLVM emits the object file (if any); LLD links it into the final product.
- return wasm;
- }
-
- // What path should this Wasm linker code output to?
- // If using LLD to link, this code should produce an object file so that it
- // can be passed to LLD.
- const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path;
-
- wasm.base.file = try emit.root_dir.handle.createFile(sub_path, .{
+ wasm.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
.truncate = true,
.read = true,
.mode = if (fs.has_executable_bit)
@@ -3031,7 +3016,7 @@ pub fn createEmpty(
else
0,
});
- wasm.name = sub_path;
+ wasm.name = emit.sub_path;
return wasm;
}
@@ -3116,7 +3101,6 @@ fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {
pub fn deinit(wasm: *Wasm) void {
const gpa = wasm.base.comp.gpa;
- if (wasm.llvm_object) |llvm_object| llvm_object.deinit();
wasm.navs_exe.deinit(gpa);
wasm.navs_obj.deinit(gpa);
@@ -3132,7 +3116,7 @@ pub fn deinit(wasm: *Wasm) void {
wasm.mir_instructions.deinit(gpa);
wasm.mir_extra.deinit(gpa);
- wasm.all_zcu_locals.deinit(gpa);
+ wasm.mir_locals.deinit(gpa);
if (wasm.dwarf) |*dwarf| dwarf.deinit();
@@ -3192,34 +3176,94 @@ pub fn deinit(wasm: *Wasm) void {
wasm.missing_exports.deinit(gpa);
}
-pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index, air: Air, liveness: Air.Liveness) !void {
+pub fn updateFunc(
+ wasm: *Wasm,
+ pt: Zcu.PerThread,
+ func_index: InternPool.Index,
+ any_mir: *const codegen.AnyMir,
+) !void {
if (build_options.skip_non_native and builtin.object_format != .wasm) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (wasm.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
dev.check(.wasm_backend);
+ // This linker implementation only works with codegen backend `.stage2_wasm`.
+ const mir = &any_mir.wasm;
const zcu = pt.zcu;
const gpa = zcu.gpa;
- try wasm.functions.ensureUnusedCapacity(gpa, 1);
- try wasm.zcu_funcs.ensureUnusedCapacity(gpa, 1);
-
const ip = &zcu.intern_pool;
+ const is_obj = zcu.comp.config.output_mode == .Obj;
+ const target = &zcu.comp.root_mod.resolved_target.result;
const owner_nav = zcu.funcInfo(func_index).owner_nav;
log.debug("updateFunc {}", .{ip.getNav(owner_nav).fqn.fmt(ip)});
+ // For Wasm, we do not lower the MIR to code just yet. That lowering happens during `flush`,
+ // after garbage collection, which can affect function and global indexes, which affects the
+ // LEB integer encoding, which affects the output binary size.
+
+ // However, we do move the MIR into a more efficient in-memory representation, where the arrays
+ // for all functions are packed together rather than keeping them each in their own `Mir`.
+ const mir_instructions_off: u32 = @intCast(wasm.mir_instructions.len);
+ const mir_extra_off: u32 = @intCast(wasm.mir_extra.items.len);
+ const mir_locals_off: u32 = @intCast(wasm.mir_locals.items.len);
+ {
+ // Copying MultiArrayList data is a little non-trivial. Resize, then memcpy both slices.
+ const old_len = wasm.mir_instructions.len;
+ try wasm.mir_instructions.resize(gpa, old_len + mir.instructions.len);
+ const dest_slice = wasm.mir_instructions.slice().subslice(old_len, mir.instructions.len);
+ const src_slice = mir.instructions;
+ @memcpy(dest_slice.items(.tag), src_slice.items(.tag));
+ @memcpy(dest_slice.items(.data), src_slice.items(.data));
+ }
+ try wasm.mir_extra.appendSlice(gpa, mir.extra);
+ try wasm.mir_locals.appendSlice(gpa, mir.locals);
+
+ // We also need to populate some global state from `mir`.
+ try wasm.zcu_indirect_function_set.ensureUnusedCapacity(gpa, mir.indirect_function_set.count());
+ for (mir.indirect_function_set.keys()) |nav| wasm.zcu_indirect_function_set.putAssumeCapacity(nav, {});
+ for (mir.func_tys.keys()) |func_ty| {
+ const fn_info = zcu.typeToFunc(.fromInterned(func_ty)).?;
+ _ = try wasm.internFunctionType(fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target);
+ }
+ wasm.error_name_table_ref_count += mir.error_name_table_ref_count;
+ // We need to populate UAV data. In theory, we can lower the UAV values while we fill `mir.uavs`.
+ // However, lowering the data might cause *more* UAVs to be created, and mixing them up would be
+ // a headache. So instead, just write `undefined` placeholder code and use the `ZcuDataStarts`.
const zds: ZcuDataStarts = .init(wasm);
+ for (mir.uavs.keys(), mir.uavs.values()) |uav_val, uav_align| {
+ if (uav_align != .none) {
+ const gop = try wasm.overaligned_uavs.getOrPut(gpa, uav_val);
+ gop.value_ptr.* = if (gop.found_existing) gop.value_ptr.maxStrict(uav_align) else uav_align;
+ }
+ if (is_obj) {
+ const gop = try wasm.uavs_obj.getOrPut(gpa, uav_val);
+ if (!gop.found_existing) gop.value_ptr.* = undefined; // `zds` handles lowering
+ } else {
+ const gop = try wasm.uavs_exe.getOrPut(gpa, uav_val);
+ if (!gop.found_existing) gop.value_ptr.* = .{
+ .code = undefined, // `zds` handles lowering
+ .count = 0,
+ };
+ gop.value_ptr.count += 1;
+ }
+ }
+ try zds.finish(wasm, pt); // actually generates the UAVs
+
+ try wasm.functions.ensureUnusedCapacity(gpa, 1);
+ try wasm.zcu_funcs.ensureUnusedCapacity(gpa, 1);
// This converts AIR to MIR but does not yet lower to wasm code.
- // That lowering happens during `flush`, after garbage collection, which
- // can affect function and global indexes, which affects the LEB integer
- // encoding, which affects the output binary size.
- const function = try CodeGen.function(wasm, pt, func_index, air, liveness);
- wasm.zcu_funcs.putAssumeCapacity(func_index, .{ .function = function });
+ wasm.zcu_funcs.putAssumeCapacity(func_index, .{ .function = .{
+ .instructions_off = mir_instructions_off,
+ .instructions_len = @intCast(mir.instructions.len),
+ .extra_off = mir_extra_off,
+ .extra_len = @intCast(mir.extra.len),
+ .locals_off = mir_locals_off,
+ .locals_len = @intCast(mir.locals.len),
+ .prologue = mir.prologue,
+ } });
wasm.functions.putAssumeCapacity(.pack(wasm, .{ .zcu_func = @enumFromInt(wasm.zcu_funcs.entries.len - 1) }), {});
-
- try zds.finish(wasm, pt);
}
// 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
if (build_options.skip_non_native and builtin.object_format != .wasm) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (wasm.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav_index);
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
@@ -3308,8 +3351,6 @@ pub fn deleteExport(
exported: Zcu.Exported,
name: InternPool.NullTerminatedString,
) void {
- if (wasm.llvm_object != null) return;
-
const zcu = wasm.base.comp.zcu.?;
const ip = &zcu.intern_pool;
const name_slice = name.toSlice(ip);
@@ -3332,7 +3373,6 @@ pub fn updateExports(
if (build_options.skip_non_native and builtin.object_format != .wasm) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
- if (wasm.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
const zcu = pt.zcu;
const gpa = zcu.gpa;
@@ -3379,21 +3419,6 @@ pub fn loadInput(wasm: *Wasm, input: link.Input) !void {
}
}
-pub fn flush(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- const comp = wasm.base.comp;
- const use_lld = build_options.have_llvm and comp.config.use_lld;
- const diags = &comp.link_diags;
-
- if (use_lld) {
- return wasm.linkWithLLD(arena, tid, prog_node) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.LinkFailure => return error.LinkFailure,
- else => |e| return diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),
- };
- }
- return wasm.flushModule(arena, tid, prog_node);
-}
-
pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!void {
const tracy = trace(@src());
defer tracy.end();
@@ -3785,37 +3810,25 @@ fn markTable(wasm: *Wasm, i: ObjectTableIndex) link.File.FlushError!void {
try wasm.tables.put(wasm.base.comp.gpa, .fromObjectTable(i), {});
}
-pub fn flushModule(
+pub fn flush(
wasm: *Wasm,
arena: Allocator,
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
) link.File.FlushError!void {
// The goal is to never use this because it's only needed if we need to
- // write to InternPool, but flushModule is too late to be writing to the
+ // write to InternPool, but flush is too late to be writing to the
// InternPool.
_ = tid;
const comp = wasm.base.comp;
- const use_lld = build_options.have_llvm and comp.config.use_lld;
const diags = &comp.link_diags;
const gpa = comp.gpa;
- if (wasm.llvm_object) |llvm_object| {
- try wasm.base.emitLlvmObject(arena, llvm_object, prog_node);
- if (use_lld) return;
- }
-
if (comp.verbose_link) Compilation.dump_argv(wasm.dump_argv_list.items);
- if (wasm.base.zcu_object_sub_path) |path| {
- const module_obj_path: Path = .{
- .root_dir = wasm.base.emit.root_dir,
- .sub_path = if (fs.path.dirname(wasm.base.emit.sub_path)) |dirname|
- try fs.path.join(arena, &.{ dirname, path })
- else
- path,
- };
- openParseObjectReportingFailure(wasm, module_obj_path);
+ if (wasm.base.zcu_object_basename) |raw| {
+ const zcu_obj_path: Path = try comp.resolveEmitPathFlush(arena, .temp, raw);
+ openParseObjectReportingFailure(wasm, zcu_obj_path);
try prelink(wasm, prog_node);
}
@@ -3850,432 +3863,6 @@ pub fn flushModule(
};
}
-fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
- dev.check(.lld_linker);
-
- const tracy = trace(@src());
- defer tracy.end();
-
- const comp = wasm.base.comp;
- const diags = &comp.link_diags;
- const shared_memory = comp.config.shared_memory;
- const export_memory = comp.config.export_memory;
- const import_memory = comp.config.import_memory;
- const target = comp.root_mod.resolved_target.result;
-
- const gpa = comp.gpa;
-
- const directory = wasm.base.emit.root_dir; // Just an alias to make it shorter to type.
- const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path});
-
- // If there is no Zig code to compile, then we should skip flushing the output file because it
- // will not be part of the linker line anyway.
- const module_obj_path: ?[]const u8 = if (comp.zcu != null) blk: {
- try wasm.flushModule(arena, tid, prog_node);
-
- if (fs.path.dirname(full_out_path)) |dirname| {
- break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? });
- } else {
- break :blk wasm.base.zcu_object_sub_path.?;
- }
- } else null;
-
- const sub_prog_node = prog_node.start("LLD Link", 0);
- defer sub_prog_node.end();
-
- const is_obj = comp.config.output_mode == .Obj;
- const compiler_rt_path: ?Path = blk: {
- if (comp.compiler_rt_lib) |lib| break :blk lib.full_object_path;
- if (comp.compiler_rt_obj) |obj| break :blk obj.full_object_path;
- break :blk null;
- };
- const ubsan_rt_path: ?Path = blk: {
- if (comp.ubsan_rt_lib) |lib| break :blk lib.full_object_path;
- if (comp.ubsan_rt_obj) |obj| break :blk obj.full_object_path;
- break :blk null;
- };
-
- const id_symlink_basename = "lld.id";
-
- var man: Cache.Manifest = undefined;
- defer if (!wasm.base.disable_lld_caching) man.deinit();
-
- var digest: [Cache.hex_digest_len]u8 = undefined;
-
- if (!wasm.base.disable_lld_caching) {
- man = comp.cache_parent.obtain();
-
- // We are about to obtain this lock, so here we give other processes a chance first.
- wasm.base.releaseLock();
-
- comptime assert(Compilation.link_hash_implementation_version == 14);
-
- try link.hashInputs(&man, comp.link_inputs);
- for (comp.c_object_table.keys()) |key| {
- _ = try man.addFilePath(key.status.success.object_path, null);
- }
- try man.addOptionalFile(module_obj_path);
- try man.addOptionalFilePath(compiler_rt_path);
- try man.addOptionalFilePath(ubsan_rt_path);
- man.hash.addOptionalBytes(wasm.entry_name.slice(wasm));
- man.hash.add(wasm.base.stack_size);
- man.hash.add(wasm.base.build_id);
- man.hash.add(import_memory);
- man.hash.add(export_memory);
- man.hash.add(wasm.import_table);
- man.hash.add(wasm.export_table);
- man.hash.addOptional(wasm.initial_memory);
- man.hash.addOptional(wasm.max_memory);
- man.hash.add(shared_memory);
- man.hash.addOptional(wasm.global_base);
- man.hash.addListOfBytes(wasm.export_symbol_names);
- // strip does not need to go into the linker hash because it is part of the hash namespace
-
- // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
- _ = try man.hit();
- digest = man.final();
-
- var prev_digest_buf: [digest.len]u8 = undefined;
- const prev_digest: []u8 = Cache.readSmallFile(
- directory.handle,
- id_symlink_basename,
- &prev_digest_buf,
- ) catch |err| blk: {
- log.debug("WASM LLD new_digest={s} error: {s}", .{ std.fmt.fmtSliceHexLower(&digest), @errorName(err) });
- // Handle this as a cache miss.
- break :blk prev_digest_buf[0..0];
- };
- if (mem.eql(u8, prev_digest, &digest)) {
- log.debug("WASM LLD digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});
- // Hot diggity dog! The output binary is already there.
- wasm.base.lock = man.toOwnedLock();
- return;
- }
- log.debug("WASM LLD prev_digest={s} new_digest={s}", .{ std.fmt.fmtSliceHexLower(prev_digest), std.fmt.fmtSliceHexLower(&digest) });
-
- // We are about to change the output file to be different, so we invalidate the build hash now.
- directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
- error.FileNotFound => {},
- else => |e| return e,
- };
- }
-
- if (is_obj) {
- // LLD's WASM driver does not support the equivalent of `-r` so we do a simple file copy
- // here. TODO: think carefully about how we can avoid this redundant operation when doing
- // build-obj. See also the corresponding TODO in linkAsArchive.
- const the_object_path = blk: {
- if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
-
- if (comp.c_object_table.count() != 0)
- break :blk comp.c_object_table.keys()[0].status.success.object_path;
-
- if (module_obj_path) |p|
- break :blk Path.initCwd(p);
-
- // TODO I think this is unreachable. Audit this situation when solving the above TODO
- // regarding eliding redundant object -> object transformations.
- return error.NoObjectsToLink;
- };
- try fs.Dir.copyFile(
- the_object_path.root_dir.handle,
- the_object_path.sub_path,
- directory.handle,
- wasm.base.emit.sub_path,
- .{},
- );
- } else {
- // Create an LLD command line and invoke it.
- var argv = std.ArrayList([]const u8).init(gpa);
- defer argv.deinit();
- // We will invoke ourselves as a child process to gain access to LLD.
- // This is necessary because LLD does not behave properly as a library -
- // it calls exit() and does not reset all global data between invocations.
- const linker_command = "wasm-ld";
- try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
- try argv.append("--error-limit=0");
-
- if (comp.config.lto != .none) {
- switch (comp.root_mod.optimize_mode) {
- .Debug => {},
- .ReleaseSmall => try argv.append("-O2"),
- .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
- }
- }
-
- if (import_memory) {
- try argv.append("--import-memory");
- }
-
- if (export_memory) {
- try argv.append("--export-memory");
- }
-
- if (wasm.import_table) {
- assert(!wasm.export_table);
- try argv.append("--import-table");
- }
-
- if (wasm.export_table) {
- assert(!wasm.import_table);
- try argv.append("--export-table");
- }
-
- // For wasm-ld we only need to specify '--no-gc-sections' when the user explicitly
- // specified it as garbage collection is enabled by default.
- if (!wasm.base.gc_sections) {
- try argv.append("--no-gc-sections");
- }
-
- if (comp.config.debug_format == .strip) {
- try argv.append("-s");
- }
-
- if (wasm.initial_memory) |initial_memory| {
- const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory});
- try argv.append(arg);
- }
-
- if (wasm.max_memory) |max_memory| {
- const arg = try std.fmt.allocPrint(arena, "--max-memory={d}", .{max_memory});
- try argv.append(arg);
- }
-
- if (shared_memory) {
- try argv.append("--shared-memory");
- }
-
- if (wasm.global_base) |global_base| {
- const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base});
- try argv.append(arg);
- } else {
- // We prepend it by default, so when a stack overflow happens the runtime will trap correctly,
- // rather than silently overwrite all global declarations. See https://github.com/ziglang/zig/issues/4496
- //
- // The user can overwrite this behavior by setting the global-base
- try argv.append("--stack-first");
- }
-
- // Users are allowed to specify which symbols they want to export to the wasm host.
- for (wasm.export_symbol_names) |symbol_name| {
- const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name});
- try argv.append(arg);
- }
-
- if (comp.config.rdynamic) {
- try argv.append("--export-dynamic");
- }
-
- if (wasm.entry_name.slice(wasm)) |entry_name| {
- try argv.appendSlice(&.{ "--entry", entry_name });
- } else {
- try argv.append("--no-entry");
- }
-
- try argv.appendSlice(&.{
- "-z",
- try std.fmt.allocPrint(arena, "stack-size={d}", .{wasm.base.stack_size}),
- });
-
- switch (wasm.base.build_id) {
- .none => try argv.append("--build-id=none"),
- .fast, .uuid, .sha1 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
- @tagName(wasm.base.build_id),
- })),
- .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{
- std.fmt.fmtSliceHexLower(hs.toSlice()),
- })),
- .md5 => {},
- }
-
- if (wasm.import_symbols) {
- try argv.append("--allow-undefined");
- }
-
- if (comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic) {
- try argv.append("--shared");
- }
- if (comp.config.pie) {
- try argv.append("--pie");
- }
-
- try argv.appendSlice(&.{ "-o", full_out_path });
-
- if (target.cpu.arch == .wasm64) {
- try argv.append("-mwasm64");
- }
-
- const is_exe_or_dyn_lib = comp.config.output_mode == .Exe or
- (comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic);
-
- if (comp.config.link_libc and is_exe_or_dyn_lib) {
- if (target.os.tag == .wasi) {
- for (comp.wasi_emulated_libs) |crt_file| {
- try argv.append(try comp.crtFileAsString(
- arena,
- wasi_libc.emulatedLibCRFileLibName(crt_file),
- ));
- }
-
- try argv.append(try comp.crtFileAsString(
- arena,
- wasi_libc.execModelCrtFileFullName(comp.config.wasi_exec_model),
- ));
- try argv.append(try comp.crtFileAsString(arena, "libc.a"));
- }
-
- if (comp.zigc_static_lib) |zigc| {
- try argv.append(try zigc.full_object_path.toString(arena));
- }
-
- if (comp.config.link_libcpp) {
- try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena));
- try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena));
- }
- }
-
- // Positional arguments to the linker such as object files.
- var whole_archive = false;
- for (comp.link_inputs) |link_input| switch (link_input) {
- .object, .archive => |obj| {
- if (obj.must_link and !whole_archive) {
- try argv.append("-whole-archive");
- whole_archive = true;
- } else if (!obj.must_link and whole_archive) {
- try argv.append("-no-whole-archive");
- whole_archive = false;
- }
- try argv.append(try obj.path.toString(arena));
- },
- .dso => |dso| {
- try argv.append(try dso.path.toString(arena));
- },
- .dso_exact => unreachable,
- .res => unreachable,
- };
- if (whole_archive) {
- try argv.append("-no-whole-archive");
- whole_archive = false;
- }
-
- for (comp.c_object_table.keys()) |key| {
- try argv.append(try key.status.success.object_path.toString(arena));
- }
- if (module_obj_path) |p| {
- try argv.append(p);
- }
-
- if (compiler_rt_path) |p| {
- try argv.append(try p.toString(arena));
- }
-
- if (ubsan_rt_path) |p| {
- try argv.append(try p.toStringZ(arena));
- }
-
- if (comp.verbose_link) {
- // Skip over our own name so that the LLD linker name is the first argv item.
- Compilation.dump_argv(argv.items[1..]);
- }
-
- if (std.process.can_spawn) {
- // If possible, we run LLD as a child process because it does not always
- // behave properly as a library, unfortunately.
- // https://github.com/ziglang/zig/issues/3825
- var child = std.process.Child.init(argv.items, arena);
- if (comp.clang_passthrough_mode) {
- child.stdin_behavior = .Inherit;
- child.stdout_behavior = .Inherit;
- child.stderr_behavior = .Inherit;
-
- const term = child.spawnAndWait() catch |err| {
- log.err("failed to spawn (passthrough mode) LLD {s}: {s}", .{ argv.items[0], @errorName(err) });
- return error.UnableToSpawnWasm;
- };
- switch (term) {
- .Exited => |code| {
- if (code != 0) {
- std.process.exit(code);
- }
- },
- else => std.process.abort(),
- }
- } else {
- child.stdin_behavior = .Ignore;
- child.stdout_behavior = .Ignore;
- child.stderr_behavior = .Pipe;
-
- try child.spawn();
-
- const stderr = try child.stderr.?.reader().readAllAlloc(arena, std.math.maxInt(usize));
-
- const term = child.wait() catch |err| {
- log.err("failed to spawn LLD {s}: {s}", .{ argv.items[0], @errorName(err) });
- return error.UnableToSpawnWasm;
- };
-
- switch (term) {
- .Exited => |code| {
- if (code != 0) {
- diags.lockAndParseLldStderr(linker_command, stderr);
- return error.LinkFailure;
- }
- },
- else => {
- return diags.fail("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
- },
- }
-
- if (stderr.len != 0) {
- log.warn("unexpected LLD stderr:\n{s}", .{stderr});
- }
- }
- } else {
- const exit_code = try lldMain(arena, argv.items, false);
- if (exit_code != 0) {
- if (comp.clang_passthrough_mode) {
- std.process.exit(exit_code);
- } else {
- return diags.fail("{s} returned exit code {d}:\n{s}", .{ argv.items[0], exit_code });
- }
- }
- }
-
- // Give +x to the .wasm file if it is an executable and the OS is WASI.
- // Some systems may be configured to execute such binaries directly. Even if that
- // is not the case, it means we will get "exec format error" when trying to run
- // it, and then can react to that in the same way as trying to run an ELF file
- // from a foreign CPU architecture.
- if (fs.has_executable_bit and target.os.tag == .wasi and
- comp.config.output_mode == .Exe)
- {
- // TODO: what's our strategy for reporting linker errors from this function?
- // report a nice error here with the file path if it fails instead of
- // just returning the error code.
- // chmod does not interact with umask, so we use a conservative -rwxr--r-- here.
- std.posix.fchmodat(fs.cwd().fd, full_out_path, 0o744, 0) catch |err| switch (err) {
- error.OperationNotSupported => unreachable, // Not a symlink.
- else => |e| return e,
- };
- }
- }
-
- if (!wasm.base.disable_lld_caching) {
- // Update the file with the digest. If it fails we can continue; it only
- // means that the next invocation will have an unnecessary cache miss.
- Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
- log.warn("failed to save linking hash digest symlink: {s}", .{@errorName(err)});
- };
- // Again failure here only means an unnecessary cache miss.
- man.writeManifest() catch |err| {
- log.warn("failed to write cache manifest when linking: {s}", .{@errorName(err)});
- };
- // We hang on to this lock so that the output file path can be used without
- // other processes clobbering it.
- wasm.base.lock = man.toOwnedLock();
- }
-}
-
fn defaultEntrySymbolName(
preloaded_strings: *const PreloadedStrings,
wasi_exec_model: std.builtin.WasiExecModel,
@@ -4465,58 +4052,54 @@ pub fn symbolNameIndex(wasm: *Wasm, name: String) Allocator.Error!SymbolTableInd
return @enumFromInt(gop.index);
}
-pub fn refUavObj(wasm: *Wasm, ip_index: InternPool.Index, orig_ptr_ty: InternPool.Index) !UavsObjIndex {
- const comp = wasm.base.comp;
- const zcu = comp.zcu.?;
- const ip = &zcu.intern_pool;
- const gpa = comp.gpa;
- assert(comp.config.output_mode == .Obj);
-
- if (orig_ptr_ty != .none) {
- const abi_alignment = Zcu.Type.fromInterned(ip.typeOf(ip_index)).abiAlignment(zcu);
- const explicit_alignment = ip.indexToKey(orig_ptr_ty).ptr_type.flags.alignment;
- if (explicit_alignment.compare(.gt, abi_alignment)) {
- const gop = try wasm.overaligned_uavs.getOrPut(gpa, ip_index);
- gop.value_ptr.* = if (gop.found_existing) gop.value_ptr.maxStrict(explicit_alignment) else explicit_alignment;
- }
- }
-
- const gop = try wasm.uavs_obj.getOrPut(gpa, ip_index);
- if (!gop.found_existing) gop.value_ptr.* = .{
- // Lowering the value is delayed to avoid recursion.
- .code = undefined,
- .relocs = undefined,
- };
- return @enumFromInt(gop.index);
-}
-
-pub fn refUavExe(wasm: *Wasm, ip_index: InternPool.Index, orig_ptr_ty: InternPool.Index) !UavsExeIndex {
+pub fn addUavReloc(
+ wasm: *Wasm,
+ reloc_offset: usize,
+ uav_val: InternPool.Index,
+ orig_ptr_ty: InternPool.Index,
+ addend: u32,
+) !void {
const comp = wasm.base.comp;
const zcu = comp.zcu.?;
const ip = &zcu.intern_pool;
const gpa = comp.gpa;
- assert(comp.config.output_mode != .Obj);
- if (orig_ptr_ty != .none) {
- const abi_alignment = Zcu.Type.fromInterned(ip.typeOf(ip_index)).abiAlignment(zcu);
- const explicit_alignment = ip.indexToKey(orig_ptr_ty).ptr_type.flags.alignment;
- if (explicit_alignment.compare(.gt, abi_alignment)) {
- const gop = try wasm.overaligned_uavs.getOrPut(gpa, ip_index);
- gop.value_ptr.* = if (gop.found_existing) gop.value_ptr.maxStrict(explicit_alignment) else explicit_alignment;
- }
- }
-
- const gop = try wasm.uavs_exe.getOrPut(gpa, ip_index);
- if (gop.found_existing) {
- gop.value_ptr.count += 1;
+ @"align": {
+ const ptr_type = ip.indexToKey(orig_ptr_ty).ptr_type;
+ const this_align = ptr_type.flags.alignment;
+ if (this_align == .none) break :@"align";
+ const abi_align = Zcu.Type.fromInterned(ptr_type.child).abiAlignment(zcu);
+ if (this_align.compare(.lte, abi_align)) break :@"align";
+ const gop = try wasm.overaligned_uavs.getOrPut(gpa, uav_val);
+ gop.value_ptr.* = if (gop.found_existing) gop.value_ptr.maxStrict(this_align) else this_align;
+ }
+
+ if (comp.config.output_mode == .Obj) {
+ const gop = try wasm.uavs_obj.getOrPut(gpa, uav_val);
+ if (!gop.found_existing) gop.value_ptr.* = undefined; // to avoid recursion, `ZcuDataStarts` will lower the value later
+ try wasm.out_relocs.append(gpa, .{
+ .offset = @intCast(reloc_offset),
+ .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav_val) },
+ .tag = switch (wasm.pointerSize()) {
+ 32 => .memory_addr_i32,
+ 64 => .memory_addr_i64,
+ else => unreachable,
+ },
+ .addend = @intCast(addend),
+ });
} else {
- gop.value_ptr.* = .{
- // Lowering the value is delayed to avoid recursion.
- .code = undefined,
- .count = 1,
+ const gop = try wasm.uavs_exe.getOrPut(gpa, uav_val);
+ if (!gop.found_existing) gop.value_ptr.* = .{
+ .code = undefined, // to avoid recursion, `ZcuDataStarts` will lower the value later
+ .count = 0,
};
+ gop.value_ptr.count += 1;
+ try wasm.uav_fixups.append(gpa, .{
+ .uavs_exe_index = @enumFromInt(gop.index),
+ .offset = @intCast(reloc_offset),
+ .addend = addend,
+ });
}
- return @enumFromInt(gop.index);
}
pub 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 {
}
/// Asserts it is called after `Flush.data_segments` is fully populated and sorted.
-pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) u32 {
+pub fn uavAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 {
assert(wasm.flush_buffer.memory_layout_finished);
const comp = wasm.base.comp;
assert(comp.config.output_mode != .Obj);
+ const uav_index: UavsExeIndex = @enumFromInt(wasm.uavs_exe.getIndex(ip_index).?);
const ds_id: DataSegmentId = .pack(wasm, .{ .uav_exe = uav_index });
return wasm.flush_buffer.data_segments.get(ds_id).?;
}
diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig
index 7ed72e8518..60f5971e40 100644
--- a/src/link/Wasm/Flush.zig
+++ b/src/link/Wasm/Flush.zig
@@ -9,6 +9,7 @@ const Alignment = Wasm.Alignment;
const String = Wasm.String;
const Relocation = Wasm.Relocation;
const InternPool = @import("../../InternPool.zig");
+const Mir = @import("../../arch/wasm/Mir.zig");
const build_options = @import("build_options");
@@ -868,7 +869,21 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
.enum_type => {
try emitTagNameFunction(wasm, binary_bytes, f.data_segments.get(.__zig_tag_name_table).?, i.value(wasm).tag_name.table_index, ip_index);
},
- else => try i.value(wasm).function.lower(wasm, binary_bytes),
+ else => {
+ const func = i.value(wasm).function;
+ const mir: Mir = .{
+ .instructions = wasm.mir_instructions.slice().subslice(func.instructions_off, func.instructions_len),
+ .extra = wasm.mir_extra.items[func.extra_off..][0..func.extra_len],
+ .locals = wasm.mir_locals.items[func.locals_off..][0..func.locals_len],
+ .prologue = func.prologue,
+ // These fields are unused by `lower`.
+ .uavs = undefined,
+ .indirect_function_set = undefined,
+ .func_tys = undefined,
+ .error_name_table_ref_count = undefined,
+ };
+ try mir.lower(wasm, binary_bytes);
+ },
}
},
};
diff --git a/src/link/Xcoff.zig b/src/link/Xcoff.zig
index 525d99d391..fd143713ff 100644
--- a/src/link/Xcoff.zig
+++ b/src/link/Xcoff.zig
@@ -13,14 +13,12 @@ const Path = std.Build.Cache.Path;
const Zcu = @import("../Zcu.zig");
const InternPool = @import("../InternPool.zig");
const Compilation = @import("../Compilation.zig");
+const codegen = @import("../codegen.zig");
const link = @import("../link.zig");
const trace = @import("../tracy.zig").trace;
const build_options = @import("build_options");
-const Air = @import("../Air.zig");
-const LlvmObject = @import("../codegen/llvm.zig").Object;
base: link.File,
-llvm_object: LlvmObject.Ptr,
pub fn createEmpty(
arena: Allocator,
@@ -36,23 +34,20 @@ pub fn createEmpty(
assert(!use_lld); // Caught by Compilation.Config.resolve.
assert(target.os.tag == .aix); // Caught by Compilation.Config.resolve.
- const llvm_object = try LlvmObject.create(arena, comp);
const xcoff = try arena.create(Xcoff);
xcoff.* = .{
.base = .{
.tag = .xcoff,
.comp = comp,
.emit = emit,
- .zcu_object_sub_path = emit.sub_path,
+ .zcu_object_basename = emit.sub_path,
.gc_sections = options.gc_sections orelse false,
.print_gc_sections = options.print_gc_sections,
.stack_size = options.stack_size orelse 0,
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
.file = null,
- .disable_lld_caching = options.disable_lld_caching,
.build_id = options.build_id,
},
- .llvm_object = llvm_object,
};
return xcoff;
@@ -70,27 +65,27 @@ pub fn open(
}
pub fn deinit(self: *Xcoff) void {
- self.llvm_object.deinit();
+ _ = self;
}
pub fn updateFunc(
self: *Xcoff,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: Air,
- liveness: Air.Liveness,
+ mir: *const codegen.AnyMir,
) link.File.UpdateNavError!void {
- if (build_options.skip_non_native and builtin.object_format != .xcoff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
- try self.llvm_object.updateFunc(pt, func_index, air, liveness);
+ _ = self;
+ _ = pt;
+ _ = func_index;
+ _ = mir;
+ unreachable; // we always use llvm
}
pub fn updateNav(self: *Xcoff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
- if (build_options.skip_non_native and builtin.object_format != .xcoff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
- return self.llvm_object.updateNav(pt, nav);
+ _ = self;
+ _ = pt;
+ _ = nav;
+ unreachable; // we always use llvm
}
pub fn updateExports(
@@ -99,21 +94,19 @@ pub fn updateExports(
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
) !void {
- if (build_options.skip_non_native and builtin.object_format != .xcoff)
- @panic("Attempted to compile for object format that was disabled by build configuration");
-
- return self.llvm_object.updateExports(pt, exported, export_indices);
+ _ = self;
+ _ = pt;
+ _ = exported;
+ _ = export_indices;
+ unreachable; // we always use llvm
}
pub fn flush(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
- return self.flushModule(arena, tid, prog_node);
-}
-
-pub fn flushModule(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
if (build_options.skip_non_native and builtin.object_format != .xcoff)
@panic("Attempted to compile for object format that was disabled by build configuration");
+ _ = self;
+ _ = arena;
_ = tid;
-
- try self.base.emitLlvmObject(arena, self.llvm_object, prog_node);
+ _ = prog_node;
}
diff --git a/src/main.zig b/src/main.zig
index 20ccf4b7ec..3821fafb80 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -699,55 +699,30 @@ const Emit = union(enum) {
yes_default_path,
yes: []const u8,
- const Resolved = struct {
- data: ?Compilation.EmitLoc,
- dir: ?fs.Dir,
-
- fn deinit(self: *Resolved) void {
- if (self.dir) |*dir| {
- dir.close();
- }
- }
- };
-
- fn resolve(emit: Emit, default_basename: []const u8, output_to_cache: bool) !Resolved {
- var resolved: Resolved = .{ .data = null, .dir = null };
- errdefer resolved.deinit();
-
- switch (emit) {
- .no => {},
- .yes_default_path => {
- resolved.data = Compilation.EmitLoc{
- .directory = if (output_to_cache) null else .{
- .path = null,
- .handle = fs.cwd(),
- },
- .basename = default_basename,
- };
- },
- .yes => |full_path| {
- const basename = fs.path.basename(full_path);
- if (fs.path.dirname(full_path)) |dirname| {
- const handle = try fs.cwd().openDir(dirname, .{});
- resolved = .{
- .dir = handle,
- .data = Compilation.EmitLoc{
- .basename = basename,
- .directory = .{
- .path = dirname,
- .handle = handle,
- },
- },
- };
- } else {
- resolved.data = Compilation.EmitLoc{
- .basename = basename,
- .directory = .{ .path = null, .handle = fs.cwd() },
+ const OutputToCacheReason = enum { listen, @"zig run", @"zig test" };
+ fn resolve(emit: Emit, default_basename: []const u8, output_to_cache: ?OutputToCacheReason) Compilation.CreateOptions.Emit {
+ return switch (emit) {
+ .no => .no,
+ .yes_default_path => if (output_to_cache != null) .yes_cache else .{ .yes_path = default_basename },
+ .yes => |path| if (output_to_cache) |reason| {
+ switch (reason) {
+ .listen => fatal("--listen incompatible with explicit output path '{s}'", .{path}),
+ .@"zig run", .@"zig test" => fatal(
+ "'{s}' with explicit output path '{s}' requires explicit '-femit-bin=path' or '-fno-emit-bin'",
+ .{ @tagName(reason), path },
+ ),
+ }
+ } else e: {
+ // If there's a dirname, check that dir exists. This will give a more descriptive error than `Compilation` otherwise would.
+ if (fs.path.dirname(path)) |dir_path| {
+ var dir = fs.cwd().openDir(dir_path, .{}) catch |err| {
+ fatal("unable to open output directory '{s}': {s}", .{ dir_path, @errorName(err) });
};
+ dir.close();
}
+ break :e .{ .yes_path = path };
},
- }
- return resolved;
+ };
}
};
@@ -867,9 +842,9 @@ fn buildOutputType(
var linker_allow_undefined_version: bool = false;
var linker_enable_new_dtags: ?bool = null;
var disable_c_depfile = false;
- var linker_sort_section: ?link.File.Elf.SortSection = null;
+ var linker_sort_section: ?link.File.Lld.Elf.SortSection = null;
var linker_gc_sections: ?bool = null;
- var linker_compress_debug_sections: ?link.File.Elf.CompressDebugSections = null;
+ var linker_compress_debug_sections: ?link.File.Lld.Elf.CompressDebugSections = null;
var linker_allow_shlib_undefined: ?bool = null;
var allow_so_scripts: bool = false;
var linker_bind_global_refs_locally: ?bool = null;
@@ -921,7 +896,7 @@ fn buildOutputType(
var debug_compiler_runtime_libs = false;
var opt_incremental: ?bool = null;
var install_name: ?[]const u8 = null;
- var hash_style: link.File.Elf.HashStyle = .both;
+ var hash_style: link.File.Lld.Elf.HashStyle = .both;
var entitlements: ?[]const u8 = null;
var pagezero_size: ?u64 = null;
var lib_search_strategy: link.UnresolvedInput.SearchStrategy = .paths_first;
@@ -1196,11 +1171,11 @@ fn buildOutputType(
install_name = args_iter.nextOrFatal();
} else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) {
const param = arg["--compress-debug-sections=".len..];
- linker_compress_debug_sections = std.meta.stringToEnum(link.File.Elf.CompressDebugSections, param) orelse {
+ linker_compress_debug_sections = std.meta.stringToEnum(link.File.Lld.Elf.CompressDebugSections, param) orelse {
fatal("expected --compress-debug-sections=[none|zlib|zstd], found '{s}'", .{param});
};
} else if (mem.eql(u8, arg, "--compress-debug-sections")) {
- linker_compress_debug_sections = link.File.Elf.CompressDebugSections.zlib;
+ linker_compress_debug_sections = link.File.Lld.Elf.CompressDebugSections.zlib;
} else if (mem.eql(u8, arg, "-pagezero_size")) {
const next_arg = args_iter.nextOrFatal();
pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| {
@@ -2368,7 +2343,7 @@ fn buildOutputType(
if (it.only_arg.len == 0) {
linker_compress_debug_sections = .zlib;
} else {
- linker_compress_debug_sections = std.meta.stringToEnum(link.File.Elf.CompressDebugSections, it.only_arg) orelse {
+ linker_compress_debug_sections = std.meta.stringToEnum(link.File.Lld.Elf.CompressDebugSections, it.only_arg) orelse {
fatal("expected [none|zlib|zstd] after --compress-debug-sections, found '{s}'", .{it.only_arg});
};
}
@@ -2505,7 +2480,7 @@ fn buildOutputType(
linker_print_map = true;
} else if (mem.eql(u8, arg, "--sort-section")) {
const arg1 = linker_args_it.nextOrFatal();
- linker_sort_section = std.meta.stringToEnum(link.File.Elf.SortSection, arg1) orelse {
+ linker_sort_section = std.meta.stringToEnum(link.File.Lld.Elf.SortSection, arg1) orelse {
fatal("expected [name|alignment] after --sort-section, found '{s}'", .{arg1});
};
} else if (mem.eql(u8, arg, "--allow-shlib-undefined") or
@@ -2551,7 +2526,7 @@ fn buildOutputType(
try linker_export_symbol_names.append(arena, linker_args_it.nextOrFatal());
} else if (mem.eql(u8, arg, "--compress-debug-sections")) {
const arg1 = linker_args_it.nextOrFatal();
- linker_compress_debug_sections = std.meta.stringToEnum(link.File.Elf.CompressDebugSections, arg1) orelse {
+ linker_compress_debug_sections = std.meta.stringToEnum(link.File.Lld.Elf.CompressDebugSections, arg1) orelse {
fatal("expected [none|zlib|zstd] after --compress-debug-sections, found '{s}'", .{arg1});
};
} else if (mem.startsWith(u8, arg, "-z")) {
@@ -2764,7 +2739,7 @@ fn buildOutputType(
mem.eql(u8, arg, "--hash-style"))
{
const next_arg = linker_args_it.nextOrFatal();
- hash_style = std.meta.stringToEnum(link.File.Elf.HashStyle, next_arg) orelse {
+ hash_style = std.meta.stringToEnum(link.File.Lld.Elf.HashStyle, next_arg) orelse {
fatal("expected [sysv|gnu|both] after --hash-style, found '{s}'", .{
next_arg,
});
@@ -2830,7 +2805,7 @@ fn buildOutputType(
.link => {
create_module.opts.output_mode = if (is_shared_lib) .Lib else .Exe;
if (emit_bin != .no) {
- emit_bin = if (out_path) |p| .{ .yes = p } else EmitBin.yes_a_out;
+ emit_bin = if (out_path) |p| .{ .yes = p } else .yes_a_out;
}
if (emit_llvm) {
fatal("-emit-llvm cannot be used when linking", .{});
@@ -3208,7 +3183,17 @@ fn buildOutputType(
var cleanup_emit_bin_dir: ?fs.Dir = null;
defer if (cleanup_emit_bin_dir) |*dir| dir.close();
- const output_to_cache = listen != .none;
+ // For `zig run` and `zig test`, we don't want to put the binary in the cwd by default. So, if
+ // the binary is requested with no explicit path (as is the default), we emit to the cache.
+ const output_to_cache: ?Emit.OutputToCacheReason = switch (listen) {
+ .stdio, .ip4 => .listen,
+ .none => if (arg_mode == .run and emit_bin == .yes_default_path)
+ .@"zig run"
+ else if (arg_mode == .zig_test and emit_bin == .yes_default_path)
+ .@"zig test"
+ else
+ null,
+ };
const optional_version = if (have_version) version else null;
const root_name = if (provided_name) |n| n else main_mod.fully_qualified_name;
@@ -3225,150 +3210,57 @@ fn buildOutputType(
},
};
- const a_out_basename = switch (target.ofmt) {
- .coff => "a.exe",
- else => "a.out",
- };
-
- const emit_bin_loc: ?Compilation.EmitLoc = switch (emit_bin) {
- .no => null,
- .yes_default_path => Compilation.EmitLoc{
- .directory = blk: {
- switch (arg_mode) {
- .run, .zig_test => break :blk null,
- .build, .cc, .cpp, .translate_c, .zig_test_obj => {
- if (output_to_cache) {
- break :blk null;
- } else {
- break :blk .{ .path = null, .handle = fs.cwd() };
- }
- },
- }
- },
- .basename = if (clang_preprocessor_mode == .pch)
- try std.fmt.allocPrint(arena, "{s}.pch", .{root_name})
- else
- try std.zig.binNameAlloc(arena, .{
+ const emit_bin_resolved: Compilation.CreateOptions.Emit = switch (emit_bin) {
+ .no => .no,
+ .yes_default_path => emit: {
+ if (output_to_cache != null) break :emit .yes_cache;
+ const name = switch (clang_preprocessor_mode) {
+ .pch => try std.fmt.allocPrint(arena, "{s}.pch", .{root_name}),
+ else => try std.zig.binNameAlloc(arena, .{
.root_name = root_name,
.target = target,
.output_mode = create_module.resolved_options.output_mode,
.link_mode = create_module.resolved_options.link_mode,
.version = optional_version,
}),
+ };
+ break :emit .{ .yes_path = name };
},
- .yes => |full_path| b: {
- const basename = fs.path.basename(full_path);
- if (fs.path.dirname(full_path)) |dirname| {
- const handle = fs.cwd().openDir(dirname, .{}) catch |err| {
- fatal("unable to open output directory '{s}': {s}", .{ dirname, @errorName(err) });
- };
- cleanup_emit_bin_dir = handle;
- break :b Compilation.EmitLoc{
- .basename = basename,
- .directory = .{
- .path = dirname,
- .handle = handle,
- },
- };
- } else {
- break :b Compilation.EmitLoc{
- .basename = basename,
- .directory = .{ .path = null, .handle = fs.cwd() },
+ .yes => |path| if (output_to_cache != null) {
+ assert(output_to_cache == .listen); // there was an explicit bin path
+ fatal("--listen incompatible with explicit output path '{s}'", .{path});
+ } else emit: {
+ // If there's a dirname, check that dir exists. This will give a more descriptive error than `Compilation` otherwise would.
+ if (fs.path.dirname(path)) |dir_path| {
+ var dir = fs.cwd().openDir(dir_path, .{}) catch |err| {
+ fatal("unable to open output directory '{s}': {s}", .{ dir_path, @errorName(err) });
};
+ dir.close();
}
+ break :emit .{ .yes_path = path };
},
- .yes_a_out => Compilation.EmitLoc{
- .directory = .{ .path = null, .handle = fs.cwd() },
- .basename = a_out_basename,
+ .yes_a_out => emit: {
+ assert(output_to_cache == null);
+ break :emit .{ .yes_path = switch (target.ofmt) {
+ .coff => "a.exe",
+ else => "a.out",
+ } };
},
};
const default_h_basename = try std.fmt.allocPrint(arena, "{s}.h", .{root_name});
- var emit_h_resolved = emit_h.resolve(default_h_basename, output_to_cache) catch |err| {
- switch (emit_h) {
- .yes => |p| {
- fatal("unable to open directory from argument '-femit-h', '{s}': {s}", .{
- p, @errorName(err),
- });
- },
- .yes_default_path => {
- fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{
- default_h_basename, @errorName(err),
- });
- },
- .no => unreachable,
- }
- };
- defer emit_h_resolved.deinit();
+ const emit_h_resolved = emit_h.resolve(default_h_basename, output_to_cache);
const default_asm_basename = try std.fmt.allocPrint(arena, "{s}.s", .{root_name});
- var emit_asm_resolved = emit_asm.resolve(default_asm_basename, output_to_cache) catch |err| {
- switch (emit_asm) {
- .yes => |p| {
- fatal("unable to open directory from argument '-femit-asm', '{s}': {s}", .{
- p, @errorName(err),
- });
- },
- .yes_default_path => {
- fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{
- default_asm_basename, @errorName(err),
- });
- },
- .no => unreachable,
- }
- };
- defer emit_asm_resolved.deinit();
+ const emit_asm_resolved = emit_asm.resolve(default_asm_basename, output_to_cache);
const default_llvm_ir_basename = try std.fmt.allocPrint(arena, "{s}.ll", .{root_name});
- var emit_llvm_ir_resolved = emit_llvm_ir.resolve(default_llvm_ir_basename, output_to_cache) catch |err| {
- switch (emit_llvm_ir) {
- .yes => |p| {
- fatal("unable to open directory from argument '-femit-llvm-ir', '{s}': {s}", .{
- p, @errorName(err),
- });
- },
- .yes_default_path => {
- fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{
- default_llvm_ir_basename, @errorName(err),
- });
- },
- .no => unreachable,
- }
- };
- defer emit_llvm_ir_resolved.deinit();
+ const emit_llvm_ir_resolved = emit_llvm_ir.resolve(default_llvm_ir_basename, output_to_cache);
const default_llvm_bc_basename = try std.fmt.allocPrint(arena, "{s}.bc", .{root_name});
- var emit_llvm_bc_resolved = emit_llvm_bc.resolve(default_llvm_bc_basename, output_to_cache) catch |err| {
- switch (emit_llvm_bc) {
- .yes => |p| {
- fatal("unable to open directory from argument '-femit-llvm-bc', '{s}': {s}", .{
- p, @errorName(err),
- });
- },
- .yes_default_path => {
- fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{
- default_llvm_bc_basename, @errorName(err),
- });
- },
- .no => unreachable,
- }
- };
- defer emit_llvm_bc_resolved.deinit();
+ const emit_llvm_bc_resolved = emit_llvm_bc.resolve(default_llvm_bc_basename, output_to_cache);
- var emit_docs_resolved = emit_docs.resolve("docs", output_to_cache) catch |err| {
- switch (emit_docs) {
- .yes => |p| {
- fatal("unable to open directory from argument '-femit-docs', '{s}': {s}", .{
- p, @errorName(err),
- });
- },
- .yes_default_path => {
- fatal("unable to open directory 'docs': {s}", .{@errorName(err)});
- },
- .no => unreachable,
- }
- };
- defer emit_docs_resolved.deinit();
+ const emit_docs_resolved = emit_docs.resolve("docs", output_to_cache);
const is_exe_or_dyn_lib = switch (create_module.resolved_options.output_mode) {
.Obj => false,
@@ -3378,7 +3270,7 @@ fn buildOutputType(
// Note that cmake when targeting Windows will try to execute
// zig cc to make an executable and output an implib too.
const implib_eligible = is_exe_or_dyn_lib and
- emit_bin_loc != null and target.os.tag == .windows;
+ emit_bin_resolved != .no and target.os.tag == .windows;
if (!implib_eligible) {
if (!emit_implib_arg_provided) {
emit_implib = .no;
@@ -3387,22 +3279,18 @@ fn buildOutputType(
}
}
const default_implib_basename = try std.fmt.allocPrint(arena, "{s}.lib", .{root_name});
- var emit_implib_resolved = switch (emit_implib) {
- .no => Emit.Resolved{ .data = null, .dir = null },
- .yes => |p| emit_implib.resolve(default_implib_basename, output_to_cache) catch |err| {
- fatal("unable to open directory from argument '-femit-implib', '{s}': {s}", .{
- p, @errorName(err),
+ const emit_implib_resolved: Compilation.CreateOptions.Emit = switch (emit_implib) {
+ .no => .no,
+ .yes => emit_implib.resolve(default_implib_basename, output_to_cache),
+ .yes_default_path => emit: {
+ if (output_to_cache != null) break :emit .yes_cache;
+ const p = try fs.path.join(arena, &.{
+ fs.path.dirname(emit_bin_resolved.yes_path) orelse ".",
+ default_implib_basename,
});
- },
- .yes_default_path => Emit.Resolved{
- .data = Compilation.EmitLoc{
- .directory = emit_bin_loc.?.directory,
- .basename = default_implib_basename,
- },
- .dir = null,
+ break :emit .{ .yes_path = p };
},
};
- defer emit_implib_resolved.deinit();
var thread_pool: ThreadPool = undefined;
try thread_pool.init(.{
@@ -3456,7 +3344,7 @@ fn buildOutputType(
src.src_path = try dirs.local_cache.join(arena, &.{sub_path});
}
- if (build_options.have_llvm and emit_asm != .no) {
+ if (build_options.have_llvm and emit_asm_resolved != .no) {
// LLVM has no way to set this non-globally.
const argv = [_][*:0]const u8{ "zig (LLVM option parsing)", "--x86-asm-syntax=intel" };
@import("codegen/llvm/bindings.zig").ParseCommandLineOptions(argv.len, &argv);
@@ -3472,23 +3360,11 @@ fn buildOutputType(
fatal("--debug-incremental requires -fincremental", .{});
}
- const disable_lld_caching = !output_to_cache;
-
const cache_mode: Compilation.CacheMode = b: {
+ // Once incremental compilation is the default, we'll want some smarter logic here,
+ // considering things like the backend in use and whether there's a ZCU.
+ if (output_to_cache == null) break :b .none;
if (incremental) break :b .incremental;
- if (disable_lld_caching) break :b .incremental;
- if (!create_module.resolved_options.have_zcu) break :b .whole;
-
- // TODO: once we support incremental compilation for the LLVM backend
- // via saving the LLVM module into a bitcode file and restoring it,
- // along with compiler state, this clause can be removed so that
- // incremental cache mode is used for LLVM backend too.
- if (create_module.resolved_options.use_llvm) break :b .whole;
-
- // Eventually, this default should be `.incremental`. However, since incremental
- // compilation is currently an opt-in feature, it makes a strictly worse default cache mode
- // than `.whole`.
- // https://github.com/ziglang/zig/issues/21165
break :b .whole;
};
@@ -3510,13 +3386,13 @@ fn buildOutputType(
.main_mod = main_mod,
.root_mod = root_mod,
.std_mod = std_mod,
- .emit_bin = emit_bin_loc,
- .emit_h = emit_h_resolved.data,
- .emit_asm = emit_asm_resolved.data,
- .emit_llvm_ir = emit_llvm_ir_resolved.data,
- .emit_llvm_bc = emit_llvm_bc_resolved.data,
- .emit_docs = emit_docs_resolved.data,
- .emit_implib = emit_implib_resolved.data,
+ .emit_bin = emit_bin_resolved,
+ .emit_h = emit_h_resolved,
+ .emit_asm = emit_asm_resolved,
+ .emit_llvm_ir = emit_llvm_ir_resolved,
+ .emit_llvm_bc = emit_llvm_bc_resolved,
+ .emit_docs = emit_docs_resolved,
+ .emit_implib = emit_implib_resolved,
.lib_directories = create_module.lib_directories.items,
.rpath_list = create_module.rpath_list.items,
.symbol_wrap_set = symbol_wrap_set,
@@ -3599,7 +3475,6 @@ fn buildOutputType(
.test_filters = test_filters.items,
.test_name_prefix = test_name_prefix,
.test_runner_path = test_runner_path,
- .disable_lld_caching = disable_lld_caching,
.cache_mode = cache_mode,
.subsystem = subsystem,
.debug_compile_errors = debug_compile_errors,
@@ -3744,13 +3619,8 @@ fn buildOutputType(
}) {
dev.checkAny(&.{ .run_command, .test_command });
- if (test_exec_args.items.len == 0 and target.ofmt == .c) default_exec_args: {
+ if (test_exec_args.items.len == 0 and target.ofmt == .c and emit_bin_resolved != .no) {
// Default to using `zig run` to execute the produced .c code from `zig test`.
- const c_code_loc = emit_bin_loc orelse break :default_exec_args;
- const c_code_directory = c_code_loc.directory orelse comp.bin_file.?.emit.root_dir;
- const c_code_path = try fs.path.join(arena, &[_][]const u8{
- c_code_directory.path orelse ".", c_code_loc.basename,
- });
try test_exec_args.appendSlice(arena, &.{ self_exe_path, "run" });
if (dirs.zig_lib.path) |p| {
try test_exec_args.appendSlice(arena, &.{ "-I", p });
@@ -3775,7 +3645,7 @@ fn buildOutputType(
if (create_module.dynamic_linker) |dl| {
try test_exec_args.appendSlice(arena, &.{ "--dynamic-linker", dl });
}
- try test_exec_args.append(arena, c_code_path);
+ try test_exec_args.append(arena, null); // placeholder for the path of the emitted C source file
}
try runOrTest(
@@ -4354,12 +4224,22 @@ fn runOrTest(
runtime_args_start: ?usize,
link_libc: bool,
) !void {
- const lf = comp.bin_file orelse return;
- // A naive `directory.join` here will indeed get the correct path to the binary,
- // however, in the case of cwd, we actually want `./foo` so that the path can be executed.
- const exe_path = try fs.path.join(arena, &[_][]const u8{
- lf.emit.root_dir.path orelse ".", lf.emit.sub_path,
- });
+ const raw_emit_bin = comp.emit_bin orelse return;
+ const exe_path = switch (comp.cache_use) {
+ .none => p: {
+ if (fs.path.isAbsolute(raw_emit_bin)) break :p raw_emit_bin;
+ // Use `fs.path.join` to make a file in the cwd is still executed properly.
+ break :p try fs.path.join(arena, &.{
+ ".",
+ raw_emit_bin,
+ });
+ },
+ .whole, .incremental => try comp.dirs.local_cache.join(arena, &.{
+ "o",
+ &Cache.binToHex(comp.digest.?),
+ raw_emit_bin,
+ }),
+ };
var argv = std.ArrayList([]const u8).init(gpa);
defer argv.deinit();
@@ -5087,16 +4967,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
};
};
- const exe_basename = try std.zig.binNameAlloc(arena, .{
- .root_name = "build",
- .target = resolved_target.result,
- .output_mode = .Exe,
- });
- const emit_bin: Compilation.EmitLoc = .{
- .directory = null, // Use the local zig-cache.
- .basename = exe_basename,
- };
-
process.raiseFileDescriptorLimit();
const cwd_path = try introspect.getResolvedCwd(arena);
@@ -5357,8 +5227,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
.config = config,
.root_mod = root_mod,
.main_mod = build_mod,
- .emit_bin = emit_bin,
- .emit_h = null,
+ .emit_bin = .yes_cache,
.self_exe_path = self_exe_path,
.thread_pool = &thread_pool,
.verbose_cc = verbose_cc,
@@ -5386,8 +5255,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
// Since incremental compilation isn't done yet, we use cache_mode = whole
// above, and thus the output file is already closed.
//try comp.makeBinFileExecutable();
- child_argv.items[argv_index_exe] =
- try dirs.local_cache.join(arena, &.{comp.cache_use.whole.bin_sub_path.?});
+ child_argv.items[argv_index_exe] = try dirs.local_cache.join(arena, &.{
+ "o",
+ &Cache.binToHex(comp.digest.?),
+ comp.emit_bin.?,
+ });
}
if (process.can_spawn) {
@@ -5504,16 +5376,6 @@ fn jitCmd(
.is_explicit_dynamic_linker = false,
};
- const exe_basename = try std.zig.binNameAlloc(arena, .{
- .root_name = options.cmd_name,
- .target = resolved_target.result,
- .output_mode = .Exe,
- });
- const emit_bin: Compilation.EmitLoc = .{
- .directory = null, // Use the global zig-cache.
- .basename = exe_basename,
- };
-
const self_exe_path = fs.selfExePathAlloc(arena) catch |err| {
fatal("unable to find self exe path: {s}", .{@errorName(err)});
};
@@ -5605,8 +5467,7 @@ fn jitCmd(
.config = config,
.root_mod = root_mod,
.main_mod = root_mod,
- .emit_bin = emit_bin,
- .emit_h = null,
+ .emit_bin = .yes_cache,
.self_exe_path = self_exe_path,
.thread_pool = &thread_pool,
.cache_mode = .whole,
@@ -5637,7 +5498,11 @@ fn jitCmd(
};
}
- const exe_path = try dirs.global_cache.join(arena, &.{comp.cache_use.whole.bin_sub_path.?});
+ const exe_path = try dirs.global_cache.join(arena, &.{
+ "o",
+ &Cache.binToHex(comp.digest.?),
+ comp.emit_bin.?,
+ });
child_argv.appendAssumeCapacity(exe_path);
}
diff --git a/src/target.zig b/src/target.zig
index 247b783439..0cecc168f5 100644
--- a/src/target.zig
+++ b/src/target.zig
@@ -739,7 +739,7 @@ pub fn functionPointerMask(target: std.Target) ?u64 {
pub fn supportsTailCall(target: std.Target, backend: std.builtin.CompilerBackend) bool {
switch (backend) {
- .stage1, .stage2_llvm => return @import("codegen/llvm.zig").supportsTailCall(target),
+ .stage2_llvm => return @import("codegen/llvm.zig").supportsTailCall(target),
.stage2_c => return true,
else => return false,
}
@@ -850,7 +850,9 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
},
.separate_thread => switch (backend) {
.stage2_llvm => false,
- else => true,
+ .stage2_c, .stage2_wasm, .stage2_x86_64 => true,
+ // TODO: most self-hosted backends should be able to support this without too much work.
+ else => false,
},
};
}